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.
Suggested-by: Peter Xu <pet...@redhat.com> Signed-off-by: Avihai Horon <avih...@nvidia.com> --- include/migration/register.h | 5 +++++ migration/savevm.h | 1 + migration/migration.c | 4 ++++ migration/savevm.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/include/migration/register.h b/include/migration/register.h index 90914f32f5..2b12c6adec 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -20,6 +20,11 @@ typedef struct SaveVMHandlers { /* This runs inside the iothread lock. */ 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); int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); diff --git a/migration/savevm.h b/migration/savevm.h index e894bbc143..74669733dd 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -31,6 +31,7 @@ bool qemu_savevm_state_blocked(Error **errp); void qemu_savevm_non_migratable_list(strList **reasons); +int qemu_savevm_state_prepare(Error **errp); void qemu_savevm_state_setup(QEMUFile *f); bool qemu_savevm_state_guest_unplug_pending(void); int qemu_savevm_state_resume_prepare(MigrationState *s); diff --git a/migration/migration.c b/migration/migration.c index 92866a8f49..914783f07b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1634,6 +1634,10 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, migrate_set_block_incremental(true); } + if (qemu_savevm_state_prepare(errp)) { + return false; + } + migrate_init(s); /* * set mig_stats compression_counters memory to zero for a diff --git a/migration/savevm.c b/migration/savevm.c index 5bf8b59a7d..818510ec57 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1233,6 +1233,30 @@ bool qemu_savevm_state_guest_unplug_pending(void) 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) { MigrationState *ms = migrate_get_current(); @@ -1619,6 +1643,11 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) return -EINVAL; } + ret = qemu_savevm_state_prepare(errp); + if (ret) { + return ret; + } + migrate_init(ms); memset(&mig_stats, 0, sizeof(mig_stats)); memset(&compression_counters, 0, sizeof(compression_counters)); -- 2.26.3