---
 block/qcow2-cluster.c |    8 ++++++--
 block/qcow2-dedup.c   |    7 +++++++
 block/qcow2.h         |    3 +++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index dbcb6d2..ef91216 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -709,6 +709,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, 
QCowL2Meta *m)
     qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
 
     for (i = 0; i < m->nb_clusters; i++) {
+        uint64_t flags = 0;
         /* if two concurrent writes happen to the same unallocated cluster
         * each write allocates separate cluster and writes data concurrently.
         * The first one to complete updates l2 table with pointer to its
@@ -718,9 +719,11 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, 
QCowL2Meta *m)
         if(l2_table[l2_index + i] != 0)
             old_cluster[j++] = l2_table[l2_index + i];
 
+        flags = m->oflag_copied ? QCOW_OFLAG_COPIED : 0;
+        flags |= m->to_deduplicate ? QCOW_OFLAG_TO_DEDUP : 0;
+
         l2_table[l2_index + i] = cpu_to_be64((cluster_offset +
-                    (i << s->cluster_bits)) |
-                    (m->oflag_copied ? QCOW_OFLAG_COPIED : 0));
+                    (i << s->cluster_bits)) | flags);
      }
 
 
@@ -1036,6 +1039,7 @@ again:
 
                 .oflag_copied   = true,
                 .overwrite      = false,
+                .to_deduplicate = qcow2_must_deduplicate(bs),
             };
             qemu_co_queue_init(&(*m)->dependent_requests);
             QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c
index de6e3a3..3d512e5 100644
--- a/block/qcow2-dedup.c
+++ b/block/qcow2-dedup.c
@@ -37,6 +37,12 @@ static int qcow2_dedup_read_write_hash(BlockDriverState *bs,
                                        uint64_t physical_sect,
                                        bool write);
 
+bool qcow2_must_deduplicate(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    return s->has_dedup && s->dedup_status != QCOW_DEDUP_STARTED;
+}
+
 /*
  * Save the dedup table information into the header extensions
  *
@@ -310,6 +316,7 @@ static int qcow2_dedup_link_l2(BlockDriverState *bs,
         },
         .oflag_copied   = false,
         .overwrite      = overwrite,
+        .to_deduplicate = false,
     };
     return qcow2_alloc_cluster_link_l2(bs, &m);
 }
diff --git a/block/qcow2.h b/block/qcow2.h
index 359a50f..da7e57e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -312,6 +312,8 @@ typedef struct QCowL2Meta
     bool oflag_copied;
     /* set to true if we are overwriting an L2 table entry */
     bool overwrite;
+    /* set to true if the cluster must be tagged with QCOW_OFLAG_TO_DEDUP */
+    bool to_deduplicate;
 
     /**
      * The COW Region between the start of the first allocated cluster and the
@@ -466,6 +468,7 @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache 
*c, uint64_t offset,
 int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
 
 /* qcow2-dedup.c functions */
+bool qcow2_must_deduplicate(BlockDriverState *bs);
 int qcow2_dedup_read_missing_and_concatenate(BlockDriverState *bs,
                                              QEMUIOVector *qiov,
                                              uint64_t sector,
-- 
1.7.10.4


Reply via email to