[PATCH 12/19] qemu: migration_cookie: Add XML handling for setting up bitmap migration

Jiri Denemark jdenemar at redhat.com
Thu Feb 18 10:58:05 UTC 2021


On Thu, Feb 11, 2021 at 16:37:51 +0100, Peter Krempa wrote:
> In cases where we are copying the storage we need to ensure that also
> bitmaps are copied properly. This patch adds migration cookie XML
> infrastructure which will allow the migration sides reach consensus on
> which bitmaps to migrate.
> 
> Signed-off-by: Peter Krempa <pkrempa at redhat.com>
> ---
>  src/qemu/qemu_migration_cookie.c | 134 +++++++++++++++++++++++++++++++
>  src/qemu/qemu_migration_cookie.h |  34 ++++++++
>  2 files changed, 168 insertions(+)
> 
> diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c
> index 6f2b1b2f57..94ba9c83d0 100644
> --- a/src/qemu/qemu_migration_cookie.c
> +++ b/src/qemu/qemu_migration_cookie.c
...
> @@ -758,6 +795,48 @@ qemuMigrationCookieNBDXMLFormat(qemuMigrationCookieNBDPtr nbd,
>  }
> 
> 
> +static void
> +qemuMigrationCookieBlockDirtyBitmapsFormat(virBufferPtr buf,
> +                                           GSList *bitmaps)
> +{
> +    g_auto(virBuffer) disksBuf = VIR_BUFFER_INIT_CHILD(buf);
> +    GSList *nextdisk;
> +
> +    for (nextdisk = bitmaps; nextdisk; nextdisk = nextdisk->next) {
> +        qemuMigrationBlockDirtyBitmapsDiskPtr disk = nextdisk->data;
> +        g_auto(virBuffer) diskAttrBuf = VIR_BUFFER_INITIALIZER;
> +        g_auto(virBuffer) diskChildBuf = VIR_BUFFER_INIT_CHILD(&disksBuf);
> +        bool hasBitmaps = false;
> +        GSList *nextbitmap;
> +
> +        if (disk->skip || !disk->bitmaps)
> +            continue;
> +
> +        for (nextbitmap = disk->bitmaps; nextbitmap; nextbitmap = nextbitmap->next) {
> +            qemuMigrationBlockDirtyBitmapsDiskBitmapPtr bitmap = nextbitmap->data;
> +
> +            if (bitmap->skip)
> +                continue;
> +
> +            virBufferAsprintf(&diskChildBuf,
> +                              "<bitmap name='%s' alias='%s'/>\n",
> +                              bitmap->bitmapname, bitmap->alias);
> +
> +            hasBitmaps = true;
> +        }
> +
> +        if (!hasBitmaps)
> +            continue;

You could drop hasBitmaps and call virBufferUse instead, but not a big
deal.

> +
> +        virBufferAsprintf(&diskAttrBuf, " target='%s'", disk->target);
> +        virXMLFormatElement(&disksBuf, "disk", &diskAttrBuf, &diskChildBuf);
> +    }
> +
> +
> +    virXMLFormatElement(buf, "blockDirtyBitmaps", NULL, &disksBuf);
> +}
> +
> +
>  int
>  qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
>                               virQEMUCapsPtr qemuCaps,
> @@ -829,6 +908,9 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
>      if (mig->flags & QEMU_MIGRATION_COOKIE_CAPS)
>          qemuMigrationCookieCapsXMLFormat(buf, mig->caps);
> 
> +    if (mig->flags & QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS)
> +        qemuMigrationCookieBlockDirtyBitmapsFormat(buf, mig->blockDirtyBitmaps);
> +
>      virBufferAdjustIndent(buf, -2);
>      virBufferAddLit(buf, "</qemu-migration>\n");
>      return 0;
> @@ -1132,6 +1214,53 @@ qemuMigrationCookieXMLParseMandatoryFeatures(xmlXPathContextPtr ctxt,
>  }
> 
> 
> +static int
> +qemuMigrationCookieBlockDirtyBitmapsParse(xmlXPathContextPtr ctxt,
> +                                          qemuMigrationCookiePtr mig)
> +{
> +    g_autoslist(qemuMigrationBlockDirtyBitmapsDisk) disks = NULL;
> +    g_autofree xmlNodePtr *disknodes = NULL;
> +    int ndisknodes;
> +    size_t i;
> +    VIR_XPATH_NODE_AUTORESTORE(ctxt)
> +
> +    if ((ndisknodes = virXPathNodeSet("./blockDirtyBitmaps/disk", ctxt, &disknodes)) < 0)
> +        return -1;
> +
> +    for (i = 0; i < ndisknodes; i++) {
> +        GSList *bitmaps = NULL;
> +        qemuMigrationBlockDirtyBitmapsDiskPtr disk;
> +        g_autofree xmlNodePtr *bitmapnodes = NULL;
> +        int nbitmapnodes;
> +        size_t j;
> +
> +        ctxt->node = disknodes[i];
> +
> +        if ((nbitmapnodes = virXPathNodeSet("./bitmap", ctxt, &bitmapnodes)) < 0)
> +            return -1;
> +
> +        for (j = 0; j < nbitmapnodes; j++) {
> +            qemuMigrationBlockDirtyBitmapsDiskBitmapPtr bitmap;
> +
> +            bitmap = g_new0(qemuMigrationBlockDirtyBitmapsDiskBitmap, 1);
> +            bitmap->bitmapname = virXMLPropString(bitmapnodes[j], "name");
> +            bitmap->alias = virXMLPropString(bitmapnodes[j], "alias");

So what if the attributes do not exist? And virXMLPropString does not
abort on OOM. You should check for the result being non-NULL here.

> +            bitmaps = g_slist_prepend(bitmaps, bitmap);
> +        }
> +
> +        disk = g_new0(qemuMigrationBlockDirtyBitmapsDisk, 1);
> +        disk->target = virXMLPropString(disknodes[i], "target");

And here as well.

> +        disk->bitmaps = g_slist_reverse(bitmaps);
> +
> +        disks = g_slist_prepend(disks, disk);
> +    }
> +
> +    mig->blockDirtyBitmaps = g_slist_reverse(g_steal_pointer(&disks));
> +
> +    return 0;
> +}
> +
> +
>  static int
>  qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
>                              virQEMUDriverPtr driver,
...

With the checks for virXMLPropString result added

Reviewed-by: Jiri Denemark <jdenemar at redhat.com>




More information about the libvir-list mailing list