On Mon, Dec 29, 2025 at 06:14:52PM -0300, Fabiano Rosas wrote:
> Peter Xu <[email protected]> writes:
> 
> > On Fri, Dec 26, 2025 at 06:19:24PM -0300, Fabiano Rosas wrote:
> >> Now that everything is in channel.c, it's easier to browse this code
> >> if it's all in the same place. It's also easier to grasp what the
> >> connection flow is if both sides of the connection are close together.
> >> 
> >> Signed-off-by: Fabiano Rosas <[email protected]>
> >> ---
> >>  migration/channel.c | 86 +++++++++++++++++++++++----------------------
> >>  migration/channel.h | 14 ++++++--
> >>  2 files changed, 56 insertions(+), 44 deletions(-)
> >> 
> >> diff --git a/migration/channel.c b/migration/channel.c
> >> index 042e01b224..ba9aa1c58b 100644
> >> --- a/migration/channel.c
> >> +++ b/migration/channel.c
> >> @@ -31,10 +31,11 @@
> >>  #include "trace.h"
> >>  #include "yank_functions.h"
> >>  
> >> -bool migration_connect_outgoing(MigrationAddress *addr, Error **errp)
> >> +bool migration_connect(MigrationAddress *addr, bool out, Error **errp)
> >>  {
> >>      g_autoptr(QIOChannel) ioc = NULL;
> >>      SocketAddress *saddr;
> >> +    ERRP_GUARD();
> >>  
> >>      switch (addr->transport) {
> >>      case MIGRATION_ADDRESS_TYPE_SOCKET:
> >> @@ -44,15 +45,24 @@ bool migration_connect_outgoing(MigrationAddress 
> >> *addr, Error **errp)
> >>          case SOCKET_ADDRESS_TYPE_INET:
> >>          case SOCKET_ADDRESS_TYPE_UNIX:
> >>          case SOCKET_ADDRESS_TYPE_VSOCK:
> >> -            socket_connect_outgoing(saddr, errp);
> >> -            /*
> >> -             * async: after the socket is connected, calls
> >> -             * migration_channel_connect_outgoing() directly.
> >> -             */
> >> -            return true;
> >> +            if (out) {
> >
> > Personally I wouldn't suggest we merge the outgoing / incoming with
> > migration_connect() then split paths once more in this exact function.
> >
> > I got this conclusion when I started to count how many "if (out)" are
> > there..  When there're too much, it may imply we need to think more..
> >
> 
> Well, compared to before, there 50% less "if (addr->transport == ...)",
> this is top level programming! =D

Yep, though that'll be the only part got deduplicated.

Reading migration_connect() will definitely break my flow of thoughts when
hitting so many "if (out)", and I'll be a bit puzzled on how the code runs.

I'm not sure if I'm the only one, though.

If we really want, we can introduce a MigrationAddressOps, providing one
ops for each type of MigrationAddress, differently on both sides:

/* Return true if success; when false errp will be set */
bool (*MigrationAddressOp)(MigrationAddress *addr, QIOChannel **channel, Error 
**errp)

Then define:

MigrationAddressOps[MIGRATION_ADDRESS_TYPE__MAX] addr_ops_outgoing = { ... };
MigrationAddressOps[MIGRATION_ADDRESS_TYPE__MAX] addr_ops_incoming = { ... };

And use them..  but it may also be an overkill when we only have incoming /
outgoing anyway..  So IMHO the existing code (after you refactored many of
the rest!) looks still pretty decent to me.

> 
> This part of the series is highly subjective, if there's a patch you
> don't like it we can drop it, let's not dwell on it.. Just read my words
> below on the previous patch, which I think you may be mistaken about.

Thanks, yes I was indeed mistaken and overlooked something. :)

> 
> > This also answers part of my confusion when reading the previous patch - if
> > that was only paving way for this one, IMHO it may not be as worthwhile,
> > and I would tend to avoid both.
> >
> 
> Patch 21 is just a cleanup after patch 19 moves the call to
> migration_channel_connect_outgoing from being inside the transport
> routines to this top level here at migration_connect(), which moves the
> places where MigrationState is used as well. So it removes unused
> passing of MigrationState along with the SocketConnectionData.

Now after I read it again, I agree with those removal of *s where they're
not used, like for:

  fd_connect_outgoing()
  exec_connect_outgoing()
  file_connect_outgoing()

I think socket_connect_outgoing() should also be fine, but maybe better to
have a pre-requisite patch removing SocketConnectData?

For most of the rest, IMHO we don't get much benefit from removing *s from
the parameters, especially inside qmp_migrate()..

So IMHO you were right in the commit log there, that we should justify
every use of migrate_get_current() to deserve fetching from a global, and
we should avoid using it in new code whenever possible.  IMHO we should
stick with that.

Imagine the old days we debug when *s can become null, and the more we
reference the global, the harder we fight those things (taking one refcount
from the very top caller would work for all the sub-callers OTOH, when we
justify one place thread-safe and justify all the rest).  More referencing
globals normally will just make things harder for us.  This rule applies to
all the globals.. not only *s.

> 
> > Thoughts?
> >
> >> +                socket_connect_outgoing(saddr, errp);
> >> +                /*
> >> +                 * async: after the socket is connected, calls
> >> +                 * migration_channel_connect_outgoing() directly.
> >> +                 */
> >> +                return true;
> >> +            } else {
> >> +                socket_connect_incoming(saddr, errp);
> >> +            }
> >> +
> >>              break;
> >>          case SOCKET_ADDRESS_TYPE_FD:
> >> -            ioc = fd_connect_outgoing(saddr->u.fd.str, errp);
> >> +            if (out) {
> >> +                ioc = fd_connect_outgoing(saddr->u.fd.str, errp);
> >> +            } else {
> >> +                fd_connect_incoming(saddr->u.fd.str, errp);
> >> +            }
> >>              break;
> >>          default:
> >>              g_assert_not_reached();
> >> @@ -62,16 +72,28 @@ bool migration_connect_outgoing(MigrationAddress 
> >> *addr, Error **errp)
> >>  
> >>  #ifdef CONFIG_RDMA
> >>      case MIGRATION_ADDRESS_TYPE_RDMA:
> >> -        ioc = rdma_connect_outgoing(&addr->u.rdma, errp);
> >> +        if (out) {
> >> +            ioc = rdma_connect_outgoing(&addr->u.rdma, errp);
> >> +        } else {
> >> +            rdma_connect_incoming(&addr->u.rdma, errp);
> >> +        }
> >>          break;
> >>  #endif
> >>  
> >>      case MIGRATION_ADDRESS_TYPE_EXEC:
> >> -        ioc = exec_connect_outgoing(addr->u.exec.args, errp);
> >> +        if (out) {
> >> +            ioc = exec_connect_outgoing(addr->u.exec.args, errp);
> >> +        } else {
> >> +            exec_connect_incoming(addr->u.exec.args, errp);
> >> +        }
> >>          break;
> >>  
> >>      case MIGRATION_ADDRESS_TYPE_FILE:
> >> -        ioc = file_connect_outgoing(&addr->u.file, errp);
> >> +        if (out) {
> >> +            ioc = file_connect_outgoing(&addr->u.file, errp);
> >> +        } else {
> >> +            file_connect_incoming(&addr->u.file, errp);
> >> +        }
> >>          break;
> >>  
> >>      default:
> >> @@ -79,42 +101,22 @@ bool migration_connect_outgoing(MigrationAddress 
> >> *addr, Error **errp)
> >>          break;
> >>      }
> >>  
> >> -    if (!ioc) {
> >> -        return false;
> >> -    }
> >> -
> >> -    migration_channel_connect_outgoing(ioc);
> >> -    return true;
> >> -}
> >> -
> >> -void migration_connect_incoming(MigrationAddress *addr, Error **errp)
> >> -{
> >> -    if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
> >> -        SocketAddress *saddr = &addr->u.socket;
> >> -        if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
> >> -            saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
> >> -            saddr->type == SOCKET_ADDRESS_TYPE_VSOCK) {
> >> -            socket_connect_incoming(saddr, errp);
> >> -        } else if (saddr->type == SOCKET_ADDRESS_TYPE_FD) {
> >> -            fd_connect_incoming(saddr->u.fd.str, errp);
> >> +    if (out) {
> >> +        if (!ioc) {
> >> +            return false;
> >>          }
> >> -#ifdef CONFIG_RDMA
> >> -    } else if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
> >> -        rdma_connect_incoming(&addr->u.rdma, errp);
> >> -#endif
> >> -    } else if (addr->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
> >> -        exec_connect_incoming(addr->u.exec.args, errp);
> >> -    } else if (addr->transport == MIGRATION_ADDRESS_TYPE_FILE) {
> >> -        file_connect_incoming(&addr->u.file, errp);
> >> -    } else {
> >> -        error_setg(errp, "unknown migration protocol");
> >> +
> >> +        migration_channel_connect_outgoing(ioc);
> >> +        return true;
> >>      }
> >>  
> >>      /*
> >> -     * async: the above routines all wait for the incoming connection
> >> -     * and call back to migration_channel_process_incoming() to start
> >> -     * the migration.
> >> +     * async: on the incoming side all of the transport routines above
> >> +     * wait for the incoming connection and call back to
> >> +     * migration_channel_process_incoming() to start the migration.
> >>       */
> >> +
> >> +    return !*errp;
> >>  }
> >>  
> >>  bool migration_has_main_and_multifd_channels(void)
> >> diff --git a/migration/channel.h b/migration/channel.h
> >> index 8cf16bfda9..86934fee38 100644
> >> --- a/migration/channel.h
> >> +++ b/migration/channel.h
> >> @@ -39,6 +39,16 @@ int migration_channel_read_peek(QIOChannel *ioc,
> >>  bool migration_has_main_and_multifd_channels(void);
> >>  bool migration_has_all_channels(void);
> >>  
> >> -bool migration_connect_outgoing(MigrationAddress *addr, Error **errp);
> >> -void migration_connect_incoming(MigrationAddress *addr, Error **errp);
> >> +bool migration_connect(MigrationAddress *addr, bool out, Error **errp);
> >> +static inline bool migration_connect_outgoing(MigrationAddress *addr,
> >> +                                              Error **errp)
> >> +{
> >> +    return migration_connect(addr, true, errp);
> >> +}
> >> +
> >> +static inline bool migration_connect_incoming(MigrationAddress *addr,
> >> +                                              Error **errp)
> >> +{
> >> +    return migration_connect(addr, false, errp);
> >> +}
> >>  #endif
> >> -- 
> >> 2.51.0
> >> 
> 

-- 
Peter Xu


Reply via email to