*/
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "trace.h"
#include "block/block_int.h"
#include "block/blockjob.h"
return bitmap->successor;
}
-bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap)
+static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap)
{
return bitmap->busy;
}
* or it can be Disabled and not recording writes.
* (4) Locked: Whether Active or Disabled, the user cannot modify this bitmap
* in any way from the monitor.
+ * (5) Inconsistent: This is a persistent bitmap whose "in use" bit is set, and
+ * is unusable by QEMU. It can be deleted to remove it from
+ * the qcow2.
*/
DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
{
- if (bdrv_dirty_bitmap_has_successor(bitmap)) {
+ if (bdrv_dirty_bitmap_inconsistent(bitmap)) {
+ return DIRTY_BITMAP_STATUS_INCONSISTENT;
+ } else if (bdrv_dirty_bitmap_has_successor(bitmap)) {
return DIRTY_BITMAP_STATUS_FROZEN;
} else if (bdrv_dirty_bitmap_busy(bitmap)) {
return DIRTY_BITMAP_STATUS_LOCKED;
!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.
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)) {
}
/* Called with BQL taken. */
-void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
+void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent)
{
qemu_mutex_lock(bitmap->mutex);
bitmap->persistent = persistent;
qemu_mutex_unlock(bitmap->mutex);
}
-bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
+bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap)
{
return bitmap->persistent && !bitmap->migration;
}
{
bool ret;
- /* only bitmaps from one bds are supported */
- assert(dest->mutex == src->mutex);
-
qemu_mutex_lock(dest->mutex);
+ if (src->mutex != dest->mutex) {
+ qemu_mutex_lock(src->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);
+ if (bdrv_dirty_bitmap_check(src, BDRV_BITMAP_ALLOW_RO, errp)) {
goto out;
}
out:
qemu_mutex_unlock(dest->mutex);
+ if (src->mutex != dest->mutex) {
+ qemu_mutex_unlock(src->mutex);
+ }
}