[PATCH Libvirt v3 04/10] qemu_driver: Implement qemuDomainSetVcpuDirtyLimit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx>

Implement qemuDomainSetVcpuDirtyLimit, which can be used to
set or cancel the upper limit of the dirty page rate for
virtual CPUs.

Signed-off-by: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx>
---
 src/qemu/qemu_driver.c       | 131 +++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c      |  13 ++++
 src/qemu/qemu_monitor.h      |   5 ++
 src/qemu/qemu_monitor_json.c |  43 ++++++++++++
 src/qemu/qemu_monitor_json.h |   5 ++
 5 files changed, 197 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d4da937b0..64d97c0fba 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19876,6 +19876,136 @@ qemuDomainFDAssociate(virDomainPtr domain,
     return ret;
 }
 
+static void
+qemuDomainSetDirtyLimit(virDomainVcpuDef *vcpu,
+                        unsigned long long rate)
+{
+    if (rate > 0) {
+        vcpu->dirtyLimitSet = true;
+        vcpu->dirty_limit = rate;
+    } else {
+        vcpu->dirtyLimitSet = false;
+        vcpu->dirty_limit = 0;
+    }
+}
+
+static void
+qemuDomainSetVcpuDirtyLimitConfig(virDomainDef *def,
+                                  int vcpu,
+                                  unsigned long long rate)
+{
+    def->individualvcpus = true;
+
+    if (vcpu == -1) {
+        size_t maxvcpus = virDomainDefGetVcpusMax(def);
+        size_t i;
+        for (i = 0; i < maxvcpus; i++) {
+            qemuDomainSetDirtyLimit(virDomainDefGetVcpu(def, i), rate);
+        }
+    } else {
+        qemuDomainSetDirtyLimit(virDomainDefGetVcpu(def, vcpu), rate);
+    }
+}
+
+static int
+qemuDomainSetVcpuDirtyLimitInternal(virQEMUDriver *driver,
+                                    virDomainObj *vm,
+                                    virDomainDef *def,
+                                    virDomainDef *persistentDef,
+                                    int vcpu,
+                                    unsigned long long rate)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    qemuDomainObjPrivate *priv = vm->privateData;
+
+    VIR_DEBUG("vcpu %d, rate %llu", vcpu, rate);
+    if (def) {
+        qemuDomainObjEnterMonitor(vm);
+        if (qemuMonitorSetVcpuDirtyLimit(priv->mon, vcpu, rate) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Failed to set dirty page rate limit"));
+            qemuDomainObjExitMonitor(vm);
+            return -1;
+        }
+        qemuDomainObjExitMonitor(vm);
+        qemuDomainSetVcpuDirtyLimitConfig(def, vcpu, rate);
+    }
+
+    if (persistentDef) {
+        qemuDomainSetVcpuDirtyLimitConfig(persistentDef, vcpu, rate);
+        if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+static int
+qemuDomainSetVcpuDirtyLimit(virDomainPtr domain,
+                            int vcpu,
+                            unsigned long long rate,
+                            unsigned int flags)
+{
+    virQEMUDriver *driver = domain->conn->privateData;
+    virDomainObj *vm = NULL;
+    qemuDomainObjPrivate *priv;
+    virDomainDef *def = NULL;
+    virDomainDef *persistentDef = NULL;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    if (!(vm = qemuDomainObjFromDomain(domain)))
+        return -1;
+
+    if (virDomainSetVcpuDirtyLimitEnsureACL(domain->conn, vm->def, flags) < 0)
+        goto cleanup;
+
+    if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+        goto endjob;
+
+    if (persistentDef) {
+        if (vcpu >= 0 && vcpu >= (int)virDomainDefGetVcpusMax(persistentDef)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("vcpu %1$d is not present in persistent config"),
+                           vcpu);
+            goto endjob;
+        }
+    }
+
+    if (def) {
+        if (virDomainObjCheckActive(vm) < 0)
+            goto endjob;
+
+        priv = vm->privateData;
+        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VCPU_DIRTY_LIMIT)) {
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                           _("QEMU does not support setting dirty page rate limit"));
+            goto endjob;
+        }
+
+        if (vcpu >= 0 && vcpu >= (int)virDomainDefGetVcpusMax(def)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("vcpu %1$d is not present in live config"),
+                           vcpu);
+            goto endjob;
+        }
+    }
+
+    ret = qemuDomainSetVcpuDirtyLimitInternal(driver, vm, def, persistentDef,
+                                              vcpu, rate);
+
+ endjob:
+    virDomainObjEndJob(vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
 
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
@@ -20126,6 +20256,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
     .domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
     .domainFDAssociate = qemuDomainFDAssociate, /* 9.0.0 */
+    .domainSetVcpuDirtyLimit = qemuDomainSetVcpuDirtyLimit, /* 9.7.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 7053539c7d..90bc0e62c9 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4500,3 +4500,16 @@ qemuMonitorGetStatsByQOMPath(virJSONValue *arr,
 
     return NULL;
 }
+
+
+int
+qemuMonitorSetVcpuDirtyLimit(qemuMonitor *mon,
+                             int vcpu,
+                             unsigned long long rate)
+{
+    VIR_DEBUG("set vcpu %d dirty page rate limit %llu", vcpu, rate);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONSetVcpuDirtyLimit(mon, vcpu, rate);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 6c590933aa..07a05365cf 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1579,3 +1579,8 @@ qemuMonitorExtractQueryStats(virJSONValue *info);
 virJSONValue *
 qemuMonitorGetStatsByQOMPath(virJSONValue *arr,
                              char *qom_path);
+
+int
+qemuMonitorSetVcpuDirtyLimit(qemuMonitor *mon,
+                             int vcpu,
+                             unsigned long long rate);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 5b9edadcf7..c8f6069566 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8852,3 +8852,46 @@ qemuMonitorJSONQueryStats(qemuMonitor *mon,
 
     return virJSONValueObjectStealArray(reply, "return");
 }
+
+/**
+ * qemuMonitorJSONSetVcpuDirtyLimit:
+ * @mon: monitor object
+ * @vcpu: virtual cpu index to be set, -1 affects all virtual CPUs
+ * @rate: dirty page rate upper limit to be set, use 0 to disable
+ *        and a positive value to enable
+ *
+ * Returns -1 on failure.
+ */
+int
+qemuMonitorJSONSetVcpuDirtyLimit(qemuMonitor *mon,
+                                 int vcpu,
+                                 unsigned long long rate)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+
+    if (rate != 0) {
+        /* set the vcpu dirty page rate limit */
+        if (!(cmd = qemuMonitorJSONMakeCommand("set-vcpu-dirty-limit",
+                                               "k:cpu-index", vcpu,
+                                               "U:dirty-rate", rate,
+                                               NULL))) {
+            return -1;
+        }
+    } else {
+        /* cancel the vcpu dirty page rate limit */
+        if (!(cmd = qemuMonitorJSONMakeCommand("cancel-vcpu-dirty-limit",
+                                               "k:cpu-index", vcpu,
+                                               NULL))) {
+            return -1;
+        }
+    }
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return -1;
+
+    return 0;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 06023b98ea..89f61b3052 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -825,3 +825,8 @@ qemuMonitorJSONQueryStats(qemuMonitor *mon,
                           qemuMonitorQueryStatsTargetType target,
                           char **vcpus,
                           GPtrArray *providers);
+
+int
+qemuMonitorJSONSetVcpuDirtyLimit(qemuMonitor *mon,
+                                 int vcpu,
+                                 unsigned long long rate);
-- 
2.38.5





[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux