migration: allow multifd for socket protocol only

To: <quintela@redhat.com>, <dgilbert@redhat.com>, <qemu-devel@nongnu.org>
CC: Li Zhijian <lizhijian@cn.fujitsu.com>
Date: Sat, 31 Jul 2021 22:05:51 +0800 (5 weeks, 4 days, 17 hours ago)

multifd with unsupported protocol will cause a segment fault.
(gdb) bt
 #0  0x0000563b4a93faf8 in socket_connect (addr=0x0, errp=0x7f7f02675410) at ../util/qemu-sockets.c:1190
 #1 0x0000563b4a797a03 in qio_channel_socket_connect_sync
(ioc=0x563b4d16e8c0, addr=0x0, errp=0x7f7f02675410) at
../io/channel-socket.c:145
 #2  0x0000563b4a797abf in qio_channel_socket_connect_worker (task=0x563b4cd86c30, opaque=0x0) at ../io/channel-socket.c:168
 #3  0x0000563b4a792631 in qio_task_thread_worker (opaque=0x563b4cd86c30) at ../io/task.c:124
 #4  0x0000563b4a91da69 in qemu_thread_start (args=0x563b4c44bb80) at ../util/qemu-thread-posix.c:541
 #5  0x00007f7fe9b5b3f9 in ?? ()
 #6  0x0000000000000000 in ?? ()

It's enough to check migrate_multifd_is_allowed() in multifd cleanup() and
multifd setup() though there are so many other places using migrate_use_multifd().

Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
Li Zhijian 2021-09-09 09:29:50 +02:00 committed by Juan Quintela
parent 1230a25f6f
commit b7acd65707
3 changed files with 28 additions and 2 deletions

View File

@ -453,10 +453,12 @@ static void qemu_start_incoming_migration(const char *uri, Error **errp)
{
const char *p = NULL;
migrate_protocol_allow_multifd(false); /* reset it anyway */
qapi_event_send_migration(MIGRATION_STATUS_SETUP);
if (strstart(uri, "tcp:", &p) ||
strstart(uri, "unix:", NULL) ||
strstart(uri, "vsock:", NULL)) {
migrate_protocol_allow_multifd(true);
socket_start_incoming_migration(p ? p : uri, errp);
#ifdef CONFIG_RDMA
} else if (strstart(uri, "rdma:", &p)) {
@ -2280,9 +2282,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
}
}
migrate_protocol_allow_multifd(false);
if (strstart(uri, "tcp:", &p) ||
strstart(uri, "unix:", NULL) ||
strstart(uri, "vsock:", NULL)) {
migrate_protocol_allow_multifd(true);
socket_start_outgoing_migration(s, p ? p : uri, &local_err);
#ifdef CONFIG_RDMA
} else if (strstart(uri, "rdma:", &p)) {

View File

@ -531,7 +531,7 @@ void multifd_save_cleanup(void)
{
int i;
if (!migrate_use_multifd()) {
if (!migrate_use_multifd() || !migrate_multifd_is_allowed()) {
return;
}
multifd_send_terminate_threads(NULL);
@ -868,6 +868,17 @@ cleanup:
multifd_new_send_channel_cleanup(p, sioc, local_err);
}
static bool migrate_allow_multifd;
void migrate_protocol_allow_multifd(bool allow)
{
migrate_allow_multifd = allow;
}
bool migrate_multifd_is_allowed(void)
{
return migrate_allow_multifd;
}
int multifd_save_setup(Error **errp)
{
int thread_count;
@ -878,6 +889,11 @@ int multifd_save_setup(Error **errp)
if (!migrate_use_multifd()) {
return 0;
}
if (!migrate_multifd_is_allowed()) {
error_setg(errp, "multifd is not supported by current protocol");
return -1;
}
s = migrate_get_current();
thread_count = migrate_multifd_channels();
multifd_send_state = g_malloc0(sizeof(*multifd_send_state));
@ -971,7 +987,7 @@ int multifd_load_cleanup(Error **errp)
{
int i;
if (!migrate_use_multifd()) {
if (!migrate_use_multifd() || !migrate_multifd_is_allowed()) {
return 0;
}
multifd_recv_terminate_threads(NULL);
@ -1120,6 +1136,10 @@ int multifd_load_setup(Error **errp)
if (!migrate_use_multifd()) {
return 0;
}
if (!migrate_multifd_is_allowed()) {
error_setg(errp, "multifd is not supported by current protocol");
return -1;
}
thread_count = migrate_multifd_channels();
multifd_recv_state = g_malloc0(sizeof(*multifd_recv_state));
multifd_recv_state->params = g_new0(MultiFDRecvParams, thread_count);

View File

@ -13,6 +13,8 @@
#ifndef QEMU_MIGRATION_MULTIFD_H
#define QEMU_MIGRATION_MULTIFD_H
bool migrate_multifd_is_allowed(void);
void migrate_protocol_allow_multifd(bool allow);
int multifd_save_setup(Error **errp);
void multifd_save_cleanup(void);
int multifd_load_setup(Error **errp);