migration: Add .save_prepare() handler to struct SaveVMHandlers
Add a new .save_prepare() handler to struct SaveVMHandlers. This handler is called early, even before migration starts, and can be used by devices to perform early checks. Refactor migrate_init() to be able to return errors and call .save_prepare() from there. Suggested-by: Peter Xu <peterx@redhat.com> Signed-off-by: Avihai Horon <avihaih@nvidia.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
parent
f543aa222d
commit
08fc4cb517
|
@ -20,6 +20,11 @@ typedef struct SaveVMHandlers {
|
||||||
/* This runs inside the iothread lock. */
|
/* This runs inside the iothread lock. */
|
||||||
SaveStateHandler *save_state;
|
SaveStateHandler *save_state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save_prepare is called early, even before migration starts, and can be
|
||||||
|
* used to perform early checks.
|
||||||
|
*/
|
||||||
|
int (*save_prepare)(void *opaque, Error **errp);
|
||||||
void (*save_cleanup)(void *opaque);
|
void (*save_cleanup)(void *opaque);
|
||||||
int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque);
|
int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque);
|
||||||
int (*save_live_complete_precopy)(QEMUFile *f, void *opaque);
|
int (*save_live_complete_precopy)(QEMUFile *f, void *opaque);
|
||||||
|
|
|
@ -1392,8 +1392,15 @@ bool migration_is_active(MigrationState *s)
|
||||||
s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void migrate_init(MigrationState *s)
|
int migrate_init(MigrationState *s, Error **errp)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = qemu_savevm_state_prepare(errp);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reinitialise all migration state, except
|
* Reinitialise all migration state, except
|
||||||
* parameters/capabilities that the user set, and
|
* parameters/capabilities that the user set, and
|
||||||
|
@ -1432,6 +1439,8 @@ void migrate_init(MigrationState *s)
|
||||||
memset(&mig_stats, 0, sizeof(mig_stats));
|
memset(&mig_stats, 0, sizeof(mig_stats));
|
||||||
memset(&compression_counters, 0, sizeof(compression_counters));
|
memset(&compression_counters, 0, sizeof(compression_counters));
|
||||||
migration_reset_vfio_bytes_transferred();
|
migration_reset_vfio_bytes_transferred();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int migrate_add_blocker_internal(Error *reason, Error **errp)
|
int migrate_add_blocker_internal(Error *reason, Error **errp)
|
||||||
|
@ -1641,7 +1650,9 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
|
||||||
migrate_set_block_incremental(true);
|
migrate_set_block_incremental(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
migrate_init(s);
|
if (migrate_init(s, errp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,7 +472,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in);
|
||||||
bool migration_is_setup_or_active(int state);
|
bool migration_is_setup_or_active(int state);
|
||||||
bool migration_is_running(int state);
|
bool migration_is_running(int state);
|
||||||
|
|
||||||
void migrate_init(MigrationState *s);
|
int migrate_init(MigrationState *s, Error **errp);
|
||||||
bool migration_is_blocked(Error **errp);
|
bool migration_is_blocked(Error **errp);
|
||||||
/* True if outgoing migration has entered postcopy phase */
|
/* True if outgoing migration has entered postcopy phase */
|
||||||
bool migration_in_postcopy(void);
|
bool migration_in_postcopy(void);
|
||||||
|
|
|
@ -1233,6 +1233,30 @@ bool qemu_savevm_state_guest_unplug_pending(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qemu_savevm_state_prepare(Error **errp)
|
||||||
|
{
|
||||||
|
SaveStateEntry *se;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
|
||||||
|
if (!se->ops || !se->ops->save_prepare) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (se->ops->is_active) {
|
||||||
|
if (!se->ops->is_active(se->opaque)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = se->ops->save_prepare(se->opaque, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void qemu_savevm_state_setup(QEMUFile *f)
|
void qemu_savevm_state_setup(QEMUFile *f)
|
||||||
{
|
{
|
||||||
MigrationState *ms = migrate_get_current();
|
MigrationState *ms = migrate_get_current();
|
||||||
|
@ -1619,7 +1643,10 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
migrate_init(ms);
|
ret = migrate_init(ms, errp);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ms->to_dst_file = f;
|
ms->to_dst_file = f;
|
||||||
|
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
bool qemu_savevm_state_blocked(Error **errp);
|
bool qemu_savevm_state_blocked(Error **errp);
|
||||||
void qemu_savevm_non_migratable_list(strList **reasons);
|
void qemu_savevm_non_migratable_list(strList **reasons);
|
||||||
|
int qemu_savevm_state_prepare(Error **errp);
|
||||||
void qemu_savevm_state_setup(QEMUFile *f);
|
void qemu_savevm_state_setup(QEMUFile *f);
|
||||||
bool qemu_savevm_state_guest_unplug_pending(void);
|
bool qemu_savevm_state_guest_unplug_pending(void);
|
||||||
int qemu_savevm_state_resume_prepare(MigrationState *s);
|
int qemu_savevm_state_resume_prepare(MigrationState *s);
|
||||||
|
|
Loading…
Reference in New Issue