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

Jim Fehlig jfehlig at suse.com
Fri Nov 14 04:23:00 UTC 2014


Michal Privoznik wrote:
> 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.

Ah, yes, thanks for catching that.  In fact, I need to cleanup all the
listening sockets on failure too.

Also, while reordering this series I mistakenly dropped a patch that
fixes a race condition introduced by moving the receive processing to a
thread.

V2 on the way.  Sorry for wasting your time on an incomplete V1.

Regards,
Jim




More information about the libvir-list mailing list