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@xxxxxxxx> >> --- >> 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list