aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2020-07-30 14:02:33 +0200
committerEric Blake <eblake@redhat.com>2020-08-03 08:59:37 -0500
commitfe16c7ddf82b25e54cb76936a4cdf6bf9327ece5 (patch)
treec7b5141c7969224e80992cf99155985cf727fef4 /block
parent6c5dfc9ccb643a0d50fdec9f10806b14960571d1 (diff)
qcow2: Release read-only bitmaps when inactivated
During migration, we release all bitmaps after storing them on disk, as long as they are (1) stored on disk, (2) not read-only, and (3) consistent. (2) seems arbitrary, though. The reason we do not release them is because we do not write them, as there is no need to; and then we just forget about all bitmaps that we have not written to the file. However, read-only persistent bitmaps are still in the file and in sync with their in-memory representation, so we may as well release them just like any R/W bitmap that we have updated. It leads to actual problems, too: After migration, letting the source continue may result in an error if there were any bitmaps on read-only nodes (such as backing images), because those have not been released by bdrv_inactive_all(), but bdrv_invalidate_cache_all() attempts to reload them (which fails, because they are still present in memory). Signed-off-by: Max Reitz <mreitz@redhat.com> Message-Id: <20200730120234.49288-2-mreitz@redhat.com> Tested-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/qcow2-bitmap.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 1f38806ca6..8c34b2aef7 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1562,11 +1562,22 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
Qcow2Bitmap *bm;
if (!bdrv_dirty_bitmap_get_persistence(bitmap) ||
- bdrv_dirty_bitmap_readonly(bitmap) ||
bdrv_dirty_bitmap_inconsistent(bitmap)) {
continue;
}
+ if (bdrv_dirty_bitmap_readonly(bitmap)) {
+ /*
+ * Store the bitmap in the associated Qcow2Bitmap so it
+ * can be released later
+ */
+ bm = find_bitmap_by_name(bm_list, name);
+ if (bm) {
+ bm->dirty_bitmap = bitmap;
+ }
+ continue;
+ }
+
need_write = true;
if (check_constraints_on_bitmap(bs, name, granularity, errp) < 0) {
@@ -1618,7 +1629,9 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
/* allocate clusters and store bitmaps */
QSIMPLEQ_FOREACH(bm, bm_list, entry) {
- if (bm->dirty_bitmap == NULL) {
+ BdrvDirtyBitmap *bitmap = bm->dirty_bitmap;
+
+ if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) {
continue;
}
@@ -1641,6 +1654,7 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
g_free(tb);
}
+success:
if (release_stored) {
QSIMPLEQ_FOREACH(bm, bm_list, entry) {
if (bm->dirty_bitmap == NULL) {
@@ -1651,13 +1665,14 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
}
}
-success:
bitmap_list_free(bm_list);
return;
fail:
QSIMPLEQ_FOREACH(bm, bm_list, entry) {
- if (bm->dirty_bitmap == NULL || bm->table.offset == 0) {
+ if (bm->dirty_bitmap == NULL || bm->table.offset == 0 ||
+ bdrv_dirty_bitmap_readonly(bm->dirty_bitmap))
+ {
continue;
}