[[RESEND] 7/8] migration/dirtyrate: Introduce DomainGetDirtyRateInfo API

Hao Wang posted 1 patch 1 week ago
Failed in applying to current master (apply log)
include/libvirt/libvirt-domain.h | 13 ++++++
src/driver-hypervisor.h          |  7 ++++
src/libvirt-domain.c             | 46 +++++++++++++++++++++
src/libvirt_public.syms          |  5 +++
src/qemu/qemu_driver.c           | 71 ++++++++++++++++++++++++++++++++
src/remote/remote_driver.c       |  1 +
src/remote/remote_protocol.x     | 21 +++++++++-
7 files changed, 163 insertions(+), 1 deletion(-)

[[RESEND] 7/8] migration/dirtyrate: Introduce DomainGetDirtyRateInfo API

Posted by Hao Wang 1 week ago
Introduce DomainGetDirtyRateInfo API for domain's memory dirty rate
calculation and query.

Signed-off-by: Hao Wang <wanghao232@huawei.com>
Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Reviewed-by: Chuan Zheng <zhengchuan@huawei.com>
---
 include/libvirt/libvirt-domain.h | 13 ++++++
 src/driver-hypervisor.h          |  7 ++++
 src/libvirt-domain.c             | 46 +++++++++++++++++++++
 src/libvirt_public.syms          |  5 +++
 src/qemu/qemu_driver.c           | 71 ++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c       |  1 +
 src/remote/remote_protocol.x     | 21 +++++++++-
 7 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 68a760816a..9e148a238b 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -5064,4 +5064,17 @@ struct _virDomainDirtyRateInfo {
 
 typedef virDomainDirtyRateInfo *virDomainDirtyRateInfoPtr;
 
+/**
+ * virDomainDirtyRateInfoPtr:
+ *
+ * a virDomainDirtyRateInfoPtr is a pointer to a virDomainDirtyRateInfo structure.
+ */
+
+typedef virDomainDirtyRateInfo *virDomainDirtyRateInfoPtr;
+
+int virDomainGetDirtyRateInfo(virDomainPtr domain,
+                              virDomainDirtyRateInfoPtr info,
+                              long long sec,
+                              int flags);
+
 #endif /* LIBVIRT_DOMAIN_H */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index bce023017d..dc2aefa910 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1387,6 +1387,12 @@ typedef char *
 (*virDrvDomainBackupGetXMLDesc)(virDomainPtr domain,
                                 unsigned int flags);
 
+typedef int
+(*virDrvDomainGetDirtyRateInfo)(virDomainPtr domain,
+                                virDomainDirtyRateInfoPtr info,
+                                long long sec,
+                                int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1650,4 +1656,5 @@ struct _virHypervisorDriver {
     virDrvDomainAgentSetResponseTimeout domainAgentSetResponseTimeout;
     virDrvDomainBackupBegin domainBackupBegin;
     virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc;
+    virDrvDomainGetDirtyRateInfo domainGetDirtyRateInfo;
 };
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 3c5f55176a..8714c1ca93 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12758,3 +12758,49 @@ virDomainBackupGetXMLDesc(virDomainPtr domain,
     virDispatchError(conn);
     return NULL;
 }
+
+
+/**
+ * virDomainGetDirtyRateInfo:
+ * @domain: a domain object.
+ * @info: return value of current domain's memory dirty rate info.
+ * @sec: show dirty rate within specified seconds.
+ * @flags: the flags of getdirtyrate action -- calculate and/or query.
+ *
+ * Get the current domain's memory dirty rate (in MB/s).
+ *
+ * Returns 0 in case of success, -1 otherwise.
+ */
+int
+virDomainGetDirtyRateInfo(virDomainPtr domain,
+                          virDomainDirtyRateInfoPtr info,
+                          long long sec,
+                          int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "info = %p, seconds=%lld", info, sec);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(info, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (info)
+        memset(info, 0, sizeof(*info));
+
+    if (conn->driver->domainGetDirtyRateInfo) {
+        if (conn->driver->domainGetDirtyRateInfo(domain, info, sec, flags) < 0)
+            goto error;
+        VIR_DOMAIN_DEBUG(domain, "info = %p, seconds=%lld", info, sec);
+        return 0;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 539d2e3943..11864f48b1 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -873,4 +873,9 @@ LIBVIRT_6.0.0 {
         virDomainBackupGetXMLDesc;
 } LIBVIRT_5.10.0;
 
+LIBVIRT_6.9.0 {
+    global:
+        virDomainGetDirtyRateInfo;
+} LIBVIRT_6.0.0;
+
 # .... define new API here using predicted next version number ....
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8457cbfb4b..3ef8253cb5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20055,6 +20055,76 @@ qemuDomainAgentSetResponseTimeout(virDomainPtr dom,
 }
 
 
+#define MIN_DIRTYRATE_CALCULATION_PERIOD    1    /* 1s */
+#define MAX_DIRTYRATE_CALCULATION_PERIOD    60   /* 60s */
+
+static int
+qemuDomainGetDirtyRateInfo(virDomainPtr dom,
+                           virDomainDirtyRateInfoPtr info,
+                           long long sec,
+                           int flags)
+{
+    virDomainObjPtr vm = NULL;
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    int ret = -1;
+
+    if (!(vm = qemuDomainObjFromDomain(dom)))
+        return ret;
+
+    if (virDomainGetDirtyRateInfoEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_DIRTYRATE,
+                                   VIR_DOMAIN_JOB_OPERATION_DIRTYRATE, 0) < 0)
+        goto cleanup;
+
+    qemuDomainObjSetAsyncJobMask(vm, (QEMU_JOB_DEFAULT_MASK |
+                                 JOB_MASK(QEMU_JOB_SUSPEND)));
+
+    if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
+        goto endjob;
+
+    if (flags & VIR_DOMAIN_DIRTYRATE_CALC) {
+        if (sec < MIN_DIRTYRATE_CALCULATION_PERIOD || sec > MAX_DIRTYRATE_CALCULATION_PERIOD) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           "seconds=%lld is invalid, please choose value within [1, 60].", sec);
+            goto endjob;
+        }
+
+        if (qemuDomainCalculateDirtyRate(dom, vm, sec) < 0) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("can't calculate domain's dirty rate"));
+            goto endjob;
+        }
+    }
+
+    if (flags & VIR_DOMAIN_DIRTYRATE_QUERY) {
+        if (flags & VIR_DOMAIN_DIRTYRATE_CALC) {
+            struct timespec ts = { .tv_sec = sec, .tv_nsec = 50 * 1000 * 1000ull };
+
+            virObjectUnlock(vm);
+            nanosleep(&ts, NULL);
+            virObjectLock(vm);
+        }
+
+        if (qemuDomainQueryDirtyRate(dom, vm, info) < 0) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("can't query domain's dirty rate"));
+            goto endjob;
+        }
+    }
+
+    ret = 0;
+
+ endjob:
+    qemuDomainObjEndAsyncJob(driver, vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectURIProbe = qemuConnectURIProbe,
@@ -20294,6 +20364,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainAgentSetResponseTimeout = qemuDomainAgentSetResponseTimeout, /* 5.10.0 */
     .domainBackupBegin = qemuDomainBackupBegin, /* 6.0.0 */
     .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */
+    .domainGetDirtyRateInfo = qemuDomainGetDirtyRateInfo, /* 6.9.0 */
 };
 
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index d318224605..5ea49f1f4e 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8426,6 +8426,7 @@ static virHypervisorDriver hypervisor_driver = {
     .domainAgentSetResponseTimeout = remoteDomainAgentSetResponseTimeout, /* 5.10.0 */
     .domainBackupBegin = remoteDomainBackupBegin, /* 6.0.0 */
     .domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */
+    .domainGetDirtyRateInfo = remoteDomainGetDirtyRateInfo, /* 6.9.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index f4d6147676..ce3d0519c9 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3771,6 +3771,19 @@ struct remote_domain_backup_get_xml_desc_ret {
     remote_nonnull_string xml;
 };
 
+struct remote_domain_get_dirty_rate_info_args {
+    remote_nonnull_domain dom;
+    hyper sec;
+    int flags;
+};
+
+struct remote_domain_get_dirty_rate_info_ret { /* insert@1 */
+    int status;
+    hyper dirtyRate;
+    hyper startTime;
+    hyper calcTime;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6668,5 +6681,11 @@ enum remote_procedure {
      * @priority: high
      * @acl: domain:read
      */
-    REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422
+    REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422,
+
+    /**
+     * @generate: both
+     * @acl: domain:read
+     */
+    REMOTE_PROC_DOMAIN_GET_DIRTY_RATE_INFO = 423
 };
-- 
2.23.0