Delete a mirrored snapshot by picking which of the two files in the mirror to reopen. This is not atomic, so we update the snapshot in place as we iterate through each successful disk. Since we limited mirrored snapshots to transient domains, there is no persistent configuration to update. This mode implies deleting the snapshot metadata but preserving the new file. * src/qemu/qemu_driver.c (qemuDomainSnapshotDelete): Honor new flags. (qemuDomainSnapshotDeleteMirror): New helper function. --- src/qemu/qemu_driver.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 89aa56c..428ba0f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11222,6 +11222,61 @@ qemuDomainSnapshotReparentChildren(void *payload, rep->driver->snapshotDir); } +/* Must be called while holding a job. */ +static int +qemuDomainSnapshotDeleteMirror(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainSnapshotObjPtr snap, + bool pivot) +{ + int i; + int ret = 0; + qemuDomainObjPrivatePtr priv = vm->privateData; + char *device = NULL; + char *file; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + return -1; + } + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + + for (i = 0; i < snap->def->ndisks; i++) { + if (!snap->def->disks[i].mirror) + continue; + VIR_FREE(device); + if (virAsprintf(&device, "drive-%s", + vm->def->disks[i]->info.alias) < 0) { + virReportOOMError(); + break; + } + file = pivot ? snap->def->disks[i].mirror : snap->def->disks[i].file; + if (qemuMonitorDriveReopen(priv->mon, device, file, + snap->def->disks[i].driverType) < 0) + break; + /* TODO: Release lock and reset label. */ + + VIR_FREE(vm->def->disks[i]->src); + vm->def->disks[i]->src = file; + if (pivot) + snap->def->disks[i].file = snap->def->disks[i].mirror; + snap->def->disks[i].mirror = NULL; + } + VIR_FREE(device); + if (i < snap->def->ndisks) + ret = -1; + + qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0 && + qemuDomainSnapshotWriteMetadata(vm, snap, driver->snapshotDir) < 0) + VIR_WARN("failed writing snapshot '%s' after partial mirror deletion", + snap->def->name); + return ret; +} + static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) { @@ -11234,10 +11289,14 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, struct snap_reparent rep; bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY); int external = 0; + bool mirror_abort = (flags & VIR_DOMAIN_SNAPSHOT_DELETE_MIRROR_ABORT) != 0; + bool mirror_pivot = (flags & VIR_DOMAIN_SNAPSHOT_DELETE_MIRROR_PIVOT) != 0; virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY | - VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1); + VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY | + VIR_DOMAIN_SNAPSHOT_DELETE_MIRROR_ABORT | + VIR_DOMAIN_SNAPSHOT_DELETE_MIRROR_PIVOT, -1); qemuDriverLock(driver); virUUIDFormat(snapshot->domain->uuid, uuidstr); @@ -11262,8 +11321,16 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, _("domain has active disk mirrors")); goto cleanup; } + if (!(mirror_abort || mirror_pivot)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("must specify whether to abort or pivot " + "mirrors before deleting snapshot")); + goto cleanup; + } + flags |= VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY; + } else if (mirror_abort || mirror_pivot) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("deletion of active disk mirrors unimplemented")); + _("snapshot has no disk mirrors")); goto cleanup; } @@ -11286,6 +11353,10 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; + if ((mirror_abort || mirror_pivot) && + qemuDomainSnapshotDeleteMirror(driver, vm, snap, mirror_pivot) < 0) + goto endjob; + if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) { rem.driver = driver; -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list