A device may take over a resource from the source in post_load(), e.g. vhost-vsock acquires the device ownership on a CPR target. If the incoming migration fails afterwards, there's currently no way for the device to give that resource back before the source is told about the failure, over the return path or via the MIGRATION event, and resumes, or before the target exits.
Add a notifier list for that, called from the failure path of process_incoming_migration_co() before the failure is published. Signed-off-by: Andrey Drobyshev <[email protected]> --- include/migration/misc.h | 7 +++++++ migration/migration.c | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/migration/misc.h b/include/migration/misc.h index 019717f4cda..08d110750fc 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -112,6 +112,13 @@ void migration_add_notifier_modes(NotifierWithReturn *notify, */ void migration_remove_notifier(NotifierWithReturn *notify); +/* + * Incoming side: @notify is called when an incoming migration fails, + * before the target dies or before the source is told about the failure. + */ +void migration_incoming_add_failure_notifier(Notifier *notify); +void migration_incoming_remove_failure_notifier(Notifier *notify); + void migration_file_set_error(int ret, Error *err); /* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */ diff --git a/migration/migration.c b/migration/migration.c index fab7949fe11..01e11f91fd9 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -71,6 +71,8 @@ #define INMIGRATE_DEFAULT_EXIT_ON_ERROR true static GSList *migration_state_notifiers[MIG_MODE__MAX]; +static NotifierList incoming_failure_notifiers = + NOTIFIER_LIST_INITIALIZER(incoming_failure_notifiers); /* Messages sent on the return path from destination to source */ enum mig_rp_message_type { @@ -815,6 +817,16 @@ process_incoming_migration_co(void *opaque) goto out; fail: + /* + * Allow the devices which have registered their callbacks for + * migration target failure to undo the changes they may have + * done in post_load(). + * + * Do that before the failure is published in any way: the MIGRATION + * event emitted by migrate_set_state() below, the return path (if + * present) in migration_incoming_state_destroy(), or the exit(). + */ + notifier_list_notify(&incoming_failure_notifiers, NULL); migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_FAILED); migrate_error_propagate(s, local_err); @@ -1590,6 +1602,16 @@ void migration_add_notifier(NotifierWithReturn *notify, migration_add_notifier_mode(notify, func, MIG_MODE_NORMAL); } +void migration_incoming_add_failure_notifier(Notifier *notify) +{ + notifier_list_add(&incoming_failure_notifiers, notify); +} + +void migration_incoming_remove_failure_notifier(Notifier *notify) +{ + notifier_remove(notify); +} + void migration_remove_notifier(NotifierWithReturn *notify) { if (notify->notify) { -- 2.47.1
