[libvirt] [PATCHv3 10/10] threshold: add write threshold setting in qemu

Peter Krempa pkrempa at redhat.com
Tue Jun 23 14:01:54 UTC 2015


On Mon, Jun 22, 2015 at 17:06:46 -0600, Eric Blake wrote:
> Time to wire up the new API to call into the QMP command for setting
> a write threshold.
> 
> For now, the API only allows setting the threshold on the active
> layer.  But I left TODOs in the series for places that need
> touching to find and support node names of backing files, so that
> we can use "vda[1]" notation to register for a threshold on the
> backing image during an active commit operation.
> 
> * src/qemu/qemu_driver.c (qemuDomainBlockSetWriteThreshold): New
> function.
> * src/qemu/qemu_monitor.c (qemuMonitorBlockSetWriteThreshold):
> Likewise.
> * src/qemu/qemu_monitor.h (qemuMonitorBlockSetWriteThreshold):
> Likewise.
> * src/qemu/qemu_monitor_json.c
> (qemuMonitorJSONBlockSetWriteThreshold): Likewise.
> * src/qemu/qemu_monitor_json.h
> (qemuMonitorJSONBlockSetWriteThreshold): Likewise.
> 
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
>  src/qemu/qemu_driver.c       | 95 ++++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor.c      | 13 ++++++
>  src/qemu/qemu_monitor.h      |  5 +++
>  src/qemu/qemu_monitor_json.c | 30 ++++++++++++++
>  src/qemu/qemu_monitor_json.h |  3 ++
>  5 files changed, 146 insertions(+)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 72e256b..732f102 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -17906,6 +17906,100 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
>      return ret;
>  }
> 
> +
> +static int
> +qemuDomainBlockSetWriteThreshold(virDomainPtr dom,
> +                                 const char *path,
> +                                 unsigned long long threshold,
> +                                 unsigned int flags)
> +{
> +    virQEMUDriverPtr driver = dom->conn->privateData;
> +    virDomainObjPtr vm = NULL;
> +    qemuDomainObjPrivatePtr priv;
> +    virDomainDiskDefPtr disk = NULL;
> +    virCapsPtr caps = NULL;
> +    virQEMUDriverConfigPtr cfg = NULL;
> +    const char *node = NULL;
> +    int ret = -1;
> +
> +    virCheckFlags(VIR_DOMAIN_BLOCK_SET_WRITE_THRESHOLD_PROPORTION, -1);
> +
> +    if (!(vm = qemuDomObjFromDomain(dom)))
> +        return -1;
> +    priv = vm->privateData;
> +
> +    if (virDomainBlockSetWriteThresholdEnsureACL(dom->conn, vm->def) < 0)
> +        goto cleanup;
> +
> +    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
> +        goto cleanup;
> +    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_WRITE_THRESHOLD) ||
> +        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_AUTO_NODE_NAMES)) {
> +        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> +                       _("block write threshold not supported by this "
> +                         "qemu binary"));
> +        goto cleanup;
> +    }
> +
> +    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
> +        goto cleanup;
> +
> +    if (!virDomainObjIsActive(vm)) {
> +        virReportError(VIR_ERR_OPERATION_INVALID,
> +                       "%s", _("domain is not running"));
> +        goto endjob;
> +    }
> +
> +    if (!(disk = virDomainDiskByName(vm->def, path, false))) {
> +        virReportError(VIR_ERR_INVALID_ARG,
> +                       _("invalid path %s not assigned to domain"), path);
> +        goto endjob;
> +    }
> +
> +    if (!(node = qemuDomainDiskGetAllocationNode(driver, vm, disk))) {
> +        virReportError(VIR_ERR_INVALID_ARG,
> +                       _("cannot track threshold events on disk '%s'"),
> +                       path);
> +        goto endjob;
> +    }
> +
> +    cfg = virQEMUDriverGetConfig(driver);
> +    if (qemuStorageLimitsRefresh(driver, cfg, vm, disk->src) < 0)

This function begins with a rather long comment explaining that it's not
entirely a good idea to use it on online VMs and especially on
write-enabled disk sources. Shouldn't we query the monitor rather than
use that?

> +        goto endjob;
> +
> +    if (flags & VIR_DOMAIN_BLOCK_SET_WRITE_THRESHOLD_PROPORTION) {
> +        /* Caller already sanitized max value to 1000000.  Use of
> +         * floating point intermediary reduces (but does not
> +         * eliminate) rounding error, but since we already document a
> +         * granularity of parts per million, it shouldn't matter too
> +         * much if the answer is a few bytes off.  */
> +        threshold *= disk->src->physical / 1e6;
> +    } else {
> +        if (threshold > disk->src->physical) {
> +            virReportError(VIR_ERR_INVALID_ARG,
> +                           _("threshold %llu exceeds disk size %llu"),
> +                           threshold, disk->src->physical);
> +            goto endjob;
> +        }
> +    }
> +
> +    qemuDomainObjEnterMonitor(driver, vm);
> +    ret = qemuMonitorBlockSetWriteThreshold(priv->mon, node, threshold);
> +    if (qemuDomainObjExitMonitor(driver, vm) < 0)
> +        ret = -1;
> +
> +
> + endjob:
> +    qemuDomainObjEndJob(driver, vm);
> +
> + cleanup:
> +    virDomainObjEndAPI(&vm);
> +    virObjectUnref(caps);
> +    virObjectUnref(cfg);
> +    return ret;
> +}
> +
> +
>  static int
>  qemuDomainGetDiskErrors(virDomainPtr dom,
>                          virDomainDiskErrorPtr errors,
> @@ -20037,6 +20131,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
>      .nodeSuspendForDuration = qemuNodeSuspendForDuration, /* 0.9.8 */
>      .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
>      .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
> +    .domainBlockSetWriteThreshold = qemuDomainBlockSetWriteThreshold, /* 1.3.0 */
>      .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
>      .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
>      .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index c4b6073..2ff34e2 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -1866,6 +1866,19 @@ qemuMonitorBlockStatsUpdateThreshold(qemuMonitorPtr mon,
> 
> 
>  int
> +qemuMonitorBlockSetWriteThreshold(qemuMonitorPtr mon,
> +                                  const char *dev_name,

This function needs a node name passed so it should also be called that
way to avoid confusion since the function lacks docs.


> +                                  unsigned long long threshold)
> +{
> +    VIR_DEBUG("dev_name=%s, threshold=%llu", dev_name, threshold);
> +
> +    QEMU_CHECK_MONITOR_JSON(mon);
> +
> +    return qemuMonitorJSONBlockSetWriteThreshold(mon, dev_name, threshold);
> +}
> +
> +
> +int
>  qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
>                            const char *dev_name,
>                            unsigned long long *extent)

Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150623/92bc3066/attachment-0001.sig>


More information about the libvir-list mailing list