From: "Daniel P. Berrange" <berrange@redhat.com>
To: Juan Quintela <quintela@redhat.com>
Cc: qemu-devel@nongnu.org, lvivier@redhat.com, dgilbert@redhat.com,
peterx@redhat.com
Subject: Re: [Qemu-devel] [PATCH v6 11/19] migration: Start of multiple fd work
Date: Fri, 11 Aug 2017 16:22:56 +0100 [thread overview]
Message-ID: <20170811152256.GS2554@redhat.com> (raw)
In-Reply-To: <20170808162629.32493-12-quintela@redhat.com>
On Tue, Aug 08, 2017 at 06:26:21PM +0200, Juan Quintela wrote:
> We create new channels for each new thread created. We send through
> them a string containing <uuid> multifd <channel number> so we are
> sure that we connect the right channels in both sides.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
>
> --
> Split SocketArgs into incoming and outgoing args
>
> Use UUID's on the initial message, so we are sure we are connecting to
> the right channel.
>
> Remove init semaphore. Now that we use uuids on the init message, we
> know that this is our channel.
>
> Fix recv socket destwroy, we were destroying send channels.
> This was very interesting, because we were using an unreferred object
> without problems.
>
> Move to struct of pointers
> init channel sooner.
> split recv thread creation.
> listen on main thread
> We count the number of created threads to know when we need to stop listening
> Use g_strdup_printf
> report channel id on errors
> ---
> migration/migration.c | 5 +++
> migration/ram.c | 99 +++++++++++++++++++++++++++++++++++++++++++--------
> migration/ram.h | 3 ++
> migration/socket.c | 36 ++++++++++++++++++-
> migration/socket.h | 10 ++++++
> 5 files changed, 138 insertions(+), 15 deletions(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index e36e880..944d6e2 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -413,6 +413,11 @@ void migration_ioc_process_incoming(QIOChannel *ioc)
> */
> bool migration_has_all_channels(void)
> {
> + if (migrate_use_multifd()) {
> + int thread_count = migrate_multifd_threads();
> +
> + return thread_count == multifd_created_threads();
> + }
> return true;
> }
>
> diff --git a/migration/ram.c b/migration/ram.c
> index 9fb3496..e9fa556 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -36,6 +36,7 @@
> #include "xbzrle.h"
> #include "ram.h"
> #include "migration.h"
> +#include "socket.h"
> #include "migration/register.h"
> #include "migration/misc.h"
> #include "qemu-file.h"
> @@ -46,6 +47,8 @@
> #include "exec/ram_addr.h"
> #include "qemu/rcu_queue.h"
> #include "migration/colo.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/uuid.h"
>
> /***********************************************************/
> /* ram save/restore */
> @@ -361,6 +364,7 @@ static void compress_threads_save_setup(void)
> struct MultiFDSendParams {
> uint8_t id;
> QemuThread thread;
> + QIOChannel *c;
> QemuSemaphore sem;
> QemuMutex mutex;
> bool quit;
> @@ -401,6 +405,7 @@ void multifd_save_cleanup(void)
> qemu_thread_join(&p->thread);
> qemu_mutex_destroy(&p->mutex);
> qemu_sem_destroy(&p->sem);
> + socket_send_channel_destroy(p->c);
> }
> g_free(multifd_send_state->params);
> multifd_send_state->params = NULL;
> @@ -408,9 +413,26 @@ void multifd_save_cleanup(void)
> multifd_send_state = NULL;
> }
>
> +/* Default uuid for multifd when qemu is not started with uuid */
> +static char multifd_uuid[] = "5c49fd7e-af88-4a07-b6e8-091fd696ad40";
Why is this better than just using the qemu_uuid unconditionally.
UUIC, it'll just be 00000000-0000-0000-0000-000000000000.
Either way you've got a non-unique UUID if multiple QEMUs are
started, so I dont see a benefit in inventing a new uuid here.
> +/* strlen(multifd) + '-' + <channel id> + '-' + UUID_FMT + '\0' */
> +#define MULTIFD_UUID_MSG (7 + 1 + 3 + 1 + UUID_FMT_LEN + 1)
> +
> static void *multifd_send_thread(void *opaque)
> {
> MultiFDSendParams *p = opaque;
> + char *string;
> + char *string_uuid;
> +
> + if (qemu_uuid_set) {
> + string_uuid = qemu_uuid_unparse_strdup(&qemu_uuid);
> + } else {
> + string_uuid = g_strdup(multifd_uuid);
> + }
> + string = g_strdup_printf("%s multifd %03d", string_uuid, p->id);
> + g_free(string_uuid);
> + qio_channel_write(p->c, string, MULTIFD_UUID_MSG, &error_abort);
Must check return code here as it can do a short write, which won't
trigger error_abort. Also you must not use error_abort at all. QEMU
must not abort when migration hits an I/O error as that needlessly
kills the user's VM.
I also think it is not nice to be formatting a string with printf
here, sending it and then using scanf to extract the data. If we
need to send structured data, then we should define a proper binary
format for it eg
struct MigrateUUIDMsg {
uint32_t chnanelid;
QemuUUID uuid;
} __attribute__((__packed__));
and then just send the raw struct across.
> + g_free(string);
>
> while (true) {
> qemu_mutex_lock(&p->mutex);
> @@ -445,6 +467,12 @@ int multifd_save_setup(void)
> qemu_sem_init(&p->sem, 0);
> p->quit = false;
> p->id = i;
> + p->c = socket_send_channel_create();
> + if (!p->c) {
> + error_report("Error creating a send channel");
> + multifd_save_cleanup();
> + return -1;
> + }
We should pass an 'Error *' object into socket_send_channel_create()
so that we can receive & report the actual error message, instead
of a useless generic message.
> @@ -522,10 +556,54 @@ static void *multifd_recv_thread(void *opaque)
> return NULL;
> }
>
> +void multifd_new_channel(QIOChannel *ioc)
> +{
> + MultiFDRecvParams *p = g_new0(MultiFDRecvParams, 1);
> + MigrationState *s = migrate_get_current();
> + char string[MULTIFD_UUID_MSG];
> + char string_uuid[UUID_FMT_LEN];
> + char *uuid;
> + int id;
> +
> + qio_channel_read(ioc, string, sizeof(string), &error_abort);
Must not use error_abort which kills the whole VM ungracefully
> + sscanf(string, "%s multifd %03d", string_uuid, &id);
> +
> + if (qemu_uuid_set) {
> + uuid = qemu_uuid_unparse_strdup(&qemu_uuid);
> + } else {
> + uuid = g_strdup(multifd_uuid);
> + }
> + if (strcmp(string_uuid, uuid)) {
> + error_report("multifd: received uuid '%s' and expected uuid '%s'"
> + " for channel %d", string_uuid, uuid, id);
> + migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE,
> + MIGRATION_STATUS_FAILED);
> + terminate_multifd_recv_threads();
> + return;
> + }
> + g_free(uuid);
As mentioned above, we should receive a binary struct here instead
of playing games with scanf.
> +
> + if (multifd_recv_state->params[id] != NULL) {
> + error_report("multifd: received id '%d' is already setup'", id);
> + migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE,
> + MIGRATION_STATUS_FAILED);
> + terminate_multifd_recv_threads();
> + return;
> + }
> + qemu_mutex_init(&p->mutex);
> + qemu_sem_init(&p->sem, 0);
> + p->quit = false;
> + p->id = id;
> + p->c = ioc;
> + atomic_set(&multifd_recv_state->params[id], p);
> + multifd_recv_state->count++;
> + qemu_thread_create(&p->thread, "multifd_recv", multifd_recv_thread, p,
> + QEMU_THREAD_JOINABLE);
> +}
> +
> int multifd_load_setup(void)
> {
> int thread_count;
> - uint8_t i;
>
> if (!migrate_use_multifd()) {
> return 0;
> @@ -534,22 +612,15 @@ int multifd_load_setup(void)
> multifd_recv_state = g_malloc0(sizeof(*multifd_recv_state));
> multifd_recv_state->params = g_new0(MultiFDRecvParams *, thread_count);
> multifd_recv_state->count = 0;
> - for (i = 0; i < thread_count; i++) {
> - char thread_name[16];
> - MultiFDRecvParams *p = multifd_recv_state->params[i];
> -
> - qemu_mutex_init(&p->mutex);
> - qemu_sem_init(&p->sem, 0);
> - p->quit = false;
> - p->id = i;
> - snprintf(thread_name, sizeof(thread_name), "multifdrecv_%d", i);
> - qemu_thread_create(&p->thread, thread_name, multifd_recv_thread, p,
> - QEMU_THREAD_JOINABLE);
> - multifd_recv_state->count++;
> - }
It us a little strange to be deleting a bunch of code you just added in the
previous patch
> + multifd_recv_state->quit = false;
> return 0;
> }
> diff --git a/migration/socket.c b/migration/socket.c
> index dee8690..5dd6f42 100644
> --- a/migration/socket.c
> +++ b/migration/socket.c
> @@ -26,6 +26,38 @@
> #include "io/channel-socket.h"
> #include "trace.h"
>
> +int socket_recv_channel_destroy(QIOChannel *recv)
> +{
> + /* Remove channel */
> + object_unref(OBJECT(recv));
> + return 0;
> +}
> +
> +struct SocketOutgoingArgs {
> + SocketAddress *saddr;
> + Error **errp;
> +} outgoing_args;
> +
> +QIOChannel *socket_send_channel_create(void)
> +{
> + QIOChannelSocket *sioc = qio_channel_socket_new();
> +
> + qio_channel_socket_connect_sync(sioc, outgoing_args.saddr,
> + outgoing_args.errp);
> + qio_channel_set_delay(QIO_CHANNEL(sioc), false);
> + return QIO_CHANNEL(sioc);
> +}
> +
> +int socket_send_channel_destroy(QIOChannel *send)
> +{
> + /* Remove channel */
> + object_unref(OBJECT(send));
> + if (outgoing_args.saddr) {
> + qapi_free_SocketAddress(outgoing_args.saddr);
> + outgoing_args.saddr = NULL;
> + }
> + return 0;
> +}
>
> static SocketAddress *tcp_build_address(const char *host_port, Error **errp)
> {
> @@ -96,6 +128,9 @@ static void socket_start_outgoing_migration(MigrationState *s,
> struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
>
> data->s = s;
> + outgoing_args.saddr = saddr;
> + outgoing_args.errp = errp;
Taking a stack local 'errp' pointer and saving it for later use
in a global variable is asking for trouble. There's no guarantee
that stack frame will still be valid when 'outgoing_args.errp'
is later used.
> +
> if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
> data->hostname = g_strdup(saddr->u.inet.host);
> }
> @@ -106,7 +141,6 @@ static void socket_start_outgoing_migration(MigrationState *s,
> socket_outgoing_migration,
> data,
> socket_connect_data_free);
> - qapi_free_SocketAddress(saddr);
> }
>
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2017-08-11 15:23 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-08 16:26 [Qemu-devel] [PATCH v6 00/19] Multifd Juan Quintela
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 01/19] migration: Create migration_ioc_process_incoming() Juan Quintela
2017-08-11 3:47 ` Peter Xu
2017-09-06 11:07 ` Juan Quintela
2017-09-08 4:16 ` Peter Xu
2017-09-13 9:41 ` Juan Quintela
2017-08-11 14:50 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 02/19] migration: Teach it about G_SOURCE_REMOVE Juan Quintela
2017-08-10 14:56 ` Daniel P. Berrange
2017-08-11 3:49 ` Peter Xu
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 03/19] migration: Add comments to channel functions Juan Quintela
2017-08-10 14:57 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 04/19] migration: Create migration_has_all_channels Juan Quintela
2017-08-10 14:58 ` Daniel P. Berrange
2017-08-10 15:17 ` Eric Blake
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 05/19] qio: Create new qio_channel_{readv, writev}_all Juan Quintela
2017-08-10 15:04 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 06/19] migration: Add multifd capability Juan Quintela
2017-08-11 7:14 ` Peter Xu
2017-08-11 14:52 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 07/19] migration: Create x-multifd-threads parameter Juan Quintela
2017-08-11 7:15 ` Peter Xu
2017-08-11 14:56 ` Daniel P. Berrange
2017-09-13 10:12 ` Juan Quintela
2017-09-13 10:18 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 08/19] migration: Create x-multifd-group parameter Juan Quintela
2017-08-11 7:16 ` Peter Xu
2017-08-11 15:03 ` Daniel P. Berrange
2017-09-13 10:25 ` Juan Quintela
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 09/19] migration: Create multifd migration threads Juan Quintela
2017-08-15 6:42 ` Peter Xu
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 10/19] migration: Split migration_fd_process_incoming Juan Quintela
2017-08-11 15:10 ` Daniel P. Berrange
2017-08-15 6:43 ` Peter Xu
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 11/19] migration: Start of multiple fd work Juan Quintela
2017-08-11 15:22 ` Daniel P. Berrange [this message]
2017-08-14 13:43 ` Juan Quintela
2017-08-14 13:50 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 12/19] migration: Create ram_multifd_page Juan Quintela
2017-08-11 15:25 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 13/19] migration: Really use multiple pages at a time Juan Quintela
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 14/19] migration: Send the fd number which we are going to use for this page Juan Quintela
2017-08-14 15:47 ` Dr. David Alan Gilbert
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 15/19] migration: Create thread infrastructure for multifd recv side Juan Quintela
2017-08-11 4:35 ` Peter Xu
2017-08-11 15:29 ` Daniel P. Berrange
2017-09-13 9:53 ` Juan Quintela
2017-09-13 11:26 ` Juan Quintela
2017-09-13 11:45 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 16/19] migration: Test new fd infrastructure Juan Quintela
2017-08-11 15:32 ` Daniel P. Berrange
2017-08-11 15:35 ` Daniel P. Berrange
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 17/19] migration: Rename initial_bytes Juan Quintela
2017-08-11 19:01 ` Dr. David Alan Gilbert
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 18/19] migration: Transfer pages over new channels Juan Quintela
2017-08-11 15:34 ` Daniel P. Berrange
2017-08-16 16:38 ` Dr. David Alan Gilbert
2017-08-08 16:26 ` [Qemu-devel] [PATCH v6 19/19] migration: Flush receive queue Juan Quintela
2017-08-11 4:16 ` Peter Xu
2017-08-08 23:37 ` [Qemu-devel] [PATCH v6 00/19] Multifd no-reply
-- strict thread matches above, loose matches on Subject: below --
2017-08-08 16:22 Juan Quintela
2017-08-08 16:22 ` [Qemu-devel] [PATCH v6 11/19] migration: Start of multiple fd work Juan Quintela
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170811152256.GS2554@redhat.com \
--to=berrange@redhat.com \
--cc=dgilbert@redhat.com \
--cc=lvivier@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).