@@ -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;
+}
@@ -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);
Signed-off-by: Devin Nakamura <devin122@gmail.com> --- block/qcow2-refcount.c | 34 ++++++++++++++++++++++++++++++++++ block/qcow2.h | 2 ++ 2 files changed, 36 insertions(+), 0 deletions(-)