Patchwork [RFC,V7,20/32] qcow2: Drop hash for a given cluster when dedup makes refcount > 2^16/2.

login
register
mail settings
Submitter Benoît Canet
Date March 15, 2013, 2:49 p.m.
Message ID <1363358986-8360-21-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/228033/
State New
Headers show

Comments

Benoît Canet - March 15, 2013, 2:49 p.m.
A new physical cluster with the same hash value will be used for further
occurrence of this hash.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block/qcow2-dedup.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 5 deletions(-)

Patch

diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c
index 2aca01a..e017721 100644
--- a/block/qcow2-dedup.c
+++ b/block/qcow2-dedup.c
@@ -38,6 +38,8 @@  static int qcow2_dedup_read_write_hash(BlockDriverState *bs,
                                        uint64_t *first_logical_sect,
                                        uint64_t physical_sect,
                                        bool write);
+static void qcow2_remove_hash_node(BlockDriverState *bs,
+                                   QCowHashNode *hash_node);
 
 bool qcow2_must_deduplicate(BlockDriverState *bs)
 {
@@ -416,6 +418,38 @@  static int qcow2_clear_l2_copied_flag_if_needed(BlockDriverState *bs,
                                        true);
 }
 
+/* Force to use a new physical cluster and QCowHashNode when the refcount pass
+ * 2^16/2.
+ *
+ * @cluster_index: the index of the physical cluster
+ * @ret:           0 on success, -errno on error
+ */
+static int qcow2_dedup_refcount_half_max_reached(BlockDriverState *bs,
+                                                 uint64_t cluster_index,
+                                                 QCowHashNode *hash_node)
+{
+    int ret = 0;
+
+    /* mark this hash so we won't load it anymore at startup after writing it */
+    hash_node->first_logical_sect |= QCOW_DEDUP_FLAG_HALF_MAX_REFCOUNT;
+
+    /* write to disk */
+    ret = qcow2_dedup_read_write_hash(bs,
+                                      &hash_node->hash,
+                                      &hash_node->first_logical_sect,
+                                      hash_node->physical_sect,
+                                      true);
+
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* remove the QCowHashNode from ram so we won't use it anymore for dedup */
+    qcow2_remove_hash_node(bs, hash_node);
+
+    return 0;
+}
+
 /* This function deduplicate a cluster
  *
  * @logical_sect: The logical sector of the write
@@ -428,13 +462,23 @@  static int qcow2_deduplicate_cluster(BlockDriverState *bs,
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t cluster_index = hash_node->physical_sect / s->cluster_sectors;
-    int ret = 0;
+    int refcount, ret = 0;
 
     /* Increment the refcount of the cluster */
-    ret = qcow2_update_cluster_refcount(bs,
-                                        cluster_index,
-                                        1,
-                                        false);
+    refcount = qcow2_update_cluster_refcount(bs,
+                                             cluster_index,
+                                             1,
+                                             false);
+
+    if (refcount < 0) {
+        return ret;
+    }
+
+    if (refcount >= 0xFFFF/2) {
+        ret = qcow2_dedup_refcount_half_max_reached(bs,
+                                                    cluster_index,
+                                                    hash_node);
+    }
 
     if (ret < 0) {
         return ret;