Patchwork [PULL,09/31] qcow2: Fix discard

login
register
mail settings
Submitter Kevin Wolf
Date April 30, 2014, 6:23 p.m.
Message ID <1398882243-14783-10-git-send-email-kwolf@redhat.com>
Download mbox | patch
Permalink /patch/344283/
State New
Headers show

Comments

Kevin Wolf - April 30, 2014, 6:23 p.m.
From: Max Reitz <mreitz@redhat.com>

discard_single_l2() should not implement its own version of
qcow2_get_cluster_type(), but rather rely on this already existing
function. By doing so, it will work for compressed clusters as well
(which it did not so far).

Also, rename "old_offset" to "old_l2_entry", as both are quite different
(and the value is indeed of the latter kind).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-cluster.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

Patch

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 331ab08..b746429 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1360,9 +1360,9 @@  static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
     nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
 
     for (i = 0; i < nb_clusters; i++) {
-        uint64_t old_offset;
+        uint64_t old_l2_entry;
 
-        old_offset = be64_to_cpu(l2_table[l2_index + i]);
+        old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);
 
         /*
          * Make sure that a discarded area reads back as zeroes for v3 images
@@ -1373,12 +1373,22 @@  static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
          * TODO We might want to use bdrv_get_block_status(bs) here, but we're
          * holding s->lock, so that doesn't work today.
          */
-        if (old_offset & QCOW_OFLAG_ZERO) {
-            continue;
-        }
+        switch (qcow2_get_cluster_type(old_l2_entry)) {
+            case QCOW2_CLUSTER_UNALLOCATED:
+                if (!bs->backing_hd) {
+                    continue;
+                }
+                break;
 
-        if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
-            continue;
+            case QCOW2_CLUSTER_ZERO:
+                continue;
+
+            case QCOW2_CLUSTER_NORMAL:
+            case QCOW2_CLUSTER_COMPRESSED:
+                break;
+
+            default:
+                abort();
         }
 
         /* First remove L2 entries */
@@ -1390,7 +1400,7 @@  static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
         }
 
         /* Then decrease the refcount */
-        qcow2_free_any_clusters(bs, old_offset, 1, type);
+        qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
     }
 
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);