diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 355bbd5151..501996bc84 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4664,4 +4664,9 @@ int virDomainSetVcpu(virDomainPtr domain, int state, unsigned int flags); +int virDomainSetBlockThreshold(virDomainPtr domain, + const char *dev, + unsigned long long threshold, + unsigned int flags); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index b81420aefe..3053d7ae8c 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1257,6 +1257,13 @@ typedef int int state, unsigned int flags); +typedef int +(*virDrvDomainSetBlockThreshold)(virDomainPtr domain, + const char *dev, + unsigned long long threshold, + unsigned int flags); + + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1496,6 +1503,7 @@ struct _virHypervisorDriver { virDrvDomainGetGuestVcpus domainGetGuestVcpus; virDrvDomainSetGuestVcpus domainSetGuestVcpus; virDrvDomainSetVcpu domainSetVcpu; + virDrvDomainSetBlockThreshold domainSetBlockThreshold; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d8c88e06c4..0cd80a6095 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11822,3 +11822,59 @@ virDomainSetVcpu(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetBlockThreshold: + * @domain: pointer to domain object + * @dev: string specifying the block device or backing chain element + * @threshold: threshold in bytes when to fire the event + * @flags: currently unused, callers should pass 0 + * + * Set the threshold level for delivering the + * VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD if the device or backing chain element + * described by @dev is written beyond the set threshold level. The threshold + * level is unset once the event fires. The event might not be delivered at all + * if libvirtd was not running at the moment when the threshold was reached. + * + * Hypervisors report the last written sector of an image in the bulk stats API + * (virConnectGetAllDomainStats/virDomainListGetStats) as + * "block..allocation" in the VIR_DOMAIN_STATS_BLOCK group. The current + * threshold value is reported as "block..threshold". + * + * This event allows to use thin-provisioned storage which needs management + * tools to grow it without the need for polling of the data. + * + * Returns 0 if the operation has started, -1 on failure. + */ +int +virDomainSetBlockThreshold(virDomainPtr domain, + const char *dev, + unsigned long long threshold, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(domain, "dev='%s' threshold=%llu flags=%x", + NULLSTR(dev), threshold, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + virCheckReadOnlyGoto(domain->conn->flags, error); + + virCheckNonNullArgGoto(dev, error); + + if (domain->conn->driver->domainSetBlockThreshold) { + int ret; + ret = domain->conn->driver->domainSetBlockThreshold(domain, dev, + threshold, 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 04ef58021b..428cf2e194 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -755,6 +755,7 @@ LIBVIRT_3.0.0 { LIBVIRT_3.1.0 { global: + virDomainSetBlockThreshold; virDomainSetVcpu; } LIBVIRT_3.0.0; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index efa47beafb..27bcc9b925 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8436,6 +8436,7 @@ static virHypervisorDriver hypervisor_driver = { .domainGetGuestVcpus = remoteDomainGetGuestVcpus, /* 2.0.0 */ .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */ .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */ + .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 39dd2b728e..87b2bd365a 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3402,6 +3402,14 @@ struct remote_secret_event_value_changed_msg { remote_nonnull_secret secret; }; +struct remote_domain_set_block_threshold_args { + remote_nonnull_domain dom; + remote_nonnull_string dev; + unsigned hyper threshold; + unsigned int flags; +}; + + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -6048,6 +6056,13 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_DOMAIN_EVENT_BLOCK_THRESHOLD = 385 + REMOTE_PROC_DOMAIN_EVENT_BLOCK_THRESHOLD = 385, + + /** + * @generate: both + * @acl: domain:write + */ + REMOTE_PROC_DOMAIN_SET_BLOCK_THRESHOLD = 386 + }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 67e43a4acd..a46fe37bfb 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2840,6 +2840,12 @@ struct remote_secret_event_value_changed_msg { int callbackID; remote_nonnull_secret secret; }; +struct remote_domain_set_block_threshold_args { + remote_nonnull_domain dom; + remote_nonnull_string dev; + uint64_t threshold; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3226,4 +3232,5 @@ enum remote_procedure { REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383, REMOTE_PROC_DOMAIN_SET_VCPU = 384, REMOTE_PROC_DOMAIN_EVENT_BLOCK_THRESHOLD = 385, + REMOTE_PROC_DOMAIN_SET_BLOCK_THRESHOLD = 386, };