mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
blockcommit: turn on active commit
With this in place, I can (finally!) now do: virsh blockcommit $dom vda --shallow --verbose --pivot and watch qemu shorten the backing chain by one, followed by libvirt automatically updating the dumpxml output, effectively undoing the work of virsh snapshot-commit --no-metadata --disk-only. Commit is SOOOO much faster than blockpull, when I'm still fairly close in time to when the temporary qcow2 wrapper file was created via a snapshot operation! * src/qemu/qemu_driver.c (qemuDomainBlockCommit): Implement live commit. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
232a31bea3
commit
cfb16b8ed7
@ -15512,9 +15512,11 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
char *topPath = NULL;
|
char *topPath = NULL;
|
||||||
char *basePath = NULL;
|
char *basePath = NULL;
|
||||||
char *backingPath = NULL;
|
char *backingPath = NULL;
|
||||||
|
virStorageSourcePtr mirror = NULL;
|
||||||
|
|
||||||
/* XXX Add support for COMMIT_ACTIVE, COMMIT_DELETE */
|
/* XXX Add support for COMMIT_DELETE */
|
||||||
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
|
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
|
||||||
|
VIR_DOMAIN_BLOCK_COMMIT_ACTIVE |
|
||||||
VIR_DOMAIN_BLOCK_COMMIT_RELATIVE, -1);
|
VIR_DOMAIN_BLOCK_COMMIT_RELATIVE, -1);
|
||||||
|
|
||||||
if (!(vm = qemuDomObjFromDomain(dom)))
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
@ -15563,9 +15565,6 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
&top_parent)))
|
&top_parent)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
/* FIXME: qemu 2.0 supports active commit, but as a two-stage
|
|
||||||
* process; qemu 2.1 is further improving active commit. We need
|
|
||||||
* to start supporting it in libvirt. */
|
|
||||||
if (topSource == disk->src) {
|
if (topSource == disk->src) {
|
||||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
@ -15579,6 +15578,12 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
disk->dst);
|
disk->dst);
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
if (disk->mirror) {
|
||||||
|
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
||||||
|
_("disk '%s' already in active block job"),
|
||||||
|
disk->dst);
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
} else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
|
} else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("active commit requested but '%s' is not active"),
|
_("active commit requested but '%s' is not active"),
|
||||||
@ -15609,6 +15614,16 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For an active commit, clone enough of the base to act as the mirror */
|
||||||
|
if (topSource == disk->src) {
|
||||||
|
if (!(mirror = virStorageSourceCopy(baseSource, false)))
|
||||||
|
goto endjob;
|
||||||
|
if (virStorageSourceInitChainElement(mirror,
|
||||||
|
disk->src,
|
||||||
|
false) < 0)
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
/* For the commit to succeed, we must allow qemu to open both the
|
/* For the commit to succeed, we must allow qemu to open both the
|
||||||
* 'base' image and the parent of 'top' as read/write; 'top' might
|
* 'base' image and the parent of 'top' as read/write; 'top' might
|
||||||
* not have a parent, or might already be read-write. XXX It
|
* not have a parent, or might already be read-write. XXX It
|
||||||
@ -15653,13 +15668,33 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
* if any, through to qemu, since qemu may behave differently
|
* if any, through to qemu, since qemu may behave differently
|
||||||
* depending on whether the input was specified as relative or
|
* depending on whether the input was specified as relative or
|
||||||
* absolute (that is, our absolute top_canon may do the wrong
|
* absolute (that is, our absolute top_canon may do the wrong
|
||||||
* thing if the user specified a relative name). */
|
* thing if the user specified a relative name). Be prepared for
|
||||||
|
* a ready event to occur while locks are dropped. */
|
||||||
|
if (mirror) {
|
||||||
|
disk->mirror = mirror;
|
||||||
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
|
||||||
|
}
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
ret = qemuMonitorBlockCommit(priv->mon, device,
|
ret = qemuMonitorBlockCommit(priv->mon, device,
|
||||||
topPath, basePath, backingPath,
|
topPath, basePath, backingPath,
|
||||||
bandwidth);
|
bandwidth);
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
|
if (mirror) {
|
||||||
|
if (ret == 0) {
|
||||||
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
|
||||||
|
mirror = NULL;
|
||||||
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
|
VIR_WARN("Unable to save status on vm %s after block job",
|
||||||
|
vm->def->name);
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
} else {
|
||||||
|
disk->mirror = NULL;
|
||||||
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
endjob:
|
endjob:
|
||||||
if (ret < 0 && clean_access) {
|
if (ret < 0 && clean_access) {
|
||||||
/* Revert access to read-only, if possible. */
|
/* Revert access to read-only, if possible. */
|
||||||
@ -15669,6 +15704,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
qemuDomainPrepareDiskChainElement(driver, vm, top_parent,
|
qemuDomainPrepareDiskChainElement(driver, vm, top_parent,
|
||||||
VIR_DISK_CHAIN_READ_ONLY);
|
VIR_DISK_CHAIN_READ_ONLY);
|
||||||
}
|
}
|
||||||
|
virStorageSourceFree(mirror);
|
||||||
if (!qemuDomainObjEndJob(driver, vm))
|
if (!qemuDomainObjEndJob(driver, vm))
|
||||||
vm = NULL;
|
vm = NULL;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user