[libvirt] [PATCH 1/3] libxl: Receive migration data in a thread

Michal Privoznik mprivozn at redhat.com
Thu Nov 13 13:04:20 UTC 2014


On 13.11.2014 03:36, Jim Fehlig wrote:
> The libxl driver receives migration data within an IO callback invoked
> by the event loop, effectively disabling the event loop while migration
> occurs.
>
> This patch moves receving of the migration data to a thread.  The
> incoming connection is still accepted in the IO callback, but control
> is immediately returned to the event loop after spawning the thread.
>
> Signed-off-by: Jim Fehlig <jfehlig at suse.com>
> ---
>   src/libxl/libxl_migration.c | 60 +++++++++++++++++++++++++++++++--------------
>   1 file changed, 42 insertions(+), 18 deletions(-)
>
> diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
> index 0b562f7..1940209 100644
> --- a/src/libxl/libxl_migration.c
> +++ b/src/libxl/libxl_migration.c
> @@ -35,6 +35,7 @@
>   #include "vircommand.h"
>   #include "virstring.h"
>   #include "virobject.h"
> +#include "virthread.h"
>   #include "rpc/virnetsocket.h"
>   #include "libxl_domain.h"
>   #include "libxl_driver.h"
> @@ -48,6 +49,7 @@ VIR_LOG_INIT("libxl.libxl_migration");
>   typedef struct _libxlMigrationDstArgs {
>       virObject parent;
>
> +    int recvfd;
>       virConnectPtr conn;
>       virDomainObjPtr vm;
>       unsigned int flags;
> @@ -82,31 +84,18 @@ libxlMigrationDstArgsOnceInit(void)
>   VIR_ONCE_GLOBAL_INIT(libxlMigrationDstArgs)
>
>   static void
> -libxlDoMigrateReceive(virNetSocketPtr sock,
> -                      int events ATTRIBUTE_UNUSED,
> -                      void *opaque)
> +libxlDoMigrateReceive(void *opaque)
>   {
>       libxlMigrationDstArgs *args = opaque;
> -    virConnectPtr conn = args->conn;
>       virDomainObjPtr vm = args->vm;
>       virNetSocketPtr *socks = args->socks;
>       size_t nsocks = args->nsocks;
>       bool paused = args->flags & VIR_MIGRATE_PAUSED;
> -    libxlDriverPrivatePtr driver = conn->privateData;
> -    virNetSocketPtr client_sock;
> -    int recvfd = -1;
> +    libxlDriverPrivatePtr driver = args->conn->privateData;
> +    int recvfd = args->recvfd;
>       size_t i;
>       int ret;
>
> -    if (virNetSocketAccept(sock, &client_sock) < 0) {
> -        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> -                       _("Fail to accept migration connection"));
> -        goto cleanup;
> -    }
> -    VIR_DEBUG("Accepted migration connection\n");
> -    recvfd = virNetSocketDupFD(client_sock, true);
> -    virObjectUnref(client_sock);
> -
>       virObjectLock(vm);
>       ret = libxlDomainStart(driver, vm, paused, recvfd);
>       virObjectUnlock(vm);
> @@ -114,7 +103,6 @@ libxlDoMigrateReceive(virNetSocketPtr sock,
>       if (ret < 0 && !vm->persistent)
>           virDomainObjListRemove(driver->domains, vm);
>
> - cleanup:
>       /* Remove all listen socks from event handler, and close them. */
>       for (i = 0; i < nsocks; i++) {
>           virNetSocketUpdateIOCallback(socks[i], 0);
> @@ -127,6 +115,42 @@ libxlDoMigrateReceive(virNetSocketPtr sock,
>       VIR_FORCE_CLOSE(recvfd);
>   }
>
> +
> +static void
> +libxlMigrateReceive(virNetSocketPtr sock,
> +                    int events ATTRIBUTE_UNUSED,
> +                    void *opaque)
> +{
> +    libxlMigrationDstArgs *args = opaque;
> +    virNetSocketPtr client_sock;
> +    int recvfd;
> +    virThread thread;
> +
> +    /* Accept migration connection */
> +    virNetSocketAccept(sock, &client_sock);
> +    if (client_sock == NULL) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("Failed to accept migration connection"));
> +        return;
> +    }
> +    VIR_DEBUG("Accepted migration connection."
> +              "  Spawing thread to process migration data");
> +    recvfd = virNetSocketDupFD(client_sock, true);
> +    virObjectUnref(client_sock);
> +
> +    /*
> +     * Avoid blocking the event loop.  Start a thread to receive
> +     * the migration data
> +     */
> +    args->recvfd = recvfd;
> +    if (virThreadCreate(&thread, false,
> +                        libxlDoMigrateReceive, args) < 0) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("Failed to create thread for receiving migration data"));

I believe you want VIR_FORCE_CLOSE(args->recvfd) in case thread creation 
failed.

> +    }
> +}
> +
> +
>   static int
>   libxlDoMigrateSend(libxlDriverPrivatePtr driver,
>                      virDomainObjPtr vm,
> @@ -376,7 +400,7 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
>
>           if (virNetSocketAddIOCallback(socks[i],
>                                         VIR_EVENT_HANDLE_READABLE,
> -                                      libxlDoMigrateReceive,
> +                                      libxlMigrateReceive,
>                                         args,
>                                         virObjectFreeCallback) < 0)
>               continue;
>

ACK with that fixed.

Michal




More information about the libvir-list mailing list