diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 69d38ecc62..97e2ffc404 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4061,11 +4061,15 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver, goto endjob; } - if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) - goto endjob; + if (STRPREFIX(devAlias, "vcpu")) { + qemuDomainRemoveVcpuAlias(driver, vm, devAlias); + } else { + if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) + goto endjob; - if (qemuDomainRemoveDevice(driver, vm, &dev) < 0) - goto endjob; + if (qemuDomainRemoveDevice(driver, vm, &dev) < 0) + goto endjob; + } if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("unable to save domain status after removing device %s", @@ -4659,60 +4663,6 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver, } -static int -qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver, - virDomainObjPtr vm, - unsigned int vcpu) -{ - qemuDomainObjPrivatePtr priv = vm->privateData; - virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu); - int ret = -1; - int rc; - int oldvcpus = virDomainDefGetVcpus(vm->def); - - if (!vcpuinfo->online) { - virReportError(VIR_ERR_INVALID_ARG, - _("vCPU '%u' is already offline"), vcpu); - return -1; - } - - vcpuinfo->online = false; - - qemuDomainObjEnterMonitor(driver, vm); - - rc = qemuMonitorSetCPU(priv->mon, vcpu, false); - - if (qemuDomainObjExitMonitor(driver, vm) < 0) - goto cleanup; - - if (rc < 0) { - virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false); - vcpuinfo->online = true; - goto cleanup; - } - - if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0) - goto cleanup; - - if (qemuDomainValidateVcpuInfo(vm) < 0) { - /* rollback vcpu count if the setting has failed */ - virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false); - vcpuinfo->online = true; - goto cleanup; - } - - virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", true); - - if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu) < 0) - goto cleanup; - - ret = 0; - - cleanup: - return ret; -} - - static int qemuDomainSetVcpusAgent(virDomainObjPtr vm, unsigned int nvcpus) @@ -4889,7 +4839,6 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver, unsigned int nvcpus) { qemuDomainObjPrivatePtr priv = vm->privateData; - size_t i; virCgroupPtr cgroup_temp = NULL; char *mem_mask = NULL; char *all_nodes_str = NULL; @@ -4926,8 +4875,11 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver, break; } } else { - for (i = virDomainDefGetVcpus(vm->def) - 1; i >= nvcpus; i--) { - if ((rc = qemuDomainHotplugDelVcpu(driver, vm, i)) < 0) + for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0; nextvcpu--) { + if (!virBitmapIsBitSet(vcpumap, nextvcpu)) + continue; + + if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0) break; } } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 31ef22f7e2..1bdde5bed6 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4419,3 +4419,111 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver, qemuDomainResetDeviceRemoval(vm); return ret; } + + +static int +qemuDomainRemoveVcpu(virQEMUDriverPtr driver, + virDomainObjPtr vm, + unsigned int vcpu) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu); + qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo); + int oldvcpus = virDomainDefGetVcpus(vm->def); + unsigned int nvcpus = vcpupriv->vcpus; + size_t i; + + if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0) + return -1; + + /* validation requires us to set the expected state prior to calling it */ + for (i = vcpu; i < vcpu + nvcpus; i++) { + vcpuinfo = virDomainDefGetVcpu(vm->def, i); + vcpuinfo->online = false; + } + + if (qemuDomainValidateVcpuInfo(vm) < 0) { + /* rollback vcpu count if the setting has failed */ + virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false); + + for (i = vcpu; i < vcpu + nvcpus; i++) { + vcpuinfo = virDomainDefGetVcpu(vm->def, i); + vcpuinfo->online = true; + } + return -1; + } + + virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true); + + for (i = vcpu; i < vcpu + nvcpus; i++) { + vcpuinfo = virDomainDefGetVcpu(vm->def, i); + if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i) < 0) + return -1; + } + + return 0; +} + + +void +qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver, + virDomainObjPtr vm, + const char *alias) +{ + virDomainVcpuDefPtr vcpu; + qemuDomainVcpuPrivatePtr vcpupriv; + size_t i; + + for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) { + vcpu = virDomainDefGetVcpu(vm->def, i); + vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu); + + if (STREQ_NULLABLE(alias, vcpupriv->alias)) { + qemuDomainRemoveVcpu(driver, vm, i); + return; + } + } +} + + +int +qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver, + virDomainObjPtr vm, + unsigned int vcpu) +{ + virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu); + qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo); + int oldvcpus = virDomainDefGetVcpus(vm->def); + unsigned int nvcpus = vcpupriv->vcpus; + int rc; + + if (!vcpupriv->alias) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("vcpu '%u' can't be unplugged"), vcpu); + return -1; + } + + qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias); + + qemuDomainObjEnterMonitor(driver, vm); + + rc = qemuMonitorDelDevice(qemuDomainGetMonitor(vm), vcpupriv->alias); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + return -1; + + if (rc < 0) { + virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false); + return -1; + } + + if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) { + if (rc == 0) + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("vcpu unplug request timed out")); + + return -1; + } + + return qemuDomainRemoveVcpu(driver, vm, vcpu); +} diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 165d345bbc..b048cf4688 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -105,6 +105,13 @@ int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainRNGDefPtr rng); +int qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver, + virDomainObjPtr vm, + unsigned int vcpu); +void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver, + virDomainObjPtr vm, + const char *alias); + int qemuDomainChrInsert(virDomainDefPtr vmdef, virDomainChrDefPtr chr);