On Thu, Feb 11, 2021 at 16:37:53 +0100, Peter Krempa wrote:
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(a)redhat.com>
---
src/qemu/qemu_domain.c | 90 ++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_domain.h | 15 +++++++
2 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 53b4fb5f4f..ed37917670 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);
I just realized this now although the same pattern is used in previous
patches... Shouldn't g_slist_free_full be able to cope with NULL making
the if () check before it redundant?
VIR_FREE(priv);
}
@@ -165,6 +180,28 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf,
return 0;
}
+
+static void
+qemuDomainObjPrivateXMLFormatMigrationBlockDirtyBitmapsTemp(virBufferPtr buf,
+ GSList *bitmaps)
The naming is pretty inconsistent here, how about
qemuDomainObjPrivateXMLFormatMigrateTempBitmap(...)?
+{
+ 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,14 @@ 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;
+
+ if (priv->migTempBitmaps)
+ qemuDomainObjPrivateXMLFormatMigrationBlockDirtyBitmapsTemp(buf,
+
priv->migTempBitmaps);
You could just directly call the formatting function as it won't format
anything when priv->migTempBitmaps is an empty list.
+ }
if (priv->migParams)
qemuMigrationParamsFormat(buf, priv->migParams);
@@ -267,6 +309,45 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm,
return 0;
}
+
+static int
+qemuDomainParseJobPrivateXMLMigrationBlockDirtyBitmapsTemp(qemuDomainJobPrivatePtr
jobPriv,
+ xmlXPathContextPtr ctxt)
qemuDomainObjPrivateXMLParseMigrateTempBitmap would make the naming a
bit more consistent with other formatting and parsing functions.
+{
+ 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++) {
+ g_autofree char *bitmapname = virXMLPropString(nodes[i], "name");
+ g_autofree char *nodename = virXMLPropString(nodes[i], "nodename");
+ qemuDomainJobPrivateMigrateTempBitmapPtr bmp;
+
+ if (!bitmapname || !nodename) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed <tempBlockDirtyBitmaps>"));
+ return -1;
+ }
Right, something similar is needed in patch 12/19. Although you could
mention extend the error message here and mention the error happened in
a status XML.
And you could even get away without the temp variables by marking bmp
for autoclean and stealing its content when adding to the list.
+
+ bmp = g_new0(qemuDomainJobPrivateMigrateTempBitmap, 1);
+ bmp->nodename = g_steal_pointer(&nodename);
+ bmp->bitmapname = g_steal_pointer(&bitmapname);
+
+ bitmaps = g_slist_prepend(bitmaps, bmp);
+ }
+
+ jobPriv->migTempBitmaps = g_slist_reverse(g_steal_pointer(&bitmaps));
+ return 0;
+}
+
+
static int
qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt,
qemuDomainJobObjPtr job,
@@ -277,6 +358,9 @@ qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt,
if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0)
return -1;
+ if (qemuDomainParseJobPrivateXMLMigrationBlockDirtyBitmapsTemp(priv, ctxt) < 0)
+ return -1;
+
if (qemuMigrationParamsParse(ctxt, &priv->migParams) < 0)
return -1;
...
No matter whether you decide to change the functions names...
Reviewed-by: Jiri Denemark <jdenemar(a)redhat.com>