Use the code for creating or attaching new storage source in the
snapshot code and switch to 'blockdev-snapshot' for creating the
snapshot itself.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_driver.c | 104 ++++++++++++++++++++++++++++++++++-------
1 file changed, 88 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6e10b691e9..c22f74adaa 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15270,6 +15270,8 @@ struct _qemuDomainSnapshotDiskData {
bool prepared; /* @src was prepared using qemuDomainStorageSourceAccessAllow */
virDomainDiskDefPtr disk;
char *relPath; /* relative path component to fill into original disk */
+ qemuBlockStorageSourceChainDataPtr crdata;
+ bool blockdevadded;
virStorageSourcePtr persistsrc;
virDomainDiskDefPtr persistdisk;
@@ -15283,7 +15285,8 @@ static void
qemuDomainSnapshotDiskDataCleanup(qemuDomainSnapshotDiskDataPtr data,
size_t ndata,
virQEMUDriverPtr driver,
- virDomainObjPtr vm)
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob)
{
size_t i;
@@ -15294,6 +15297,15 @@ qemuDomainSnapshotDiskDataCleanup(qemuDomainSnapshotDiskDataPtr
data,
/* on success of the snapshot the 'src' and 'persistsrc'
properties will
* be set to NULL by qemuDomainSnapshotUpdateDiskSources */
if (data[i].src) {
+ if (data[i].blockdevadded) {
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+
+ qemuBlockStorageSourceAttachRollback(qemuDomainGetMonitor(vm),
+ data[i].crdata->srcdata[0]);
+ ignore_value(qemuDomainObjExitMonitor(driver, vm));
+ }
+ }
+
if (data[i].created &&
virStorageFileUnlink(data[i].src) < 0) {
VIR_WARN("Unable to remove just-created %s",
@@ -15312,6 +15324,7 @@ qemuDomainSnapshotDiskDataCleanup(qemuDomainSnapshotDiskDataPtr
data,
VIR_FREE(data[i].relPath);
}
+ qemuBlockStorageSourceChainDataFree(data[i].crdata);
VIR_FREE(data);
}
@@ -15319,15 +15332,20 @@ qemuDomainSnapshotDiskDataCleanup(qemuDomainSnapshotDiskDataPtr
data,
static int
qemuDomainSnapshotDiskDataCollectOne(virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virQEMUDriverConfigPtr cfg,
virDomainDiskDefPtr disk,
virDomainSnapshotDiskDefPtr snapdisk,
qemuDomainSnapshotDiskDataPtr dd,
- bool reuse)
+ bool reuse,
+ bool blockdev,
+ qemuDomainAsyncJob asyncJob)
{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
char *backingStoreStr;
virDomainDiskDefPtr persistdisk;
bool supportsCreate;
bool supportsBacking;
+ int rc;
dd->disk = disk;
@@ -15393,6 +15411,44 @@ qemuDomainSnapshotDiskDataCollectOne(virQEMUDriverPtr driver,
dd->prepared = true;
+ if (blockdev) {
+ /* create a terminator for the snapsot disks so that qemu does not try
+ * to open them at first */
+ virObjectUnref(dd->src->backingStore);
+ if (!(dd->src->backingStore = virStorageSourceNew()))
+ return -1;
+
+ if (qemuDomainPrepareStorageSourceBlockdev(dd->disk, dd->src,
+ priv, cfg) < 0)
+ return -1;
+
+ if (!(dd->crdata =
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(dd->src,
+
priv->qemuCaps)))
+ return -1;
+
+ if (reuse) {
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ rc = qemuBlockStorageSourceAttachApply(qemuDomainGetMonitor(vm),
+ dd->crdata->srcdata[0]);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+ return -1;
+ } else {
+ if (qemuBlockStorageSourceCreateDetectSize(vm, dd->src,
dd->disk->src,
+ asyncJob) < 0)
+ return -1;
+
+ if (qemuBlockStorageSourceCreate(vm, dd->src, dd->disk->src,
+ NULL, dd->crdata->srcdata[0],
+ asyncJob) < 0)
+ return -1;
+ }
+
+ dd->blockdevadded = true;
+ }
+
return 0;
}
@@ -15407,7 +15463,10 @@ static int
qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainMomentObjPtr snap,
+ virQEMUDriverConfigPtr cfg,
bool reuse,
+ bool blockdev,
+ qemuDomainAsyncJob asyncJob,
qemuDomainSnapshotDiskDataPtr *rdata,
size_t *rndata)
{
@@ -15424,9 +15483,10 @@ qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver,
if (snapdef->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
continue;
- if (qemuDomainSnapshotDiskDataCollectOne(driver, vm, vm->def->disks[i],
+ if (qemuDomainSnapshotDiskDataCollectOne(driver, vm, cfg,
vm->def->disks[i],
snapdef->disks + i,
- data + ndata++, reuse) < 0)
+ data + ndata++, reuse, blockdev,
+ asyncJob) < 0)
goto cleanup;
}
@@ -15435,7 +15495,7 @@ qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver,
ret = 0;
cleanup:
- qemuDomainSnapshotDiskDataCleanup(data, ndata, driver, vm);
+ qemuDomainSnapshotDiskDataCleanup(data, ndata, driver, vm, asyncJob);
return ret;
}
@@ -15456,13 +15516,15 @@ qemuDomainSnapshotUpdateDiskSourcesRenumber(virStorageSourcePtr
src)
* @driver: QEMU driver
* @vm: domain object
* @dd: snapshot disk data object
+ * @blockdev: -blockdev is in use for the VM
*
* Updates disk definition after a successful snapshot.
*/
static void
qemuDomainSnapshotUpdateDiskSources(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainSnapshotDiskDataPtr dd)
+ qemuDomainSnapshotDiskDataPtr dd,
+ bool blockdev)
{
/* storage driver access won'd be needed */
if (dd->initialized)
@@ -15475,11 +15537,13 @@ qemuDomainSnapshotUpdateDiskSources(virQEMUDriverPtr driver,
dd->disk->src->readonly = true;
VIR_STEAL_PTR(dd->disk->src->relPath, dd->relPath);
+ virObjectUnref(dd->src->backingStore);
VIR_STEAL_PTR(dd->src->backingStore, dd->disk->src);
VIR_STEAL_PTR(dd->disk->src, dd->src);
/* fix numbering of disks */
- qemuDomainSnapshotUpdateDiskSourcesRenumber(dd->disk->src);
+ if (!blockdev)
+ qemuDomainSnapshotUpdateDiskSourcesRenumber(dd->disk->src);
if (dd->persistdisk) {
VIR_STEAL_PTR(dd->persistsrc->backingStore, dd->persistdisk->src);
@@ -15506,6 +15570,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
qemuDomainSnapshotDiskDataPtr diskdata = NULL;
size_t ndiskdata = 0;
virErrorPtr orig_err = NULL;
+ bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
if (virDomainObjCheckActive(vm) < 0)
return -1;
@@ -15515,8 +15580,8 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
/* prepare a list of objects to use in the vm definition so that we don't
* have to roll back later */
- if (qemuDomainSnapshotDiskDataCollect(driver, vm, snap, reuse,
- &diskdata, &ndiskdata) < 0)
+ if (qemuDomainSnapshotDiskDataCollect(driver, vm, snap, cfg, reuse, blockdev,
+ asyncJob, &diskdata, &ndiskdata) <
0)
goto cleanup;
/* check whether there's anything to do */
@@ -15530,11 +15595,18 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
* VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL with a valid file name and
* qcow2 format. */
for (i = 0; i < ndiskdata; i++) {
- if (qemuBlockSnapshotAddLegacy(actions,
- diskdata[i].disk,
- diskdata[i].src,
- reuse) < 0)
- goto cleanup;
+ if (blockdev) {
+ if (qemuBlockSnapshotAddBlockdev(actions,
+ diskdata[i].disk,
+ diskdata[i].src))
+ goto cleanup;
+ } else {
+ if (qemuBlockSnapshotAddLegacy(actions,
+ diskdata[i].disk,
+ diskdata[i].src,
+ reuse) < 0)
+ goto cleanup;
+ }
}
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
@@ -15551,7 +15623,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", rc
>= 0);
if (rc == 0)
- qemuDomainSnapshotUpdateDiskSources(driver, vm, dd);
+ qemuDomainSnapshotUpdateDiskSources(driver, vm, dd, blockdev);
}
if (rc < 0)
@@ -15583,7 +15655,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
vm->newDef) < 0))
ret = -1;
- qemuDomainSnapshotDiskDataCleanup(diskdata, ndiskdata, driver, vm);
+ qemuDomainSnapshotDiskDataCleanup(diskdata, ndiskdata, driver, vm, asyncJob);
virErrorRestore(&orig_err);
return ret;
--
2.21.0