Re: [PATCH v3 5/6] qemu: Introduce to handle transient disk
On Thu, Sep 17, 2020 at 09:30:44 -0400, Masayoshi Mizuma wrote: > From: Masayoshi Mizuma > > Here is the implementation of transient option for qcow2 and raw format > disk. This gets available directive in domain xml file > like as: > > > > > > > > > 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 . > The filename of the new qcow2 image is original-source-file.TRANSIENT. > > Signed-off-by: Masayoshi Mizuma > --- > 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) > +retur
[PATCH v3 5/6] qemu: Introduce to handle transient disk
From: Masayoshi Mizuma Here is the implementation of transient option for qcow2 and raw format disk. This gets available directive in domain xml file like as: 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 . The filename of the new qcow2 image is original-source-file.TRANSIENT. Signed-off-by: Masayoshi Mizuma --- 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))) +re