On 02/06/2013 08:52 AM, Michal Privoznik wrote:
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.
---
src/qemu/qemu_domain.c | 30 ++++++++++++++++++++++++++++--
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_migration.c | 13 +++++++++++++
src/qemu/qemu_process.c | 8 ++++++++
4 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d7d7163..6090623 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -232,10 +232,15 @@ error:
static void qemuDomainObjPrivateFree(void *data)
{
+ size_t i;
qemuDomainObjPrivatePtr priv = data;
virObjectUnref(priv->caps);
+ for (i = 0; i < priv->nnbdDisk; i++)
+ VIR_FREE(priv->nbdDisk[i]);
+ VIR_FREE(priv->nbdDisk);
+
qemuDomainPCIAddressSetFree(priv->pciaddrs);
virDomainChrSourceDefFree(priv->monConfig);
qemuDomainObjFreeJob(priv);
@@ -264,6 +269,7 @@ static int 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) {
@@ -286,7 +292,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void
*data)
if (priv->nvcpupids) {
- int i;
virBufferAddLit(buf, " <vcpus>\n");
for (i = 0 ; i < priv->nvcpupids ; i++) {
virBufferAsprintf(buf, " <vcpu pid='%d'/>\n",
priv->vcpupids[i]);
@@ -295,7 +300,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void
*data)
}
if (priv->caps) {
- int i;
virBufferAddLit(buf, " <qemuCaps>\n");
for (i = 0 ; i < QEMU_CAPS_LAST ; i++) {
if (qemuCapsGet(priv->caps, i)) {
@@ -329,6 +333,13 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void
*data)
if (priv->fakeReboot)
virBufferAsprintf(buf, " <fakereboot/>\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;
}
@@ -474,6 +485,21 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
void *data)
priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) ==
1;
+ n = virXPathNodeSet("./nbdDisk/disk", ctxt, &nodes);
+ if (n < 0)
+ goto error;
+ if (n) {
+ if (VIR_REALLOC_N(priv->nbdDisk, n) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ priv->nnbdDisk = n;
+
+ for (i = 0; i < n; i++)
+ if (!(priv->nbdDisk[i] = virXMLPropString(nodes[i], "src")))
+ goto error;
If we fail in here, then nbdDisk[] entries from i -> n will be empty.
Will this cause issues elsewhere (such as qemuProcessStop() below)
because other code assumes each nnbdDisk entry is populated with something?
Also I think the for() needs {} since we have multiple lines following.
+ }
+
return 0;
error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index e8555d3..3548a51 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -155,6 +155,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 f3edd51..1379b23 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1561,6 +1561,7 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuMigrationCookiePtr mig)
{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
int ret = -1;
size_t i = 0;
@@ -1607,6 +1608,11 @@ qemuMigrationPreCreateStorage(virQEMUDriverPtr driver,
goto cleanup;
}
+ if ((VIR_REALLOC_N(priv->nbdDisk, priv->nnbdDisk + 1) < 0) ||
+ !(priv->nbdDisk[priv->nnbdDisk++] = strdup(disk->src))) {
+ virReportOOMError();
+ goto cleanup;
+ }
}
ret = 0;
@@ -4042,6 +4048,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
int cookie_flags = 0;
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ size_t i;
VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
@@ -4192,6 +4199,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 2c57e0e..73420e3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4245,6 +4245,14 @@ void qemuProcessStop(virQEMUDriverPtr driver,
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;