Allow a notifier to be added for multiple migration modes.
To allow a notifier to appear on multiple per-node lists, use
a generic list type. We can no longer use NotifierWithReturnList,
because it shoe horns the notifier onto a single list.
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
---
include/migration/misc.h | 12 ++++++++++
migration/migration.c | 60 +++++++++++++++++++++++++++++++++++++-----------
2 files changed, 59 insertions(+), 13 deletions(-)
diff --git a/include/migration/misc.h b/include/migration/misc.h
index a261f99..592b930 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
@@ -95,7 +95,19 @@ void migration_add_notifier(NotifierWithReturn *notify,
void migration_add_notifier_mode(NotifierWithReturn *notify,
MigrationNotifyFunc func, MigMode mode);
+/*
+ * Same as migration_add_notifier, but applies to all @mode in the argument
+ * list. The list is terminated by -1 or MIG_MODE_ALL. For the latter,
+ * the notifier is added for all modes.
+ */
+void migration_add_notifier_modes(NotifierWithReturn *notify,
+ MigrationNotifyFunc func, MigMode mode, ...);
+
+/*
+ * Remove a notifier from all modes.
+ */
void migration_remove_notifier(NotifierWithReturn *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 10c216d..08a98f7 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -74,11 +74,7 @@
#define INMIGRATE_DEFAULT_EXIT_ON_ERROR true
-static NotifierWithReturnList migration_state_notifiers[] = {
- NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_NORMAL),
- NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_REBOOT),
- NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_TRANSFER),
-};
+static GSList *migration_state_notifiers[MIG_MODE__MAX];
/* Messages sent on the return path from destination to source */
enum mig_rp_message_type {
@@ -1665,23 +1661,51 @@ void migration_cancel(void)
}
}
+static int get_modes(MigMode mode, va_list ap);
+
+static void add_notifiers(NotifierWithReturn *notify, int modes)
+{
+ for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) {
+ if (modes & BIT(mode)) {
+ migration_state_notifiers[mode] =
+ g_slist_prepend(migration_state_notifiers[mode], notify);
+ }
+ }
+}
+
+void migration_add_notifier_modes(NotifierWithReturn *notify,
+ MigrationNotifyFunc func, MigMode mode, ...)
+{
+ int modes;
+ va_list ap;
+
+ va_start(ap, mode);
+ modes = get_modes(mode, ap);
+ va_end(ap);
+
+ notify->notify = (NotifierWithReturnFunc)func;
+ add_notifiers(notify, modes);
+}
+
void migration_add_notifier_mode(NotifierWithReturn *notify,
MigrationNotifyFunc func, MigMode mode)
{
- notify->notify = (NotifierWithReturnFunc)func;
- notifier_with_return_list_add(&migration_state_notifiers[mode], notify);
+ migration_add_notifier_modes(notify, func, mode, -1);
}
void migration_add_notifier(NotifierWithReturn *notify,
MigrationNotifyFunc func)
{
- migration_add_notifier_mode(notify, func, MIG_MODE_NORMAL);
+ migration_add_notifier_modes(notify, func, MIG_MODE_NORMAL, -1);
}
void migration_remove_notifier(NotifierWithReturn *notify)
{
if (notify->notify) {
- notifier_with_return_remove(notify);
+ for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) {
+ migration_blockers[mode] =
+ g_slist_remove(migration_state_notifiers[mode], notify);
+ }
notify->notify = NULL;
}
}
@@ -1691,13 +1715,23 @@ int migration_call_notifiers(MigrationState *s, MigrationEventType type,
{
MigMode mode = s->parameters.mode;
MigrationEvent e;
+ NotifierWithReturn *notifier;
+ GSList *elem, *next;
int ret;
e.type = type;
- ret = notifier_with_return_list_notify(&migration_state_notifiers[mode],
- &e, errp);
- assert(!ret || type == MIG_EVENT_PRECOPY_SETUP);
- return ret;
+
+ for (elem = migration_state_notifiers[mode]; elem; elem = next) {
+ next = elem->next;
+ notifier = (NotifierWithReturn *)elem->data;
+ ret = notifier->notify(notifier, &e, errp);
+ if (ret) {
+ assert(type == MIG_EVENT_PRECOPY_SETUP);
+ return ret;
+ }
+ }
+
+ return 0;
}
bool migration_has_failed(MigrationState *s)
--
1.8.3.1
On 9/22/25 15:49, Steve Sistare wrote: > Allow a notifier to be added for multiple migration modes. > To allow a notifier to appear on multiple per-node lists, use > a generic list type. We can no longer use NotifierWithReturnList, > because it shoe horns the notifier onto a single list. > > Signed-off-by: Steve Sistare <steven.sistare@oracle.com> > Reviewed-by: Fabiano Rosas <farosas@suse.de> > --- > include/migration/misc.h | 12 ++++++++++ > migration/migration.c | 60 +++++++++++++++++++++++++++++++++++++----------- > 2 files changed, 59 insertions(+), 13 deletions(-) > > diff --git a/include/migration/misc.h b/include/migration/misc.h > index a261f99..592b930 100644 > --- a/include/migration/misc.h > +++ b/include/migration/misc.h > @@ -95,7 +95,19 @@ void migration_add_notifier(NotifierWithReturn *notify, > void migration_add_notifier_mode(NotifierWithReturn *notify, > MigrationNotifyFunc func, MigMode mode); > > +/* > + * Same as migration_add_notifier, but applies to all @mode in the argument > + * list. The list is terminated by -1 or MIG_MODE_ALL. For the latter, > + * the notifier is added for all modes. > + */ > +void migration_add_notifier_modes(NotifierWithReturn *notify, > + MigrationNotifyFunc func, MigMode mode, ...); > + > +/* > + * Remove a notifier from all modes. > + */ > void migration_remove_notifier(NotifierWithReturn *notify); > + > void migration_file_set_error(int ret, Error *err); I think the include/migration/misc.h file should be updated with proper documentation, like found in include/migration/blocker.h. > > /* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */ > diff --git a/migration/migration.c b/migration/migration.c > index 10c216d..08a98f7 100644 > --- a/migration/migration.c > +++ b/migration/migration.c > @@ -74,11 +74,7 @@ > > #define INMIGRATE_DEFAULT_EXIT_ON_ERROR true > > -static NotifierWithReturnList migration_state_notifiers[] = { > - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_NORMAL), > - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_REBOOT), > - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_TRANSFER), > -}; > +static GSList *migration_state_notifiers[MIG_MODE__MAX]; > > /* Messages sent on the return path from destination to source */ > enum mig_rp_message_type { > @@ -1665,23 +1661,51 @@ void migration_cancel(void) > } > } > > +static int get_modes(MigMode mode, va_list ap); > + > +static void add_notifiers(NotifierWithReturn *notify, int modes) > +{ > + for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) { > + if (modes & BIT(mode)) { > + migration_state_notifiers[mode] = > + g_slist_prepend(migration_state_notifiers[mode], notify); > + } > + } > +} > + > +void migration_add_notifier_modes(NotifierWithReturn *notify, > + MigrationNotifyFunc func, MigMode mode, ...) > +{ > + int modes; > + va_list ap; > + > + va_start(ap, mode); > + modes = get_modes(mode, ap); > + va_end(ap); No sanity check needed ? Could we have conflicting modes ? Just asking. Thanks, C. > + notify->notify = (NotifierWithReturnFunc)func; > + add_notifiers(notify, modes); > +} > + > void migration_add_notifier_mode(NotifierWithReturn *notify, > MigrationNotifyFunc func, MigMode mode) > { > - notify->notify = (NotifierWithReturnFunc)func; > - notifier_with_return_list_add(&migration_state_notifiers[mode], notify); > + migration_add_notifier_modes(notify, func, mode, -1); > } > > void migration_add_notifier(NotifierWithReturn *notify, > MigrationNotifyFunc func) > { > - migration_add_notifier_mode(notify, func, MIG_MODE_NORMAL); > + migration_add_notifier_modes(notify, func, MIG_MODE_NORMAL, -1); > } > > void migration_remove_notifier(NotifierWithReturn *notify) > { > if (notify->notify) { > - notifier_with_return_remove(notify); > + for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) { > + migration_blockers[mode] = > + g_slist_remove(migration_state_notifiers[mode], notify); > + } > notify->notify = NULL; > } > } > @@ -1691,13 +1715,23 @@ int migration_call_notifiers(MigrationState *s, MigrationEventType type, > { > MigMode mode = s->parameters.mode; > MigrationEvent e; > + NotifierWithReturn *notifier; > + GSList *elem, *next; > int ret; > > e.type = type; > - ret = notifier_with_return_list_notify(&migration_state_notifiers[mode], > - &e, errp); > - assert(!ret || type == MIG_EVENT_PRECOPY_SETUP); > - return ret; > + > + for (elem = migration_state_notifiers[mode]; elem; elem = next) { > + next = elem->next; > + notifier = (NotifierWithReturn *)elem->data; > + ret = notifier->notify(notifier, &e, errp); > + if (ret) { > + assert(type == MIG_EVENT_PRECOPY_SETUP); > + return ret; > + } > + } > + > + return 0; > } > > bool migration_has_failed(MigrationState *s)
On 9/22/2025 11:18 AM, Cédric Le Goater wrote: > On 9/22/25 15:49, Steve Sistare wrote: >> Allow a notifier to be added for multiple migration modes. >> To allow a notifier to appear on multiple per-node lists, use >> a generic list type. We can no longer use NotifierWithReturnList, >> because it shoe horns the notifier onto a single list. >> >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com> >> Reviewed-by: Fabiano Rosas <farosas@suse.de> >> --- >> include/migration/misc.h | 12 ++++++++++ >> migration/migration.c | 60 +++++++++++++++++++++++++++++++++++++----------- >> 2 files changed, 59 insertions(+), 13 deletions(-) >> >> diff --git a/include/migration/misc.h b/include/migration/misc.h >> index a261f99..592b930 100644 >> --- a/include/migration/misc.h >> +++ b/include/migration/misc.h >> @@ -95,7 +95,19 @@ void migration_add_notifier(NotifierWithReturn *notify, >> void migration_add_notifier_mode(NotifierWithReturn *notify, >> MigrationNotifyFunc func, MigMode mode); >> +/* >> + * Same as migration_add_notifier, but applies to all @mode in the argument >> + * list. The list is terminated by -1 or MIG_MODE_ALL. For the latter, >> + * the notifier is added for all modes. >> + */ >> +void migration_add_notifier_modes(NotifierWithReturn *notify, >> + MigrationNotifyFunc func, MigMode mode, ...); >> + >> +/* >> + * Remove a notifier from all modes. >> + */ >> void migration_remove_notifier(NotifierWithReturn *notify); >> + >> void migration_file_set_error(int ret, Error *err); > > I think the include/migration/misc.h file should be updated with > proper documentation, like found in include/migration/blocker.h. > >> /* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */ >> diff --git a/migration/migration.c b/migration/migration.c >> index 10c216d..08a98f7 100644 >> --- a/migration/migration.c >> +++ b/migration/migration.c >> @@ -74,11 +74,7 @@ >> #define INMIGRATE_DEFAULT_EXIT_ON_ERROR true >> -static NotifierWithReturnList migration_state_notifiers[] = { >> - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_NORMAL), >> - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_REBOOT), >> - NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_TRANSFER), >> -}; >> +static GSList *migration_state_notifiers[MIG_MODE__MAX]; >> /* Messages sent on the return path from destination to source */ >> enum mig_rp_message_type { >> @@ -1665,23 +1661,51 @@ void migration_cancel(void) >> } >> } >> +static int get_modes(MigMode mode, va_list ap); >> + >> +static void add_notifiers(NotifierWithReturn *notify, int modes) >> +{ >> + for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) { >> + if (modes & BIT(mode)) { >> + migration_state_notifiers[mode] = >> + g_slist_prepend(migration_state_notifiers[mode], notify); >> + } >> + } >> +} >> + >> +void migration_add_notifier_modes(NotifierWithReturn *notify, >> + MigrationNotifyFunc func, MigMode mode, ...) >> +{ >> + int modes; >> + va_list ap; >> + >> + va_start(ap, mode); >> + modes = get_modes(mode, ap); >> + va_end(ap); > > No sanity check needed ? Could we have conflicting modes ? Just asking. No conflicts. A notifier can apply to one or more nodes. Only the caller knows what is necessary. - Steve >> + notify->notify = (NotifierWithReturnFunc)func; >> + add_notifiers(notify, modes); >> +} >> + >> void migration_add_notifier_mode(NotifierWithReturn *notify, >> MigrationNotifyFunc func, MigMode mode) >> { >> - notify->notify = (NotifierWithReturnFunc)func; >> - notifier_with_return_list_add(&migration_state_notifiers[mode], notify); >> + migration_add_notifier_modes(notify, func, mode, -1); >> } >> void migration_add_notifier(NotifierWithReturn *notify, >> MigrationNotifyFunc func) >> { >> - migration_add_notifier_mode(notify, func, MIG_MODE_NORMAL); >> + migration_add_notifier_modes(notify, func, MIG_MODE_NORMAL, -1); >> } >> void migration_remove_notifier(NotifierWithReturn *notify) >> { >> if (notify->notify) { >> - notifier_with_return_remove(notify); >> + for (MigMode mode = 0; mode < MIG_MODE__MAX; mode++) { >> + migration_blockers[mode] = >> + g_slist_remove(migration_state_notifiers[mode], notify); >> + } >> notify->notify = NULL; >> } >> } >> @@ -1691,13 +1715,23 @@ int migration_call_notifiers(MigrationState *s, MigrationEventType type, >> { >> MigMode mode = s->parameters.mode; >> MigrationEvent e; >> + NotifierWithReturn *notifier; >> + GSList *elem, *next; >> int ret; >> e.type = type; >> - ret = notifier_with_return_list_notify(&migration_state_notifiers[mode], >> - &e, errp); >> - assert(!ret || type == MIG_EVENT_PRECOPY_SETUP); >> - return ret; >> + >> + for (elem = migration_state_notifiers[mode]; elem; elem = next) { >> + next = elem->next; >> + notifier = (NotifierWithReturn *)elem->data; >> + ret = notifier->notify(notifier, &e, errp); >> + if (ret) { >> + assert(type == MIG_EVENT_PRECOPY_SETUP); >> + return ret; >> + } >> + } >> + >> + return 0; >> } >> bool migration_has_failed(MigrationState *s) >
© 2016 - 2025 Red Hat, Inc.