[PATCH v3 0/6] qemu: implementation of transient disk option

This patchset tries to implement transient option for qcow2 and raw format disk. It gets user available to set <transient/> to the domain xml file like as: <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/guest.qcow2'/> <target dev='vda' bus='virtio'/> <transient/> </disk> Any changes which the Guest does to the disk is dropped when the Guest is shutdowned. There are some limitations for transient disk option so far: - Supported disk format is qcow2 and raw - blockdev capability is required for qemu - Following features are blocked with transient disk option - blockjobs - Migration - Disk hotplug Masayoshi Mizuma (6): qemu: Block blockjobs when transient disk option is enabled qemu: Block disk hotplug when transient disk option is enabled qemu: Block migration when transient disk option is enabled qemu: update the validation for transient disk option qemu: Introduce to handle transient disk qemu: Add transient disk handler to start and stop the guest src/qemu/qemu_domain.c | 7 +++ src/qemu/qemu_hotplug.c | 6 +++ src/qemu/qemu_migration.c | 10 ++++ src/qemu/qemu_process.c | 10 ++++ src/qemu/qemu_snapshot.c | 103 +++++++++++++++++++++++++++++++++++--- src/qemu/qemu_snapshot.h | 5 ++ src/qemu/qemu_validate.c | 25 ++++++++- src/util/virstoragefile.c | 2 + src/util/virstoragefile.h | 4 ++ 9 files changed, 164 insertions(+), 8 deletions(-) -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_domain.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 785cee6f18..1ce0f70971 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10794,6 +10794,13 @@ qemuDomainDiskBlockJobIsSupported(virDomainObjPtr vm, return false; } + if (disk->transient) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("block jobs are not supported on transient disk '%s'"), + disk->dst); + return false; + } + return true; } -- 2.27.0

On Thu, Sep 17, 2020 at 09:30:40 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_domain.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On Fri, Sep 18, 2020 at 14:53:53 +0200, Peter Krempa wrote:
On Thu, Sep 17, 2020 at 09:30:40 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_domain.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Actually, I'd prefer some explanation in the commit message. No need to re-send for now as I'll probably be fixing some things in other patches as well.

On Fri, Sep 18, 2020 at 02:57:08PM +0200, Peter Krempa wrote:
On Fri, Sep 18, 2020 at 14:53:53 +0200, Peter Krempa wrote:
On Thu, Sep 17, 2020 at 09:30:40 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_domain.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Actually, I'd prefer some explanation in the commit message. No need to re-send for now as I'll probably be fixing some things in other patches as well.
Got it, thank you so much for your help! - Masa

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_hotplug.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e2c6e14c2e..20dcec7b65 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1031,6 +1031,12 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, return -1; } + if (disk->transient) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("transient disk hotplug isn't supported")); + return -1; + } + if (virDomainDiskTranslateSourcePool(disk) < 0) goto cleanup; -- 2.27.0

On Thu, Sep 17, 2020 at 09:30:41 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_hotplug.c | 6 ++++++ 1 file changed, 6 insertions(+)
Similarly to previous commit, the code is good but the commit message could actually describe the reasons. Reviewed-by: Peter Krempa <pkrempa@redhat.com>

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Block migration when transient disk option is enabled because migration requires some blockjobs. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_migration.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a530c17582..7316d74677 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1397,6 +1397,16 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver, _("cannot migrate this domain without dbus-vmstate support")); return false; } + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + + if (disk->transient) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("migration with transient disk is not supported")); + return false; + } + } } return true; -- 2.27.0

On Thu, Sep 17, 2020 at 09:30:42 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Block migration when transient disk option is enabled because migration requires some blockjobs.
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_migration.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a530c17582..7316d74677 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1397,6 +1397,16 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver, _("cannot migrate this domain without dbus-vmstate support")); return false; } + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + + if (disk->transient) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("migration with transient disk is not supported"));
transient disk '%s' is not supported and use disk->dst as '%s'
+ return false; + } + }
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Update validation of transient disk option. The option for qemu is supported with under condistions. - qemu has blockdev feature - the type is file and the format is qcow2 and raw - writable disk Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_validate.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 070f1c962b..9cf78ca0c9 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2002,6 +2002,28 @@ qemuValidateDomainDeviceDefDiskSerial(const char *value) } +static int +qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef *disk, + virQEMUCapsPtr qemuCaps) +{ + if ((!qemuCaps) || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) + return false; + + if (disk->src->readonly) + return false; + + if ((disk->src->format != VIR_STORAGE_FILE_QCOW2) && + (disk->src->format != VIR_STORAGE_FILE_RAW) && + (disk->src->type != VIR_STORAGE_TYPE_FILE)) { + return false; + } + + if (virStorageSourceIsEmpty(disk->src)) + return false; + + return true; +} + static int qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, virQEMUCapsPtr qemuCaps) @@ -2186,7 +2208,8 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, } } - if (disk->transient) { + if ((disk->transient) && + !qemuValidateDomainDeviceDefDiskTransient(disk, qemuCaps)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("transient disks not supported yet")); return -1; -- 2.27.0

On Thu, Sep 17, 2020 at 09:30:43 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Update validation of transient disk option. The option for qemu is supported with under condistions.
- qemu has blockdev feature - the type is file and the format is qcow2 and raw - writable disk
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_validate.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 070f1c962b..9cf78ca0c9 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2002,6 +2002,28 @@ qemuValidateDomainDeviceDefDiskSerial(const char *value) }
+static int
This is declared as returning 'int'
+qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef *disk,
If this function is called qemuValidateDomainDeviceDefDiskTransient it should also do all of the validation including reporting errors.
+ virQEMUCapsPtr qemuCaps) +{ + if ((!qemuCaps) || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV))
Parentheses are not required around negation
+ return false;
but returns booleans instead
+ + if (disk->src->readonly) + return false; + + if ((disk->src->format != VIR_STORAGE_FILE_QCOW2) && + (disk->src->format != VIR_STORAGE_FILE_RAW) && + (disk->src->type != VIR_STORAGE_TYPE_FILE)) { + return false; + } + + if (virStorageSourceIsEmpty(disk->src)) + return false; + + return true; +} + static int qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, virQEMUCapsPtr qemuCaps) @@ -2186,7 +2208,8 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, } }
- if (disk->transient) { + if ((disk->transient) && + !qemuValidateDomainDeviceDefDiskTransient(disk, qemuCaps)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("transient disks not supported yet"));
The error messages this produces are really suboptimal. You don't know whether your qemu is old, whether incorrect format is used or whether it's a network disk.
return -1;
I'll rewrite this patch to produce better error messages and fix the problems above.

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Here is the implementation of transient option for qcow2 and raw format disk. This gets available <transient/> directive in domain xml file like as: <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/guest.qcow2'/> <target dev='vda' bus='virtio'/> <transient/> </disk> When the qemu command line options are built, a new qcow2 image is created with backing qcow2 by using blockdev-snapshot command. The backing image is the qcow2 file which is set as <source>. The filename of the new qcow2 image is original-source-file.TRANSIENT. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_snapshot.c | 103 +++++++++++++++++++++++++++++++++++--- src/qemu/qemu_snapshot.h | 5 ++ src/util/virstoragefile.c | 2 + src/util/virstoragefile.h | 4 ++ 4 files changed, 107 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 1e8ea80b22..67fdc488e0 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1158,7 +1158,8 @@ qemuSnapshotCreateDiskActive(virQEMUDriverPtr driver, virHashTablePtr blockNamedNodeData, unsigned int flags, virQEMUDriverConfigPtr cfg, - qemuDomainAsyncJob asyncJob) + qemuDomainAsyncJob asyncJob, + bool domSave) { qemuDomainObjPrivatePtr priv = vm->privateData; g_autoptr(virJSONValue) actions = NULL; @@ -1201,17 +1202,26 @@ qemuSnapshotCreateDiskActive(virQEMUDriverPtr driver, virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", rc >= 0); - if (rc == 0) + if (rc == 0) { qemuSnapshotDiskUpdateSource(driver, vm, dd, blockdev); + + if (dd->disk->transient) { + /* Mark the transient working is completed to make sure we can */ + /* remove the transient disk when the guest is shutdown. */ + dd->disk->src->transientEstablished = true; + } + } } if (rc < 0) goto cleanup; - if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0 || - (vm->newDef && virDomainDefSave(vm->newDef, driver->xmlopt, - cfg->configDir) < 0)) - goto cleanup; + if (domSave) { + if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0 || + (vm->newDef && virDomainDefSave(vm->newDef, driver->xmlopt, + cfg->configDir) < 0)) + goto cleanup; + } ret = 0; @@ -1349,7 +1359,7 @@ qemuSnapshotCreateActiveExternal(virQEMUDriverPtr driver, if ((ret = qemuSnapshotCreateDiskActive(driver, vm, snap, blockNamedNodeData, flags, cfg, - QEMU_ASYNC_JOB_SNAPSHOT)) < 0) + QEMU_ASYNC_JOB_SNAPSHOT, true)) < 0) goto cleanup; /* the snapshot is complete now */ @@ -2264,3 +2274,82 @@ qemuSnapshotDelete(virDomainObjPtr vm, cleanup: return ret; } + + +static int +qemuSnapshotSetupTransientDisk(virDomainSnapshotDiskDefPtr def, + virStorageSourcePtr src) +{ + g_autoptr(virStorageSource) trans = NULL; + + if (!(trans = virStorageSourceNew())) + return -1; + + trans->path = g_strdup_printf("%s.TRANSIENT", src->path); + if (virFileExists(trans->path)) { + virReportError(VIR_ERR_INVALID_ARG, + _("Transient disk '%s' for '%s' exists"), + trans->path, src->path); + return -1; + } + + trans->type = VIR_STORAGE_TYPE_FILE; + trans->format = VIR_STORAGE_FILE_QCOW2; + + def->src = g_steal_pointer(&trans); + + return 0; +} + + +int +qemuSnapshotCreateTransientDisk(virQEMUDriverPtr driver, + virDomainObjPtr vm, + int asyncJob) +{ + int rc; + size_t i; + virDomainMomentObjPtr snap = NULL; + g_autoptr(virDomainSnapshotDef) snapdef = NULL; + g_autoptr(virHashTable) blockNamedNodeData = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); + + if (!(snapdef = virDomainSnapshotDefNew())) + return -1; + + snapdef->parent.name = g_strdup_printf("transient"); + + snapdef->ndisks = vm->def->ndisks; + if (VIR_ALLOC_N(snapdef->disks, snapdef->ndisks) < 0) + return -1; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + virDomainSnapshotDiskDefPtr snapdisk = &(snapdef->disks[i]); + + if (disk->transient) { + if ((rc = qemuSnapshotSetupTransientDisk(snapdisk, disk->src)) < 0) + return -1; + + } else { + snapdisk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE; + } + } + + if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, snapdef))) + return -1; + + if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob))) + goto cleanup; + + /* The last argument domSave is false here because transient disk config */ + /* is volatile so we don't need to save it. */ + rc = qemuSnapshotCreateDiskActive(driver, vm, snap, blockNamedNodeData, + 0, cfg, asyncJob, false); + + cleanup: + virDomainSnapshotObjListRemove(vm->snapshots, snap); + + return rc; +} diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h index 8b3ebe87b1..d57ef4b8a4 100644 --- a/src/qemu/qemu_snapshot.h +++ b/src/qemu/qemu_snapshot.h @@ -53,3 +53,8 @@ int qemuSnapshotDelete(virDomainObjPtr vm, virDomainSnapshotPtr snapshot, unsigned int flags); + +int +qemuSnapshotCreateTransientDisk(virQEMUDriverPtr driver, + virDomainObjPtr vm, + int asyncJob); diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 97a346db28..636f27ef09 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2456,6 +2456,8 @@ virStorageSourceCopy(const virStorageSource *src, def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled; def->ssh_user = g_strdup(src->ssh_user); + def->transientEstablished = src->transientEstablished; + return g_steal_pointer(&def); } diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 87763cf389..0dc275c11e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -384,6 +384,10 @@ struct _virStorageSource { /* these must not be used apart from formatting the output JSON in the qemu driver */ char *ssh_user; bool ssh_host_key_check_disabled; + + /* set to true if the storage source is setup as a transient disk. */ + /* The changes to the disk are dropped after the guest machine is shutdown. */ + bool transientEstablished; }; G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSource, virObjectUnref); -- 2.27.0

On Thu, Sep 17, 2020 at 09:30:44 -0400, Masayoshi Mizuma wrote:
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Here is the implementation of transient option for qcow2 and raw format disk. This gets available <transient/> directive in domain xml file like as:
<disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/guest.qcow2'/> <target dev='vda' bus='virtio'/> <transient/> </disk>
When the qemu command line options are built, a new qcow2 image is created with backing qcow2 by using blockdev-snapshot command. The backing image is the qcow2 file which is set as <source>. The filename of the new qcow2 image is original-source-file.TRANSIENT.
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_snapshot.c | 103 +++++++++++++++++++++++++++++++++++--- src/qemu/qemu_snapshot.h | 5 ++ src/util/virstoragefile.c | 2 + src/util/virstoragefile.h | 4 ++ 4 files changed, 107 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 1e8ea80b22..67fdc488e0 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1158,7 +1158,8 @@ qemuSnapshotCreateDiskActive(virQEMUDriverPtr driver, virHashTablePtr blockNamedNodeData, unsigned int flags, virQEMUDriverConfigPtr cfg, - qemuDomainAsyncJob asyncJob) + qemuDomainAsyncJob asyncJob, + bool domSave) { qemuDomainObjPrivatePtr priv = vm->privateData; g_autoptr(virJSONValue) actions = NULL; @@ -1201,17 +1202,26 @@ qemuSnapshotCreateDiskActive(virQEMUDriverPtr driver,
virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", rc >= 0);
- if (rc == 0) + if (rc == 0) { qemuSnapshotDiskUpdateSource(driver, vm, dd, blockdev); + + if (dd->disk->transient) { + /* Mark the transient working is completed to make sure we can */ + /* remove the transient disk when the guest is shutdown. */ + dd->disk->src->transientEstablished = true; + } + } }
if (rc < 0) goto cleanup;
- if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0 || - (vm->newDef && virDomainDefSave(vm->newDef, driver->xmlopt, - cfg->configDir) < 0)) - goto cleanup; + if (domSave) { + if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0 || + (vm->newDef && virDomainDefSave(vm->newDef, driver->xmlopt, + cfg->configDir) < 0)) + goto cleanup; + }
ret = 0;
@@ -1349,7 +1359,7 @@ qemuSnapshotCreateActiveExternal(virQEMUDriverPtr driver,
if ((ret = qemuSnapshotCreateDiskActive(driver, vm, snap, blockNamedNodeData, flags, cfg, - QEMU_ASYNC_JOB_SNAPSHOT)) < 0) + QEMU_ASYNC_JOB_SNAPSHOT, true)) < 0) goto cleanup;
/* the snapshot is complete now */ @@ -2264,3 +2274,82 @@ qemuSnapshotDelete(virDomainObjPtr vm, cleanup: return ret; } + + +static int +qemuSnapshotSetupTransientDisk(virDomainSnapshotDiskDefPtr def, + virStorageSourcePtr src) +{ + g_autoptr(virStorageSource) trans = NULL; + + if (!(trans = virStorageSourceNew())) + return -1; + + trans->path = g_strdup_printf("%s.TRANSIENT", src->path); + if (virFileExists(trans->path)) { + virReportError(VIR_ERR_INVALID_ARG, + _("Transient disk '%s' for '%s' exists"), + trans->path, src->path); + return -1; + } + + trans->type = VIR_STORAGE_TYPE_FILE; + trans->format = VIR_STORAGE_FILE_QCOW2; + + def->src = g_steal_pointer(&trans); + + return 0; +} + + +int +qemuSnapshotCreateTransientDisk(virQEMUDriverPtr driver, + virDomainObjPtr vm, + int asyncJob) +{ + int rc; + size_t i; + virDomainMomentObjPtr snap = NULL; + g_autoptr(virDomainSnapshotDef) snapdef = NULL; + g_autoptr(virHashTable) blockNamedNodeData = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); + + if (!(snapdef = virDomainSnapshotDefNew())) + return -1;
This shouldn't be necessary if you factor out stuff out of qemuSnapshotCreateDiskActive. I'll send a prerequisite patch doing the refactor as I've requested last time.
+ + snapdef->parent.name = g_strdup_printf("transient"); + + snapdef->ndisks = vm->def->ndisks; + if (VIR_ALLOC_N(snapdef->disks, snapdef->ndisks) < 0) + return -1; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + virDomainSnapshotDiskDefPtr snapdisk = &(snapdef->disks[i]); + + if (disk->transient) { + if ((rc = qemuSnapshotSetupTransientDisk(snapdisk, disk->src)) < 0) + return -1; + + } else { + snapdisk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE; + } + } + + if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, snapdef))) + return -1; + + if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob))) + goto cleanup; + + /* The last argument domSave is false here because transient disk config */ + /* is volatile so we don't need to save it. */ + rc = qemuSnapshotCreateDiskActive(driver, vm, snap, blockNamedNodeData, + 0, cfg, asyncJob, false); + + cleanup: + virDomainSnapshotObjListRemove(vm->snapshots, snap);
+ + return rc; +} diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h index 8b3ebe87b1..d57ef4b8a4 100644 --- a/src/qemu/qemu_snapshot.h +++ b/src/qemu/qemu_snapshot.h @@ -53,3 +53,8 @@ int qemuSnapshotDelete(virDomainObjPtr vm, virDomainSnapshotPtr snapshot, unsigned int flags); + +int +qemuSnapshotCreateTransientDisk(virQEMUDriverPtr driver, + virDomainObjPtr vm, + int asyncJob); diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 97a346db28..636f27ef09 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2456,6 +2456,8 @@ virStorageSourceCopy(const virStorageSource *src, def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled; def->ssh_user = g_strdup(src->ssh_user);
+ def->transientEstablished = src->transientEstablished; + return g_steal_pointer(&def); }
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 87763cf389..0dc275c11e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -384,6 +384,10 @@ struct _virStorageSource { /* these must not be used apart from formatting the output JSON in the qemu driver */ char *ssh_user; bool ssh_host_key_check_disabled; + + /* set to true if the storage source is setup as a transient disk. */ + /* The changes to the disk are dropped after the guest machine is shutdown. */ + bool transientEstablished;
This is not written into the status XML, so after libvirtd restart you lose the value. That means that the transient file will not be removed after VM shutdown if libvirtd was restarted. IMO it's not even necessary to store this, I'll see whether I can remove it.
};
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSource, virObjectUnref); -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> The transient disk is attached before the guest starts. Remove the transient disk when the guest does shutdown. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_process.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index b1af35b933..387b8071f4 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -60,6 +60,7 @@ #include "qemu_firmware.h" #include "qemu_backup.h" #include "qemu_dbus.h" +#include "qemu_snapshot.h" #include "cpu/cpu.h" #include "cpu/cpu_x86.h" @@ -7053,6 +7054,10 @@ qemuProcessLaunch(virConnectPtr conn, qemuProcessAutoDestroyAdd(driver, vm, conn) < 0) goto cleanup; + VIR_DEBUG("Setting up transient disk"); + if (qemuSnapshotCreateTransientDisk(driver, vm, asyncJob) < 0) + goto cleanup; + ret = 0; cleanup: @@ -7689,6 +7694,11 @@ void qemuProcessStop(virQEMUDriverPtr driver, } qemuBlockRemoveImageMetadata(driver, vm, disk->dst, disk->src); + + if ((disk->transient) && (disk->src->transientEstablished)) { + VIR_DEBUG("unlink transient disk: %s", disk->src->path); + unlink(disk->src->path); + } } } -- 2.27.0
participants (2)
-
Masayoshi Mizuma
-
Peter Krempa