Patchwork [RFC,16/24] qcow2: add qcow2_drop_leaked_clusters()

login
register
mail settings
Submitter Devin Nakamura
Date July 29, 2011, 4:49 a.m.
Message ID <1311914994-20482-17-git-send-email-devin122@gmail.com>
Download mbox | patch
Permalink /patch/107339/
State New
Headers show

Comments

Devin Nakamura - July 29, 2011, 4:49 a.m.
Signed-off-by: Devin Nakamura <devin122@gmail.com>
---
 block/qcow2-refcount.c |   34 ++++++++++++++++++++++++++++++++++
 block/qcow2.h          |    2 ++
 2 files changed, 36 insertions(+), 0 deletions(-)
Kevin Wolf - Aug. 1, 2011, 2:18 p.m.
Am 29.07.2011 06:49, schrieb Devin Nakamura:
> Signed-off-by: Devin Nakamura <devin122@gmail.com>
> ---
>  block/qcow2-refcount.c |   34 ++++++++++++++++++++++++++++++++++
>  block/qcow2.h          |    2 ++
>  2 files changed, 36 insertions(+), 0 deletions(-)

Just for the record, discussed on IRC: Maybe it would be better to leave
this functionality inside the normal qcow2_check_refcounts()
implementation which would get a new flag that says "fix leaked clusters".

This would allow a trivial implementation of a qemu-img check --fix,
which is something that we've been wanting for a while.

Kevin

Patch

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 75f1f88..2f78a71 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1202,3 +1202,37 @@  fail:
 
     return ret;
 }
+
+int qcow2_drop_leaked_clusters(BlockDriverState *bs) {
+    BDRVQcowState *s = bs->opaque;
+    int64_t size;
+    int nb_clusters, refcount, i;
+    uint16_t *refcount_table;
+    BdrvCheckResult res;
+    int ret;
+
+    ret = inc_refcount_table(bs, &res, &refcount_table);
+    if (ret) {
+        goto fail;
+    }
+    size = bdrv_getlength(bs->file);
+    nb_clusters = size_to_clusters(s, size);
+
+    for(i = 0; i < nb_clusters; i++) {
+        refcount = get_refcount(bs, i);
+        refcount = refcount_table[i] - refcount;
+        if (refcount < 0) { //we only want to change leaked clusters
+            ret = update_cluster_refcount(bs, i , refcount);
+            if (ret) {
+                goto fail;
+            }
+        }
+    }
+
+    ret = 0;
+
+fail:
+    qemu_free(refcount_table);
+
+    return ret;
+}
diff --git a/block/qcow2.h b/block/qcow2.h
index 6a0a21b..e9efb74 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -193,6 +193,8 @@  int qcow2_update_snapshot_refcount(BlockDriverState *bs,
 
 int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res);
 
+int qcow2_drop_leaked_clusters(BlockDriverState *bs) ;
+
 /* qcow2-cluster.c functions */
 int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size);
 void qcow2_l2_cache_reset(BlockDriverState *bs);