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 <akash.kulhalli@oracle.com> --- 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