Enable cpuset cgroup and synchronous vcpupin info to cgroup.

vcpu threads pin are implemented using sched_setaffinity(), but
not controlled by cgroup. This patch does the following things:

    1) enable cpuset cgroup
    2) reflect all the vcpu threads pin info to cgroup

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
This commit is contained in:
Hu Tao 2012-08-21 17:18:30 +08:00 committed by Daniel Veillard
parent a5dd8b808c
commit fe1d32596c
6 changed files with 146 additions and 23 deletions

View File

@ -82,6 +82,7 @@ virCgroupGetCpuShares;
virCgroupGetCpuacctPercpuUsage; virCgroupGetCpuacctPercpuUsage;
virCgroupGetCpuacctStat; virCgroupGetCpuacctStat;
virCgroupGetCpuacctUsage; virCgroupGetCpuacctUsage;
virCgroupGetCpusetCpus;
virCgroupGetCpusetMems; virCgroupGetCpusetMems;
virCgroupGetFreezerState; virCgroupGetFreezerState;
virCgroupGetMemSwapHardLimit; virCgroupGetMemSwapHardLimit;
@ -100,6 +101,7 @@ virCgroupSetBlkioWeight;
virCgroupSetCpuCfsPeriod; virCgroupSetCpuCfsPeriod;
virCgroupSetCpuCfsQuota; virCgroupSetCpuCfsQuota;
virCgroupSetCpuShares; virCgroupSetCpuShares;
virCgroupSetCpusetCpus;
virCgroupSetCpusetMems; virCgroupSetCpusetMems;
virCgroupSetFreezerState; virCgroupSetFreezerState;
virCgroupSetMemSwapHardLimit; virCgroupSetMemSwapHardLimit;

View File

@ -491,11 +491,45 @@ cleanup:
return -1; return -1;
} }
int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
virDomainVcpuPinDefPtr *vcpupin,
int nvcpupin,
int vcpuid)
{
int i, rc = 0;
char *new_cpus = NULL;
for (i = 0; i < nvcpupin; i++) {
if (vcpuid == vcpupin[i]->vcpuid) {
new_cpus = virDomainCpuSetFormat(vcpupin[i]->cpumask,
VIR_DOMAIN_CPUMASK_LEN);
if (!new_cpus) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to convert cpu mask"));
rc = -1;
goto cleanup;
}
rc = virCgroupSetCpusetCpus(cgroup, new_cpus);
if (rc != 0) {
virReportSystemError(-rc,
"%s",
_("Unable to set cpuset.cpus"));
goto cleanup;
}
}
}
cleanup:
VIR_FREE(new_cpus);
return rc;
}
int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm) int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
{ {
virCgroupPtr cgroup = NULL; virCgroupPtr cgroup = NULL;
virCgroupPtr cgroup_vcpu = NULL; virCgroupPtr cgroup_vcpu = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr def = vm->def;
int rc; int rc;
unsigned int i; unsigned int i;
unsigned long long period = vm->def->cputune.period; unsigned long long period = vm->def->cputune.period;
@ -567,6 +601,15 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
} }
} }
/* Set vcpupin in cgroup if vcpupin xml is provided */
if (def->cputune.nvcpupin &&
qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET) &&
qemuSetupCgroupVcpuPin(cgroup_vcpu,
def->cputune.vcpupin,
def->cputune.nvcpupin,
i) < 0)
goto cleanup;
virCgroupFree(&cgroup_vcpu); virCgroupFree(&cgroup_vcpu);
} }

View File

@ -53,6 +53,10 @@ int qemuSetupCgroup(struct qemud_driver *driver,
int qemuSetupCgroupVcpuBW(virCgroupPtr cgroup, int qemuSetupCgroupVcpuBW(virCgroupPtr cgroup,
unsigned long long period, unsigned long long period,
long long quota); long long quota);
int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
virDomainVcpuPinDefPtr *vcpupin,
int nvcpupin,
int vcpuid);
int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm); int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm);
int qemuSetupCgroupForEmulator(struct qemud_driver *driver, int qemuSetupCgroupForEmulator(struct qemud_driver *driver,
virDomainObjPtr vm); virDomainObjPtr vm);

View File

@ -3716,11 +3716,15 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainDefPtr persistentDef = NULL; virDomainDefPtr persistentDef = NULL;
virCgroupPtr cgroup_dom = NULL;
virCgroupPtr cgroup_vcpu = NULL;
int maxcpu, hostcpus; int maxcpu, hostcpus;
virNodeInfo nodeinfo; virNodeInfo nodeinfo;
int ret = -1; int ret = -1;
qemuDomainObjPrivatePtr priv; qemuDomainObjPrivatePtr priv;
bool canResetting = true; bool canResetting = true;
int newVcpuPinNum = 0;
virDomainVcpuPinDefPtr *newVcpuPin = NULL;
int pcpu; int pcpu;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
@ -3769,16 +3773,54 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_LIVE) { if (flags & VIR_DOMAIN_AFFECT_LIVE) {
if (priv->vcpupids != NULL) { if (priv->vcpupids == NULL) {
if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
cpumap, maplen, maxcpu) < 0)
goto cleanup;
} else {
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cpu affinity is not supported")); "%s", _("cpu affinity is not supported"));
goto cleanup; goto cleanup;
} }
if (vm->def->cputune.vcpupin) {
newVcpuPin = virDomainVcpuPinDefCopy(vm->def->cputune.vcpupin,
vm->def->cputune.nvcpupin);
if (!newVcpuPin)
goto cleanup;
newVcpuPinNum = vm->def->cputune.nvcpupin;
} else {
if (VIR_ALLOC(newVcpuPin) < 0) {
virReportOOMError();
goto cleanup;
}
newVcpuPinNum = 0;
}
if (virDomainVcpuPinAdd(newVcpuPin, &newVcpuPinNum, cpumap, maplen, vcpu) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to update vcpupin"));
virDomainVcpuPinDefFree(newVcpuPin, newVcpuPinNum);
goto cleanup;
}
/* Configure the corresponding cpuset cgroup before set affinity. */
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup_dom, 0) == 0 &&
virCgroupForVcpu(cgroup_dom, vcpu, &cgroup_vcpu, 0) == 0 &&
qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
virReportError(VIR_ERR_OPERATION_INVALID,
_("failed to set cpuset.cpus in cgroup"
" for vcpu %d"), vcpu);
goto cleanup;
}
} else {
if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
cpumap, maplen, maxcpu) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to set cpu affinity for vcpu %d"),
vcpu);
goto cleanup;
}
}
if (canResetting) { if (canResetting) {
if (virDomainVcpuPinDel(vm->def, vcpu) < 0) { if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -3787,25 +3829,17 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
goto cleanup; goto cleanup;
} }
} else { } else {
if (!vm->def->cputune.vcpupin) { if (vm->def->cputune.vcpupin)
if (VIR_ALLOC(vm->def->cputune.vcpupin) < 0) { virDomainVcpuPinDefFree(vm->def->cputune.vcpupin, vm->def->cputune.nvcpupin);
virReportOOMError();
goto cleanup; vm->def->cputune.vcpupin = newVcpuPin;
} vm->def->cputune.nvcpupin = newVcpuPinNum;
vm->def->cputune.nvcpupin = 0; newVcpuPin = NULL;
}
if (virDomainVcpuPinAdd(vm->def->cputune.vcpupin,
&vm->def->cputune.nvcpupin,
cpumap,
maplen,
vcpu) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to update or add vcpupin xml of "
"a running domain"));
goto cleanup;
}
} }
if (newVcpuPin)
virDomainVcpuPinDefFree(newVcpuPin, newVcpuPinNum);
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto cleanup; goto cleanup;
} }
@ -3846,6 +3880,10 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
ret = 0; ret = 0;
cleanup: cleanup:
if (cgroup_vcpu)
virCgroupFree(&cgroup_vcpu);
if (cgroup_dom)
virCgroupFree(&cgroup_dom);
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
return ret; return ret;

View File

@ -543,7 +543,8 @@ static int virCgroupMakeGroup(virCgroupPtr parent, virCgroupPtr group,
/* We need to control cpu bandwidth for each vcpu now */ /* We need to control cpu bandwidth for each vcpu now */
if ((flags & VIR_CGROUP_VCPU) && if ((flags & VIR_CGROUP_VCPU) &&
(i != VIR_CGROUP_CONTROLLER_CPU && (i != VIR_CGROUP_CONTROLLER_CPU &&
i != VIR_CGROUP_CONTROLLER_CPUACCT)) { i != VIR_CGROUP_CONTROLLER_CPUACCT &&
i != VIR_CGROUP_CONTROLLER_CPUSET)) {
/* treat it as unmounted and we can use virCgroupAddTask */ /* treat it as unmounted and we can use virCgroupAddTask */
VIR_FREE(group->controllers[i].mountPoint); VIR_FREE(group->controllers[i].mountPoint);
continue; continue;
@ -1401,6 +1402,38 @@ int virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
mems); mems);
} }
/**
* virCgroupSetCpusetCpus:
*
* @group: The cgroup to set cpuset.cpus for
* @cpus: the cpus to set
*
* Retuens: 0 on success
*/
int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
{
return virCgroupSetValueStr(group,
VIR_CGROUP_CONTROLLER_CPUSET,
"cpuset.cpus",
cpus);
}
/**
* virCgroupGetCpusetCpus:
*
* @group: The cgroup to get cpuset.cpus for
* @cpus: the cpus to get
*
* Retuens: 0 on success
*/
int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
{
return virCgroupGetValueStr(group,
VIR_CGROUP_CONTROLLER_CPUSET,
"cpuset.cpus",
cpus);
}
/** /**
* virCgroupDenyAllDevices: * virCgroupDenyAllDevices:
* *

View File

@ -151,6 +151,9 @@ int virCgroupGetFreezerState(virCgroupPtr group, char **state);
int virCgroupSetCpusetMems(virCgroupPtr group, const char *mems); int virCgroupSetCpusetMems(virCgroupPtr group, const char *mems);
int virCgroupGetCpusetMems(virCgroupPtr group, char **mems); int virCgroupGetCpusetMems(virCgroupPtr group, char **mems);
int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus);
int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus);
int virCgroupRemove(virCgroupPtr group); int virCgroupRemove(virCgroupPtr group);
void virCgroupFree(virCgroupPtr *group); void virCgroupFree(virCgroupPtr *group);