On Tue, Aug 02, 2022 at 10:13:40PM +0800, ~hyman wrote:
From: Hyman Huang(黄勇) <yong.huang(a)smartx.com>
Introduce virDomainSetVcpuDirtyLimit API to set or cancel the
dirty page rate upper limit.
The API will throttle the virtual CPU as needed to keep their dirty
page rate within the limit. Since it just throttles the virtual CPU,
which dirties memory, read processes in the guest OS aren't penalized.
The feature therefor could, in some scenes, be used to provide
quality-of-service in the aspect of the memory workload for virtual
CPUs.
Signed-off-by: Hyman Huang(黄勇) <yong.huang(a)smartx.com>
---
include/libvirt/libvirt-domain.h | 4 +++
src/driver-hypervisor.h | 7 ++++
src/libvirt-domain.c | 59 ++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 18 +++++++++-
src/remote_protocol-structs | 7 ++++
7 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index a1902546bb..3d3c7cdcba 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -6506,4 +6506,8 @@ int virDomainFDAssociate(virDomainPtr domain,
int *fds,
unsigned int flags);
+int virDomainSetVcpuDirtyLimit(virDomainPtr domain,
+ int vcpu,
+ unsigned long long rate,
+ unsigned int flags);
We've generally tried to avoid adding single purpose APIs for
tunable parameters, instead using APIs with virTypedParameter
arrays to allow bulk updates.
I note that we don't appear to have any mechanism currently
to set the VCPU scheduler tunables either
Perhaps we should have a more general
virDomainSetVCPUTuneParameters(virDomainPtr domain,
int vcpu,
virTypedParameterPtr params,
unsigned int params,
unsigned int flags);
#endif /* LIBVIRT_DOMAIN_H */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 5219344b72..e61b9efca5 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1448,6 +1448,12 @@ typedef int
int *fds,
unsigned int flags);
+typedef int
+(*virDrvDomainSetVcpuDirtyLimit)(virDomainPtr domain,
+ int vcpu,
+ unsigned long long rate,
+ unsigned int flags);
+
typedef struct _virHypervisorDriver virHypervisorDriver;
/**
@@ -1720,4 +1726,5 @@ struct _virHypervisorDriver {
virDrvDomainGetMessages domainGetMessages;
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
virDrvDomainFDAssociate domainFDAssociate;
+ virDrvDomainSetVcpuDirtyLimit domainSetVcpuDirtyLimit;
};
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 6616294fc1..5b505cc519 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -14041,3 +14041,62 @@ virDomainFDAssociate(virDomainPtr domain,
virDispatchError(conn);
return -1;
}
+
+/**
+ * virDomainSetVcpuDirtyLimit:
+ * @domain: pointer to domain object
+ * @vcpu: index of the limited virtual CPU
+ * @rate: upper limit of dirty page rate (mebibyte/s) for virtual CPUs
+ * @flags: bitwise-OR of virDomainModificationImpact
+ *
+ * Dynamically set the dirty page rate upper limit for the virtual CPUs.
+ *
+ * @vcpu may be a positive value, zero, or equal to -1. If -1 is set,
+ * the change affects all virtual CPUs of VM; it affects the specified
+ * virtual CPU otherwise.
+ * @rate may be 0 to cancel the limit or a positive value to enable. The
+ * hypervisors are free to round it down to the nearest mebibyte/s.
+ *
+ * The API will throttle the virtual CPU as needed to keep their dirty
+ * page rate within the limit set by @rate. Since it just throttles the
+ * virtual CPU, which dirties memory, read processes in the guest OS
+ * aren't penalized. This could, in some scenes, be used to provide
+ * quality-of-service in the aspect of the memory workload for virtual
+ * CPUs.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ *
+ * Since: 9.7.0
+ */
+int
+virDomainSetVcpuDirtyLimit(virDomainPtr domain,
+ int vcpu,
+ unsigned long long rate,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "vcpu=%d, rate=%llu, flags=0x%x",
+ vcpu, rate, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, -1);
+ conn = domain->conn;
+
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ if (conn->driver->domainSetVcpuDirtyLimit) {
+ int ret;
+ ret = conn->driver->domainSetVcpuDirtyLimit(domain, vcpu, rate, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(domain->conn);
+ return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index bd1e916d2a..602494935d 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -934,6 +934,7 @@ LIBVIRT_9.0.0 {
LIBVIRT_9.7.0 {
global:
+ virDomainSetVcpuDirtyLimit;
virNetworkGetMetadata;
virNetworkSetMetadata;
} LIBVIRT_9.0.0;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 0b925f8edc..15d023154b 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8110,6 +8110,7 @@ static virHypervisorDriver hypervisor_driver = {
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
.domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */
.domainFDAssociate = remoteDomainFDAssociate, /* 9.0.0 */
+ .domainSetVcpuDirtyLimit = remoteDomainSetVcpuDirtyLimit, /* 9.7.0 */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 7ff059e393..72b2684912 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3955,6 +3955,14 @@ struct remote_domain_fd_associate_args {
remote_nonnull_string name;
unsigned int flags;
};
+
+struct remote_domain_set_vcpu_dirty_limit_args {
+ remote_nonnull_domain dom;
+ int vcpu;
+ unsigned hyper rate;
+ unsigned int flags;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -7008,5 +7016,13 @@ enum remote_procedure {
* @generate: both
* @acl: network:read
*/
- REMOTE_PROC_NETWORK_GET_METADATA = 445
+ REMOTE_PROC_NETWORK_GET_METADATA = 445,
+
+ /**
+ * @generate: both
+ * @acl: domain:write
+ * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE
+ * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG
+ */
+ REMOTE_PROC_DOMAIN_SET_VCPU_DIRTY_LIMIT = 446
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index c07e0af1e6..715a121f36 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -3290,6 +3290,12 @@ struct remote_domain_fd_associate_args {
remote_nonnull_string name;
u_int flags;
};
+struct remote_domain_set_vcpu_dirty_limit_args {
+ remote_nonnull_domain dom;
+ int vcpu;
+ uint64_t rate;
+ u_int flags;
+};
enum remote_procedure {
REMOTE_PROC_CONNECT_OPEN = 1,
REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3736,4 +3742,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
REMOTE_PROC_NETWORK_SET_METADATA = 444,
REMOTE_PROC_NETWORK_GET_METADATA = 445,
+ REMOTE_PROC_DOMAIN_SET_VCPU_DIRTY_LIMIT = 446,
};
--
2.38.5
With regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|