Patchwork [RFC,V4,11/30] qcow2: create function to load deduplication hashes at startup.

login
register
mail settings
Submitter Benoît Canet
Date Jan. 2, 2013, 4:16 p.m.
Message ID <1357143393-29832-12-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/209102/
State New
Headers show

Comments

Benoît Canet - Jan. 2, 2013, 4:16 p.m.
Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block/qcow2-dedup.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++
 block/qcow2.h       |    1 +
 2 files changed, 69 insertions(+)

Patch

diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c
index b998a2d..4c391e5 100644
--- a/block/qcow2-dedup.c
+++ b/block/qcow2-dedup.c
@@ -918,3 +918,71 @@  int qcow2_dedup_store_new_hashes(BlockDriverState *bs,
 
     return ret;
 }
+
+static void qcow2_dedup_insert_hash_and_preserve_newer(BlockDriverState *bs,
+                                                       QCowHashNode *hash_node)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowHashNode *newer_hash_node;
+
+    newer_hash_node = g_tree_lookup(s->dedup_tree_by_sect,
+                                    &hash_node->physical_sect);
+
+    if (!newer_hash_node) {
+        g_tree_insert(s->dedup_tree_by_hash, &hash_node->hash, hash_node);
+        g_tree_insert(s->dedup_tree_by_sect, &hash_node->physical_sect,
+                      hash_node);
+    } else {
+        g_free(hash_node);
+    }
+}
+
+/*
+ * This coroutine load the deduplication hashes in the 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;
+    QCowHash hash, null_hash;
+    uint64_t max_clusters, i;
+    uint64_t first_logical_sect;
+    int nb_hash_in_hash_block = s->hash_block_size / (HASH_LENGTH + 8);
+    QCowHashNode *hash_node;
+
+    /* prepare the null hash */
+    memset(&null_hash, 0, sizeof(null_hash));
+
+    max_clusters = s->dedup_table_size * nb_hash_in_hash_block;
+
+    for (i = 0; i < max_clusters; i++) {
+        /* get the hash */
+        qemu_co_mutex_lock(&s->lock);
+        ret = qcow2_dedup_read_write_hash(bs, &hash,
+                                          &first_logical_sect,
+                                          i * s->cluster_sectors,
+                                          false);
+
+        if (ret < 0) {
+            qemu_co_mutex_unlock(&s->lock);
+            error_report("Failed to load deduplication hash.");
+            continue;
+        }
+
+        /* if the hash is null don't load it */
+        if (!memcmp(hash.data, null_hash.data, HASH_LENGTH)) {
+            qemu_co_mutex_unlock(&s->lock);
+            continue;
+        }
+
+        hash_node = qcow2_dedup_build_qcow_hash_node(&hash,
+                                                     i * s->cluster_sectors,
+                                                     first_logical_sect);
+        qcow2_dedup_insert_hash_and_preserve_newer(bs, hash_node);
+        qemu_co_mutex_unlock(&s->lock);
+    }
+}
diff --git a/block/qcow2.h b/block/qcow2.h
index afa730e..5cbfc82 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -467,5 +467,6 @@  int qcow2_dedup_store_new_hashes(BlockDriverState *bs,
                                  int count,
                                  uint64_t logical_sect,
                                  uint64_t physical_sect);
+void coroutine_fn qcow2_co_load_dedup_hashes(void *opaque);
 
 #endif