Prasad Pandit <[email protected]> writes:

> On Fri, 9 Jan 2026 at 18:14, Fabiano Rosas <[email protected]> wrote:
>> Encapsulate the MigrationChannelList parsing in a new
>> migrate_channels_parse() located at channel.c.
>>
>> This also makes the memory management of the MigrationAddress more
>> uniform. Previously, half the parsing code (uri parsing) would
>> allocate memory for the address while the other half (channel parsing)
>> would instead pass the original QAPI object along. After this patch,
>> the MigrationAddress is always QAPI_CLONEd, so the callers can use
>> g_autoptr(MigrationAddress) in all cases.
>>
>> Reviewed-by: Peter Xu <[email protected]>
>> Signed-off-by: Fabiano Rosas <[email protected]>
>> ---
>>  migration/channel.c   | 45 ++++++++++++++++++++++++++++++++++++++
>>  migration/channel.h   |  5 +++++
>>  migration/migration.c | 50 ++++++++++++-------------------------------
>>  3 files changed, 64 insertions(+), 36 deletions(-)
>>
>> diff --git a/migration/channel.c b/migration/channel.c
>> index 56c80b5cdf..8b71b3f430 100644
>> --- a/migration/channel.c
>> +++ b/migration/channel.c
>> @@ -11,6 +11,7 @@
>>   */
>>
>>  #include "qemu/osdep.h"
>> +#include "qemu/cutils.h"
>>  #include "channel.h"
>>  #include "exec.h"
>>  #include "fd.h"
>> @@ -20,7 +21,9 @@
>>  #include "migration.h"
>>  #include "multifd.h"
>>  #include "options.h"
>> +#include "qapi/clone-visitor.h"
>>  #include "qapi/qapi-types-migration.h"
>> +#include "qapi/qapi-visit-migration.h"
>>  #include "qapi/error.h"
>>  #include "qemu-file.h"
>>  #include "qemu/yank.h"
>> @@ -280,3 +283,45 @@ int migration_channel_read_peek(QIOChannel *ioc,
>>
>>      return 0;
>>  }
>> +
>> +bool migrate_channels_parse(MigrationChannelList *channels,
>> +                            MigrationChannel **main_channelp,
>> +                            MigrationChannel **cpr_channelp,
>> +                            Error **errp)
>> +{
>> +    MigrationChannel *channelv[MIGRATION_CHANNEL_TYPE__MAX] = { NULL };
>> +    bool single_channel = cpr_channelp ? false : true;
>> +
>> +    if (single_channel && channels->next) {
>> +        error_setg(errp, "Channel list must have only one entry, "
>> +                   "for type 'main'");
>> +        return false;
>> +    }
>
> * Instead of the single_channel variable above, we could say
> (!cpr_channelp && channels->next)? and avoid the single_channel
> variable.
>

ok

>> +    for ( ; channels; channels = channels->next) {
>> +        MigrationChannelType type;
>> +
>> +        type = channels->value->channel_type;
>> +        if (channelv[type]) {
>> +            error_setg(errp, "Channel list has more than one %s entry",
>> +                       MigrationChannelType_str(type));
>> +            return false;
>> +        }
>> +        channelv[type] = channels->value;
>> +    }
>> +
>> +    if (cpr_channelp) {
>> +        *cpr_channelp = QAPI_CLONE(MigrationChannel,
>> +                                   channelv[MIGRATION_CHANNEL_TYPE_CPR]);
>> +    }
>> +
>> +    *main_channelp = QAPI_CLONE(MigrationChannel,
>> +                                channelv[MIGRATION_CHANNEL_TYPE_MAIN]);
>> +
>> +    if (!(*main_channelp)->addr) {
>> +        error_setg(errp, "Channel list has no main entry");
>> +        return false;
>> +    }
>> +
>> +    return true;
>> +}
>> diff --git a/migration/channel.h b/migration/channel.h
>> index 8264fe327d..5110fb45a4 100644
>> --- a/migration/channel.h
>> +++ b/migration/channel.h
>> @@ -42,4 +42,9 @@ bool migration_has_all_channels(void);
>>  void migration_connect_outgoing(MigrationState *s, MigrationAddress *addr,
>>                                  Error **errp);
>>  void migration_connect_incoming(MigrationAddress *addr, Error **errp);
>> +
>> +bool migrate_channels_parse(MigrationChannelList *channels,
>> +                            MigrationChannel **main_channelp,
>> +                            MigrationChannel **cpr_channelp,
>> +                            Error **errp);
>>  #endif
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 3c93fb23cc..98c1f38e8e 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -741,8 +741,7 @@ static void qemu_setup_incoming_migration(const char 
>> *uri, bool has_channels,
>>                                            MigrationChannelList *channels,
>>                                            Error **errp)
>>  {
>> -    g_autoptr(MigrationChannel) channel = NULL;
>> -    MigrationAddress *addr = NULL;
>> +    g_autoptr(MigrationChannel) main_ch = NULL;
>>      MigrationIncomingState *mis = migration_incoming_get_current();
>>
>>      /*
>> @@ -754,25 +753,20 @@ static void qemu_setup_incoming_migration(const char 
>> *uri, bool has_channels,
>>      }
>>
>>      if (channels) {
>> -        /* To verify that Migrate channel list has only item */
>> -        if (channels->next) {
>> -            error_setg(errp, "Channel list must have only one entry, "
>> -                             "for type 'main'");
>> +        if (!migrate_channels_parse(channels, &main_ch, NULL, errp)) {
>>              return;
>>          }
>> -        addr = channels->value->addr;
>>      }
>>
>>      if (uri) {
>>          /* caller uses the old URI syntax */
>> -        if (!migrate_uri_parse(uri, &channel, errp)) {
>> +        if (!migrate_uri_parse(uri, &main_ch, errp)) {
>>              return;
>>          }
>> -        addr = channel->addr;
>>      }
>>
>>      /* transport mechanism not suitable for migration? */
>> -    if (!migration_transport_compatible(addr, errp)) {
>> +    if (!migration_transport_compatible(main_ch->addr, errp)) {
>>          return;
>>      }
>>
>> @@ -780,7 +774,7 @@ static void qemu_setup_incoming_migration(const char 
>> *uri, bool has_channels,
>>          return;
>>      }
>>
>> -    migration_connect_incoming(addr, errp);
>> +    migration_connect_incoming(main_ch->addr, errp);
>>
>>      /* Close cpr socket to tell source that we are listening */
>>      cpr_state_close();
>> @@ -2116,10 +2110,8 @@ void qmp_migrate(const char *uri, bool has_channels,
>>                   bool has_resume, bool resume, Error **errp)
>>  {
>>      MigrationState *s = migrate_get_current();
>> -    g_autoptr(MigrationChannel) channel = NULL;
>> -    MigrationAddress *addr = NULL;
>> -    MigrationChannel *channelv[MIGRATION_CHANNEL_TYPE__MAX] = { NULL };
>> -    MigrationChannel *cpr_channel = NULL;
>> +    g_autoptr(MigrationChannel) main_ch = NULL;
>> +    g_autoptr(MigrationChannel) cpr_ch = NULL;
>>
>>      /*
>>       * Having preliminary checks for uri and channel
>> @@ -2130,38 +2122,24 @@ void qmp_migrate(const char *uri, bool has_channels,
>>      }
>>
>>      if (channels) {
>> -        for ( ; channels; channels = channels->next) {
>> -            MigrationChannelType type = channels->value->channel_type;
>> -
>> -            if (channelv[type]) {
>> -                error_setg(errp, "Channel list has more than one %s entry",
>> -                           MigrationChannelType_str(type));
>> -                return;
>> -            }
>> -            channelv[type] = channels->value;
>> -        }
>> -        cpr_channel = channelv[MIGRATION_CHANNEL_TYPE_CPR];
>> -        addr = channelv[MIGRATION_CHANNEL_TYPE_MAIN]->addr;
>> -        if (!addr) {
>> -            error_setg(errp, "Channel list has no main entry");
>> +        if (!migrate_channels_parse(channels, &main_ch, &cpr_ch, errp)) {
>>              return;
>>          }
>>      }
>>
>>      if (uri) {
>>          /* caller uses the old URI syntax */
>> -        if (!migrate_uri_parse(uri, &channel, errp)) {
>> +        if (!migrate_uri_parse(uri, &main_ch, errp)) {
>>              return;
>>          }
>> -        addr = channel->addr;
>>      }
>>
>>      /* transport mechanism not suitable for migration? */
>> -    if (!migration_transport_compatible(addr, errp)) {
>> +    if (!migration_transport_compatible(main_ch->addr, errp)) {
>>          return;
>>      }
>>
>> -    if (migrate_mode() == MIG_MODE_CPR_TRANSFER && !cpr_channel) {
>> +    if (migrate_mode() == MIG_MODE_CPR_TRANSFER && !cpr_ch) {
>>          error_setg(errp, "missing 'cpr' migration channel");
>>          return;
>>      }
>
> * This check for (_CPR_TRANSFER && !cpr_ch) and error could be moved
> to migrate_channels_parse() as is done for the main_ch.
>

Hm, it would then apply to the incoming side as well which can't set the
mode due to how cpr-transfer works. But I guess it's fine as the
invocation of migration_channel_parse_input is already different between
src and dst. I'll change it. Thanks

>> @@ -2178,7 +2156,7 @@ void qmp_migrate(const char *uri, bool has_channels,
>>       */
>>      Error *local_err = NULL;
>>
>> -    if (!cpr_state_save(cpr_channel, &local_err)) {
>> +    if (!cpr_state_save(cpr_ch, &local_err)) {
>>          goto out;
>>      }
>>
>> @@ -2194,10 +2172,10 @@ void qmp_migrate(const char *uri, bool has_channels,
>>       */
>>      if (migrate_mode() == MIG_MODE_CPR_TRANSFER) {
>>          migrate_hup_add(s, cpr_state_ioc(), 
>> (GSourceFunc)qmp_migrate_finish_cb,
>> -                        QAPI_CLONE(MigrationAddress, addr));
>> +                        QAPI_CLONE(MigrationAddress, main_ch->addr));
>>
>>      } else {
>> -        qmp_migrate_finish(addr, errp);
>> +        qmp_migrate_finish(main_ch->addr, errp);
>>      }
>>
>>  out:
>> --
>
> * Otherwise it looks okay.
> Reviewed-by: Prasad Pandit <[email protected]>
>
> Thank you.
> ---
>   - Prasad

Reply via email to