Skip to contentSkip to conversation

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

PATCH In review Zhang Haoyu 2 participants 2 messages Nov 7, 2014 – Nov 13, 2014 Block layer

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 qcow2-cache: conditionally call bdrv_flush() in qcow2_cache_flush()

Needless to call bdrv_flush() in qcow2_cache_flush() if no cache entry is dirty.

---
 block/qcow2-cache.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
block/qcow2-cache.c +13 -11
index 904f6b1..09ee155 100644
@@ -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(),
Signature · 1 line
1.7.12.4
#1 lore raw
Quoted 2 lines · Zhang Haoyu

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.

Quoted 5 lines
---
 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.