mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-03 10:25:16 +00:00
qemu: cgroup: Extract temporary relaxing of cgroup setting for vcpu hotplug
When hot-adding vcpus qemu needs to allocate some structures in the DMA zone which may be outside of the numa pinning. Extract the code doing this in a set of helpers so that it can be reused.
This commit is contained in:
parent
e2c63714a8
commit
eb5dee3534
@ -1127,3 +1127,93 @@ qemuRemoveCgroup(virDomainObjPtr vm)
|
|||||||
|
|
||||||
return virCgroupRemove(priv->cgroup);
|
return virCgroupRemove(priv->cgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
qemuCgroupEmulatorAllNodesDataFree(qemuCgroupEmulatorAllNodesDataPtr data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
virCgroupFree(&data->emulatorCgroup);
|
||||||
|
VIR_FREE(data->emulatorMemMask);
|
||||||
|
VIR_FREE(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuCgroupEmulatorAllNodesAllow:
|
||||||
|
* @cgroup: domain cgroup pointer
|
||||||
|
* @retData: filled with structure used to roll back the operation
|
||||||
|
*
|
||||||
|
* Allows all NUMA nodes for the qemu emulator thread temporarily. This is
|
||||||
|
* necessary when hotplugging cpus since it requires memory allocated in the
|
||||||
|
* DMA region. Afterwards the operation can be reverted by
|
||||||
|
* qemuCgrouEmulatorAllNodesRestore.
|
||||||
|
*
|
||||||
|
* Returns 0 on success -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qemuCgroupEmulatorAllNodesAllow(virCgroupPtr cgroup,
|
||||||
|
qemuCgroupEmulatorAllNodesDataPtr *retData)
|
||||||
|
{
|
||||||
|
qemuCgroupEmulatorAllNodesDataPtr data = NULL;
|
||||||
|
char *all_nodes_str = NULL;
|
||||||
|
virBitmapPtr all_nodes = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!virNumaIsAvailable() ||
|
||||||
|
!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(all_nodes = virNumaGetHostNodeset()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(all_nodes_str = virBitmapFormat(all_nodes)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(data) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
|
||||||
|
false, &data->emulatorCgroup) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virCgroupGetCpusetMems(data->emulatorCgroup, &data->emulatorMemMask) < 0 ||
|
||||||
|
virCgroupSetCpusetMems(data->emulatorCgroup, all_nodes_str) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
VIR_STEAL_PTR(*retData, data);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(all_nodes_str);
|
||||||
|
virBitmapFree(all_nodes);
|
||||||
|
qemuCgroupEmulatorAllNodesDataFree(data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuCgrouEmulatorAllNodesRestore:
|
||||||
|
* @data: data structure created by qemuCgroupEmulatorAllNodesAllow
|
||||||
|
*
|
||||||
|
* Rolls back the setting done by qemuCgroupEmulatorAllNodesAllow and frees the
|
||||||
|
* associated data.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
qemuCgrouEmulatorAllNodesRestore(qemuCgroupEmulatorAllNodesDataPtr data)
|
||||||
|
{
|
||||||
|
virErrorPtr err;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
err = virSaveLastError();
|
||||||
|
virCgroupSetCpusetMems(data->emulatorCgroup, data->emulatorMemMask);
|
||||||
|
virSetError(err);
|
||||||
|
virFreeError(err);
|
||||||
|
|
||||||
|
qemuCgroupEmulatorAllNodesDataFree(data);
|
||||||
|
}
|
||||||
|
@ -57,4 +57,15 @@ int qemuSetupCgroupCpusetCpus(virCgroupPtr cgroup, virBitmapPtr cpumask);
|
|||||||
int qemuSetupGlobalCpuCgroup(virDomainObjPtr vm);
|
int qemuSetupGlobalCpuCgroup(virDomainObjPtr vm);
|
||||||
int qemuRemoveCgroup(virDomainObjPtr vm);
|
int qemuRemoveCgroup(virDomainObjPtr vm);
|
||||||
|
|
||||||
|
typedef struct _qemuCgroupEmulatorAllNodesData qemuCgroupEmulatorAllNodesData;
|
||||||
|
typedef qemuCgroupEmulatorAllNodesData *qemuCgroupEmulatorAllNodesDataPtr;
|
||||||
|
struct _qemuCgroupEmulatorAllNodesData {
|
||||||
|
virCgroupPtr emulatorCgroup;
|
||||||
|
char *emulatorMemMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
int qemuCgroupEmulatorAllNodesAllow(virCgroupPtr cgroup,
|
||||||
|
qemuCgroupEmulatorAllNodesDataPtr *data);
|
||||||
|
void qemuCgrouEmulatorAllNodesRestore(qemuCgroupEmulatorAllNodesDataPtr data);
|
||||||
|
|
||||||
#endif /* __QEMU_CGROUP_H__ */
|
#endif /* __QEMU_CGROUP_H__ */
|
||||||
|
@ -4853,11 +4853,7 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
|
|||||||
unsigned int nvcpus)
|
unsigned int nvcpus)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
virCgroupPtr cgroup_temp = NULL;
|
qemuCgroupEmulatorAllNodesDataPtr emulatorCgroup = NULL;
|
||||||
char *mem_mask = NULL;
|
|
||||||
char *all_nodes_str = NULL;
|
|
||||||
virBitmapPtr all_nodes = NULL;
|
|
||||||
virErrorPtr err = NULL;
|
|
||||||
virBitmapPtr vcpumap = NULL;
|
virBitmapPtr vcpumap = NULL;
|
||||||
ssize_t nextvcpu = -1;
|
ssize_t nextvcpu = -1;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -4866,22 +4862,8 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
|
|||||||
if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus)))
|
if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virNumaIsAvailable() &&
|
if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
|
||||||
virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
|
goto cleanup;
|
||||||
if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
|
|
||||||
false, &cgroup_temp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(all_nodes = virNumaGetHostNodeset()))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(all_nodes_str = virBitmapFormat(all_nodes)))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (virCgroupGetCpusetMems(cgroup_temp, &mem_mask) < 0 ||
|
|
||||||
virCgroupSetCpusetMems(cgroup_temp, all_nodes_str) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nvcpus > virDomainDefGetVcpus(vm->def)) {
|
if (nvcpus > virDomainDefGetVcpus(vm->def)) {
|
||||||
while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
|
while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
|
||||||
@ -4909,17 +4891,7 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (mem_mask) {
|
qemuCgrouEmulatorAllNodesRestore(emulatorCgroup);
|
||||||
err = virSaveLastError();
|
|
||||||
virCgroupSetCpusetMems(cgroup_temp, mem_mask);
|
|
||||||
virSetError(err);
|
|
||||||
virFreeError(err);
|
|
||||||
VIR_FREE(mem_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_FREE(all_nodes_str);
|
|
||||||
virBitmapFree(all_nodes);
|
|
||||||
virCgroupFree(&cgroup_temp);
|
|
||||||
virBitmapFree(vcpumap);
|
virBitmapFree(vcpumap);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user