Patchwork [RFC,V7,14/32] qcow2: Create qcow2_is_cluster_to_dedup.

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

Comments

Benoît Canet - March 15, 2013, 2:49 p.m.
Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block/qcow2-cluster.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++++
 block/qcow2.h         |    4 ++++
 2 files changed, 56 insertions(+)

Patch

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 3cbb64f..bc42fc6 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -488,6 +488,58 @@  out:
     return ret;
 }
 
+/* Check if a cluster is to deduplicate given it's index
+ *
+ * @index:         The logical index of the cluster starting from 0
+ * @physical_sect: The physical sector of the cluster as return value
+ * @err:           0 on success, negative on error
+ * @ret:           True if the cluster is to deduplicate else false
+ */
+bool qcow2_is_cluster_to_dedup(BlockDriverState *bs,
+                               uint64_t index,
+                               uint64_t *physical_sect,
+                               int *err)
+{
+    BDRVQcowState *s = bs->opaque;
+    unsigned int l1_index, l2_index;
+    uint64_t offset;
+    uint64_t l2_offset;
+    uint64_t *l2_table = NULL;
+
+    *physical_sect = 0;
+    *err = 0;
+
+    l1_index = index >> s->l2_bits;
+
+    if (l1_index >= s->l1_size) {
+        return false;
+    }
+
+    /* no l1 entry */
+    if (!(s->l1_table[l1_index] & L1E_OFFSET_MASK)) {
+        return false;
+    }
+
+    l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
+
+    *err = l2_load(bs, l2_offset, &l2_table);
+    if (*err < 0) {
+        return false;
+    }
+
+    l2_index = index & (s->l2_size - 1);
+
+    offset = be64_to_cpu(l2_table[l2_index]);
+    *physical_sect = (offset & L2E_OFFSET_MASK) >> 9;
+
+    *err = qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
+    if (*err < 0) {
+        return false;
+    }
+
+    return offset & QCOW_OFLAG_PENDING_DEDUP;
+}
+
 /*
  * get_cluster_table
  *
diff --git a/block/qcow2.h b/block/qcow2.h
index 2eab1a4..59c4881 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -438,6 +438,10 @@  int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
 int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
     int nb_sectors);
 int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors);
+bool qcow2_is_cluster_to_dedup(BlockDriverState *bs,
+                               uint64_t index,
+                               uint64_t *physical_sect,
+                               int *ret);
 
 /* qcow2-snapshot.c functions */
 int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);