Patchwork [RFC,V3,02/24] qcow2: Add deduplication structures and fields.

login
register
mail settings
Submitter Benoît Canet
Date Nov. 26, 2012, 1:05 p.m.
Message ID <1353935123-24199-3-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/201665/
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.h |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
Stefan Hajnoczi - Dec. 11, 2012, 11:34 a.m.
On Mon, Nov 26, 2012 at 02:05:01PM +0100, Benoît Canet wrote:
> diff --git a/block/qcow2.h b/block/qcow2.h
> index b4eb654..e192001 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -58,6 +58,23 @@
>  
>  #define DEFAULT_CLUSTER_SIZE 65536
>  
> +/* deduplication node */
> +typedef struct {
> +    uint8_t *hash;         /* 32 bytes hash of a given cluster */

Pointer to the hash value instead of storing the value inline?  At this
point in the series I'm not sure yet why it's not stored inline.  That
way we'd avoid a 4- or 8-byte pointer to a separately allocated 32-byte
blob.  Maybe there is a reason later on...

Stefan

Patch

diff --git a/block/qcow2.h b/block/qcow2.h
index b4eb654..e192001 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -58,6 +58,23 @@ 
 
 #define DEFAULT_CLUSTER_SIZE 65536
 
+/* deduplication node */
+typedef struct {
+    uint8_t *hash;         /* 32 bytes hash of a given cluster */
+    uint64_t offset;       /* offset where the cluster is stored (sectors) */
+    uint64_t first_logical_offset;
+} QCowHashNode;
+
+/* Undedupable hashes that must be written later to disk */
+typedef struct QCowHashElement {
+    uint8_t *hash;
+    QTAILQ_ENTRY(QCowHashElement) next;
+} QCowHashElement;
+
+typedef struct UndedupableHashes {
+    QTAILQ_HEAD(, QCowHashElement) undedupable_hashes;
+} UndedupableHashes;
+
 typedef struct QCowHeader {
     uint32_t magic;
     uint32_t version;
@@ -114,8 +131,10 @@  enum {
 enum {
     QCOW2_INCOMPAT_DIRTY_BITNR   = 0,
     QCOW2_INCOMPAT_DIRTY         = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
+    QCOW2_INCOMPAT_DEDUP_BITNR   = 1,
+    QCOW2_INCOMPAT_DEDUP         = 1 << QCOW2_INCOMPAT_DEDUP_BITNR,
 
-    QCOW2_INCOMPAT_MASK          = QCOW2_INCOMPAT_DIRTY,
+    QCOW2_INCOMPAT_MASK          = QCOW2_INCOMPAT_DIRTY | QCOW2_INCOMPAT_DEDUP,
 };
 
 /* Compatible feature bits */
@@ -148,6 +167,7 @@  typedef struct BDRVQcowState {
 
     Qcow2Cache* l2_table_cache;
     Qcow2Cache* refcount_block_cache;
+    Qcow2Cache *dedup_cluster_cache;
 
     uint8_t *cluster_cache;
     uint8_t *cluster_data;
@@ -160,6 +180,12 @@  typedef struct BDRVQcowState {
     int64_t free_cluster_index;
     int64_t free_byte_offset;
 
+    bool has_dedup;
+    uint64_t *dedup_table;
+    uint64_t dedup_table_offset;
+    int32_t dedup_table_size;
+    GTree *dedup_tree_by_hash;
+    GTree *dedup_tree_by_offset;
     CoMutex lock;
 
     uint32_t crypt_method; /* current crypt method, 0 if no key yet */