[29/29] qcow2-dirty-bitmap: refcounts
diff mbox

Message ID 1470668720-211300-30-git-send-email-vsementsov@virtuozzo.com
State New
Headers show

Commit Message

Vladimir Sementsov-Ogievskiy Aug. 8, 2016, 3:05 p.m. UTC
Calculate refcounts for dirty bitmaps.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
---
 block/qcow2-bitmap.c   | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--
 block/qcow2-refcount.c | 14 +++++++-----
 block/qcow2.h          |  5 +++++
 3 files changed, 70 insertions(+), 7 deletions(-)

Patch
diff mbox

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index def2005..b24fa27 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -253,6 +253,62 @@  static int load_autoload_bitmaps(BlockDriverState *bs, Error **errp)
     return 0;
 }
 
+static int bitmap_table_load(BlockDriverState *bs, QCow2BitmapHeader *bmh,
+                             uint64_t **table);
+int qcow2_dirty_bitmaps_refcounts(BlockDriverState *bs,
+                                  BdrvCheckResult *res,
+                                  void **refcount_table,
+                                  int64_t *refcount_table_size)
+{
+    BDRVQcow2State *s = bs->opaque;
+    QCow2BitmapHeader *h,
+                      *begin = (QCow2BitmapHeader *)s->bitmap_directory,
+                      *end = (QCow2BitmapHeader *)
+                          (s->bitmap_directory + s->bitmap_directory_size);
+
+    int i;
+    int ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+                        s->bitmap_directory_offset,
+                        s->bitmap_directory_size);
+    if (ret < 0) {
+        return ret;
+    }
+
+    for (h = begin; h < end; h = next_dir_entry(h)) {
+        uint64_t *bitmap_table = NULL;
+
+        ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+                            h->bitmap_table_offset,
+                            h->bitmap_table_size);
+        if (ret < 0) {
+            return ret;
+        }
+
+        ret = bitmap_table_load(bs, h, &bitmap_table);
+        if (ret < 0) {
+            return ret;
+        }
+
+        for (i = 0; i < h->bitmap_table_size; ++i) {
+            uint64_t off = be64_to_cpu(bitmap_table[i]);
+            if (off <= 1) {
+                continue;
+            }
+
+            ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+                                off, s->cluster_size);
+            if (ret < 0) {
+                g_free(bitmap_table);
+                return ret;
+            }
+        }
+
+        g_free(bitmap_table);
+    }
+
+    return 0;
+}
+
 static int handle_in_use_bitmaps(BlockDriverState *bs);
 int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
 {
@@ -351,8 +407,6 @@  static void do_free_bitmap_clusters(BlockDriverState *bs,
                         QCOW2_DISCARD_ALWAYS);
 }
 
-static int bitmap_table_load(BlockDriverState *bs, QCow2BitmapHeader *bmh,
-                             uint64_t **table);
 static int free_bitmap_clusters(BlockDriverState *bs, QCow2BitmapHeader *bmh)
 {
     int ret;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index cbfb3fe..05bcc57 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1309,11 +1309,9 @@  static int realloc_refcount_array(BDRVQcow2State *s, void **array,
  *
  * Modifies the number of errors in res.
  */
-static int inc_refcounts(BlockDriverState *bs,
-                         BdrvCheckResult *res,
-                         void **refcount_table,
-                         int64_t *refcount_table_size,
-                         int64_t offset, int64_t size)
+int inc_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+                  void **refcount_table, int64_t *refcount_table_size,
+                  int64_t offset, int64_t size)
 {
     BDRVQcow2State *s = bs->opaque;
     uint64_t start, last, cluster_offset, k, refcount;
@@ -1843,6 +1841,12 @@  static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
         return ret;
     }
 
+    /* dirty bitmaps */
+    ret = qcow2_dirty_bitmaps_refcounts(bs, res, refcount_table, nb_clusters);
+    if (ret < 0) {
+        return ret;
+    }
+
     return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters);
 }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 74d395b..3359c14 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -564,6 +564,9 @@  int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
                                  int64_t size);
 int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
+int inc_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+                  void **refcount_table, int64_t *refcount_table_size,
+                  int64_t offset, int64_t size);
 
 int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
                                 BlockDriverAmendStatusCB *status_cb,
@@ -623,6 +626,8 @@  BdrvDirtyBitmap *qcow2_bitmap_load(BlockDriverState *bs, const char *name,
 void qcow2_bitmap_store(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
                         Error **errp);
 int qcow2_delete_bitmaps(BlockDriverState *bs);
+int qcow2_dirty_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+    void **refcount_table, int64_t *refcount_table_size);
 
 /* qcow2-cache.c functions */
 Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);