If migratioin fails because of whatever reason and we've
pre-created any disks, we should remove them instead of letting
them lying around. Moreover, we need to save the disks sources
into domain status file in case libvirtd gets restarted.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_domain.c | 29 +++++++++++++++++++++++++++--
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_migration.c | 18 ++++++++++++++++++
src/qemu/qemu_process.c | 8 ++++++++
4 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 64cd278..9117a68 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -239,11 +239,17 @@ error:
static void
qemuDomainObjPrivateFree(void *data)
{
+ size_t i;
qemuDomainObjPrivatePtr priv = data;
virObjectUnref(priv->qemuCaps);
virCgroupFree(&priv->cgroup);
+
+ for (i = 0; i < priv->nnbdDisk; i++)
+ VIR_FREE(priv->nbdDisk[i]);
+ VIR_FREE(priv->nbdDisk);
+
qemuDomainPCIAddressSetFree(priv->pciaddrs);
qemuDomainCCWAddressSetFree(priv->ccwaddrs);
virDomainChrSourceDefFree(priv->monConfig);
@@ -275,6 +281,7 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
qemuDomainObjPrivatePtr priv = data;
const char *monitorpath;
enum qemuDomainJob job;
+ size_t i;
/* priv->monitor_chr is set only for qemu */
if (priv->monConfig) {
@@ -297,7 +304,6 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
if (priv->nvcpupids) {
- size_t i;
virBufferAddLit(buf, " <vcpus>\n");
for (i = 0; i < priv->nvcpupids; i++) {
virBufferAsprintf(buf, " <vcpu pid='%d'/>\n",
priv->vcpupids[i]);
@@ -306,7 +312,6 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
}
if (priv->qemuCaps) {
- size_t i;
virBufferAddLit(buf, " <qemuCaps>\n");
for (i = 0; i < QEMU_CAPS_LAST; i++) {
if (virQEMUCapsGet(priv->qemuCaps, i)) {
@@ -350,6 +355,13 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
virBufferAddLit(buf, " </devices>\n");
}
+ if (priv->nnbdDisk) {
+ virBufferAddLit(buf, " <nbdDisk>\n");
+ for (i = 0; i < priv->nnbdDisk; i++)
+ virBufferAsprintf(buf, " <disk src='%s'/>\n",
priv->nbdDisk[i]);
+ virBufferAddLit(buf, " </nbdDisk>\n");
+ }
+
return 0;
}
@@ -511,6 +523,19 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
}
VIR_FREE(nodes);
+ n = virXPathNodeSet("./nbdDisk/disk", ctxt, &nodes);
+ if (n < 0)
+ goto error;
+ if (n) {
+ if (VIR_REALLOC_N(priv->nbdDisk, n) < 0)
+ goto error;
+ priv->nnbdDisk = n;
+
+ for (i = 0; i < n; i++)
+ if (!(priv->nbdDisk[i] = virXMLPropString(nodes[i], "src")))
+ goto error;
+ }
+
return 0;
error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b6e6e33..ff872c2 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -160,6 +160,8 @@ struct _qemuDomainObjPrivate {
unsigned long migMaxBandwidth;
char *origname;
int nbdPort; /* Port used for migration with NBD */
+ size_t nnbdDisk;
+ char **nbdDisk; /* src of disks we want to transfer via NBD */
virChrdevsPtr devs;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 5080b0a..931853e 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1585,6 +1585,7 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
{
int ret = -1;
size_t i = 0;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
if (!mig->nbd || !mig->nbd->ndisks) {
/* nothing to do here */
@@ -1596,6 +1597,7 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
int format;
size_t bytes;
int index;
+ char *path = NULL;
index = virDomainDiskIndexByName(vm->def, mig->nbd->disk[i].target,
false);
if (index < 0) {
@@ -1616,12 +1618,14 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
case VIR_STORAGE_FILE_RAW:
if (qemuMigrationPreCreateStorageRaw(driver, vm, disk, bytes) < 0)
goto cleanup;
+ path = disk->src;
break;
case VIR_STORAGE_FILE_QCOW:
case VIR_STORAGE_FILE_QCOW2:
if (qemuMigrationPreCreateStorageQCOW(driver, disk,
format, bytes) < 0)
goto cleanup;
+ path = disk->src;
break;
/* While these we don't know yet. */
@@ -1650,6 +1654,13 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
virStorageFileFormatTypeToString(format), disk->src);
break;
}
+
+ if (path) {
+ if (VIR_REALLOC_N(priv->nbdDisk, priv->nnbdDisk + 1) < 0 ||
+ VIR_STRDUP(priv->nbdDisk[priv->nnbdDisk], path) < 0)
+ goto cleanup;
+ priv->nnbdDisk++;
+ }
}
ret = 0;
@@ -4594,6 +4605,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virCapsPtr caps = NULL;
+ size_t i;
VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
@@ -4747,6 +4759,12 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
VIR_DOMAIN_EVENT_SUSPENDED,
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
}
+
+ /* Free disks transferred via NBD so they don't get deleted */
+ for (i = 0; i < priv->nnbdDisk; i++)
+ VIR_FREE(priv->nbdDisk[i]);
+ VIR_FREE(priv->nbdDisk);
+ priv->nnbdDisk = 0;
}
if (virDomainObjIsActive(vm) &&
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c7cec5a..34c0292 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4167,6 +4167,14 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virPortAllocatorRelease(driver->remotePorts, priv->nbdPort);
priv->nbdPort = 0;
+ for (i = 0; i < priv->nnbdDisk; i++) {
+ VIR_DEBUG("Unlinking %s due to unsuccessful NBD transfer",
+ priv->nbdDisk[i]);
+ if (unlink(priv->nbdDisk[i]) < 0)
+ virReportSystemError(errno, _("Unable to unlink %s"),
+ priv->nbdDisk[i]);
+ }
+
if (priv->agent) {
qemuAgentClose(priv->agent);
priv->agent = NULL;
--
1.8.1.5