Add status XML infrastructure for storing a list of block dirty bitmaps which are temporarily used when migrating a VM with VIR_MIGRATE_NON_SHARED_DISK for cleanup after a libvirtd restart during migration. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> Reviewed-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- src/qemu/qemu_domain.c | 87 ++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.h | 15 ++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 541d592bbe..bb14fe2e33 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -86,6 +86,18 @@ qemuJobAllocPrivate(void) } +void +qemuDomainJobPrivateMigrateTempBitmapFree(qemuDomainJobPrivateMigrateTempBitmapPtr bmp) +{ + if (!bmp) + return; + + g_free(bmp->nodename); + g_free(bmp->bitmapname); + g_free(bmp); +} + + static void qemuJobFreePrivate(void *opaque) { @@ -95,6 +107,9 @@ qemuJobFreePrivate(void *opaque) return; qemuMigrationParamsFree(priv->migParams); + if (priv->migTempBitmaps) + g_slist_free_full(priv->migTempBitmaps, + (GDestroyNotify) qemuDomainJobPrivateMigrateTempBitmapFree); g_free(priv); } @@ -165,6 +180,28 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, return 0; } + +static void +qemuDomainObjPrivateXMLFormatMigrateTempBitmap(virBufferPtr buf, + GSList *bitmaps) +{ + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + GSList *next; + + for (next = bitmaps; next; next = next->next) { + qemuDomainJobPrivateMigrateTempBitmapPtr t = next->data; + g_auto(virBuffer) bitmapBuf = VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&bitmapBuf, " name='%s'", t->bitmapname); + virBufferAsprintf(&bitmapBuf, " nodename='%s'", t->nodename); + + virXMLFormatElement(&childBuf, "bitmap", &bitmapBuf, NULL); + } + + virXMLFormatElement(buf, "tempBlockDirtyBitmaps", NULL, &childBuf); +} + + static int qemuDomainFormatJobPrivate(virBufferPtr buf, qemuDomainJobObjPtr job, @@ -172,9 +209,12 @@ qemuDomainFormatJobPrivate(virBufferPtr buf, { qemuDomainJobPrivatePtr priv = job->privateData; - if (job->asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT && - qemuDomainObjPrivateXMLFormatNBDMigration(buf, vm) < 0) - return -1; + if (job->asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) { + if (qemuDomainObjPrivateXMLFormatNBDMigration(buf, vm) < 0) + return -1; + + qemuDomainObjPrivateXMLFormatMigrateTempBitmap(buf, priv->migTempBitmaps); + } if (priv->migParams) qemuMigrationParamsFormat(buf, priv->migParams); @@ -267,6 +307,44 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, return 0; } + +static int +qemuDomainObjPrivateXMLParseMigrateTempBitmap(qemuDomainJobPrivatePtr jobPriv, + xmlXPathContextPtr ctxt) +{ + g_autoslist(qemuDomainJobPrivateMigrateTempBitmap) bitmaps = NULL; + g_autofree xmlNodePtr *nodes = NULL; + size_t i; + int n; + + if ((n = virXPathNodeSet("./tempBlockDirtyBitmaps/bitmap", ctxt, &nodes)) < 0) + return -1; + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) { + qemuDomainJobPrivateMigrateTempBitmapPtr bmp; + + bmp = g_new0(qemuDomainJobPrivateMigrateTempBitmap, 1); + bmp->nodename = virXMLPropString(nodes[i], "nodename"); + bmp->bitmapname = virXMLPropString(nodes[i], "name"); + + bitmaps = g_slist_prepend(bitmaps, bmp); + + if (!bmp->bitmapname || !bmp->nodename) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed <tempBlockDirtyBitmaps> in status XML")); + return -1; + } + + } + + jobPriv->migTempBitmaps = g_slist_reverse(g_steal_pointer(&bitmaps)); + return 0; +} + + static int qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, qemuDomainJobObjPtr job, @@ -277,6 +355,9 @@ qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) return -1; + if (qemuDomainObjPrivateXMLParseMigrateTempBitmap(priv, ctxt) < 0) + return -1; + if (qemuMigrationParamsParse(ctxt, &priv->migParams) < 0) return -1; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 9a7d997d65..949307229b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -487,6 +487,20 @@ struct _qemuDomainXmlNsDef { char **capsdel; }; + +typedef struct _qemuDomainJobPrivateMigrateTempBitmap qemuDomainJobPrivateMigrateTempBitmap; +typedef qemuDomainJobPrivateMigrateTempBitmap *qemuDomainJobPrivateMigrateTempBitmapPtr; + +struct _qemuDomainJobPrivateMigrateTempBitmap { + char *nodename; + char *bitmapname; +}; + +void +qemuDomainJobPrivateMigrateTempBitmapFree(qemuDomainJobPrivateMigrateTempBitmapPtr bmp); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuDomainJobPrivateMigrateTempBitmap, qemuDomainJobPrivateMigrateTempBitmapFree); + + typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate; typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr; struct _qemuDomainJobPrivate { @@ -495,6 +509,7 @@ struct _qemuDomainJobPrivate { bool spiceMigrated; /* spice migration completed */ bool dumpCompleted; /* dump completed */ qemuMigrationParamsPtr migParams; + GSList *migTempBitmaps; /* temporary block dirty bitmaps - qemuDomainJobPrivateMigrateTempBitmap */ }; int qemuDomainObjStartWorker(virDomainObjPtr dom); -- 2.29.2