[libvirt] [PATCHv3 17/19] blockjob: implement shallow commit flag in qemu
Laine Stump
laine at laine.org
Thu Oct 18 18:46:01 UTC 2012
On 10/17/2012 06:30 PM, Eric Blake wrote:
> Now that we can crawl the chain of backing files, we can do
> argument validation and implement the 'shallow' flag. In
> testing this, I discovered that it can be handy to pass the
> shallow flag and an explicit base, as a means of validating
> that the base is indeed the file we expected.
>
> * src/qemu/qemu_driver.c (qemuDomainBlockCommit): Crawl through
> chain to implement shallow flag.
> * src/libvirt.c (virDomainBlockCommit): Relax API.
> ---
>
> v3: rebase to changes earlier in series
>
> src/libvirt.c | 2 --
> src/qemu/qemu_driver.c | 63 ++++++++++++++++++++++++++++++++++++++++----------
> 2 files changed, 51 insertions(+), 14 deletions(-)
>
> diff --git a/src/libvirt.c b/src/libvirt.c
> index e3ddf27..6d65965 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -19381,8 +19381,6 @@ int virDomainBlockCommit(virDomainPtr dom, const char *disk,
> }
>
> virCheckNonNullArgGoto(disk, error);
> - if (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW)
> - virCheckNullArgGoto(base, error);
>
> if (conn->driver->domainBlockCommit) {
> int ret;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index c63d16b..73804fe 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -12664,8 +12664,12 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
> int ret = -1;
> int idx;
> virDomainDiskDefPtr disk;
> + const char *top_canon = NULL;
> + virStorageFileMetadataPtr top_meta = NULL;
> + const char *top_parent = NULL;
> + const char *base_canon = NULL;
>
> - virCheckFlags(0, -1);
> + virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
>
> if (!(vm = qemuDomObjFromDomain(dom)))
> goto cleanup;
> @@ -12696,20 +12700,55 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
> disk->dst);
> goto endjob;
> }
> + if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
> + goto endjob;
>
> - if (!top)
> - top = disk->src;
> + if (!top) {
> + top_canon = disk->src;
> + top_meta = disk->backingChain;
> + } else if (!(top_canon = virStorageFileChainLookup(disk->backingChain,
> + disk->src,
> + top, &top_meta,
> + &top_parent))) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("could not find top '%s' in chain for '%s'"),
> + top, path);
> + goto endjob;
> + }
> + if (!top_meta || !top_meta->backingStore) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("top '%s' in chain for '%s' has no backing file"),
> + top, path);
> + goto endjob;
> + }
> + if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW)) {
> + base_canon = top_meta->backingStore;
> + } else if (!(base_canon = virStorageFileChainLookup(top_meta, top_canon,
> + base, NULL, NULL))) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("could not find base '%s' below '%s' in chain "
> + "for '%s'"),
> + base ? base : "(default)", top_canon, path);
> + goto endjob;
> + }
> + /* Note that this code exploits the fact that
> + * virStorageFileChainLookup guarantees a simple pointer
> + * comparison will work, rather than needing full-blown STREQ. */
> + if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
> + base_canon != top_meta->backingStore) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("base '%s' is not immediately below '%s' in chain "
> + "for '%s'"),
> + base, top_canon, path);
> + goto endjob;
> + }
>
> - /* XXX For now, we are relying on qemu to check that 'top' and
> - * 'base' resolve to members of the backing chain in correct
> - * order; but if we ever get more paranoid and track the backing
> - * chain ourself, we should be pre-validating the data rather than
> - * relying on qemu. For that matter, we need to be changing the
> - * SELinux label on both 'base' and the parent of 'top', so that
> - * qemu can open(O_RDWR) those files for the duration of the
> - * commit. */
> + /* XXX We need to be changing the SELinux label on both 'base' and
> + * the parent of 'top', so that qemu can open(O_RDWR) those files
> + * for the duration of the commit. */
> qemuDomainObjEnterMonitor(driver, vm);
> - ret = qemuMonitorBlockCommit(priv->mon, device, top, base, bandwidth);
> + ret = qemuMonitorBlockCommit(priv->mon, device, top_canon, base_canon,
> + bandwidth);
> qemuDomainObjExitMonitor(driver, vm);
>
> endjob:
Previous ACK stands.
More information about the libvir-list
mailing list