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:
Peter Krempa 2016-08-16 15:02:11 +02:00
parent 00990d9f4c
commit e3229f6e44
3 changed files with 128 additions and 61 deletions

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);