ret = qemuDomainSetVcpusMax(driver, vm, def, persistentDef, nvcpus);
else
ret = qemuDomainSetVcpusInternal(driver, vm, def, persistentDef,
- nvcpus, hotpluggable);
+ nvcpus, hotpluggable, false);
endjob:
if (useAgent)
}
}
- ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map, !!state);
+ ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map,
+ !!state, false);
endjob:
virDomainObjEndJob(vm);
qemuDomainHotplugDelVcpu(virQEMUDriver *driver,
virQEMUDriverConfig *cfg,
virDomainObj *vm,
- unsigned int vcpu)
+ unsigned int vcpu,
+ bool async_unplug)
{
virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
return -1;
}
- qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
+ if (!async_unplug)
+ qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
rc = qemuDomainDeleteDevice(vm, vcpupriv->alias);
if (rc < 0) {
virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
goto cleanup;
}
+ } else if (async_unplug) {
+ /*
+ * Let DEVICE_DELETED finish the unplug asynchronously when qemu
+ * accepted the delete request.
+ */
+ return 0;
} else {
if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
if (rc == 0)
ret = 0;
cleanup:
- qemuDomainResetDeviceRemoval(vm);
+ if (!async_unplug)
+ qemuDomainResetDeviceRemoval(vm);
return ret;
}
virQEMUDriverConfig *cfg,
virDomainObj *vm,
virBitmap *vcpumap,
- bool enable)
+ bool enable,
+ bool async)
{
qemuDomainObjPrivate *priv = vm->privateData;
virCgroupEmulatorAllNodesData *emulatorCgroup = NULL;
if (!virBitmapIsBitSet(vcpumap, nextvcpu))
continue;
- if (qemuDomainHotplugDelVcpu(driver, cfg, vm, nextvcpu) < 0)
+ if (qemuDomainHotplugDelVcpu(driver, cfg, vm, nextvcpu, async) < 0)
goto cleanup;
}
}
virDomainDef *def,
virDomainDef *persistentDef,
unsigned int nvcpus,
- bool hotpluggable)
+ bool hotpluggable,
+ bool async_unplug)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autoptr(virBitmap) vcpumap = NULL;
&enable)))
return -1;
- if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable) < 0)
+ if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable,
+ async_unplug) < 0)
return -1;
}
}
+/**
+ * qemuDomainSetVcpuInternal:
+ * @driver: the QEMU driver object
+ * @vm: the domain object
+ * @def: the live domain definition
+ * @persistentDef: the persistent (config) domain definition
+ * @map: a bitmap of cpus to be set to state @state
+ * @state: enable/disable the vcpus marked in @map
+ * @async_unplug: only used in case of unplug (i.e. @state=false)
+ *
+ * When @async_unplug is set to true, libvirt will not wait for
+ * the guest to comply with the unplug request but instead return
+ * immediately after receiving the acknowledgement from QEMU. Otherwise,
+ * libvirt will wait for a brief moment (defined by qemuDomainGetUnplugTimeout)
+ * before giving up and returning control to the caller.
+ *
+ * If the request results in adding a vcpu, this parameter is ignored.
+ *
+ */
int
qemuDomainSetVcpuInternal(virQEMUDriver *driver,
virDomainObj *vm,
virDomainDef *def,
virDomainDef *persistentDef,
virBitmap *map,
- bool state)
+ bool state,
+ bool async_unplug)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autoptr(virBitmap) livevcpus = NULL;
}
if (livevcpus &&
- qemuDomainSetVcpusLive(driver, cfg, vm, livevcpus, state) < 0)
+ qemuDomainSetVcpusLive(driver, cfg, vm, livevcpus, state,
+ async_unplug) < 0)
return -1;
if (persistentDef) {