On 02/06/2013 08:52 AM, Michal Privoznik wrote: > We need to start NBD server and feed it with all non-<shared/>, > RW and source-full disks. Moreover, with new virPortAllocator we > must ensure the borrowed port for NBD server will be returned if > either migration completes or qemu process is teared down. > --- > src/qemu/qemu_migration.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++- > src/qemu/qemu_process.c | 5 +++ > 2 files changed, 88 insertions(+), 1 deletion(-) > > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index c71021d..16840b2 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -35,6 +35,7 @@ > #include "qemu_domain.h" > #include "qemu_process.h" > #include "qemu_capabilities.h" > +#include "qemu_command.h" > #include "qemu_cgroup.h" > > #include "domain_audit.h" > @@ -1091,6 +1092,80 @@ error: > return NULL; > } > > +/** > + * qemuMigrationStartNBDServer: > + * @driver: qemu driver > + * @vm: domain > + * > + * Starts NBD server. This is a newer method to copy > + * storage during migration than using 'blk' and 'inc' > + * arguments in 'migrate' monitor command. > + * Error is reported here. > + * > + * Returns 0 on success, -1 otherwise. > + */ > +static int > +qemuMigrationStartNBDServer(virQEMUDriverPtr driver, > + virDomainObjPtr vm) > +{ > + int ret = -1; > + qemuDomainObjPrivatePtr priv = vm->privateData; > + unsigned short port = 0; > + const char *listen = "0.0.0.0"; > + char *diskAlias = NULL; > + size_t i; > + > + for (i = 0; i < vm->def->ndisks; i++) { > + virDomainDiskDefPtr disk = vm->def->disks[i]; > + > + /* skip shared, RO and source-less disks */ > + if (disk->shared || disk->readonly || !disk->src) > + continue; > + > + VIR_FREE(diskAlias); > + if (virAsprintf(&diskAlias, "%s%s", > + QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + if (qemuDomainObjEnterMonitorAsync(driver, vm, > + QEMU_ASYNC_JOB_MIGRATION_IN) < 0) > + goto cleanup; > + > + if (!port) { > + if (virPortAllocatorAcquire(driver->remotePorts, &port) < 0) > + goto cleanup; > + > + if (qemuMonitorNBDServerStart(priv->mon, listen, port) < 0) { > + qemuDomainObjExitMonitorWithDriver(driver, vm); > + virReportError(VIR_ERR_OPERATION_FAILED, "%s", > + _("Unable to start nbd server")); > + goto cleanup; > + } > + } > + > + if (qemuMonitorNBDServerAdd(priv->mon, diskAlias, true) < 0) { > + qemuDomainObjExitMonitorWithDriver(driver, vm); > + > + virReportError(VIR_ERR_OPERATION_FAILED, > + _("Unable to add '%s' to NDB server"), diskAlias); > + goto cleanup; > + } > + qemuDomainObjExitMonitorWithDriver(driver, vm); > + } > + > + priv->nbdPort = port; > + ret = 0; > + > +cleanup: > + VIR_FREE(diskAlias); > + if (ret < 0) > + virPortAllocatorRelease(driver->remotePorts, port); I believe you can get here with driver->remotePorts not yet allocated which will cause issues in the Release routine. Perhaps follow what you did below and use "&& port" to indicate that you have a port value. > + return ret; > +} > + > + > /* Validate whether the domain is safe to migrate. If vm is NULL, > * then this is being run in the v2 Prepare stage on the destination > * (where we only have the target xml); if vm is provided, then this > @@ -1809,8 +1884,11 @@ done: > if (flags & VIR_MIGRATE_TUNNELLED) > VIR_DEBUG("NBD in tunnelled migration is currently not supported"); > else { > + if (qemuMigrationStartNBDServer(driver, vm) < 0) { > + /* error already reported */ > + goto endjob; > + } > cookieFlags |= QEMU_MIGRATION_COOKIE_NBD; > - priv->nbdPort = 0; > } > } > > @@ -1857,6 +1935,10 @@ cleanup: > virObjectUnlock(vm); > else > qemuDomainRemoveInactive(driver, vm); > + if (ret < 0 && priv->nbdPort) { > + virPortAllocatorRelease(driver->remotePorts, priv->nbdPort); > + priv->nbdPort = 0; > + } > } > if (event) > qemuDomainEventQueue(driver, event); > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 30f923a..2c57e0e 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -4240,6 +4240,11 @@ void qemuProcessStop(virQEMUDriverPtr driver, > } > } > > + if (priv->nbdPort) { > + virPortAllocatorRelease(driver->remotePorts, priv->nbdPort); > + priv->nbdPort = 0; > + } > + > if (priv->agent) { > qemuAgentClose(priv->agent); > priv->agent = NULL; > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list