Patchwork [RFC,V3,10/24] qcow2: create function to load deduplication hashes at startup.

login
register
mail settings
Submitter Benoît Canet
Date Nov. 26, 2012, 1:05 p.m.
Message ID <1353935123-24199-11-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/201692/
State New
Headers show

Comments

Benoît Canet - Nov. 26, 2012, 1:05 p.m.
Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block/qcow2-dedup.c |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++
 block/qcow2.h       |    1 +
 2 files changed, 67 insertions(+)

Patch

diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c
index 2ebbbcf..1760e8a 100644
--- a/block/qcow2-dedup.c
+++ b/block/qcow2-dedup.c
@@ -690,6 +690,72 @@  fail:
     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_offset,
+                                    &hash_node->offset);
+
+    if (!newer_hash_node) {
+        g_tree_insert(s->dedup_tree_by_hash, hash_node->hash, hash_node);
+        g_tree_insert(s->dedup_tree_by_offset, &hash_node->offset, hash_node);
+    } else {
+        g_free(hash_node->hash);
+        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;
+    uint8_t *hash = NULL;
+    uint8_t null_hash[HASH_LENGTH];
+    uint64_t max_cluster_offset, i;
+    uint64_t first_logical_offset;
+    int nb_hash_in_dedup_cluster = s->cluster_size / (HASH_LENGTH + 8);
+    QCowHashNode *hash_node;
+
+    /* 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,
+                                          &first_logical_offset,
+                                          i * s->cluster_sectors,
+                                          false);
+        if (ret < 0) {
+            qemu_co_mutex_unlock(&s->lock);
+            error_report("Failed to load deduplication hash.");
+        }
+
+        /* if the hash is not null load it into the tree */
+        if (memcmp(hash, null_hash, HASH_LENGTH)) {
+            hash_node = qcow2_dedup_build_qcow_hash_node(hash,
+                                                         i * s->cluster_sectors,
+                                                         first_logical_offset);
+            qcow2_dedup_insert_hash_and_preserve_newer(bs, hash_node);
+        } else {
+            free(hash);
+        }
+        qemu_co_mutex_unlock(&s->lock);
+    }
+}
+
 /*
  * Save the dedup table information into the header extensions
  *
diff --git a/block/qcow2.h b/block/qcow2.h
index 62822b7..c7edb14 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -396,6 +396,7 @@  int qcow2_dedup_write_new_hashes(BlockDriverState *bs,
                                  int hash_count,
                                  uint64_t logical_cluster_offset,
                                  uint64_t physical_cluster_offset);
+void coroutine_fn qcow2_co_load_dedup_hashes(void *opaque);
 int qcow2_dedup_grow_table(BlockDriverState *bs,
                            int min_size,
                            bool exact_size);