Signed-off-by: Benoit Canet <ben...@irqsave.net> --- block/qcow2-dedup.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ block/qcow2-refcount.c | 3 +++ block/qcow2.h | 2 ++ 3 files changed, 50 insertions(+)
diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c index da4ad5c..599cb2e 100644 --- a/block/qcow2-dedup.c +++ b/block/qcow2-dedup.c @@ -656,3 +656,48 @@ int qcow2_dedup_store_new_hashes(BlockDriverState *bs, return ret; } + +/* Clean the last reference to a given cluster when its refcount is zero + * + * @cluster_index: the index of the physical cluster + */ +void qcow2_dedup_destroy_hash(BlockDriverState *bs, + uint64_t cluster_index) +{ + BDRVQcowState *s = bs->opaque; + uint64_t offset = cluster_index * s->cluster_size; + QCowHashInfo hash_info; + uint8_t *buf; + int ret = 0; + + /* allocate buffer */ + buf = qemu_blockalign(bs, s->cluster_size); + + /* read cluster from disk */ + ret = bdrv_pread(bs->file, offset, buf, s->cluster_size); + + /* error */ + if (ret < 0) { + goto free_exit; + } + + /* clear hash info */ + memset(&hash_info, 0, sizeof(QCowHashInfo)); + + /* compute hash for the cluster */ + ret = qcow2_compute_cluster_hash(bs, + &hash_info.hash, + buf); + + + /* error */ + if (ret < 0) { + goto free_exit; + } + + /* delete hash from key value store. It will not be deduplicated anymore */ + qcow2_store_delete(bs, &s->key_value_store, &hash_info); + +free_exit: + qemu_vfree(buf); +} diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 3bd8f37..2734cd9 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -482,6 +482,9 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, ret = -EINVAL; goto fail; } + if (s->has_dedup && refcount == 0) { + qcow2_dedup_destroy_hash(bs, cluster_index); + } if (refcount == 0 && cluster_index < s->free_cluster_index) { s->free_cluster_index = cluster_index; } diff --git a/block/qcow2.h b/block/qcow2.h index 720131d..6f85e03 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -748,5 +748,7 @@ int qcow2_dedup_store_new_hashes(BlockDriverState *bs, int count, uint64_t logical_sect, uint64_t physical_sect); +void qcow2_dedup_destroy_hash(BlockDriverState *bs, + uint64_t cluster_index); #endif -- 1.7.10.4