virtio-blk: fix barrier support

Submitted by Christoph Hellwig on May 19, 2010, 10:40 a.m.

Details

Message ID 20100519104009.GA8813@lst.de
State New
Headers show

Commit Message

Christoph Hellwig May 19, 2010, 10:40 a.m.
Before issuing the barrier to the block driver we need to flush our oustanding
queue of write requests, as the flush is supposed to be issued after them.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Comments

Kevin Wolf May 19, 2010, 11:27 a.m.
Am 19.05.2010 12:40, schrieb Christoph Hellwig:
> Before issuing the barrier to the block driver we need to flush our oustanding
> queue of write requests, as the flush is supposed to be issued after them.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Thanks, applied to the block branch.

I'm going to send a pull request today to get this in ASAP. It would be
helpful to know by then why Avi's patch helps and if it should be
pushed, too. It looks merely like a workaround, so I'd love to see it
replaced by a real fix.

Kevin

Patch hide | download patch | download mbox

Index: qemu/hw/virtio-blk.c
===================================================================
--- qemu.orig/hw/virtio-blk.c	2010-05-19 11:05:23.259005741 +0200
+++ qemu/hw/virtio-blk.c	2010-05-19 11:08:09.797255846 +0200
@@ -238,10 +238,20 @@  static void do_multiwrite(BlockDriverSta
     }
 }
 
-static void virtio_blk_handle_flush(VirtIOBlockReq *req)
+static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
+    VirtIOBlockReq *req, BlockDriverState **old_bs)
 {
     BlockDriverAIOCB *acb;
 
+    /*
+     * Make sure all outstanding writes are posted to the backing device.
+     */
+    if (*old_bs != NULL) {
+        do_multiwrite(*old_bs, blkreq, *num_writes);
+    }
+    *num_writes = 0;
+    *old_bs = req->dev->bs;
+
     acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
     if (!acb) {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
@@ -314,7 +324,8 @@  static void virtio_blk_handle_request(Vi
     req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
 
     if (req->out->type & VIRTIO_BLK_T_FLUSH) {
-        virtio_blk_handle_flush(req);
+        virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes,
+            req, &mrb->old_bs);
     } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
         virtio_blk_handle_scsi(req);
     } else if (req->out->type & VIRTIO_BLK_T_OUT) {