migration: check RDMA and capabilities are compatible on both sides

Depending on the order of starting RDMA and setting capability,
they can be categorized into the following scenarios:
Source:
 S1: [set capabilities] -> [Start RDMA outgoing]
Destination:
 D1: [set capabilities] -> [Start RDMA incoming]
 D2: [Start RDMA incoming] -> [set capabilities]

Previously, compatibility between RDMA and capabilities was verified only
in scenario D1, potentially causing migration failures in other situations.

For scenarios S1 and D1, we can seamlessly incorporate
migration_transport_compatible() to address compatibility between
channels and capabilities vs transport.

For scenario D2, ensure compatibility within migrate_caps_check().

Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
Message-ID: <20250305062825.772629-3-lizhijian@fujitsu.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
Li Zhijian 2025-03-05 14:28:21 +08:00 committed by Peter Xu
parent 5134cf9b5d
commit 57be554c29
3 changed files with 42 additions and 10 deletions

View file

@ -259,6 +259,24 @@ migration_channels_and_transport_compatible(MigrationAddress *addr,
return true;
}
static bool
migration_capabilities_and_transport_compatible(MigrationAddress *addr,
Error **errp)
{
if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
return migrate_rdma_caps_check(migrate_get_current()->capabilities,
errp);
}
return true;
}
static bool migration_transport_compatible(MigrationAddress *addr, Error **errp)
{
return migration_channels_and_transport_compatible(addr, errp) &&
migration_capabilities_and_transport_compatible(addr, errp);
}
static gint page_request_addr_cmp(gconstpointer ap, gconstpointer bp)
{
uintptr_t a = (uintptr_t) ap, b = (uintptr_t) bp;
@ -750,7 +768,7 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels,
}
/* transport mechanism not suitable for migration? */
if (!migration_channels_and_transport_compatible(addr, errp)) {
if (!migration_transport_compatible(addr, errp)) {
return;
}
@ -769,14 +787,6 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels,
}
#ifdef CONFIG_RDMA
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
if (migrate_xbzrle()) {
error_setg(errp, "RDMA and XBZRLE can't be used together");
return;
}
if (migrate_multifd()) {
error_setg(errp, "RDMA and multifd can't be used together");
return;
}
rdma_start_incoming_migration(&addr->u.rdma, errp);
#endif
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
@ -2208,7 +2218,7 @@ void qmp_migrate(const char *uri, bool has_channels,
}
/* transport mechanism not suitable for migration? */
if (!migration_channels_and_transport_compatible(addr, errp)) {
if (!migration_transport_compatible(addr, errp)) {
return;
}