aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/dirty-bitmap.c42
-rw-r--r--blockdev.c49
-rw-r--r--include/block/dirty-bitmap.h13
-rw-r--r--migration/block-dirty-bitmap.c13
-rw-r--r--nbd/server.c3
5 files changed, 56 insertions, 64 deletions
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 4a2349d9dd..6170f3a454 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -174,7 +174,7 @@ bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap)
return bitmap->successor;
}
-bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap)
+static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap)
{
return bitmap->busy;
}
@@ -236,6 +236,33 @@ static bool bdrv_dirty_bitmap_recording(BdrvDirtyBitmap *bitmap)
!bitmap->successor->disabled);
}
+int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
+ Error **errp)
+{
+ if ((flags & BDRV_BITMAP_BUSY) && bdrv_dirty_bitmap_busy(bitmap)) {
+ error_setg(errp, "Bitmap '%s' is currently in use by another"
+ " operation and cannot be used", bitmap->name);
+ return -1;
+ }
+
+ if ((flags & BDRV_BITMAP_RO) && bdrv_dirty_bitmap_readonly(bitmap)) {
+ error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
+ bitmap->name);
+ return -1;
+ }
+
+ if ((flags & BDRV_BITMAP_INCONSISTENT) &&
+ bdrv_dirty_bitmap_inconsistent(bitmap)) {
+ error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used",
+ bitmap->name);
+ error_append_hint(errp, "Try block-dirty-bitmap-remove to delete"
+ " this bitmap from disk");
+ return -1;
+ }
+
+ return 0;
+}
+
/**
* Create a successor bitmap destined to replace this bitmap after an operation.
* Requires that the bitmap is not marked busy and has no successor.
@@ -248,9 +275,7 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
uint64_t granularity;
BdrvDirtyBitmap *child;
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_setg(errp, "Cannot create a successor for a bitmap that is "
- "in-use by an operation");
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
return -1;
}
if (bdrv_dirty_bitmap_has_successor(bitmap)) {
@@ -796,17 +821,10 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
qemu_mutex_lock(dest->mutex);
- if (bdrv_dirty_bitmap_busy(dest)) {
- error_setg(errp, "Bitmap '%s' is currently in use by another"
- " operation and cannot be modified", dest->name);
+ if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
goto out;
}
- if (bdrv_dirty_bitmap_readonly(dest)) {
- error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
- dest->name);
- goto out;
- }
if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
error_setg(errp, "Bitmaps are incompatible and can't be merged");
diff --git a/blockdev.c b/blockdev.c
index 364b453994..5021f8124b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2010,11 +2010,7 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
return;
}
- if (bdrv_dirty_bitmap_busy(state->bitmap)) {
- error_setg(errp, "Cannot modify a bitmap in use by another operation");
- return;
- } else if (bdrv_dirty_bitmap_readonly(state->bitmap)) {
- error_setg(errp, "Cannot clear a readonly bitmap");
+ if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_DEFAULT, errp)) {
return;
}
@@ -2059,10 +2055,7 @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
return;
}
- if (bdrv_dirty_bitmap_busy(state->bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be enabled", action->name);
+ if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
return;
}
@@ -2100,10 +2093,7 @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
return;
}
- if (bdrv_dirty_bitmap_busy(state->bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be disabled", action->name);
+ if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
return;
}
@@ -2894,10 +2884,7 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation and"
- " cannot be removed", name);
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
return;
}
@@ -2933,13 +2920,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be cleared", name);
- return;
- } else if (bdrv_dirty_bitmap_readonly(bitmap)) {
- error_setg(errp, "Bitmap '%s' is readonly and cannot be cleared", name);
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
return;
}
@@ -2957,10 +2938,7 @@ void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be enabled", name);
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
return;
}
@@ -2978,10 +2956,7 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be disabled", name);
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
return;
}
@@ -3560,10 +3535,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
bdrv_unref(target_bs);
goto out;
}
- if (bdrv_dirty_bitmap_busy(bmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be used for backup", backup->bitmap);
+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
goto out;
}
}
@@ -3673,10 +3645,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
goto out;
}
- if (bdrv_dirty_bitmap_busy(bmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently in use by another operation"
- " and cannot be used for backup", backup->bitmap);
+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
goto out;
}
}
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index bd1b6479df..2a78243954 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -5,6 +5,16 @@
#include "qapi/qapi-types-block-core.h"
#include "qemu/hbitmap.h"
+typedef enum BitmapCheckFlags {
+ BDRV_BITMAP_BUSY = 1,
+ BDRV_BITMAP_RO = 2,
+ BDRV_BITMAP_INCONSISTENT = 4,
+} BitmapCheckFlags;
+
+#define BDRV_BITMAP_DEFAULT (BDRV_BITMAP_BUSY | BDRV_BITMAP_RO | \
+ BDRV_BITMAP_INCONSISTENT)
+#define BDRV_BITMAP_ALLOW_RO (BDRV_BITMAP_BUSY | BDRV_BITMAP_INCONSISTENT)
+
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity,
const char *name,
@@ -24,6 +34,8 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap);
BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
const char *name);
+int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
+ Error **errp);
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
@@ -93,7 +105,6 @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap);
-bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap);
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
BdrvDirtyBitmap *bitmap);
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index 7057fff242..a09befeef9 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -274,6 +274,7 @@ static int init_dirty_bitmap_migration(void)
BdrvDirtyBitmap *bitmap;
DirtyBitmapMigBitmapState *dbms;
BdrvNextIterator it;
+ Error *local_err = NULL;
dirty_bitmap_mig_state.bulk_completed = false;
dirty_bitmap_mig_state.prev_bs = NULL;
@@ -301,15 +302,9 @@ static int init_dirty_bitmap_migration(void)
goto fail;
}
- if (bdrv_dirty_bitmap_busy(bitmap)) {
- error_report("Can't migrate a bitmap that is in use by another operation: '%s'",
- bdrv_dirty_bitmap_name(bitmap));
- goto fail;
- }
-
- if (bdrv_dirty_bitmap_readonly(bitmap)) {
- error_report("Can't migrate read-only dirty bitmap: '%s",
- bdrv_dirty_bitmap_name(bitmap));
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT,
+ &local_err)) {
+ error_report_err(local_err);
goto fail;
}
diff --git a/nbd/server.c b/nbd/server.c
index ebb1031f58..fd013a2817 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1510,8 +1510,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
goto fail;
}
- if (bdrv_dirty_bitmap_busy(bm)) {
- error_setg(errp, "Bitmap '%s' is in use", bitmap);
+ if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) {
goto fail;
}