QEMU incoming side may have set a wrong listen() backlog. After the support of multifd + postcopy now we have four possibilities on setting the backlog, some of them are wrong:
Vanilla: 1 (correct) Multifd: N (wrong, should be N+1) Preempt: 2 (correct) Multifd+Preempt: N (wrong, should be N+2) No real report for this, found by code observation only. Logically the backlog (pending accept requests on destination on the listening sockets) needs to be the maximum of possible channels. Otherwise if the accept queue full on destination, source QEMU may hit connection errors. Cc: Daniel P. Berrangé <[email protected]> Fixes: 0705e56496 ("multifd: Use number of channels as listen backlog") Fixes: e274188612 ("migration: enable multifd and postcopy together") Signed-off-by: Peter Xu <[email protected]> --- migration/socket.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/migration/socket.c b/migration/socket.c index f57f1a8e7c..31bfa1eeeb 100644 --- a/migration/socket.c +++ b/migration/socket.c @@ -139,21 +139,32 @@ socket_incoming_migration_end(void *opaque) object_unref(OBJECT(listener)); } +static int socket_get_max_channels(void) +{ + /* The main channel is always wanted */ + int num = 1; + + if (migrate_multifd()) { + num += migrate_multifd_channels(); + } + + if (migrate_postcopy_preempt()) { + /* The preempt channel */ + num += 1; + } + + return num; +} + void socket_connect_incoming(SocketAddress *saddr, Error **errp) { QIONetListener *listener = qio_net_listener_new(); MigrationIncomingState *mis = migration_incoming_get_current(); size_t i; - int num = 1; + int num = socket_get_max_channels(); qio_net_listener_set_name(listener, "migration-socket-listener"); - if (migrate_multifd()) { - num = migrate_multifd_channels(); - } else if (migrate_postcopy_preempt()) { - num = RAM_CHANNEL_MAX; - } - if (qio_net_listener_open_sync(listener, saddr, num, errp) < 0) { object_unref(OBJECT(listener)); return; -- 2.55.0
