[libvirt] [PATCHv3 12/19] storage: cache backing chain while qemu domain is live

Laine Stump laine at laine.org
Thu Oct 18 18:38:46 UTC 2012


On 10/17/2012 06:30 PM, Eric Blake wrote:
> Technically, we should not be re-probing any file that qemu might
> be currently writing to.  As such, we should cache the backing
> file chain prior to starting qemu.  This patch adds the cache,
> but does not use it until the next patch.
>
> Ultimately, we want to also store the chain in domain XML, so that
> it is remembered across libvirtd restarts, and so that the only
> kosher way to modify the backing chain of an offline domain will be
> through libvirt API calls, but we aren't there yet.  So for now, we
> merely invalidate the cache any time we do a live operation that
> alters the chain (block-pull, block-commit, external disk snapshot),
> as well as tear down the cache when the domain is not running.
>
> * src/conf/domain_conf.h (_virDomainDiskDef): New field.
> * src/conf/domain_conf.c (virDomainDiskDefFree): Clean new field.
> * src/qemu/qemu_domain.h (qemuDomainDetermineDiskChain): New
> prototype.
> * src/qemu/qemu_domain.c (qemuDomainDetermineDiskChain): New
> function.
> * src/qemu/qemu_driver.c (qemuDomainAttachDeviceDiskLive)
> (qemuDomainChangeDiskMediaLive): Pre-populate chain.
> (qemuDomainSnapshotCreateSingleDiskActive): Uncache chain before
> snapshot.
> * src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Update
> chain after block pull.
> ---
>
> v3: drop useless processStop cleanup, s/chain/backingChain/, don't
> make force discard errors
>
>  src/conf/domain_conf.c  |  1 +
>  src/conf/domain_conf.h  |  2 ++
>  src/qemu/qemu_domain.c  | 26 ++++++++++++++++++++++++++
>  src/qemu/qemu_domain.h  |  3 +++
>  src/qemu/qemu_driver.c  | 14 ++++++++++++++
>  src/qemu/qemu_process.c |  8 ++++++++
>  6 files changed, 54 insertions(+)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index a360c25..6487e6b 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -971,6 +971,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
>      VIR_FREE(def->src);
>      VIR_FREE(def->dst);
>      VIR_FREE(def->driverName);
> +    virStorageFileFreeMetadata(def->backingChain);
>      VIR_FREE(def->mirror);
>      VIR_FREE(def->auth.username);
>      VIR_FREE(def->wwn);
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index eec1f25..e7f0e9c 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -47,6 +47,7 @@
>  # include "virobject.h"
>  # include "device_conf.h"
>  # include "bitmap.h"
> +# include "storage_file.h"
>
>  /* forward declarations of all device types, required by
>   * virDomainDeviceDef
> @@ -568,6 +569,7 @@ struct _virDomainDiskDef {
>      } auth;
>      char *driverName;
>      int format; /* enum virStorageFileFormat */
> +    virStorageFileMetadataPtr backingChain;
>
>      char *mirror;
>      int mirrorFormat; /* enum virStorageFileFormat */
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index b51edc2..45f3a5e 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -2010,3 +2010,29 @@ qemuDomainCleanupRun(struct qemud_driver *driver,
>      priv->ncleanupCallbacks = 0;
>      priv->ncleanupCallbacks_max = 0;
>  }
> +
> +int
> +qemuDomainDetermineDiskChain(struct qemud_driver *driver,
> +                             virDomainDiskDefPtr disk,
> +                             bool force)
> +{
> +    bool probe = driver->allowDiskFormatProbing;
> +
> +    if (!disk->src)
> +        return 0;
> +
> +    if (disk->backingChain) {
> +        if (force) {
> +            virStorageFileFreeMetadata(disk->backingChain);
> +            disk->backingChain = NULL;
> +        } else {
> +            return 0;
> +        }
> +    }
> +    disk->backingChain = virStorageFileGetMetadata(disk->src, disk->format,
> +                                                   driver->user, driver->group,
> +                                                   probe);
> +    if (!disk->backingChain)
> +        return -1;
> +    return 0;
> +}
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 26b6c55..8a66f14 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -343,6 +343,9 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
>  int qemuDomainCheckDiskPresence(struct qemud_driver *driver,
>                                  virDomainObjPtr vm,
>                                  bool start_with_state);
> +int qemuDomainDetermineDiskChain(struct qemud_driver *driver,
> +                                 virDomainDiskDefPtr disk,
> +                                 bool force);
>
>  int qemuDomainCleanupAdd(virDomainObjPtr vm,
>                           qemuDomainCleanupCallback cb);
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 7f240a0..dfbf04d 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -5816,6 +5816,9 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
>          goto end;
>      }
>
> +    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
> +        goto end;
> +
>      if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
>          if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
>              virReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -6044,6 +6047,9 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
>      virCgroupPtr cgroup = NULL;
>      int ret = -1;
>
> +    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
> +        goto end;
> +
>      if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
>          if (virCgroupForDomain(driver->cgroup,
>                                 vm->def->name, &cgroup, 0) != 0) {
> @@ -10788,6 +10794,14 @@ qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
>      disk->src = source;
>      origdriver = disk->format;
>      disk->format = VIR_STORAGE_FILE_RAW; /* Don't want to probe backing files */
> +    /* XXX Here, we know we are about to alter disk->backingChain if
> +     * successful, so we nuke the existing chain so that future
> +     * commands will recompute it.  Better would be storing the chain
> +     * ourselves rather than reprobing, but this requires modifying
> +     * domain_conf and our XML to fully track the chain across
> +     * libvirtd restarts.  */
> +    virStorageFileFreeMetadata(disk->backingChain);
> +    disk->backingChain = NULL;
>
>      if (virDomainLockDiskAttach(driver->lockManager, driver->uri,
>                                  vm, disk) < 0)
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index e08ec67..0e98c8b 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -909,6 +909,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
>      if (disk) {
>          path = disk->src;
>          event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
> +        /* XXX If we completed a block pull, then recompute the cached
> +         * backing chain to match.  Better would be storing the chain
> +         * ourselves rather than reprobing, but this requires
> +         * modifying domain_conf and our XML to fully track the chain
> +         * across libvirtd restarts.  */
> +        if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL &&
> +            status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
> +            qemuDomainDetermineDiskChain(driver, disk, true);
>      }
>
>      virDomainObjUnlock(vm);

ACK.




More information about the libvir-list mailing list