[PATCH v4 03/11] qemu: snapshot: Introduce helpers for creating overlays on <transient/> disks

Masayoshi Mizuma msys.mizuma at gmail.com
Fri Sep 25 14:09:50 UTC 2020


On Thu, Sep 24, 2020 at 01:43:50PM +0200, Peter Krempa wrote:
> To implement <transient/> disks we'll need to install an overlay on top
> of the original disk image which will be discarded after the VM is
> turned off. This was initially implemented by qemu but libvirt never > picked up this option. With blockdev the qemu feature became unsupported
> so we need to do this via the snapshot code anyways.
> 
> The helpers introduced in this patch prepare a fake snapshot disk
> definition for a disk which is configured as <transient/> and use it to
> create a snapshot (without actually modifying metada or persistent def).
> 
> Signed-off-by: Peter Krempa <pkrempa at redhat.com>
> ---
>  src/qemu/qemu_snapshot.c | 91 +++++++++++++++++++++++++++++++++++++++-
>  src/qemu/qemu_snapshot.h |  5 +++
>  2 files changed, 95 insertions(+), 1 deletion(-)
> 
> diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
> index ca051071aa..d10e7b6b3a 100644
> --- a/src/qemu/qemu_snapshot.c
> +++ b/src/qemu/qemu_snapshot.c
> @@ -986,6 +986,7 @@ qemuSnapshotDiskPrepareOne(virDomainObjPtr vm,
>                             qemuSnapshotDiskDataPtr dd,
>                             virHashTablePtr blockNamedNodeData,
>                             bool reuse,
> +                           bool updateConfig,
>                             qemuDomainAsyncJob asyncJob,
>                             virJSONValuePtr actions)
>  {
> @@ -1008,7 +1009,8 @@ qemuSnapshotDiskPrepareOne(virDomainObjPtr vm,
>          return -1;
> 
>      /* modify disk in persistent definition only when the source is the same */
> -    if (vm->newDef &&
> +    if (updateConfig &&
> +        vm->newDef &&
>          (persistdisk = virDomainDiskByTarget(vm->newDef, dd->disk->dst)) &&
>          virStorageSourceIsSameLocation(dd->disk->src, persistdisk->src)) {
> 
> @@ -1116,6 +1118,54 @@ qemuSnapshotDiskPrepareActiveExternal(virDomainObjPtr vm,
>                                         snapctxt->dd + snapctxt->ndd++,
>                                         blockNamedNodeData,
>                                         reuse,
> +                                       true,
> +                                       asyncJob,
> +                                       snapctxt->actions) < 0)
> +            return NULL;
> +    }
> +
> +    return g_steal_pointer(&snapctxt);
> +}
> +
> +
> +static qemuSnapshotDiskContextPtr
> +qemuSnapshotDiskPrepareDisksTransient(virDomainObjPtr vm,
> +                                      virQEMUDriverConfigPtr cfg,
> +                                      virHashTablePtr blockNamedNodeData,
> +                                      qemuDomainAsyncJob asyncJob)
> +{
> +    g_autoptr(qemuSnapshotDiskContext) snapctxt = NULL;
> +    size_t i;
> +
> +    snapctxt = qemuSnapshotDiskContextNew(vm->def->ndisks, vm, asyncJob);
> +
> +    for (i = 0; i < vm->def->ndisks; i++) {
> +        virDomainDiskDefPtr domdisk = vm->def->disks[i];
> +        g_autoptr(virDomainSnapshotDiskDef) snapdisk = g_new0(virDomainSnapshotDiskDef, 1);
> +
> +        if (!domdisk->transient)
> +            continue;
> +
> +        /* validation code makes sure that we do this only for local disks
> +         * with a file source */
> +        snapdisk->name = g_strdup(domdisk->dst);
> +        snapdisk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
> +        snapdisk->src = virStorageSourceNew();
> +        snapdisk->src->type = VIR_STORAGE_TYPE_FILE;
> +        snapdisk->src->format = VIR_STORAGE_FILE_QCOW2;
> +        snapdisk->src->path = g_strdup_printf("%s.TRANSIENT", domdisk->src->path);
> +        if (virFileExists(snapdisk->src->path)) {
> +            virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
> +                           _("Overlay file '%s' for transient disk '%s' already exists"),
> +                           snapdisk->src->path, domdisk->dst);
> +            return NULL;
> +        }
> +
> +        if (qemuSnapshotDiskPrepareOne(vm, cfg, domdisk, snapdisk,
> +                                       snapctxt->dd + snapctxt->ndd++,
> +                                       blockNamedNodeData,
> +                                       false,
> +                                       false,
>                                         asyncJob,
>                                         snapctxt->actions) < 0)
>              return NULL;
> @@ -1253,6 +1303,45 @@ qemuSnapshotCreateActiveExternalDisks(virDomainObjPtr vm,
>  }
> 
> 
> +/**
> + * qemuSnapshotCreateDisksTransient:
> + * @vm: domain object
> + * @asyncJob: qemu async job type
> + *
> + * Creates overlays on top of disks which are configured as <transient/>. Note
> + * that the validation code ensures that <transient> disks have appropriate
> + * configuration.
> + */
> +int
> +qemuSnapshotCreateDisksTransient(virDomainObjPtr vm,
> +                                 qemuDomainAsyncJob asyncJob)
> +{
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    virQEMUDriverPtr driver = priv->driver;
> +    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
> +    g_autoptr(qemuSnapshotDiskContext) snapctxt = NULL;
> +    g_autoptr(virHashTable) blockNamedNodeData = NULL;
> +
> +    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
> +        if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
> +            return -1;
> +
> +        if (!(snapctxt = qemuSnapshotDiskPrepareDisksTransient(vm, cfg,
> +                                                               blockNamedNodeData,
> +                                                               asyncJob)))
> +            return -1;
> +
> +        if (qemuSnapshotDiskCreate(snapctxt, cfg) < 0)
> +            return -1;
> +    }
> +
> +    /* the overlays are established, so they can be deleted on a shutdown */
> +    priv->inhibitDiskTransientDelete = false;
> +
> +    return 0;
> +}
> +
> +
>  static int
>  qemuSnapshotCreateActiveExternal(virQEMUDriverPtr driver,
>                                   virDomainObjPtr vm,
> diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h
> index 8b3ebe87b1..cf9bfec542 100644
> --- a/src/qemu/qemu_snapshot.h
> +++ b/src/qemu/qemu_snapshot.h
> @@ -21,6 +21,7 @@
>  #include "virconftypes.h"
>  #include "datatypes.h"
>  #include "qemu_conf.h"
> +#include "qemu_domainjob.h"
> 
>  virDomainMomentObjPtr
>  qemuSnapObjFromName(virDomainObjPtr vm,
> @@ -53,3 +54,7 @@ int
>  qemuSnapshotDelete(virDomainObjPtr vm,
>                     virDomainSnapshotPtr snapshot,
>                     unsigned int flags);
> +
> +int
> +qemuSnapshotCreateDisksTransient(virDomainObjPtr vm,
> +                                 qemuDomainAsyncJob asyncJob);
> -- 

Tested-by: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>

Thanks a lot!
Masa




More information about the libvir-list mailing list