@@ -634,3 +634,47 @@ int qcow2_dedup_write_new_hashes(BlockDriverState *bs,
fail:
return ret;
}
+
+/*
+ * This coroutine load the deduplication hashes in the red black tree
+ *
+ * @data: the given BlockDriverState
+ * @ret: NULL
+ */
+void coroutine_fn qcow2_co_load_dedup_hashes(void *opaque)
+{
+ BlockDriverState *bs = opaque;
+ BDRVQcowState *s = bs->opaque;
+ int ret;
+ uint8_t *hash = NULL;
+ uint8_t null_hash[HASH_LENGTH];
+ uint64_t max_cluster_offset, i;
+ int nb_hash_in_dedup_cluster = s->cluster_size / HASH_LENGTH;
+
+ /* prepare the null hash */
+ memset(null_hash, 0, HASH_LENGTH);
+
+ max_cluster_offset = s->dedup_table_size * nb_hash_in_dedup_cluster;
+
+ for (i = 0; i < max_cluster_offset; i++) {
+ /* get the hash */
+ qemu_co_mutex_lock(&s->lock);
+ ret = qcow2_dedup_read_write_hash(bs, &hash,
+ i * s->cluster_sectors,
+ false);
+ qemu_co_mutex_unlock(&s->lock);
+ if (ret < 0) {
+ error_report("Failed to load deduplication hash.");
+ }
+
+ /* if the hash is not null load it into red black tree */
+ if (memcmp(hash, null_hash, HASH_LENGTH)) {
+ qemu_co_mutex_lock(&s->lock);
+ qcow2_dedup_insert_hash_in_rb_tree(bs, hash,
+ i * s->cluster_sectors);
+ qemu_co_mutex_unlock(&s->lock);
+ } else {
+ free(hash);
+ }
+ }
+}
@@ -375,5 +375,6 @@ int qcow2_dedup(BlockDriverState *bs,
int qcow2_dedup_write_new_hashes(BlockDriverState *bs,
uint64_t cluster_offset,
int count);
+void coroutine_fn qcow2_co_load_dedup_hashes(void *opaque);
#endif