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

Eric Blake eblake at redhat.com
Mon Jun 22 23:06:46 UTC 2015


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)
+        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,
+                                  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)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 8c84cdb..2d1afc4 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -410,6 +410,11 @@ int qemuMonitorBlockStatsUpdateThreshold(qemuMonitorPtr mon,
                                          virHashTablePtr stats)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);

+int qemuMonitorBlockSetWriteThreshold(qemuMonitorPtr mon,
+                                      const char *dev_name,
+                                      unsigned long long threshold)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
 int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
                               const char *dev_name,
                               unsigned long long *extent);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 46383d7..6cfba99 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2048,6 +2048,36 @@ qemuMonitorJSONBlockStatsUpdateThreshold(qemuMonitorPtr mon,
 }


+int
+qemuMonitorJSONBlockSetWriteThreshold(qemuMonitorPtr mon,
+                                      const char *dev_name,
+                                      unsigned long long threshold)
+{
+    int ret = -1;
+    int rc;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("block-set-write-threshold",
+                                           "s:node-name", dev_name,
+                                           "U:write-threshold", threshold,
+                                           NULL)))
+        return -1;
+
+    if ((rc = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
+        goto cleanup;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
+
+
 static int
 qemuMonitorJSONReportBlockExtentError(qemuMonitorBlockExtentError error)
 {
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 2f90b5c..fe00f20 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -79,6 +79,9 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
                                             bool backingChain);
 int qemuMonitorJSONBlockStatsUpdateThreshold(qemuMonitorPtr mon,
                                              virHashTablePtr stats);
+int qemuMonitorJSONBlockSetWriteThreshold(qemuMonitorPtr mon,
+                                          const char *dev_name,
+                                          unsigned long long threshold);
 int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
                                   const char *dev_name,
                                   unsigned long long *extent);
-- 
2.4.3




More information about the libvir-list mailing list