QemuMutex *mutex;
HBitmap *bitmap; /* Dirty bitmap implementation */
HBitmap *meta; /* Meta dirty bitmap */
+ bool qmp_locked; /* Bitmap is locked, it can't be modified
+ through QMP */
BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
char *name; /* Optional non-empty unique ID */
int64_t size; /* Size of the bitmap, in bytes */
return bitmap->successor;
}
+void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked)
+{
+ qemu_mutex_lock(bitmap->mutex);
+ bitmap->qmp_locked = qmp_locked;
+ qemu_mutex_unlock(bitmap->mutex);
+}
+
+bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap)
+{
+ return bitmap->qmp_locked;
+}
+
/* Called with BQL taken. */
bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
{
{
if (bdrv_dirty_bitmap_frozen(bitmap)) {
return DIRTY_BITMAP_STATUS_FROZEN;
+ } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
+ return DIRTY_BITMAP_STATUS_LOCKED;
} else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
return DIRTY_BITMAP_STATUS_DISABLED;
} else {
if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
error_setg(errp, "Cannot modify a frozen bitmap");
return;
+ } else if (bdrv_dirty_bitmap_qmp_locked(state->bitmap)) {
+ error_setg(errp, "Cannot modify a locked bitmap");
+ return;
} else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
error_setg(errp, "Cannot clear a disabled bitmap");
return;
"Bitmap '%s' is currently frozen and cannot be removed",
name);
return;
+ } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently locked and cannot be removed",
+ name);
+ return;
}
if (bdrv_dirty_bitmap_get_persistance(bitmap)) {
"Bitmap '%s' is currently frozen and cannot be modified",
name);
return;
+ } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently locked and cannot be modified",
+ name);
+ return;
} else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
error_setg(errp,
"Bitmap '%s' is currently disabled and cannot be cleared",
bdrv_unref(target_bs);
goto out;
}
+ if (bdrv_dirty_bitmap_qmp_locked(bmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently locked and cannot be used for "
+ "backup", backup->bitmap);
+ goto out;
+ }
}
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
bool persistent);
+void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked);
+
/* Functions that require manual locking. */
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
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_qmp_locked(BdrvDirtyBitmap *bitmap);
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
BdrvDirtyBitmap *bitmap);
# @active: The bitmap is actively monitoring for new writes, and can be cleared,
# deleted, or used for backup operations.
#
+# @locked: The bitmap is currently in-use by some operation and can not be
+# cleared, deleted, or used for backup operations. (Since 2.12)
+#
# Since: 2.4
##
{ 'enum': 'DirtyBitmapStatus',
- 'data': ['active', 'disabled', 'frozen'] }
+ 'data': ['active', 'disabled', 'frozen', 'locked'] }
##
# @BlockDirtyInfo: