block: maintain persistent disabled bitmaps

To maintain load/store disabled bitmap there is new approach:

 - deprecate @autoload flag of block-dirty-bitmap-add, make it ignored
 - store enabled bitmaps as "auto" to qcow2
 - store disabled bitmaps without "auto" flag to qcow2
 - on qcow2 open load "auto" bitmaps as enabled and others
   as disabled (except in_use bitmaps)

Also, adjust iotests 165 and 176 appropriately.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20180202160752.143796-1-vsementsov@virtuozzo.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2018-02-02 19:07:52 +03:00 committed by Max Reitz
parent 74f1eabf9c
commit 3e99da5e76
10 changed files with 23 additions and 39 deletions

View file

@ -52,8 +52,6 @@ struct BdrvDirtyBitmap {
Such operations must fail and both the image Such operations must fail and both the image
and this bitmap must remain unchanged while and this bitmap must remain unchanged while
this flag is set. */ this flag is set. */
bool autoload; /* For persistent bitmaps: bitmap must be
autoloaded on image opening */
bool persistent; /* bitmap must be saved to owner disk image */ bool persistent; /* bitmap must be saved to owner disk image */
QLIST_ENTRY(BdrvDirtyBitmap) list; QLIST_ENTRY(BdrvDirtyBitmap) list;
}; };
@ -104,7 +102,6 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
g_free(bitmap->name); g_free(bitmap->name);
bitmap->name = NULL; bitmap->name = NULL;
bitmap->persistent = false; bitmap->persistent = false;
bitmap->autoload = false;
} }
/* Called with BQL taken. */ /* Called with BQL taken. */
@ -261,8 +258,6 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
bitmap->successor = NULL; bitmap->successor = NULL;
successor->persistent = bitmap->persistent; successor->persistent = bitmap->persistent;
bitmap->persistent = false; bitmap->persistent = false;
successor->autoload = bitmap->autoload;
bitmap->autoload = false;
bdrv_release_dirty_bitmap(bs, bitmap); bdrv_release_dirty_bitmap(bs, bitmap);
return successor; return successor;
@ -666,19 +661,6 @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
return false; return false;
} }
/* Called with BQL taken. */
void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload)
{
qemu_mutex_lock(bitmap->mutex);
bitmap->autoload = autoload;
qemu_mutex_unlock(bitmap->mutex);
}
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap)
{
return bitmap->autoload;
}
/* Called with BQL taken. */ /* Called with BQL taken. */
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
{ {

View file

@ -933,14 +933,14 @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value); bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value);
} }
/* qcow2_load_autoloading_dirty_bitmaps() /* qcow2_load_dirty_bitmaps()
* Return value is a hint for caller: true means that the Qcow2 header was * Return value is a hint for caller: true means that the Qcow2 header was
* updated. (false doesn't mean that the header should be updated by the * updated. (false doesn't mean that the header should be updated by the
* caller, it just means that updating was not needed or the image cannot be * caller, it just means that updating was not needed or the image cannot be
* written to). * written to).
* On failure the function returns false. * On failure the function returns false.
*/ */
bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp) bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
Qcow2BitmapList *bm_list; Qcow2BitmapList *bm_list;
@ -960,14 +960,16 @@ bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
} }
QSIMPLEQ_FOREACH(bm, bm_list, entry) { QSIMPLEQ_FOREACH(bm, bm_list, entry) {
if ((bm->flags & BME_FLAG_AUTO) && !(bm->flags & BME_FLAG_IN_USE)) { if (!(bm->flags & BME_FLAG_IN_USE)) {
BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp); BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
if (bitmap == NULL) { if (bitmap == NULL) {
goto fail; goto fail;
} }
if (!(bm->flags & BME_FLAG_AUTO)) {
bdrv_disable_dirty_bitmap(bitmap);
}
bdrv_dirty_bitmap_set_persistance(bitmap, true); bdrv_dirty_bitmap_set_persistance(bitmap, true);
bdrv_dirty_bitmap_set_autoload(bitmap, true);
bm->flags |= BME_FLAG_IN_USE; bm->flags |= BME_FLAG_IN_USE;
created_dirty_bitmaps = created_dirty_bitmaps =
g_slist_append(created_dirty_bitmaps, bitmap); g_slist_append(created_dirty_bitmaps, bitmap);
@ -1369,7 +1371,7 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
bm->table.size = 0; bm->table.size = 0;
QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry); QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry);
} }
bm->flags = bdrv_dirty_bitmap_get_autoload(bitmap) ? BME_FLAG_AUTO : 0; bm->flags = bdrv_dirty_bitmap_enabled(bitmap) ? BME_FLAG_AUTO : 0;
bm->granularity_bits = ctz32(bdrv_dirty_bitmap_granularity(bitmap)); bm->granularity_bits = ctz32(bdrv_dirty_bitmap_granularity(bitmap));
bm->dirty_bitmap = bitmap; bm->dirty_bitmap = bitmap;
} }

View file

@ -1460,7 +1460,7 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
s->autoclear_features &= QCOW2_AUTOCLEAR_MASK; s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
} }
if (qcow2_load_autoloading_dirty_bitmaps(bs, &local_err)) { if (qcow2_load_dirty_bitmaps(bs, &local_err)) {
update_header = false; update_header = false;
} }
if (local_err != NULL) { if (local_err != NULL) {

View file

@ -663,7 +663,7 @@ void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
void **refcount_table, void **refcount_table,
int64_t *refcount_table_size); int64_t *refcount_table_size);
bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp); bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp);
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp); int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp); void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp); int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);

View file

@ -2825,14 +2825,9 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
if (!has_persistent) { if (!has_persistent) {
persistent = false; persistent = false;
} }
if (!has_autoload) {
autoload = false;
}
if (has_autoload && !persistent) { if (has_autoload) {
error_setg(errp, "Autoload flag must be used only for persistent " warn_report("Autoload option is deprecated and its value is ignored");
"bitmaps");
return;
} }
if (persistent && if (persistent &&
@ -2847,7 +2842,6 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
} }
bdrv_dirty_bitmap_set_persistance(bitmap, persistent); bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
bdrv_dirty_bitmap_set_autoload(bitmap, autoload);
} }
void qmp_block_dirty_bitmap_remove(const char *node, const char *name, void qmp_block_dirty_bitmap_remove(const char *node, const char *name,

View file

@ -66,7 +66,6 @@ void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap); void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value); void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload);
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
bool persistent); bool persistent);

View file

@ -1593,9 +1593,9 @@
# Qcow2 disks support persistent bitmaps. Default is false for # Qcow2 disks support persistent bitmaps. Default is false for
# block-dirty-bitmap-add. (Since: 2.10) # block-dirty-bitmap-add. (Since: 2.10)
# #
# @autoload: the bitmap will be automatically loaded when the image it is stored # @autoload: ignored and deprecated since 2.12.
# in is opened. This flag may only be specified for persistent # Currently, all dirty tracking bitmaps are loaded from Qcow2 on
# bitmaps. Default is false for block-dirty-bitmap-add. (Since: 2.10) # open.
# #
# Since: 2.4 # Since: 2.4
## ##

View file

@ -2757,6 +2757,13 @@ used and it will be removed with no replacement.
The ``convert -s snapshot_id_or_name'' argument is obsoleted The ``convert -s snapshot_id_or_name'' argument is obsoleted
by the ``convert -l snapshot_param'' argument instead. by the ``convert -l snapshot_param'' argument instead.
@section QEMU Machine Protocol (QMP) commands
@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
"autoload" parameter is now ignored. All bitmaps are automatically loaded
from qcow2 images.
@section System emulator human monitor commands @section System emulator human monitor commands
@subsection host_net_add (since 2.10.0) @subsection host_net_add (since 2.10.0)

View file

@ -64,7 +64,7 @@ class TestPersistentDirtyBitmap(iotests.QMPTestCase):
def qmpAddBitmap(self): def qmpAddBitmap(self):
self.vm.qmp('block-dirty-bitmap-add', node='drive0', self.vm.qmp('block-dirty-bitmap-add', node='drive0',
name='bitmap0', persistent=True, autoload=True) name='bitmap0', persistent=True)
def test_persistent(self): def test_persistent(self):
self.vm = self.mkVm() self.vm = self.mkVm()

View file

@ -95,7 +95,7 @@ case $reason in
"file": { "driver": "file", "filename": "$TEST_IMG" } } } "file": { "driver": "file", "filename": "$TEST_IMG" } } }
{ "execute": "block-dirty-bitmap-add", { "execute": "block-dirty-bitmap-add",
"arguments": { "node": "drive0", "name": "bitmap0", "arguments": { "node": "drive0", "name": "bitmap0",
"persistent": true, "autoload": true } } "persistent": true } }
{ "execute": "quit" } { "execute": "quit" }
EOF EOF
;; ;;