[libvirt] [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently

From 6c2de34432db674072231ad66c9e8a0a600ede8a Mon Sep 17 00:00:00 2001 From: WangYufei <james.wangyufei@huawei.com> Date: Mon, 30 Sep 2013 11:48:43 +0800 Subject: [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
When we migrate vms concurrently, there's a chance that libvirtd on destination assign the same port for different migrations, which will lead to migration failed during migration prepare phase on destination. So we use virPortAllocator here to solve the problem. Signed-off-by: WangYufei <james.wangyufei@huawei.com> --- src/qemu/qemu_command.h | 3 +++ src/qemu/qemu_conf.h | 6 +++--- src/qemu/qemu_driver.c | 6 ++++++ src/qemu/qemu_migration.c | 17 ++++++++++------- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 2e2acfb..3277ba4 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -51,6 +51,9 @@ # define QEMU_WEBSOCKET_PORT_MIN 5700 # define QEMU_WEBSOCKET_PORT_MAX 65535 +# define QEMU_MIGRATION_PORT_MIN 49152 +# define QEMU_MIGRATION_PORT_MAX 49215 + typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks; typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr; struct _qemuBuildCommandLineCallbacks { diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index da29a2a..3176085 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -221,6 +221,9 @@ struct _virQEMUDriver { /* Immutable pointer, self-locking APIs */ virPortAllocatorPtr webSocketPorts; + /* Immutable pointer, self-locking APIs */ + virPortAllocatorPtr migrationPorts; + /* Immutable pointer, lockless APIs*/ virSysinfoDefPtr hostsysinfo; @@ -242,9 +245,6 @@ struct _qemuDomainCmdlineDef { char **env_value; }; -/* Port numbers used for KVM migration. */ -# define QEMUD_MIGRATION_FIRST_PORT 49152 -# define QEMUD_MIGRATION_NUM_PORTS 64 void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e8bc04d..9437b5a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -688,6 +688,11 @@ qemuStateInitialize(bool privileged, cfg->webSocketPortMax)) == NULL) goto error; + if ((qemu_driver->migrationPorts = + virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN, + QEMU_MIGRATION_PORT_MAX)) == NULL) + goto error; + if (qemuSecurityInit(qemu_driver) < 0) goto error; @@ -994,6 +999,7 @@ qemuStateCleanup(void) { virObjectUnref(qemu_driver->domains); virObjectUnref(qemu_driver->remotePorts); virObjectUnref(qemu_driver->webSocketPorts); + virObjectUnref(qemu_driver->migrationPorts); virObjectUnref(qemu_driver->xmlopt); diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 3a1aab7..82d90bf 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2493,7 +2493,6 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, const char *origname, unsigned long flags) { - static int port = 0; int this_port; char *hostname = NULL; const char *p; @@ -2521,8 +2520,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, * to be a correct hostname which refers to the target machine). */ if (uri_in == NULL) { - this_port = QEMUD_MIGRATION_FIRST_PORT + port++; - if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0; + if (virPortAllocatorAcquire(driver->migrationPorts, + (unsigned short *)&this_port) < 0) + goto cleanup; /* Get hostname */ if ((hostname = virGetHostname()) == NULL) @@ -2578,9 +2578,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, if (uri->port == 0) { /* Generate a port */ - this_port = QEMUD_MIGRATION_FIRST_PORT + port++; - if (port == QEMUD_MIGRATION_NUM_PORTS) - port = 0; + if (virPortAllocatorAcquire(driver->migrationPorts, + (unsigned short *)&this_port) < 0) + goto cleanup; /* Caller frees */ if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0) @@ -2600,8 +2600,11 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, cleanup: virURIFree(uri); VIR_FREE(hostname); - if (ret != 0) + if (ret != 0) { VIR_FREE(*uri_out); + virPortAllocatorRelease(driver->migrationPorts, + (unsigned short)this_port); + } return ret; } -- 1.7.3.1.msysgit.0 Best Regards, -WangYufei

On Mon, Sep 30, 2013 at 03:55:21 +0000, Wangyufei (A) wrote:
From 6c2de34432db674072231ad66c9e8a0a600ede8a Mon Sep 17 00:00:00 2001 From: WangYufei <james.wangyufei@huawei.com> Date: Mon, 30 Sep 2013 11:48:43 +0800 Subject: [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
When we migrate vms concurrently, there's a chance that libvirtd on destination assign the same port for different migrations, which will lead to migration failed during migration prepare phase on destination. So we use virPortAllocator here to solve the problem.
...
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e8bc04d..9437b5a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -688,6 +688,11 @@ qemuStateInitialize(bool privileged, cfg->webSocketPortMax)) == NULL) goto error;
+ if ((qemu_driver->migrationPorts = + virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN, + QEMU_MIGRATION_PORT_MAX)) == NULL) + goto error; +
Hmm, I guess we could make the port range configurable, but that's a separate thing.
if (qemuSecurityInit(qemu_driver) < 0) goto error;
@@ -994,6 +999,7 @@ qemuStateCleanup(void) { virObjectUnref(qemu_driver->domains); virObjectUnref(qemu_driver->remotePorts); virObjectUnref(qemu_driver->webSocketPorts); + virObjectUnref(qemu_driver->migrationPorts);
virObjectUnref(qemu_driver->xmlopt);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 3a1aab7..82d90bf 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c
...
@@ -2600,8 +2600,11 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, cleanup: virURIFree(uri); VIR_FREE(hostname); - if (ret != 0) + if (ret != 0) { VIR_FREE(*uri_out); + virPortAllocatorRelease(driver->migrationPorts, + (unsigned short)this_port); + } return ret; }
I'm afraid we will also need to release the port once the migration is done. qemuMigrationPrepareCleanup and qemuMigrationFinish are the places where we should handle this. Jirka
participants (2)
-
jdenemar@redhat.com
-
Wangyufei (A)