@samitouri / QOSamiQemu / commits / 9a77ef813f

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>

Denis V. Lunev committed Jul 16, 2026 at 13:22 UTC 9a77ef813f5f915bda408f4e53c11d0ca17c5d70
3 files changed +12 -3
block/monitor/bitmap-qmp-cmds.c
+2 -2
@@ -165,11 +165,11 @@ BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
165 return NULL;
166 }
167
168 - if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
169 - errp)) {
168 + if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
169 return NULL;
170 }
171
172 + /* Dropping a bitmap needs no write access unless it is actually stored. */
173 if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
174 bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
175 {
block/qcow2-bitmap.c
+9
@@ -1487,6 +1487,15 @@ int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
1487 goto out;
1488 }
1489
1490 + if (!can_write(bs)) {
1491 + error_setg(errp, "Cannot remove persistent bitmap '%s': "
1492 + "no write access to node '%s'", name,
1493 + bdrv_get_node_name(bs));
1494 + ret = -EACCES;
1495 + bm = NULL;
1496 + goto out;
1497 + }
1498 +
1499 QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry);
1500
1501 ret = update_ext_header_and_dir(bs, bm_list);
tests/qemu-iotests/tests/remove-bitmap-from-backing.out
+1 -1
@@ -1,6 +1,6 @@
1 Trying to remove persistent bitmap from r-o base node, should fail:
2 {"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "base"}}
3 -{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap0' is readonly and cannot be modified"}}
3 +{"error": {"class": "GenericError", "desc": "Cannot remove persistent bitmap 'bitmap0': no write access to node 'base'"}}
4 Remove persistent bitmap from base node reopened to RW:
5 {"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "base"}}
6 {"return": {}}