提交 cfb16b8e 编写于 作者: E Eric Blake

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: NEric Blake <eblake@redhat.com>
上级 232a31be
...@@ -15512,9 +15512,11 @@ qemuDomainBlockCommit(virDomainPtr dom, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册