migration/block-dirty-bitmap: refactor state global variables

Move all state variables into one global struct. Reduce global
variable usage, utilizing opaque pointer where possible.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Message-Id: <20200727194236.19551-12-vsementsov@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2020-07-27 22:42:26 +03:00 committed by Eric Blake
parent d0cccbd118
commit 3b52726ec0
1 changed files with 99 additions and 80 deletions

View File

@ -128,6 +128,12 @@ typedef struct DBMSaveState {
BdrvDirtyBitmap *prev_bitmap; BdrvDirtyBitmap *prev_bitmap;
} DBMSaveState; } DBMSaveState;
typedef struct LoadBitmapState {
BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
bool migrated;
} LoadBitmapState;
/* State of the dirty bitmap migration (DBM) during load process */ /* State of the dirty bitmap migration (DBM) during load process */
typedef struct DBMLoadState { typedef struct DBMLoadState {
uint32_t flags; uint32_t flags;
@ -135,18 +141,17 @@ typedef struct DBMLoadState {
char bitmap_name[256]; char bitmap_name[256];
BlockDriverState *bs; BlockDriverState *bs;
BdrvDirtyBitmap *bitmap; BdrvDirtyBitmap *bitmap;
GSList *enabled_bitmaps;
QemuMutex finish_lock;
} DBMLoadState; } DBMLoadState;
static DBMSaveState dirty_bitmap_mig_state; typedef struct DBMState {
DBMSaveState save;
DBMLoadState load;
} DBMState;
/* State of one bitmap during load process */ static DBMState dbm_state;
typedef struct LoadBitmapState {
BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
bool migrated;
} LoadBitmapState;
static GSList *enabled_bitmaps;
QemuMutex finish_lock;
static uint32_t qemu_get_bitmap_flags(QEMUFile *f) static uint32_t qemu_get_bitmap_flags(QEMUFile *f)
{ {
@ -169,21 +174,21 @@ static void qemu_put_bitmap_flags(QEMUFile *f, uint32_t flags)
qemu_put_byte(f, flags); qemu_put_byte(f, flags);
} }
static void send_bitmap_header(QEMUFile *f, SaveBitmapState *dbms, static void send_bitmap_header(QEMUFile *f, DBMSaveState *s,
uint32_t additional_flags) SaveBitmapState *dbms, uint32_t additional_flags)
{ {
BlockDriverState *bs = dbms->bs; BlockDriverState *bs = dbms->bs;
BdrvDirtyBitmap *bitmap = dbms->bitmap; BdrvDirtyBitmap *bitmap = dbms->bitmap;
uint32_t flags = additional_flags; uint32_t flags = additional_flags;
trace_send_bitmap_header_enter(); trace_send_bitmap_header_enter();
if (bs != dirty_bitmap_mig_state.prev_bs) { if (bs != s->prev_bs) {
dirty_bitmap_mig_state.prev_bs = bs; s->prev_bs = bs;
flags |= DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME; flags |= DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME;
} }
if (bitmap != dirty_bitmap_mig_state.prev_bitmap) { if (bitmap != s->prev_bitmap) {
dirty_bitmap_mig_state.prev_bitmap = bitmap; s->prev_bitmap = bitmap;
flags |= DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME; flags |= DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME;
} }
@ -198,19 +203,22 @@ static void send_bitmap_header(QEMUFile *f, SaveBitmapState *dbms,
} }
} }
static void send_bitmap_start(QEMUFile *f, SaveBitmapState *dbms) static void send_bitmap_start(QEMUFile *f, DBMSaveState *s,
SaveBitmapState *dbms)
{ {
send_bitmap_header(f, dbms, DIRTY_BITMAP_MIG_FLAG_START); send_bitmap_header(f, s, dbms, DIRTY_BITMAP_MIG_FLAG_START);
qemu_put_be32(f, bdrv_dirty_bitmap_granularity(dbms->bitmap)); qemu_put_be32(f, bdrv_dirty_bitmap_granularity(dbms->bitmap));
qemu_put_byte(f, dbms->flags); qemu_put_byte(f, dbms->flags);
} }
static void send_bitmap_complete(QEMUFile *f, SaveBitmapState *dbms) static void send_bitmap_complete(QEMUFile *f, DBMSaveState *s,
SaveBitmapState *dbms)
{ {
send_bitmap_header(f, dbms, DIRTY_BITMAP_MIG_FLAG_COMPLETE); send_bitmap_header(f, s, dbms, DIRTY_BITMAP_MIG_FLAG_COMPLETE);
} }
static void send_bitmap_bits(QEMUFile *f, SaveBitmapState *dbms, static void send_bitmap_bits(QEMUFile *f, DBMSaveState *s,
SaveBitmapState *dbms,
uint64_t start_sector, uint32_t nr_sectors) uint64_t start_sector, uint32_t nr_sectors)
{ {
/* align for buffer_is_zero() */ /* align for buffer_is_zero() */
@ -235,7 +243,7 @@ static void send_bitmap_bits(QEMUFile *f, SaveBitmapState *dbms,
trace_send_bitmap_bits(flags, start_sector, nr_sectors, buf_size); trace_send_bitmap_bits(flags, start_sector, nr_sectors, buf_size);
send_bitmap_header(f, dbms, flags); send_bitmap_header(f, s, dbms, flags);
qemu_put_be64(f, start_sector); qemu_put_be64(f, start_sector);
qemu_put_be32(f, nr_sectors); qemu_put_be32(f, nr_sectors);
@ -254,12 +262,12 @@ static void send_bitmap_bits(QEMUFile *f, SaveBitmapState *dbms,
} }
/* Called with iothread lock taken. */ /* Called with iothread lock taken. */
static void dirty_bitmap_do_save_cleanup(void) static void dirty_bitmap_do_save_cleanup(DBMSaveState *s)
{ {
SaveBitmapState *dbms; SaveBitmapState *dbms;
while ((dbms = QSIMPLEQ_FIRST(&dirty_bitmap_mig_state.dbms_list)) != NULL) { while ((dbms = QSIMPLEQ_FIRST(&s->dbms_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&dirty_bitmap_mig_state.dbms_list, entry); QSIMPLEQ_REMOVE_HEAD(&s->dbms_list, entry);
bdrv_dirty_bitmap_set_busy(dbms->bitmap, false); bdrv_dirty_bitmap_set_busy(dbms->bitmap, false);
bdrv_unref(dbms->bs); bdrv_unref(dbms->bs);
g_free(dbms); g_free(dbms);
@ -267,7 +275,8 @@ static void dirty_bitmap_do_save_cleanup(void)
} }
/* Called with iothread lock taken. */ /* Called with iothread lock taken. */
static int add_bitmaps_to_list(BlockDriverState *bs, const char *bs_name) static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs,
const char *bs_name)
{ {
BdrvDirtyBitmap *bitmap; BdrvDirtyBitmap *bitmap;
SaveBitmapState *dbms; SaveBitmapState *dbms;
@ -322,25 +331,24 @@ static int add_bitmaps_to_list(BlockDriverState *bs, const char *bs_name)
dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT; dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT;
} }
QSIMPLEQ_INSERT_TAIL(&dirty_bitmap_mig_state.dbms_list, QSIMPLEQ_INSERT_TAIL(&s->dbms_list, dbms, entry);
dbms, entry);
} }
return 0; return 0;
} }
/* Called with iothread lock taken. */ /* Called with iothread lock taken. */
static int init_dirty_bitmap_migration(void) static int init_dirty_bitmap_migration(DBMSaveState *s)
{ {
BlockDriverState *bs; BlockDriverState *bs;
SaveBitmapState *dbms; SaveBitmapState *dbms;
GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL); GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL);
BlockBackend *blk; BlockBackend *blk;
dirty_bitmap_mig_state.bulk_completed = false; s->bulk_completed = false;
dirty_bitmap_mig_state.prev_bs = NULL; s->prev_bs = NULL;
dirty_bitmap_mig_state.prev_bitmap = NULL; s->prev_bitmap = NULL;
dirty_bitmap_mig_state.no_bitmaps = false; s->no_bitmaps = false;
/* /*
* Use blockdevice name for direct (or filtered) children of named block * Use blockdevice name for direct (or filtered) children of named block
@ -369,7 +377,7 @@ static int init_dirty_bitmap_migration(void)
} }
if (bs && bs->drv && !bs->drv->is_filter) { if (bs && bs->drv && !bs->drv->is_filter) {
if (add_bitmaps_to_list(bs, name)) { if (add_bitmaps_to_list(s, bs, name)) {
goto fail; goto fail;
} }
g_hash_table_add(handled_by_blk, bs); g_hash_table_add(handled_by_blk, bs);
@ -381,18 +389,18 @@ static int init_dirty_bitmap_migration(void)
continue; continue;
} }
if (add_bitmaps_to_list(bs, bdrv_get_node_name(bs))) { if (add_bitmaps_to_list(s, bs, bdrv_get_node_name(bs))) {
goto fail; goto fail;
} }
} }
/* unset migration flags here, to not roll back it */ /* unset migration flags here, to not roll back it */
QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
bdrv_dirty_bitmap_skip_store(dbms->bitmap, true); bdrv_dirty_bitmap_skip_store(dbms->bitmap, true);
} }
if (QSIMPLEQ_EMPTY(&dirty_bitmap_mig_state.dbms_list)) { if (QSIMPLEQ_EMPTY(&s->dbms_list)) {
dirty_bitmap_mig_state.no_bitmaps = true; s->no_bitmaps = true;
} }
g_hash_table_destroy(handled_by_blk); g_hash_table_destroy(handled_by_blk);
@ -401,18 +409,19 @@ static int init_dirty_bitmap_migration(void)
fail: fail:
g_hash_table_destroy(handled_by_blk); g_hash_table_destroy(handled_by_blk);
dirty_bitmap_do_save_cleanup(); dirty_bitmap_do_save_cleanup(s);
return -1; return -1;
} }
/* Called with no lock taken. */ /* Called with no lock taken. */
static void bulk_phase_send_chunk(QEMUFile *f, SaveBitmapState *dbms) static void bulk_phase_send_chunk(QEMUFile *f, DBMSaveState *s,
SaveBitmapState *dbms)
{ {
uint32_t nr_sectors = MIN(dbms->total_sectors - dbms->cur_sector, uint32_t nr_sectors = MIN(dbms->total_sectors - dbms->cur_sector,
dbms->sectors_per_chunk); dbms->sectors_per_chunk);
send_bitmap_bits(f, dbms, dbms->cur_sector, nr_sectors); send_bitmap_bits(f, s, dbms, dbms->cur_sector, nr_sectors);
dbms->cur_sector += nr_sectors; dbms->cur_sector += nr_sectors;
if (dbms->cur_sector >= dbms->total_sectors) { if (dbms->cur_sector >= dbms->total_sectors) {
@ -421,61 +430,66 @@ static void bulk_phase_send_chunk(QEMUFile *f, SaveBitmapState *dbms)
} }
/* Called with no lock taken. */ /* Called with no lock taken. */
static void bulk_phase(QEMUFile *f, bool limit) static void bulk_phase(QEMUFile *f, DBMSaveState *s, bool limit)
{ {
SaveBitmapState *dbms; SaveBitmapState *dbms;
QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
while (!dbms->bulk_completed) { while (!dbms->bulk_completed) {
bulk_phase_send_chunk(f, dbms); bulk_phase_send_chunk(f, s, dbms);
if (limit && qemu_file_rate_limit(f)) { if (limit && qemu_file_rate_limit(f)) {
return; return;
} }
} }
} }
dirty_bitmap_mig_state.bulk_completed = true; s->bulk_completed = true;
} }
/* for SaveVMHandlers */ /* for SaveVMHandlers */
static void dirty_bitmap_save_cleanup(void *opaque) static void dirty_bitmap_save_cleanup(void *opaque)
{ {
dirty_bitmap_do_save_cleanup(); DBMSaveState *s = &((DBMState *)opaque)->save;
dirty_bitmap_do_save_cleanup(s);
} }
static int dirty_bitmap_save_iterate(QEMUFile *f, void *opaque) static int dirty_bitmap_save_iterate(QEMUFile *f, void *opaque)
{ {
DBMSaveState *s = &((DBMState *)opaque)->save;
trace_dirty_bitmap_save_iterate(migration_in_postcopy()); trace_dirty_bitmap_save_iterate(migration_in_postcopy());
if (migration_in_postcopy() && !dirty_bitmap_mig_state.bulk_completed) { if (migration_in_postcopy() && !s->bulk_completed) {
bulk_phase(f, true); bulk_phase(f, s, true);
} }
qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS);
return dirty_bitmap_mig_state.bulk_completed; return s->bulk_completed;
} }
/* Called with iothread lock taken. */ /* Called with iothread lock taken. */
static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque) static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque)
{ {
DBMSaveState *s = &((DBMState *)opaque)->save;
SaveBitmapState *dbms; SaveBitmapState *dbms;
trace_dirty_bitmap_save_complete_enter(); trace_dirty_bitmap_save_complete_enter();
if (!dirty_bitmap_mig_state.bulk_completed) { if (!s->bulk_completed) {
bulk_phase(f, false); bulk_phase(f, s, false);
} }
QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
send_bitmap_complete(f, dbms); send_bitmap_complete(f, s, dbms);
} }
qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS);
trace_dirty_bitmap_save_complete_finish(); trace_dirty_bitmap_save_complete_finish();
dirty_bitmap_do_save_cleanup(); dirty_bitmap_save_cleanup(opaque);
return 0; return 0;
} }
@ -485,12 +499,13 @@ static void dirty_bitmap_save_pending(QEMUFile *f, void *opaque,
uint64_t *res_compatible, uint64_t *res_compatible,
uint64_t *res_postcopy_only) uint64_t *res_postcopy_only)
{ {
DBMSaveState *s = &((DBMState *)opaque)->save;
SaveBitmapState *dbms; SaveBitmapState *dbms;
uint64_t pending = 0; uint64_t pending = 0;
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
uint64_t gran = bdrv_dirty_bitmap_granularity(dbms->bitmap); uint64_t gran = bdrv_dirty_bitmap_granularity(dbms->bitmap);
uint64_t sectors = dbms->bulk_completed ? 0 : uint64_t sectors = dbms->bulk_completed ? 0 :
dbms->total_sectors - dbms->cur_sector; dbms->total_sectors - dbms->cur_sector;
@ -549,7 +564,7 @@ static int dirty_bitmap_load_start(QEMUFile *f, DBMLoadState *s)
b->bs = s->bs; b->bs = s->bs;
b->bitmap = s->bitmap; b->bitmap = s->bitmap;
b->migrated = false; b->migrated = false;
enabled_bitmaps = g_slist_prepend(enabled_bitmaps, b); s->enabled_bitmaps = g_slist_prepend(s->enabled_bitmaps, b);
} }
return 0; return 0;
@ -557,11 +572,12 @@ static int dirty_bitmap_load_start(QEMUFile *f, DBMLoadState *s)
void dirty_bitmap_mig_before_vm_start(void) void dirty_bitmap_mig_before_vm_start(void)
{ {
DBMLoadState *s = &dbm_state.load;
GSList *item; GSList *item;
qemu_mutex_lock(&finish_lock); qemu_mutex_lock(&s->finish_lock);
for (item = enabled_bitmaps; item; item = g_slist_next(item)) { for (item = s->enabled_bitmaps; item; item = g_slist_next(item)) {
LoadBitmapState *b = item->data; LoadBitmapState *b = item->data;
if (b->migrated) { if (b->migrated) {
@ -573,10 +589,10 @@ void dirty_bitmap_mig_before_vm_start(void)
g_free(b); g_free(b);
} }
g_slist_free(enabled_bitmaps); g_slist_free(s->enabled_bitmaps);
enabled_bitmaps = NULL; s->enabled_bitmaps = NULL;
qemu_mutex_unlock(&finish_lock); qemu_mutex_unlock(&s->finish_lock);
} }
static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s) static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s)
@ -585,9 +601,9 @@ static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s)
trace_dirty_bitmap_load_complete(); trace_dirty_bitmap_load_complete();
bdrv_dirty_bitmap_deserialize_finish(s->bitmap); bdrv_dirty_bitmap_deserialize_finish(s->bitmap);
qemu_mutex_lock(&finish_lock); qemu_mutex_lock(&s->finish_lock);
for (item = enabled_bitmaps; item; item = g_slist_next(item)) { for (item = s->enabled_bitmaps; item; item = g_slist_next(item)) {
LoadBitmapState *b = item->data; LoadBitmapState *b = item->data;
if (b->bitmap == s->bitmap) { if (b->bitmap == s->bitmap) {
@ -598,7 +614,7 @@ static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s)
if (bdrv_dirty_bitmap_has_successor(s->bitmap)) { if (bdrv_dirty_bitmap_has_successor(s->bitmap)) {
bdrv_dirty_bitmap_lock(s->bitmap); bdrv_dirty_bitmap_lock(s->bitmap);
if (enabled_bitmaps == NULL) { if (s->enabled_bitmaps == NULL) {
/* in postcopy */ /* in postcopy */
bdrv_reclaim_dirty_bitmap_locked(s->bitmap, &error_abort); bdrv_reclaim_dirty_bitmap_locked(s->bitmap, &error_abort);
bdrv_enable_dirty_bitmap_locked(s->bitmap); bdrv_enable_dirty_bitmap_locked(s->bitmap);
@ -617,7 +633,7 @@ static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s)
bdrv_dirty_bitmap_unlock(s->bitmap); bdrv_dirty_bitmap_unlock(s->bitmap);
} }
qemu_mutex_unlock(&finish_lock); qemu_mutex_unlock(&s->finish_lock);
} }
static int dirty_bitmap_load_bits(QEMUFile *f, DBMLoadState *s) static int dirty_bitmap_load_bits(QEMUFile *f, DBMLoadState *s)
@ -714,7 +730,7 @@ static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s)
static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id) static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
{ {
static DBMLoadState s; DBMLoadState *s = &((DBMState *)opaque)->load;
int ret = 0; int ret = 0;
trace_dirty_bitmap_load_enter(); trace_dirty_bitmap_load_enter();
@ -724,17 +740,17 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
} }
do { do {
ret = dirty_bitmap_load_header(f, &s); ret = dirty_bitmap_load_header(f, s);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
if (s.flags & DIRTY_BITMAP_MIG_FLAG_START) { if (s->flags & DIRTY_BITMAP_MIG_FLAG_START) {
ret = dirty_bitmap_load_start(f, &s); ret = dirty_bitmap_load_start(f, s);
} else if (s.flags & DIRTY_BITMAP_MIG_FLAG_COMPLETE) { } else if (s->flags & DIRTY_BITMAP_MIG_FLAG_COMPLETE) {
dirty_bitmap_load_complete(f, &s); dirty_bitmap_load_complete(f, s);
} else if (s.flags & DIRTY_BITMAP_MIG_FLAG_BITS) { } else if (s->flags & DIRTY_BITMAP_MIG_FLAG_BITS) {
ret = dirty_bitmap_load_bits(f, &s); ret = dirty_bitmap_load_bits(f, s);
} }
if (!ret) { if (!ret) {
@ -744,7 +760,7 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
if (ret) { if (ret) {
return ret; return ret;
} }
} while (!(s.flags & DIRTY_BITMAP_MIG_FLAG_EOS)); } while (!(s->flags & DIRTY_BITMAP_MIG_FLAG_EOS));
trace_dirty_bitmap_load_success(); trace_dirty_bitmap_load_success();
return 0; return 0;
@ -752,13 +768,14 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque) static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque)
{ {
DBMSaveState *s = &((DBMState *)opaque)->save;
SaveBitmapState *dbms = NULL; SaveBitmapState *dbms = NULL;
if (init_dirty_bitmap_migration() < 0) { if (init_dirty_bitmap_migration(s) < 0) {
return -1; return -1;
} }
QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
send_bitmap_start(f, dbms); send_bitmap_start(f, s, dbms);
} }
qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS);
@ -767,7 +784,9 @@ static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque)
static bool dirty_bitmap_is_active(void *opaque) static bool dirty_bitmap_is_active(void *opaque)
{ {
return migrate_dirty_bitmaps() && !dirty_bitmap_mig_state.no_bitmaps; DBMSaveState *s = &((DBMState *)opaque)->save;
return migrate_dirty_bitmaps() && !s->no_bitmaps;
} }
static bool dirty_bitmap_is_active_iterate(void *opaque) static bool dirty_bitmap_is_active_iterate(void *opaque)
@ -795,10 +814,10 @@ static SaveVMHandlers savevm_dirty_bitmap_handlers = {
void dirty_bitmap_mig_init(void) void dirty_bitmap_mig_init(void)
{ {
QSIMPLEQ_INIT(&dirty_bitmap_mig_state.dbms_list); QSIMPLEQ_INIT(&dbm_state.save.dbms_list);
qemu_mutex_init(&finish_lock); qemu_mutex_init(&dbm_state.load.finish_lock);
register_savevm_live("dirty-bitmap", 0, 1, register_savevm_live("dirty-bitmap", 0, 1,
&savevm_dirty_bitmap_handlers, &savevm_dirty_bitmap_handlers,
&dirty_bitmap_mig_state); &dbm_state);
} }