On Tue, Oct 15, 2013 at 04:24:14AM +0000, Wangyufei (A) wrote: > >From f56b290eab36bbb7a9ac53778a55638d473504d1 Mon Sep 17 00:00:00 2001 > From: WangYufei <james.wangyufei@xxxxxxxxxx> > Date: Fri, 11 Oct 2013 11:27:13 +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. In future please line wrap your commit messages at ~70 characters. > Signed-off-by: WangYufei <james.wangyufei@xxxxxxxxxx> > --- > src/qemu/qemu_command.h | 3 +++ > src/qemu/qemu_conf.h | 6 +++--- > src/qemu/qemu_domain.h | 1 + > src/qemu/qemu_driver.c | 6 ++++++ > src/qemu/qemu_migration.c | 28 +++++++++++++++++++++------- > 5 files changed, 34 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_domain.h b/src/qemu/qemu_domain.h > index 21f116c..16c55a6 100644 > --- a/src/qemu/qemu_domain.h > +++ b/src/qemu/qemu_domain.h > @@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate { > unsigned long migMaxBandwidth; > char *origname; > int nbdPort; /* Port used for migration with NBD */ > + int migrationPort; > > virChrdevsPtr devs; > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index cfdbb9a..c08a73c 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -687,6 +687,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; > > @@ -993,6 +998,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..93ae237 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -2147,6 +2147,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver, > qemuDomainJobTypeToString(priv->job.active), > qemuDomainAsyncJobTypeToString(priv->job.asyncJob)); > > + virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort); > + priv->migrationPort = 0; > + > if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN)) > return; > qemuDomainObjDiscardAsyncJob(driver, vm); > @@ -2297,6 +2300,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, > > *def = NULL; > priv = vm->privateData; > + priv->migrationPort = port; > if (VIR_STRDUP(priv->origname, origname) < 0) > goto cleanup; > > @@ -2415,6 +2419,11 @@ cleanup: > VIR_FREE(xmlout); > VIR_FORCE_CLOSE(dataFD[0]); > VIR_FORCE_CLOSE(dataFD[1]); > + if (ret < 0) { > + virPortAllocatorRelease(driver->migrationPorts, port); > + if (priv) > + priv->migrationPort = 0; > + } > if (vm) { > if (ret >= 0 || vm->persistent) > virObjectUnlock(vm); > @@ -2493,7 +2502,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 +2529,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; Just declare 'this_port' to be an 'unsigned short' instead of casting it everywhere. ACK if you fix that. As a followup, it might be desirable to make the migration port range be configurable via /etc/libvirt/qemu.conf, in the same way that we have the VNC/SPICE port range configurable. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list