From bdd847a026974634d636e65c4e00cd890cb6099d Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 12 Mar 2018 14:17:14 +0000 Subject: [PATCH 1/5] migration: convert socket server to QIONetListener Instead of creating a QIOChannelSocket directly for the migration server socket, use a QIONetListener. This provides the ability to listen on multiple sockets at the same time, so enables full support for IPv4/IPv6 dual stack. For example, '$QEMU -incoming tcp::9000' now correctly listens on both 0.0.0.0 and :: at the same time, instead of only on 0.0.0.0. Signed-off-by: Daniel P. Berrange Message-Id: <20180312141714.7223-1-berrange@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- migration/socket.c | 48 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/migration/socket.c b/migration/socket.c index 8a93fb1af5..122d8ccfbe 100644 --- a/migration/socket.c +++ b/migration/socket.c @@ -24,6 +24,7 @@ #include "migration.h" #include "qemu-file.h" #include "io/channel-socket.h" +#include "io/net-listener.h" #include "trace.h" @@ -129,34 +130,20 @@ void unix_start_outgoing_migration(MigrationState *s, } -static gboolean socket_accept_incoming_migration(QIOChannel *ioc, - GIOCondition condition, - gpointer opaque) +static void socket_accept_incoming_migration(QIONetListener *listener, + QIOChannelSocket *cioc, + gpointer opaque) { - QIOChannelSocket *sioc; - Error *err = NULL; - - sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), - &err); - if (!sioc) { - error_report("could not accept migration connection (%s)", - error_get_pretty(err)); - goto out; - } - trace_migration_socket_incoming_accepted(); - qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-incoming"); - migration_channel_process_incoming(QIO_CHANNEL(sioc)); - object_unref(OBJECT(sioc)); + qio_channel_set_name(QIO_CHANNEL(cioc), "migration-socket-incoming"); + migration_channel_process_incoming(QIO_CHANNEL(cioc)); -out: if (migration_has_all_channels()) { /* Close listening socket as its no longer needed */ - qio_channel_close(ioc, NULL); - return G_SOURCE_REMOVE; - } else { - return G_SOURCE_CONTINUE; + qio_net_listener_disconnect(listener); + + object_unref(OBJECT(listener)); } } @@ -164,21 +151,18 @@ out: static void socket_start_incoming_migration(SocketAddress *saddr, Error **errp) { - QIOChannelSocket *listen_ioc = qio_channel_socket_new(); + QIONetListener *listener = qio_net_listener_new(); - qio_channel_set_name(QIO_CHANNEL(listen_ioc), - "migration-socket-listener"); + qio_net_listener_set_name(listener, "migration-socket-listener"); - if (qio_channel_socket_listen_sync(listen_ioc, saddr, errp) < 0) { - object_unref(OBJECT(listen_ioc)); + if (qio_net_listener_open_sync(listener, saddr, errp) < 0) { + object_unref(OBJECT(listener)); return; } - qio_channel_add_watch(QIO_CHANNEL(listen_ioc), - G_IO_IN, - socket_accept_incoming_migration, - listen_ioc, - (GDestroyNotify)object_unref); + qio_net_listener_set_client_func(listener, + socket_accept_incoming_migration, + NULL, NULL); } void tcp_start_incoming_migration(const char *host_port, Error **errp) From e8a0f2f9a18f6ab4aa4896cef0010bcad1f323c4 Mon Sep 17 00:00:00 2001 From: Lidong Chen Date: Sat, 10 Mar 2018 22:32:58 +0800 Subject: [PATCH 2/5] migration: Fix rate limiting issue on RDMA migration RDMA migration implement save_page function for QEMUFile, but ram_control_save_page do not increase bytes_xfer. So when doing RDMA migration, it will use whole bandwidth. Signed-off-by: Lidong Chen Message-Id: <1520692378-1835-1-git-send-email-lidongchen@tencent.com> Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/qemu-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index e85f501f86..bb63c779cc 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -253,7 +253,7 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, if (f->hooks && f->hooks->save_page) { int ret = f->hooks->save_page(f, f->opaque, block_offset, offset, size, bytes_sent); - + f->bytes_xfer += size; if (ret != RAM_SAVE_CONTROL_DELAYED) { if (bytes_sent && *bytes_sent > 0) { qemu_update_position(f, *bytes_sent); From 44815334e10365ae5c60914c1d9fcecfe5ed5982 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 8 Mar 2018 12:18:27 +0100 Subject: [PATCH 3/5] migration/block: limit the number of parallel I/O requests the current implementation submits up to 512 I/O requests in parallel which is much to high especially for a background task. This patch adds a maximum limit of 16 I/O requests that can be submitted in parallel to avoid monopolizing the I/O device. Signed-off-by: Peter Lieven Message-Id: <1520507908-16743-5-git-send-email-pl@kamp.de> Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/block.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/migration/block.c b/migration/block.c index 5c03632257..03bbba61cb 100644 --- a/migration/block.c +++ b/migration/block.c @@ -37,6 +37,7 @@ #define MAX_IS_ALLOCATED_SEARCH (65536 * BDRV_SECTOR_SIZE) #define MAX_IO_BUFFERS 512 +#define MAX_PARALLEL_IO 16 //#define DEBUG_BLK_MIGRATION @@ -775,6 +776,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) while ((block_mig_state.submitted + block_mig_state.read_done) * BLOCK_SIZE < qemu_file_get_rate_limit(f) && + block_mig_state.submitted < MAX_PARALLEL_IO && (block_mig_state.submitted + block_mig_state.read_done) < MAX_IO_BUFFERS) { blk_mig_unlock(); From b47d1e9fe09834d0640aedc002384b0600739075 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 8 Mar 2018 12:18:28 +0100 Subject: [PATCH 4/5] migration/block: compare only read blocks against the rate limiter only read_done blocks are in the queued to be flushed to the migration stream. submitted blocks are still in flight. Signed-off-by: Peter Lieven Message-Id: <1520507908-16743-6-git-send-email-pl@kamp.de> Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/block.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/block.c b/migration/block.c index 03bbba61cb..4c04d937b1 100644 --- a/migration/block.c +++ b/migration/block.c @@ -773,8 +773,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) /* control the rate of transfer */ blk_mig_lock(); - while ((block_mig_state.submitted + - block_mig_state.read_done) * BLOCK_SIZE < + while (block_mig_state.read_done * BLOCK_SIZE < qemu_file_get_rate_limit(f) && block_mig_state.submitted < MAX_PARALLEL_IO && (block_mig_state.submitted + block_mig_state.read_done) < From 09576e74dbe697c5f0a7bc2ad7b59601457a2ff4 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Fri, 16 Mar 2018 20:21:14 +0000 Subject: [PATCH 5/5] migration: Fix block migration flag case Fix the case where when a migration with a bad protocol is tried, we leave the block migration capability set. (This is a cut down version of my 'migration: Fix block failure cases' where it's other case was fixed by Peter's dd0ee30caeebbd ) Signed-off-by: Dr. David Alan Gilbert Message-Id: <20180316202114.32345-1-dgilbert@redhat.com> Reviewed-by: Peter Xu Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 1 + 1 file changed, 1 insertion(+) diff --git a/migration/migration.c b/migration/migration.c index fc629e5965..52a5092add 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1428,6 +1428,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, "a valid migration protocol"); migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); + block_cleanup_parameters(s); return; }