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:
parent
74f1eabf9c
commit
3e99da5e76
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
10
blockdev.c
10
blockdev.c
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
##
|
##
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
;;
|
;;
|
||||||
|
Loading…
Reference in New Issue
Block a user