On Thu, Apr 23, 2026 at 17:27:28 +0530, Akash Kulhalli via Devel wrote:
> Add VIR_DOMAIN_VCPU_ASYNC_UNPLUG for virDomainSetVcpusFlags().
> 
> With this flag, success indicates that QEMU accepted the unplug
> request, while final completion is reported by the vcpu-removed
> event. Rejected requests continue to be reported by the
> device-removal-failed event.
> 
> Wire the flag through the QEMU driver, document its semantics, and
> add virsh support for setvcpus --async.
> 
> Signed-off-by: Akash Kulhalli <[email protected]>
> ---
>  docs/manpages/virsh.rst          | 13 +++++++++++--
>  include/libvirt/libvirt-domain.h |  1 +
>  src/libvirt-domain.c             | 10 ++++++++++
>  src/qemu/qemu_driver.c           | 12 ++++++++++--
>  tools/virsh-domain.c             |  8 ++++++++
>  5 files changed, 40 insertions(+), 4 deletions(-)
> 
> diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
> index 80b0ea14a8b3..f4c8e573cd47 100644
> --- a/docs/manpages/virsh.rst
> +++ b/docs/manpages/virsh.rst
> @@ -179,7 +179,8 @@ Most ``virsh`` commands act synchronously, except maybe 
> shutdown,
>  setvcpus and setmem. In those cases the fact that the ``virsh``
>  program returned, may not mean the action is complete and you
>  must poll periodically to detect that the guest completed the
> -operation.
> +operation. This asynchronous behaviour can be enforced with the
> +``--async`` flag to ``setvcpus`` only.

Skip this part. The command is synchronous and the async mode is
explicitly documented with the command.

>  
>  ``virsh`` strives for backward compatibility.  Although the ``help``
>  command only lists the preferred usage of a command, if an older
> @@ -4810,7 +4811,7 @@ setvcpus
>  
>  ::
>  
> -   setvcpus domain count [--maximum] [[--config] [--live] | [--current]] 
> [--guest] [--hotpluggable]
> +   setvcpus domain count [--maximum] [[--config] [--live] | [--current]] 
> [--guest] [--hotpluggable] [--async]
>  
>  Change the number of virtual CPUs active in a guest domain.  By default,
>  this command works on active guest domains.  To change the settings for an
> @@ -4839,6 +4840,14 @@ is up to the hypervisor whether the *--config* flag is 
> also assumed, and
>  therefore whether the XML configuration is adjusted to make the change
>  persistent.
>  
> +If *--async* is specified, live vCPU unplug requests are fired without 
> waiting
> +for the guest to comply. This affects only the live unplug part of the
> +operation; it may optionally be combined with *--config*. Final completion is

Drop the 'This affects only the...' sentence. The previous one documents
it sufficiently.

> +reported by the ``vcpu-removed`` domain event, while rejected unplug requests
> +continue to be reported by ``device-removal-failed``. If the requested count
> +increases the live vCPU count, or only affects the persistent configuration,

This sentence is also redundant IMO.

> +*--async* has no effect. This flag cannot be combined with *--guest*.
> +
>  If *--guest* is specified, then the count of cpus is modified in the guest
>  instead of the hypervisor. This flag is usable only for live domains
>  and may require guest agent to be configured in the guest.
> diff --git a/include/libvirt/libvirt-domain.h 
> b/include/libvirt/libvirt-domain.h
> index 92d5ecb32d65..016b6ea700e9 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -2605,6 +2605,7 @@ typedef enum {
>      VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count 
> (Since: 0.8.5) */
>      VIR_DOMAIN_VCPU_GUEST   = (1 << 3), /* Modify state of the cpu in the 
> guest (Since: 1.1.0) */
>      VIR_DOMAIN_VCPU_HOTPLUGGABLE = (1 << 4), /* Make vcpus added 
> hot(un)pluggable (Since: 2.4.0) */
> +    VIR_DOMAIN_VCPU_ASYNC_UNPLUG = (1 << 5), /* Don't wait for the guest to 
> comply with unplug request(s) (Since: 12.3.0) */

12.4.0


>  } virDomainVcpuFlags;
>  
>  int                     virDomainSetVcpus       (virDomainPtr domain,
> diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
> index db9eea57745c..97af1099f939 100644
> --- a/src/libvirt-domain.c
> +++ b/src/libvirt-domain.c
> @@ -7773,6 +7773,16 @@ virDomainSetVcpus(virDomainPtr domain, unsigned int 
> nvcpus)
>   * be used with live guests and is incompatible with VIR_DOMAIN_VCPU_MAXIMUM.
>   * The usage of this flag may require a guest agent configured.
>   *
> + * If @flags includes VIR_DOMAIN_VCPU_ASYNC_UNPLUG, live vCPU hot-unplug
> + * request(s) are fired without waiting for the guest to comply. Success in
> + * this mode only means that the unplug request(s) were accepted. Final
> + * completion is reported by VIR_DOMAIN_EVENT_ID_VCPU_REMOVED, carrying the
> + * XML ``<vcpu id='...'>`` value for each removed vCPU. Rejected unplug
> + * requests continue to be reported through the event
> + * VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED. The success event may be
> + * delivered before this API call returns. This flag has no effect when this
> + * operation results in an increase in the live vCPU count.
> + *
>   * Not all hypervisors can support all flag combinations.
>   *
>   * Returns 0 in case of success, -1 in case of failure.
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 4d9be3d3a9e5..c9c72b29617f 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c

[...]

> @@ -4297,13 +4299,19 @@ qemuDomainSetVcpusFlags(virDomainPtr dom,
>      if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
>          goto endjob;
>  
> +    if (async_unplug && (useAgent || !def)) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("asynchronous mode is supported only for live vcpu 
> unplug"));

Technically the unplug with guest agent (e.g. the --guest mode) is still
live so this error message is a bit misleading.

Drop the '!def' part of the condition since it IMO makes no sense and
mention the flag name (VIR_DOMAIN_VCPU_GUEST).

With the above:

Reviewed-by: Peter Krempa <[email protected]>

Reply via email to