Add VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG for virDomainSetVcpu().

Define a dedicated virDomainSetVcpuBehaviour flag type and wire the
new flag through the QEMU driver. As with setvcpus async unplug,
success indicates request acceptance while final completion is
reported by the vcpu-removed event.

Update the API documentation and add virsh support for setvcpu
--async.

Signed-off-by: Akash Kulhalli <[email protected]>
---
 docs/manpages/virsh.rst          | 10 ++++++++--
 include/libvirt/libvirt-domain.h | 14 ++++++++++++++
 src/libvirt-domain.c             | 11 ++++++++++-
 src/qemu/qemu_driver.c           | 12 ++++++++++--
 tools/virsh-domain.c             |  8 ++++++++
 5 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index f4c8e573cd47..7b3c853aea27 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -180,7 +180,7 @@ 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. This asynchronous behaviour can be enforced with the
-``--async`` flag to ``setvcpus`` only.
+``--async`` flag to ``setvcpus`` and ``setvcpu`` only.
 
 ``virsh`` strives for backward compatibility.  Although the ``help``
 command only lists the preferred usage of a command, if an older
@@ -4871,7 +4871,7 @@ setvcpu
 
 ::
 
-   setvcpu domain vcpulist [--enable] | [--disable]
+   setvcpu domain vcpulist [--enable] | [--disable] [--async]
       [[--live] [--config] | [--current]]
 
 Change state of individual vCPUs using hot(un)plug mechanism.
@@ -4891,6 +4891,12 @@ If *--current* is specified, it is equivalent to either 
*--live* or
 default. Both *--live* and *--config* flags may be given, but
 *--current* is exclusive.
 
+If *--async* is specified with *--disable*, live vCPU unplug requests are
+fired without waiting for the guest to comply. This may optionally be
+combined with *--config*. Final completion of this operation is reported
+by the ``vcpu-removed`` domain event, while rejected unplug requests continue
+to be reported by ``device-removal-failed``.
+
 
 shutdown
 --------
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 016b6ea700e9..2b6c498ed5ab 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -329,6 +329,20 @@ typedef enum {
     /* 1 << 2 is reserved for virTypedParameterFlags */
 } virDomainModificationImpact;
 
+/**
+ * virDomainSetVcpuBehaviour:
+ *
+ * These flags must be used when calling the `virDomainSetVcpu` API.
+ *
+ * Since: 12.3.0
+ */
+typedef enum {
+    VIR_DOMAIN_SETVCPU_AFFECT_CURRENT = VIR_DOMAIN_AFFECT_CURRENT, /* Affect 
current domain state. (Since: 0.9.2)  */
+    VIR_DOMAIN_SETVCPU_AFFECT_LIVE = VIR_DOMAIN_AFFECT_LIVE, /* Affect running 
domain state. (Since: 0.9.2)  */
+    VIR_DOMAIN_SETVCPU_AFFECT_CONFIG = VIR_DOMAIN_AFFECT_CONFIG, /* Affect 
persistent domain state. (Since: 0.9.2) */
+    VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG = 1 << 2 /* Do not wait for the guest to 
comply with the request (Since: 12.3.0) */
+} virDomainSetVcpuBehaviour;
+
 /**
  * virDomainInfo:
  *
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 97af1099f939..e3d1b76bcd01 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -13135,7 +13135,7 @@ virDomainSetGuestVcpus(virDomainPtr domain,
  * @domain: pointer to domain object
  * @vcpumap: text representation of a bitmap of vcpus to set
  * @state: 0 to disable/1 to enable cpus described by @vcpumap
- * @flags: bitwise-OR of virDomainModificationImpact
+ * @flags: bitwise-OR of virDomainSetVcpuBehaviour
  *
  * Enables/disables individual vcpus described by @vcpumap in the hypervisor.
  *
@@ -13144,6 +13144,15 @@ virDomainSetGuestVcpus(virDomainPtr domain,
  *
  * Note that OSes and hypervisors may require vCPU 0 to stay online.
  *
+ * If @flags includes VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG, live vCPU disable 
(hot-unplug)
+ * request(s) are fired without waiting for the guest to comply. Success in
+ * this mode means only 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 by 
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED.
+ * The success event may be delivered before this API call returns. This flag
+ * has no effect when the selected vCPUs are enabled.
+ *
  * Returns 0 on success, -1 on error.
  *
  * Since: 3.1.0
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c9c72b29617f..9a20486725cb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19177,12 +19177,14 @@ qemuDomainSetVcpu(virDomainPtr dom,
     virDomainObj *vm = NULL;
     virDomainDef *def = NULL;
     virDomainDef *persistentDef = NULL;
+    bool async_unplug = !!(flags & VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG);
     g_autoptr(virBitmap) map = NULL;
     ssize_t lastvcpu;
     int ret = -1;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
-                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+                  VIR_DOMAIN_AFFECT_CONFIG |
+                  VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG, -1);
 
     if (state != 0 && state != 1) {
         virReportInvalidArg(state, "%s", _("unsupported state value"));
@@ -19228,8 +19230,14 @@ qemuDomainSetVcpu(virDomainPtr dom,
         }
     }
 
+    if (async_unplug && (!def)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("asynchronous mode is supported only for live vcpu 
unplug"));
+        goto endjob;
+    }
+
     ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map,
-                                    !!state, false);
+                                    !!state, async_unplug);
 
  endjob:
     virDomainObjEndJob(vm);
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 1fccee4bc9ed..76369e8694ce 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -7837,6 +7837,10 @@ static const vshCmdOptDef opts_setvcpu[] = {
      .type = VSH_OT_BOOL,
      .help = N_("disable cpus specified by cpumap")
     },
+    {.name = "async",
+     .type = VSH_OT_BOOL,
+     .help = N_("return after firing vcpu unplug request")
+    },
     VIRSH_COMMON_OPT_DOMAIN_CONFIG,
     VIRSH_COMMON_OPT_DOMAIN_LIVE,
     VIRSH_COMMON_OPT_DOMAIN_CURRENT,
@@ -7851,6 +7855,7 @@ cmdSetvcpu(vshControl *ctl, const vshCmd *cmd)
     bool disable = vshCommandOptBool(cmd, "disable");
     bool config = vshCommandOptBool(cmd, "config");
     bool live = vshCommandOptBool(cmd, "live");
+    bool async = vshCommandOptBool(cmd, "async");
     const char *vcpulist = NULL;
     int state = 0;
     unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
@@ -7859,11 +7864,14 @@ cmdSetvcpu(vshControl *ctl, const vshCmd *cmd)
 
     VSH_EXCLUSIVE_OPTIONS("current", "live");
     VSH_EXCLUSIVE_OPTIONS("current", "config");
+    VSH_EXCLUSIVE_OPTIONS("async", "enable");
 
     if (config)
         flags |= VIR_DOMAIN_AFFECT_CONFIG;
     if (live)
         flags |= VIR_DOMAIN_AFFECT_LIVE;
+    if (async)
+        flags |= VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG;
 
     if (!(enable || disable)) {
         vshError(ctl, "%s", _("one of --enable, --disable is required"));
-- 
2.47.3

Reply via email to