From: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx> 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 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. Signed-off-by: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx> --- include/libvirt/libvirt-domain.h | 4 +++ src/driver-hypervisor.h | 7 ++++ src/libvirt-domain.c | 59 ++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 17 ++++++++- src/remote_protocol-structs | 7 ++++ 7 files changed, 99 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); #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 ec42bb9a53..9a60ac7f67 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -14059,3 +14059,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.6.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 80742f268e..6fc01b518f 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -932,4 +932,9 @@ LIBVIRT_9.0.0 { virDomainFDAssociate; } LIBVIRT_8.5.0; +LIBVIRT_9.6.0 { + global: + virDomainSetVcpuDirtyLimit; +} LIBVIRT_9.0.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index faad7292ed..9d7522d3bf 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8119,6 +8119,7 @@ static virHypervisorDriver hypervisor_driver = { .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */ .domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */ .domainFDAssociate = remoteDomainFDAssociate, /* 9.0.0 */ + .domainSetVcpuDirtyLimit = remoteDomainSetVcpuDirtyLimit, /* 9.6.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 5d86a51116..33bdad7865 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3935,6 +3935,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. */ @@ -6974,5 +6982,12 @@ enum remote_procedure { * @generate: none * @acl: domain:write */ - REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443 + REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443, + /** + * @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 = 444 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 3c6c230a16..f7543ec667 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -3273,6 +3273,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, @@ -3717,4 +3723,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441, REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442, REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443, + REMOTE_PROC_DOMAIN_SET_VCPU_DIRTY_LIMIT = 444, }; -- 2.38.5