Skip to contentSkip to conversation

block: flush backing_hd in the right place

PATCH Applied Christoph Hellwig 3 participants 9 messages Jan 12, 2010 – Jan 20, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 block: flush backing_hd in the right place

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

block.c +7 -10
Index: qemu/block.c
===================================================================
@@ -623,6 +623,12 @@ int bdrv_commit(BlockDriverState *bs)
     if (drv->bdrv_make_empty)
 	return drv->bdrv_make_empty(bs);
 
+    /*
+     * Make sure all data we wrote to the backing device is actually
+     * stable on disk.
+     */
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
     return 0;
 }
 
@@ -1124,12 +1130,8 @@ const char *bdrv_get_device_name(BlockDr
 
 void bdrv_flush(BlockDriverState *bs)
 {
-    if (!bs->drv)
-        return;
-    if (bs->drv->bdrv_flush)
+    if (bs->drv && bs->drv->bdrv_flush)
         bs->drv->bdrv_flush(bs);
-    if (bs->backing_hd)
-        bdrv_flush(bs->backing_hd);
 }
 
 void bdrv_flush_all(void)
@@ -1806,11 +1808,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDr
 
     if (!drv)
         return NULL;
-
-    /*
-     * Note that unlike bdrv_flush the driver is reponsible for flushing a
-     * backing image if it exists.
-     */
     return drv->bdrv_aio_flush(bs, cb, opaque);
 }
 
#1 lore raw

Am 12.01.2010 13:49, schrieb Christoph Hellwig:

Quoted 13 lines

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

Index: qemu/block.c
===================================================================

block.c +0 -0
@@ -623,6 +623,12 @@ int bdrv_commit(BlockDriverState *bs)
     if (drv->bdrv_make_empty)

block.c int bdrv_commit(BlockDriverState *bs) · line 633

Quoted 10 lines
block.c +6 -0
 	return drv->bdrv_make_empty(bs);
 
+    /*
+     * Make sure all data we wrote to the backing device is actually
+     * stable on disk.
+     */
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
     return 0;
 }

Format drivers with a bdrv_make_empty return before the flush, so it won't work for qcow1. Looks good otherwise.

If it has done a bdrv_make_empty we might also want to flush bs?

Kevin

#2 lore raw
Quoted 4 lines · Kevin Wolf
Quoted 4 lines
block.c +0 -0
@@ -623,6 +623,12 @@ int bdrv_commit(BlockDriverState *bs)
     if (drv->bdrv_make_empty)
 	return drv->bdrv_make_empty(bs);
 
Quoted 11 lines

block.c int bdrv_commit(BlockDriverState *bs) · line 633

Quoted 8 lines
block.c +6 -0
+    /*
+     * Make sure all data we wrote to the backing device is actually
+     * stable on disk.
+     */
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
     return 0;
 }

Format drivers with a bdrv_make_empty return before the flush, so it won't work for qcow1. Looks good otherwise.

Oh, okay.

Quoted 1 line

If it has done a bdrv_make_empty we might also want to flush bs?

Indeed. I'll spin a new version.

#3 lore raw

PATCH v2 1/2 block: flush backing_hd in the right place

In reply to Christoph Hellwig

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

Also flush the frontend image if we have a make_empty method that possibly writes to it.

block.c +13 -13
Index: qemu/block.c
===================================================================
@@ -589,6 +589,7 @@ int bdrv_commit(BlockDriverState *bs)
     BlockDriver *drv = bs->drv;
     int64_t i, total_sectors;
     int n, j;
+    int ret = 0;
     unsigned char sector[512];
 
     if (!drv)
@@ -620,10 +621,18 @@ int bdrv_commit(BlockDriverState *bs)
         }
     }
 
-    if (drv->bdrv_make_empty)
-	return drv->bdrv_make_empty(bs);
+    if (drv->bdrv_make_empty) {
+	ret = drv->bdrv_make_empty(bs);
+        bdrv_flush(bs);
+    }
 
-    return 0;
+    /*
+     * Make sure all data we wrote to the backing device is actually
+     * stable on disk.
+     */
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
+    return ret;
 }
 
 static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
@@ -1124,12 +1133,8 @@ const char *bdrv_get_device_name(BlockDr
 
 void bdrv_flush(BlockDriverState *bs)
 {
-    if (!bs->drv)
-        return;
-    if (bs->drv->bdrv_flush)
+    if (bs->drv && bs->drv->bdrv_flush)
         bs->drv->bdrv_flush(bs);
-    if (bs->backing_hd)
-        bdrv_flush(bs->backing_hd);
 }
 
 void bdrv_flush_all(void)
@@ -1806,11 +1811,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDr
 
     if (!drv)
         return NULL;
-
-    /*
-     * Note that unlike bdrv_flush the driver is reponsible for flushing a
-     * backing image if it exists.
-     */
     return drv->bdrv_aio_flush(bs, cb, opaque);
 }
 
#4 lore raw

Am 12.01.2010 19:13, schrieb Christoph Hellwig:

Quoted 22 lines

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

Also flush the frontend image if we have a make_empty method that possibly writes to it.

Index: qemu/block.c
===================================================================

block.c +1 -0
@@ -589,6 +589,7 @@ int bdrv_commit(BlockDriverState *bs)
     BlockDriver *drv = bs->drv;
     int64_t i, total_sectors;
     int n, j;
+    int ret = 0;
     unsigned char sector[512];
 
     if (!drv)

block.c int bdrv_commit(BlockDriverState *bs) · line 627

Quoted 9 lines
block.c +4 -2
@@ -620,10 +621,18 @@ int bdrv_commit(BlockDriverState *bs)
         }
     }
 
-    if (drv->bdrv_make_empty)
-	return drv->bdrv_make_empty(bs);
+    if (drv->bdrv_make_empty) {
+	ret = drv->bdrv_make_empty(bs);
+        bdrv_flush(bs);
+    }

Indentation is off here (but it already was before the patch). The logic looks good to me now.

Kevin

#5 lore raw
In reply to Christoph Hellwig
Quoted 6 lines · Christoph Hellwig

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

Applied. Thanks.

Regards,

Anthony Liguori

Quoted 47 lines

Index: qemu/block.c
===================================================================

block.c +7 -10
@@ -623,6 +623,12 @@ int bdrv_commit(BlockDriverState *bs)
      if (drv->bdrv_make_empty)
  	return drv->bdrv_make_empty(bs);
 
+    /*
+     * Make sure all data we wrote to the backing device is actually
+     * stable on disk.
+     */
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
      return 0;
  }
 
@@ -1124,12 +1130,8 @@ const char *bdrv_get_device_name(BlockDr
 
  void bdrv_flush(BlockDriverState *bs)
  {
-    if (!bs->drv)
-        return;
-    if (bs->drv->bdrv_flush)
+    if (bs->drv&&  bs->drv->bdrv_flush)
          bs->drv->bdrv_flush(bs);
-    if (bs->backing_hd)
-        bdrv_flush(bs->backing_hd);
  }
 
  void bdrv_flush_all(void)
@@ -1806,11 +1808,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDr
 
      if (!drv)
          return NULL;
-
-    /*
-     * Note that unlike bdrv_flush the driver is reponsible for flushing a
-     * backing image if it exists.
-     */
      return drv->bdrv_aio_flush(bs, cb, opaque);
  }
 
#6 lore raw

Am 14.01.2010 00:26, schrieb Anthony Liguori:

Quoted 9 lines · Christoph Hellwig
Quoted 6 lines

The backing device is only modified from bdrv_commit. So instead of flushing it every time bdrv_flush is called for the front-end device only flush it after we're written data to it in bdrv_commit.

Applied. Thanks.

Anthony, you seem to have missed the v2 patch that considered my review comments. Can you please apply the diff between v1 and v2 on top?

Kevin

#7 lore raw

PATCH 1/1 block: fix cache flushing in bdrv_commit

Quoted 2 lines · Kevin Wolf

Anthony, you seem to have missed the v2 patch that considered my review comments. Can you please apply the diff between v1 and v2 on top?

Here is the differences in patch form:

---
From: Christoph Hellwig <[email protected]>
Subject: block: fix cache flushing in bdrv_commit

As pointed out by Kevin Wolf the previous patch returned early if we there is a bdrv_make_empty method and it missed a cache flush for the frontend device after the bdev_make_empty call. This patch fixes it up.

block.c +6 -3
Index: qemu/block.c
===================================================================
@@ -589,6 +589,7 @@ int bdrv_commit(BlockDriverState *bs)
     BlockDriver *drv = bs->drv;
     int64_t i, total_sectors;
     int n, j;
+    int ret = 0;
     unsigned char sector[512];
 
     if (!drv)
@@ -620,8 +621,10 @@ int bdrv_commit(BlockDriverState *bs)
         }
     }
 
-    if (drv->bdrv_make_empty)
-	return drv->bdrv_make_empty(bs);
+    if (drv->bdrv_make_empty) {
+        ret = drv->bdrv_make_empty(bs);
+        bdrv_flush(bs);
+    }
 
     /*
      * Make sure all data we wrote to the backing device is actually
@@ -629,7 +632,7 @@ int bdrv_commit(BlockDriverState *bs)
      */
     if (bs->backing_hd)
         bdrv_flush(bs->backing_hd);
-    return 0;
+    return ret;
 }
 
 /*
#8 lore raw

Re: [Qemu-devel] [PATCH] block: fix cache flushing in bdrv_commit

Quoted 11 lines · Christoph Hellwig
Quoted 3 lines · Kevin Wolf

Anthony, you seem to have missed the v2 patch that considered my review comments. Can you please apply the diff between v1 and v2 on top?

Here is the differences in patch form:

---
From: Christoph Hellwig<[email protected]>
Subject: block: fix cache flushing in bdrv_commit

Quoted 7 lines

As pointed out by Kevin Wolf the previous patch returned early if we there is a bdrv_make_empty method and it missed a cache flush for the frontend device after the bdev_make_empty call. This patch fixes it up.

Applied. Thanks.

Regards,

Anthony Liguori

Quoted 38 lines

Index: qemu/block.c
===================================================================

block.c +6 -3
@@ -589,6 +589,7 @@ int bdrv_commit(BlockDriverState *bs)
      BlockDriver *drv = bs->drv;
      int64_t i, total_sectors;
      int n, j;
+    int ret = 0;
      unsigned char sector[512];
 
      if (!drv)
@@ -620,8 +621,10 @@ int bdrv_commit(BlockDriverState *bs)
          }
      }
 
-    if (drv->bdrv_make_empty)
-	return drv->bdrv_make_empty(bs);
+    if (drv->bdrv_make_empty) {
+        ret = drv->bdrv_make_empty(bs);
+        bdrv_flush(bs);
+    }
 
      /*
       * Make sure all data we wrote to the backing device is actually
@@ -629,7 +632,7 @@ int bdrv_commit(BlockDriverState *bs)
       */
      if (bs->backing_hd)
          bdrv_flush(bs->backing_hd);
-    return 0;
+    return ret;
  }
 
  /*