Commit 9a77ef813f for qemu.org
commit 9a77ef813f5f915bda408f4e53c11d0ca17c5d70
Author: Denis V. Lunev <den@openvz.org>
Date: Thu Jul 16 13:22:42 2026 +0200
block/monitor: allow dropping a bitmap never stored on disk
block-dirty-bitmap-remove refuses any readonly bitmap outright, via
the generic BDRV_BITMAP_RO check in bdrv_dirty_bitmap_check(). That
check cannot tell whether the bitmap is actually on disk, so it also
blocks dropping one that only ever existed in memory, which needs no
write at all.
Drop the blanket check and let qcow2 decide: bdrv_remove_persistent_
dirty_bitmap() already treats an absent on-disk entry as a no-op, so
such a bitmap is now released with no write attempted. For one that
is genuinely stored, qcow2_co_remove_persistent_dirty_bitmap_locked()
now checks can_write() before it would update the on-disk directory,
so removal still fails there, with a message naming the actual
reason instead of just the bitmap's readonly flag.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Eric Blake <eblake@redhat.com>
CC: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
CC: John Snow <jsnow@redhat.com>
CC: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Message-ID: <20260716112242.3000035-4-den@openvz.org>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
index d87ca982aa..aabf2790b6 100644
--- a/block/monitor/bitmap-qmp-cmds.c
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -165,11 +165,11 @@ BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
return NULL;
}
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
- errp)) {
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
return NULL;
}
+ /* Dropping a bitmap needs no write access unless it is actually stored. */
if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
{
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 256ec99878..ac5a724588 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1487,6 +1487,15 @@ int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
goto out;
}
+ if (!can_write(bs)) {
+ error_setg(errp, "Cannot remove persistent bitmap '%s': "
+ "no write access to node '%s'", name,
+ bdrv_get_node_name(bs));
+ ret = -EACCES;
+ bm = NULL;
+ goto out;
+ }
+
QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry);
ret = update_ext_header_and_dir(bs, bm_list);
diff --git a/tests/qemu-iotests/tests/remove-bitmap-from-backing.out b/tests/qemu-iotests/tests/remove-bitmap-from-backing.out
index fe105fe0a3..628fa737d9 100644
--- a/tests/qemu-iotests/tests/remove-bitmap-from-backing.out
+++ b/tests/qemu-iotests/tests/remove-bitmap-from-backing.out
@@ -1,6 +1,6 @@
Trying to remove persistent bitmap from r-o base node, should fail:
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "base"}}
-{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap0' is readonly and cannot be modified"}}
+{"error": {"class": "GenericError", "desc": "Cannot remove persistent bitmap 'bitmap0': no write access to node 'base'"}}
Remove persistent bitmap from base node reopened to RW:
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "base"}}
{"return": {}}