qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-block] [RFC PATCH 2/2] block/dirty-bitmap: implement inconsistent


From: John Snow
Subject: [Qemu-block] [RFC PATCH 2/2] block/dirty-bitmap: implement inconsistent bit
Date: Wed, 13 Feb 2019 18:36:18 -0500

Signed-off-by: John Snow <address@hidden>
---
 block/dirty-bitmap.c         | 15 +++++++++++++
 block/qcow2-bitmap.c         | 42 ++++++++++++++++++-----------------
 blockdev.c                   | 43 ++++++++++++++++++++++++++++++++++++
 include/block/dirty-bitmap.h |  1 +
 4 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index b1879d7fbd..06d8ee0d79 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -589,6 +589,7 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, 
HBitmap **out)
         *out = backup;
     }
     bdrv_dirty_bitmap_unlock(bitmap);
+    bdrv_dirty_bitmap_set_inconsistent(bitmap, false);
 }
 
 void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
@@ -776,6 +777,13 @@ bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap 
*bitmap,
     return hbitmap_next_dirty_area(bitmap->bitmap, offset, bytes);
 }
 
+void bdrv_dirty_bitmap_add_inconsistent_hint(Error **errp)
+{
+    error_append_hint(errp, "Try block-dirty-bitmap-clear to mark this "
+                      "bitmap consistent again, or block-dirty-bitmap-remove "
+                      "to delete it.");
+}
+
 void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
                              HBitmap **backup, Error **errp)
 {
@@ -798,6 +806,13 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const 
BdrvDirtyBitmap *src,
         goto out;
     }
 
+    if (bdrv_dirty_bitmap_inconsistent(dest)) {
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used as"
+                   " a merge target", dest->name);
+        bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+        goto out;
+    }
+
     if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
         error_setg(errp, "Bitmaps are incompatible and can't be merged");
         goto out;
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 3ee524da4b..9bd8bc417f 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -343,9 +343,15 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
     uint32_t granularity;
     BdrvDirtyBitmap *bitmap = NULL;
 
+    granularity = 1U << bm->granularity_bits;
+    bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp);
+    if (bitmap == NULL) {
+        goto fail;
+    }
+
     if (bm->flags & BME_FLAG_IN_USE) {
-        error_setg(errp, "Bitmap '%s' is in use", bm->name);
-        goto fail;
+        /* Data is unusable, skip loading it */
+        return bitmap;
     }
 
     ret = bitmap_table_load(bs, &bm->table, &bitmap_table);
@@ -356,12 +362,6 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
         goto fail;
     }
 
-    granularity = 1U << bm->granularity_bits;
-    bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp);
-    if (bitmap == NULL) {
-        goto fail;
-    }
-
     ret = load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not read bitmap '%s' from image",
@@ -962,20 +962,22 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
     }
 
     QSIMPLEQ_FOREACH(bm, bm_list, entry) {
-        if (!(bm->flags & BME_FLAG_IN_USE)) {
-            BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
-            if (bitmap == NULL) {
-                goto fail;
-            }
+        BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
+        if (bitmap == NULL) {
+            goto fail;
+        }
+
+        if (bm->flags & BME_FLAG_IN_USE) {
+            bdrv_dirty_bitmap_set_inconsistent(bitmap, true);
+        }
 
-            if (!(bm->flags & BME_FLAG_AUTO)) {
-                bdrv_disable_dirty_bitmap(bitmap);
-            }
-            bdrv_dirty_bitmap_set_persistance(bitmap, true);
-            bm->flags |= BME_FLAG_IN_USE;
-            created_dirty_bitmaps =
-                    g_slist_append(created_dirty_bitmaps, bitmap);
+        if (!(bm->flags & BME_FLAG_AUTO)) {
+            bdrv_disable_dirty_bitmap(bitmap);
         }
+        bdrv_dirty_bitmap_set_persistance(bitmap, true);
+        bm->flags |= BME_FLAG_IN_USE;
+        created_dirty_bitmaps =
+            g_slist_append(created_dirty_bitmaps, bitmap);
     }
 
     if (created_dirty_bitmaps != NULL) {
diff --git a/blockdev.c b/blockdev.c
index 23a4bf136e..12c6f706dd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1943,6 +1943,7 @@ typedef struct BlockDirtyBitmapState {
     HBitmap *backup;
     bool prepared;
     bool was_enabled;
+    bool was_inconsistent;
 } BlockDirtyBitmapState;
 
 static void block_dirty_bitmap_add_prepare(BlkActionState *common,
@@ -2016,6 +2017,7 @@ static void 
block_dirty_bitmap_clear_prepare(BlkActionState *common,
         return;
     }
 
+    state->was_inconsistent = bdrv_dirty_bitmap_inconsistent(state->bitmap);
     bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
 }
 
@@ -2027,6 +2029,9 @@ static void block_dirty_bitmap_restore(BlkActionState 
*common)
     if (state->backup) {
         bdrv_restore_dirty_bitmap(state->bitmap, state->backup);
     }
+    if (state->was_inconsistent) {
+        bdrv_dirty_bitmap_set_inconsistent(state->bitmap, true);
+    }
 }
 
 static void block_dirty_bitmap_free_backup(BlkActionState *common)
@@ -2063,6 +2068,12 @@ static void 
block_dirty_bitmap_enable_prepare(BlkActionState *common,
                    " and cannot be enabled", action->name);
         return;
     }
+    if (bdrv_dirty_bitmap_inconsistent(state->bitmap)) {
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be enabled",
+                   action->name);
+        bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+        return;
+    }
 
     state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
     bdrv_enable_dirty_bitmap(state->bitmap);
@@ -2104,6 +2115,12 @@ static void 
block_dirty_bitmap_disable_prepare(BlkActionState *common,
                    " and cannot be disabled", action->name);
         return;
     }
+    if (bdrv_dirty_bitmap_inconsistent(state->bitmap)) {
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be disabled",
+                   action->name);
+        bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+        return;
+    }
 
     state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
     bdrv_disable_dirty_bitmap(state->bitmap);
@@ -2948,6 +2965,13 @@ void qmp_block_dirty_bitmap_enable(const char *node, 
const char *name,
         return;
     }
 
+    if (bdrv_dirty_bitmap_inconsistent(bitmap)) {
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be enabled",
+                   name);
+        bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+        return;
+    }
+
     bdrv_enable_dirty_bitmap(bitmap);
 }
 
@@ -2969,6 +2993,13 @@ void qmp_block_dirty_bitmap_disable(const char *node, 
const char *name,
         return;
     }
 
+    if (bdrv_dirty_bitmap_inconsistent(bitmap)) {
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be disabled",
+                   name);
+        bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+        return;
+    }
+
     bdrv_disable_dirty_bitmap(bitmap);
 }
 
@@ -3544,6 +3575,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup, 
JobTxn *txn,
                        " and cannot be used for backup", backup->bitmap);
             goto out;
         }
+        if (bdrv_dirty_bitmap_inconsistent(bmap)) {
+            error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used 
for"
+                       " a backup operation", backup->bitmap);
+            bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+            goto out;
+        }
     }
     if (!backup->auto_finalize) {
         job_flags |= JOB_MANUAL_FINALIZE;
@@ -3657,6 +3694,12 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, 
JobTxn *txn,
                        " and cannot be used for backup", backup->bitmap);
             goto out;
         }
+        if (bdrv_dirty_bitmap_inconsistent(bmap)) {
+            error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used 
for"
+                       " a backup operation", backup->bitmap);
+            bdrv_dirty_bitmap_add_inconsistent_hint(errp);
+            goto out;
+        }
     }
 
     if (!backup->auto_finalize) {
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index c0d37702fd..b8485d2c94 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -105,5 +105,6 @@ bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap 
*bitmap,
 BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
                                                   BdrvDirtyBitmap *bitmap,
                                                   Error **errp);
+void bdrv_dirty_bitmap_add_inconsistent_hint(Error **errp);
 
 #endif
-- 
2.17.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]