diff mbox

qcow2-cache: conditionally call bdrv_flush() in qcow2_cache_flush()

Message ID 201411070930569161961@sangfor.com
State New
Headers show

Commit Message

Zhang Haoyu Nov. 7, 2014, 1:30 a.m. UTC
Needless to call bdrv_flush() in qcow2_cache_flush()
if no cache entry is dirty.

Signed-off-by: Zhang Haoyu <zhanghy@sangfor.com>
---
 block/qcow2-cache.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

Comments

Stefan Hajnoczi Nov. 13, 2014, 11:53 a.m. UTC | #1
On Fri, Nov 07, 2014 at 09:30:59AM +0800, Zhang Haoyu wrote:
> Needless to call bdrv_flush() in qcow2_cache_flush()
> if no cache entry is dirty.

Did you audit all qcow2 cache callers to make sure they don't rely on
the cache flush?

Maybe it's not safe to optimize it away if callers assume previously
written data will be persisted as part of qcow2 cache flushing.

We need to be very careful when optimizing out cache flushes so that we
don't introduce data integrity problems.

> 
> Signed-off-by: Zhang Haoyu <zhanghy@sangfor.com>
> ---
>  block/qcow2-cache.c | 24 +++++++++++++-----------
>  1 file changed, 13 insertions(+), 11 deletions(-)

Please post benchmark configuration and performance results, if you ran
any.  Data makes performance optimization patches much more convincing.
diff mbox

Patch

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 904f6b1..09ee155 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -110,10 +110,6 @@  static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
     BDRVQcowState *s = bs->opaque;
     int ret = 0;
 
-    if (!c->entries[i].dirty || !c->entries[i].offset) {
-        return 0;
-    }
-
     trace_qcow2_cache_entry_flush(qemu_coroutine_self(),
                                   c == s->l2_table_cache, i);
 
@@ -166,19 +162,23 @@  int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
 {
     BDRVQcowState *s = bs->opaque;
     int result = 0;
+    bool need_bdrv_flush = false;
     int ret;
     int i;
 
     trace_qcow2_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache);
 
     for (i = 0; i < c->size; i++) {
-        ret = qcow2_cache_entry_flush(bs, c, i);
-        if (ret < 0 && result != -ENOSPC) {
-            result = ret;
+        if (c->entries[i].dirty && c->entries[i].offset) {
+            ret = qcow2_cache_entry_flush(bs, c, i);
+            if (ret < 0 && result != -ENOSPC) {
+                result = ret;
+            }
+            need_bdrv_flush = true;
         }
     }
 
-    if (result == 0) {
+    if (need_bdrv_flush && result == 0) {
         ret = bdrv_flush(bs->file);
         if (ret < 0) {
             result = ret;
@@ -289,9 +289,11 @@  static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
         return i;
     }
 
-    ret = qcow2_cache_entry_flush(bs, c, i);
-    if (ret < 0) {
-        return ret;
+    if (c->entries[i].dirty && c->entries[i].offset) {
+        ret = qcow2_cache_entry_flush(bs, c, i);
+        if (ret < 0) {
+            return ret;
+        }
     }
 
     trace_qcow2_cache_get_read(qemu_coroutine_self(),