mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 20:45:18 +00:00
qemu: hotplug: Add support for VCPU unplug
This patch removes the old vcpu unplug code completely and replaces it with the new code using device_del. The old hotplug code basically never worked with any recent qemu and thus is useless. As the new code is using device_del all the implications of using it are present. Contrary to the device deletion code, the vcpu deletion code fails if the unplug request is not executed in time.
This commit is contained in:
parent
00990d9f4c
commit
e3229f6e44
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user