This patch adds a new structure, virCgroupItem, to represent
a cgroup directory(named cgroup item). cgroup directory is
created when needed and removed if no one is using it.
---
src/conf/domain_conf.h | 5 +
src/libvirt_private.syms | 7 +-
src/lxc/lxc_cgroup.c | 40 +-
src/lxc/lxc_cgroup.h | 2 +-
src/lxc/lxc_controller.c | 31 +-
src/lxc/lxc_driver.c | 177 +++----
src/lxc/lxc_process.c | 19 +-
src/qemu/qemu_cgroup.c | 162 +++---
src/qemu/qemu_cgroup.h | 3 +-
src/qemu/qemu_driver.c | 350 +++++--------
src/qemu/qemu_hotplug.c | 21 +-
src/qemu/qemu_migration.c | 20 +-
src/qemu/qemu_process.c | 7 +-
src/util/vircgroup.c | 1253 +++++++++++++++++++++------------------------
src/util/vircgroup.h | 19 +-
15 files changed, 915 insertions(+), 1201 deletions(-)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index dc411e4..395a653 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -47,6 +47,7 @@
# include "device_conf.h"
# include "virbitmap.h"
# include "virstoragefile.h"
+# include "vircgroup.h"
/* forward declarations of all device types, required by
* virDomainDeviceDef
@@ -1888,6 +1889,10 @@ struct _virDomainObj {
void (*privateDataFreeFunc)(void *);
int taint;
+
+ virCgroupPtr cgroup;
+ virCgroupPtr *vcpuCgroups;
+ virCgroupPtr cgroupEmulator;
};
typedef struct _virDomainObjList virDomainObjList;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 57e3eb4..50a668a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -85,10 +85,6 @@ virCgroupDenyAllDevices;
virCgroupDenyDevice;
virCgroupDenyDeviceMajor;
virCgroupDenyDevicePath;
-virCgroupForDomain;
-virCgroupForDriver;
-virCgroupForEmulator;
-virCgroupForVcpu;
virCgroupFree;
virCgroupGetAppRoot;
virCgroupGetBlkioWeight;
@@ -109,10 +105,11 @@ virCgroupGetMemSwapUsage;
virCgroupKill;
virCgroupKillPainfully;
virCgroupKillRecursive;
+virCgroupMakePath;
virCgroupMounted;
virCgroupMoveTask;
+virCgroupNew;
virCgroupPathOfController;
-virCgroupRemove;
virCgroupSetBlkioDeviceWeight;
virCgroupSetBlkioWeight;
virCgroupSetCpuCfsPeriod;
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index a075335..04b2513 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -242,7 +242,7 @@ int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo)
int ret;
virCgroupPtr cgroup;
- ret = virCgroupGetAppRoot(&cgroup);
+ ret = virCgroupGetAppRoot(&cgroup, true);
if (ret < 0) {
virReportSystemError(-ret, "%s",
_("Unable to get cgroup for container"));
@@ -472,53 +472,29 @@ cleanup:
}
-int virLXCCgroupSetup(virDomainDefPtr def)
+int virLXCCgroupSetup(virCgroupPtr cgroup, virDomainDefPtr def)
{
- virCgroupPtr driver = NULL;
- virCgroupPtr cgroup = NULL;
- int ret = -1;
int rc;
- rc = virCgroupForDriver("lxc", &driver, 1, 0);
- if (rc != 0) {
- virReportSystemError(-rc, "%s",
- _("Unable to get cgroup for driver"));
- goto cleanup;
- }
-
- rc = virCgroupForDomain(driver, def->name, &cgroup, 1);
- if (rc != 0) {
- virReportSystemError(-rc,
- _("Unable to create cgroup for domain %s"),
- def->name);
- goto cleanup;
- }
-
if (virLXCCgroupSetupCpuTune(def, cgroup) < 0)
- goto cleanup;
+ return -1;
if (virLXCCgroupSetupBlkioTune(def, cgroup) < 0)
- goto cleanup;
+ return -1;
if (virLXCCgroupSetupMemTune(def, cgroup) < 0)
- goto cleanup;
+ return -1;
if (virLXCCgroupSetupDeviceACL(def, cgroup) < 0)
- goto cleanup;
+ return -1;
rc = virCgroupAddTask(cgroup, getpid());
if (rc != 0) {
virReportSystemError(-rc,
_("Unable to add task %d to cgroup for domain
%s"),
getpid(), def->name);
- goto cleanup;
+ return -1;
}
- ret = 0;
-
-cleanup:
- virCgroupFree(&cgroup);
- virCgroupFree(&driver);
-
- return ret;
+ return 0;
}
diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h
index fff554b..3b3541a 100644
--- a/src/lxc/lxc_cgroup.h
+++ b/src/lxc/lxc_cgroup.h
@@ -26,7 +26,7 @@
# include "lxc_fuse.h"
# include "virusb.h"
-int virLXCCgroupSetup(virDomainDefPtr def);
+int virLXCCgroupSetup(virCgroupPtr cgroup, virDomainDefPtr def);
int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo);
int
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 2673f72..4a7a63b 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -130,6 +130,8 @@ struct _virLXCController {
int timerShutdown;
virLXCFusePtr fuse;
+
+ virCgroupPtr cgroup;
};
#include "lxc_controller_dispatch.h"
@@ -272,6 +274,8 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
VIR_FREE(ctrl->devptmx);
+ virCgroupFree(&ctrl->cgroup);
+
virDomainDefFree(ctrl->def);
VIR_FREE(ctrl->name);
@@ -548,6 +552,31 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr
ctrl)
return 0;
}
+static int virLXCControllerSetupCgroup(virLXCControllerPtr ctrl)
+{
+ virCgroupPtr appCgroup = NULL;
+ int rc;
+
+ rc = virCgroupGetAppRoot(&appCgroup, true);
+ if (rc != 0) {
+ virReportSystemError(-rc, "%s",
+ _("Unable to get cgroup for libvirt"));
+ goto cleanup;
+ }
+
+ rc = virCgroupNew("lxc", appCgroup, &ctrl->cgroup);
+ if (rc != 0) {
+ virReportSystemError(-rc, "%s",
+ _("Unable to get cgroup for driver"));
+ goto cleanup;
+ }
+
+ rc = virLXCCgroupSetup(ctrl->cgroup, ctrl->def);
+
+cleanup:
+ virCgroupFree(&appCgroup);
+ return rc;
+}
/**
* virLXCControllerSetupResourceLimits
@@ -567,7 +596,7 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr
ctrl)
if (virLXCControllerSetupNUMAPolicy(ctrl) < 0)
return -1;
- return virLXCCgroupSetup(ctrl->def);
+ return virLXCControllerSetupCgroup(ctrl);
}
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 671b19d..b265095 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -527,7 +527,6 @@ static int lxcDomainGetInfo(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm;
- virCgroupPtr cgroup = NULL;
int ret = -1, rc;
lxcDriverLock(driver);
@@ -543,22 +542,16 @@ static int lxcDomainGetInfo(virDomainPtr dom,
info->state = virDomainObjGetState(vm, NULL);
- if (!virDomainObjIsActive(vm) || driver->cgroup == NULL) {
+ if (!virDomainObjIsActive(vm) || vm->cgroup == NULL) {
info->cpuTime = 0;
info->memory = vm->def->mem.cur_balloon;
} else {
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=
0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to get cgroup for %s"),
vm->def->name);
- goto cleanup;
- }
-
- if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) {
+ if (virCgroupGetCpuacctUsage(vm->cgroup, &(info->cpuTime)) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Cannot read cputime for
domain"));
goto cleanup;
}
- if ((rc = virCgroupGetMemoryUsage(cgroup, &(info->memory))) < 0) {
+ if ((rc = virCgroupGetMemoryUsage(vm->cgroup, &(info->memory))) < 0)
{
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Cannot read memory usage for
domain"));
if (rc == -ENOENT) {
@@ -576,8 +569,6 @@ static int lxcDomainGetInfo(virDomainPtr dom,
cleanup:
lxcDriverUnlock(driver);
- if (cgroup)
- virCgroupFree(&cgroup);
if (vm)
virObjectUnlock(vm);
return ret;
@@ -708,7 +699,6 @@ cleanup:
static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
virLXCDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm;
- virCgroupPtr cgroup = NULL;
int ret = -1;
lxcDriverLock(driver);
@@ -734,19 +724,13 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long
newmem) {
goto cleanup;
}
- if (driver->cgroup == NULL) {
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cgroups must be configured on the
host"));
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0)
{
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to get cgroup for %s"), vm->def->name);
- goto cleanup;
- }
-
- if (virCgroupSetMemory(cgroup, newmem) < 0) {
+ if (virCgroupSetMemory(vm->cgroup, newmem) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Failed to set memory for domain"));
goto cleanup;
@@ -757,8 +741,6 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem)
{
cleanup:
if (vm)
virObjectUnlock(vm);
- if (cgroup)
- virCgroupFree(&cgroup);
return ret;
}
@@ -770,7 +752,6 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr cgroup = NULL;
virDomainObjPtr vm = NULL;
int ret = -1;
int rc;
@@ -797,7 +778,7 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -808,21 +789,21 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
virTypedParameterPtr param = ¶ms[i];
if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
- rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul);
+ rc = virCgroupSetMemoryHardLimit(vm->cgroup, params[i].value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory hard_limit
tunable"));
ret = -1;
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
- rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul);
+ rc = virCgroupSetMemorySoftLimit(vm->cgroup, params[i].value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory soft_limit
tunable"));
ret = -1;
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT)) {
- rc = virCgroupSetMemSwapHardLimit(cgroup, params[i].value.ul);
+ rc = virCgroupSetMemSwapHardLimit(vm->cgroup, params[i].value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set swap_hard_limit
tunable"));
@@ -832,8 +813,6 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
}
cleanup:
- if (cgroup)
- virCgroupFree(&cgroup);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -848,7 +827,6 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr cgroup = NULL;
virDomainObjPtr vm = NULL;
unsigned long long val;
int ret = -1;
@@ -874,7 +852,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to get cgroup for %s"), vm->def->name);
goto cleanup;
@@ -886,7 +864,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
switch (i) {
case 0: /* fill memory hard limit here */
- rc = virCgroupGetMemoryHardLimit(cgroup, &val);
+ rc = virCgroupGetMemoryHardLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory hard limit"));
@@ -897,7 +875,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
break;
case 1: /* fill memory soft limit here */
- rc = virCgroupGetMemorySoftLimit(cgroup, &val);
+ rc = virCgroupGetMemorySoftLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory soft limit"));
@@ -908,7 +886,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
break;
case 2: /* fill swap hard limit here */
- rc = virCgroupGetMemSwapHardLimit(cgroup, &val);
+ rc = virCgroupGetMemSwapHardLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get swap hard limit"));
@@ -932,8 +910,6 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
ret = 0;
cleanup:
- if (cgroup)
- virCgroupFree(&cgroup);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -1408,6 +1384,7 @@ static int lxcStartup(bool privileged,
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
+ virCgroupPtr appCgroup = NULL;
char *ld;
int rc;
@@ -1452,15 +1429,19 @@ static int lxcStartup(bool privileged,
lxc_driver->log_libvirtd = 0; /* by default log to container logfile */
lxc_driver->have_netns = lxcCheckNetNsSupport();
- rc = virCgroupForDriver("lxc", &lxc_driver->cgroup, privileged, 1);
- if (rc < 0) {
- char buf[1024] ATTRIBUTE_UNUSED;
- VIR_DEBUG("Unable to create cgroup for LXC driver: %s",
- virStrerror(-rc, buf, sizeof(buf)));
- /* Don't abort startup. We will explicitly report to
- * the user when they try to start a VM
- */
+ rc = virCgroupGetAppRoot(&appCgroup, privileged);
+ if (appCgroup) {
+ rc = virCgroupNew("lxc", appCgroup, &lxc_driver->cgroup);
+ if (rc < 0) {
+ char buf[1024];
+ VIR_DEBUG("Unable to create cgroup for LXC driver: %s",
+ virStrerror(-rc, buf, sizeof(buf)));
+ /* Don't abort startup. We will explicitly report to
+ * the user when they try to start a VM
+ */
+ }
}
+ virCgroupFree(&appCgroup);
/* Call function to load lxc driver configuration information */
if (lxcLoadDriverConfig(lxc_driver) < 0)
@@ -1565,6 +1546,7 @@ static int lxcShutdown(void)
VIR_FREE(lxc_driver->autostartDir);
VIR_FREE(lxc_driver->stateDir);
VIR_FREE(lxc_driver->logDir);
+ virCgroupFree(&lxc_driver->cgroup);
lxcDriverUnlock(lxc_driver);
virMutexDestroy(&lxc_driver->lock);
VIR_FREE(lxc_driver);
@@ -1754,7 +1736,6 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr vmdef = NULL;
int ret = -1;
@@ -1799,7 +1780,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
"%s", _("cgroup CPU controller is not
mounted"));
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
@@ -1812,7 +1793,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetCpuShares(group, params[i].value.ul);
+ rc = virCgroupSetCpuShares(vm->cgroup, params[i].value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set cpu shares
tunable"));
@@ -1827,7 +1808,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
}
} else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = lxcSetVcpuBWLive(group, params[i].value.ul, 0);
+ rc = lxcSetVcpuBWLive(vm->cgroup, params[i].value.ul, 0);
if (rc != 0)
goto cleanup;
@@ -1840,7 +1821,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
}
} else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = lxcSetVcpuBWLive(group, 0, params[i].value.l);
+ rc = lxcSetVcpuBWLive(vm->cgroup, 0, params[i].value.l);
if (rc != 0)
goto cleanup;
@@ -1871,7 +1852,6 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
cleanup:
virDomainDefFree(vmdef);
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -1893,7 +1873,6 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
unsigned int flags)
{
virLXCDriverPtr driver = dom->conn->privateData;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef;
unsigned long long shares = 0;
@@ -1943,13 +1922,13 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
- rc = virCgroupGetCpuShares(group, &shares);
+ rc = virCgroupGetCpuShares(vm->cgroup, &shares);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get cpu shares tunable"));
@@ -1957,7 +1936,7 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
}
if (*nparams > 1 && cpu_bw_status) {
- rc = lxcGetVcpuBWLive(group, &period, "a);
+ rc = lxcGetVcpuBWLive(vm->cgroup, &period, "a);
if (rc != 0)
goto cleanup;
}
@@ -1990,7 +1969,6 @@ out:
ret = 0;
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -2014,7 +1992,6 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
int ret = -1;
@@ -2048,7 +2025,7 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -2066,7 +2043,7 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- rc = virCgroupSetBlkioWeight(group, params[i].value.ui);
+ rc = virCgroupSetBlkioWeight(vm->cgroup, params[i].value.ui);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set blkio weight
tunable"));
@@ -2099,7 +2076,6 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
ret = 0;
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -2116,7 +2092,6 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
unsigned int val;
@@ -2153,7 +2128,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -2165,7 +2140,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
switch (i) {
case 0: /* fill blkio weight here */
- rc = virCgroupGetBlkioWeight(group, &val);
+ rc = virCgroupGetBlkioWeight(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get blkio weight"));
@@ -2207,8 +2182,6 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
ret = 0;
cleanup:
- if (group)
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
lxcDriverUnlock(driver);
@@ -2378,7 +2351,7 @@ cleanup:
return ret;
}
-static int lxcFreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
+static int lxcFreezeContainer(virDomainObjPtr vm)
{
int timeout = 1000; /* In milliseconds */
int check_interval = 1; /* In milliseconds */
@@ -2388,8 +2361,7 @@ static int lxcFreezeContainer(virLXCDriverPtr driver,
virDomainObjPtr vm)
char *state = NULL;
virCgroupPtr cgroup = NULL;
- if (!(driver->cgroup &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) ==
0))
+ if (!vm->cgroup)
return -1;
/* From here on, we know that cgroup != NULL. */
@@ -2496,7 +2468,7 @@ static int lxcDomainSuspend(virDomainPtr dom)
}
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
- if (lxcFreezeContainer(driver, vm) < 0) {
+ if (lxcFreezeContainer(vm) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Suspend operation failed"));
goto cleanup;
@@ -2521,18 +2493,15 @@ cleanup:
return ret;
}
-static int lxcUnfreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
+static int lxcUnfreezeContainer(virDomainObjPtr vm)
{
int ret;
- virCgroupPtr cgroup = NULL;
- if (!(driver->cgroup &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) ==
0))
+ if (!(vm->cgroup))
return -1;
- ret = virCgroupSetFreezerState(cgroup, "THAWED");
+ ret = virCgroupSetFreezerState(vm->cgroup, "THAWED");
- virCgroupFree(&cgroup);
return ret;
}
@@ -2561,7 +2530,7 @@ static int lxcDomainResume(virDomainPtr dom)
}
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
- if (lxcUnfreezeContainer(driver, vm) < 0) {
+ if (lxcUnfreezeContainer(vm) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Resume operation failed"));
goto cleanup;
@@ -3104,7 +3073,6 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainDiskDefPtr def = dev->data.disk;
- virCgroupPtr group = NULL;
int ret = -1;
char *dst = NULL;
struct stat sb;
@@ -3195,13 +3163,13 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
- if (virCgroupAllowDevicePath(group, def->src,
+ if (virCgroupAllowDevicePath(vm->cgroup, def->src,
(def->readonly ?
VIR_CGROUP_DEVICE_READ :
VIR_CGROUP_DEVICE_RW) |
@@ -3219,8 +3187,6 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
cleanup:
def->src = tmpsrc;
virDomainAuditDisk(vm, NULL, def->src, "attach", ret == 0);
- if (group)
- virCgroupFree(&group);
if (dst && created && ret < 0)
unlink(dst);
return ret;
@@ -3374,7 +3340,6 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
mode_t mode;
bool created = false;
virUSBDevicePtr usb = NULL;
- virCgroupPtr group = NULL;
if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -3415,7 +3380,7 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -3462,7 +3427,7 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
if (virUSBDeviceFileIterate(usb,
virLXCSetupHostUsbDeviceCgroup,
- &group) < 0)
+ &vm->cgroup) < 0)
goto cleanup;
ret = 0;
@@ -3473,7 +3438,6 @@ cleanup:
unlink(dstfile);
virUSBDeviceFree(usb);
- virCgroupFree(&group);
VIR_FREE(src);
VIR_FREE(dstfile);
VIR_FREE(dstdir);
@@ -3489,7 +3453,6 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainHostdevDefPtr def = dev->data.hostdev;
- virCgroupPtr group = NULL;
int ret = -1;
char *dst = NULL;
char *vroot = NULL;
@@ -3564,13 +3527,13 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
- if (virCgroupAllowDevicePath(group, def->source.caps.u.storage.block,
+ if (virCgroupAllowDevicePath(vm->cgroup, def->source.caps.u.storage.block,
VIR_CGROUP_DEVICE_RW |
VIR_CGROUP_DEVICE_MKNOD) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3585,8 +3548,6 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
cleanup:
virDomainAuditHostdev(vm, def, "attach", ret == 0);
- if (group)
- virCgroupFree(&group);
if (dst && created && ret < 0)
unlink(dst);
VIR_FREE(dst);
@@ -3602,7 +3563,6 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainHostdevDefPtr def = dev->data.hostdev;
- virCgroupPtr group = NULL;
int ret = -1;
char *dst = NULL;
char *vroot = NULL;
@@ -3677,13 +3637,13 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
- if (virCgroupAllowDevicePath(group, def->source.caps.u.misc.chardev,
+ if (virCgroupAllowDevicePath(vm->cgroup, def->source.caps.u.misc.chardev,
VIR_CGROUP_DEVICE_RW |
VIR_CGROUP_DEVICE_MKNOD) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3698,8 +3658,6 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
cleanup:
virDomainAuditHostdev(vm, def, "attach", ret == 0);
- if (group)
- virCgroupFree(&group);
if (dst && created && ret < 0)
unlink(dst);
VIR_FREE(dst);
@@ -3822,7 +3780,6 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainDiskDefPtr def = NULL;
- virCgroupPtr group = NULL;
int i, ret = -1;
char *dst = NULL;
@@ -3854,7 +3811,7 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -3869,7 +3826,7 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
}
virDomainAuditDisk(vm, def->src, NULL, "detach", true);
- if (virCgroupDenyDevicePath(group, def->src, VIR_CGROUP_DEVICE_RWM) != 0)
+ if (virCgroupDenyDevicePath(vm->cgroup, def->src, VIR_CGROUP_DEVICE_RWM) != 0)
VIR_WARN("cannot deny device %s for domain %s",
def->src, vm->def->name);
@@ -3880,8 +3837,6 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
cleanup:
VIR_FREE(dst);
- if (group)
- virCgroupFree(&group);
return ret;
}
@@ -3959,7 +3914,6 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainHostdevDefPtr def = NULL;
- virCgroupPtr group = NULL;
int idx, ret = -1;
char *dst = NULL;
char *vroot;
@@ -3993,7 +3947,7 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -4014,7 +3968,7 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
if (virUSBDeviceFileIterate(usb,
virLXCTeardownHostUsbDeviceCgroup,
- &group) < 0)
+ &vm->cgroup) < 0)
VIR_WARN("cannot deny device %s for domain %s",
dst, vm->def->name);
@@ -4028,7 +3982,6 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
cleanup:
virUSBDeviceFree(usb);
VIR_FREE(dst);
- virCgroupFree(&group);
return ret;
}
@@ -4040,7 +3993,6 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainHostdevDefPtr def = NULL;
- virCgroupPtr group = NULL;
int i, ret = -1;
char *dst = NULL;
@@ -4072,7 +4024,7 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -4087,7 +4039,8 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
}
virDomainAuditHostdev(vm, def, "detach", true);
- if (virCgroupDenyDevicePath(group, def->source.caps.u.storage.block,
VIR_CGROUP_DEVICE_RWM) != 0)
+ if (virCgroupDenyDevicePath(vm->cgroup, def->source.caps.u.storage.block,
+ VIR_CGROUP_DEVICE_RWM) != 0)
VIR_WARN("cannot deny device %s for domain %s",
def->source.caps.u.storage.block, vm->def->name);
@@ -4098,8 +4051,6 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
cleanup:
VIR_FREE(dst);
- if (group)
- virCgroupFree(&group);
return ret;
}
@@ -4111,7 +4062,6 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
{
virLXCDomainObjPrivatePtr priv = vm->privateData;
virDomainHostdevDefPtr def = NULL;
- virCgroupPtr group = NULL;
int i, ret = -1;
char *dst = NULL;
@@ -4143,7 +4093,7 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (vm->cgroup == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -4158,7 +4108,8 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
}
virDomainAuditHostdev(vm, def, "detach", true);
- if (virCgroupDenyDevicePath(group, def->source.caps.u.misc.chardev,
VIR_CGROUP_DEVICE_RWM) != 0)
+ if (virCgroupDenyDevicePath(vm->cgroup, def->source.caps.u.misc.chardev,
+ VIR_CGROUP_DEVICE_RWM) != 0)
VIR_WARN("cannot deny device %s for domain %s",
def->source.caps.u.misc.chardev, vm->def->name);
@@ -4169,8 +4120,6 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
cleanup:
VIR_FREE(dst);
- if (group)
- virCgroupFree(&group);
return ret;
}
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index aaa81a7..397ba1b 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -218,7 +218,6 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
virDomainObjPtr vm,
virDomainShutoffReason reason)
{
- virCgroupPtr cgroup;
int i;
virLXCDomainObjPrivatePtr priv = vm->privateData;
virNetDevVPortProfilePtr vport = NULL;
@@ -276,11 +275,7 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
virDomainConfVMNWFilterTeardown(vm);
- if (driver->cgroup &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0)
{
- virCgroupRemove(cgroup);
- virCgroupFree(&cgroup);
- }
+ virCgroupFree(&vm->cgroup);
/* now that we know it's stopped call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
@@ -685,7 +680,6 @@ int virLXCProcessStop(virLXCDriverPtr driver,
virDomainObjPtr vm,
virDomainShutoffReason reason)
{
- virCgroupPtr group = NULL;
int rc;
VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d",
@@ -707,8 +701,8 @@ int virLXCProcessStop(virLXCDriverPtr driver,
VIR_FREE(vm->def->seclabels[0]->imagelabel);
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) == 0)
{
- rc = virCgroupKillPainfully(group);
+ if (vm->cgroup) {
+ rc = virCgroupKillPainfully(vm->cgroup);
if (rc < 0) {
virReportSystemError(-rc, "%s",
_("Failed to kill container PIDs"));
@@ -732,7 +726,6 @@ int virLXCProcessStop(virLXCDriverPtr driver,
rc = 0;
cleanup:
- virCgroupFree(&group);
return rc;
}
@@ -945,6 +938,12 @@ int virLXCProcessStart(virConnectPtr conn,
return -1;
}
+ if (virCgroupNew(vm->def->name, driver->cgroup, &vm->cgroup) < 0)
{
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Unable to find cgroup for domain"));
+ return -1;
+ }
+
if (virFileMakePath(driver->logDir) < 0) {
virReportSystemError(errno,
_("Cannot create log directory '%s'"),
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 4fde1af..cd7ec33 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -210,7 +210,7 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
if (driver->cgroup == NULL)
goto done; /* Not supported, so claim success */
- rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 1);
+ rc = virCgroupNew(vm->def->name, driver->cgroup, &vm->cgroup);
if (rc != 0) {
virReportSystemError(-rc,
_("Unable to create cgroup for %s"),
@@ -218,6 +218,17 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
goto cleanup;
}
+ rc = virCgroupMakePath(vm->cgroup);
+ if (rc != 0) {
+ virReportSystemError(-rc,
+ _("Unable to create cgroup path for %s"),
+ vm->def->name);
+ virCgroupFree(&vm->cgroup);
+ goto cleanup;
+ }
+
+ cgroup = vm->cgroup;
+
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
qemuCgroupData data = { vm, cgroup };
rc = virCgroupDenyAllDevices(cgroup);
@@ -445,15 +456,10 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
}
done:
virObjectUnref(cfg);
- virCgroupFree(&cgroup);
return 0;
cleanup:
virObjectUnref(cfg);
- if (cgroup) {
- virCgroupRemove(cgroup);
- virCgroupFree(&cgroup);
- }
return -1;
}
@@ -550,7 +556,6 @@ cleanup:
int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr vm)
{
- virCgroupPtr cgroup = NULL;
virCgroupPtr cgroup_vcpu = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr def = vm->def;
@@ -558,6 +563,7 @@ int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr
vm)
unsigned int i, j;
unsigned long long period = vm->def->cputune.period;
long long quota = vm->def->cputune.quota;
+ char *vcpuName = NULL;
if ((period || quota) &&
(!driver->cgroup ||
@@ -571,35 +577,39 @@ int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr
vm)
* with virProcessInfoSetAffinity, thus the lack of cgroups is not fatal
* here.
*/
- if (driver->cgroup == NULL)
+ if (vm->cgroup == NULL)
return 0;
- rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
- if (rc != 0) {
- virReportSystemError(-rc,
- _("Unable to find cgroup for %s"),
- vm->def->name);
- goto cleanup;
- }
-
if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
/* If we don't know VCPU<->PID mapping or all vcpu runs in the same
* thread, we cannot control each vcpu.
*/
VIR_WARN("Unable to get vcpus' pids.");
- virCgroupFree(&cgroup);
return 0;
}
+ if (VIR_ALLOC_N(vm->vcpuCgroups, priv->nvcpupids) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
for (i = 0; i < priv->nvcpupids; i++) {
- rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 1);
- if (rc < 0) {
+ if (virAsprintf(&vcpuName, "vcpu%d", i) < 0)
+ goto cleanup;
+
+ if ((rc = virCgroupNew(vcpuName, vm->cgroup, &vm->vcpuCgroups[i])) <
0) {
virReportSystemError(-rc,
_("Unable to create vcpu cgroup for %s(vcpu:"
" %d)"),
vm->def->name, i);
+
goto cleanup;
}
+ VIR_FREE(vcpuName);
+ }
+
+ for (i = 0; i < priv->nvcpupids; i++) {
+ cgroup_vcpu = vm->vcpuCgroups[i];
/* move the thread for vcpu to sub dir */
rc = virCgroupAddTask(cgroup_vcpu, priv->vcpupids[i]);
@@ -632,24 +642,17 @@ int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr
vm)
break;
}
}
-
- virCgroupFree(&cgroup_vcpu);
}
- virCgroupFree(&cgroup);
return 0;
cleanup:
- if (cgroup_vcpu) {
- virCgroupRemove(cgroup_vcpu);
- virCgroupFree(&cgroup_vcpu);
- }
-
- if (cgroup) {
- virCgroupRemove(cgroup);
- virCgroupFree(&cgroup);
+ if (vm->vcpuCgroups) {
+ for (i = 0; i < priv->nvcpupids; i++) {
+ if (vm->vcpuCgroups[i])
+ virCgroupFree(&vm->vcpuCgroups[i]);
+ }
}
-
return -1;
}
@@ -659,8 +662,6 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
{
virBitmapPtr cpumask = NULL;
virBitmapPtr cpumap = NULL;
- virCgroupPtr cgroup = NULL;
- virCgroupPtr cgroup_emulator = NULL;
virDomainDefPtr def = vm->def;
unsigned long long period = vm->def->cputune.emulator_period;
long long quota = vm->def->cputune.emulator_quota;
@@ -674,20 +675,12 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
return -1;
}
- if (driver->cgroup == NULL)
- return 0; /* Not supported, so claim success */
+ if (vm->cgroup == NULL)
+ return 0;
- rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
+ rc = virCgroupNew("emulator", vm->cgroup, &vm->cgroupEmulator);
if (rc != 0) {
virReportSystemError(-rc,
- _("Unable to find cgroup for %s"),
- vm->def->name);
- goto cleanup;
- }
-
- rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 1);
- if (rc < 0) {
- virReportSystemError(-rc,
_("Unable to create emulator cgroup for %s"),
vm->def->name);
goto cleanup;
@@ -696,7 +689,7 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
if (!qemuCgroupControllerActive(driver, i))
continue;
- rc = virCgroupMoveTask(cgroup, cgroup_emulator, i);
+ rc = virCgroupMoveTask(vm->cgroup, vm->cgroupEmulator, i);
if (rc < 0) {
virReportSystemError(-rc,
_("Unable to move tasks from domain cgroup to
"
@@ -718,7 +711,7 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
if (cpumask) {
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
- rc = qemuSetupCgroupEmulatorPin(cgroup_emulator, cpumask);
+ rc = qemuSetupCgroupEmulatorPin(vm->cgroupEmulator, cpumask);
if (rc < 0)
goto cleanup;
}
@@ -727,86 +720,61 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
if (period || quota) {
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
- if ((rc = qemuSetupCgroupVcpuBW(cgroup_emulator, period,
+ if ((rc = qemuSetupCgroupVcpuBW(vm->cgroupEmulator, period,
quota)) < 0)
goto cleanup;
}
}
- virCgroupFree(&cgroup_emulator);
- virCgroupFree(&cgroup);
virBitmapFree(cpumap);
return 0;
cleanup:
virBitmapFree(cpumap);
- if (cgroup_emulator) {
- virCgroupRemove(cgroup_emulator);
- virCgroupFree(&cgroup_emulator);
- }
-
- if (cgroup) {
- virCgroupRemove(cgroup);
- virCgroupFree(&cgroup);
- }
+ if (vm->cgroupEmulator)
+ virCgroupFree(&vm->cgroupEmulator);
return rc;
}
-int qemuRemoveCgroup(virQEMUDriverPtr driver,
+int qemuRemoveCgroup(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
virDomainObjPtr vm,
- int quiet)
+ int quiet ATTRIBUTE_UNUSED)
{
- virCgroupPtr cgroup;
- int rc;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int i;
- if (driver->cgroup == NULL)
- return 0; /* Not supported, so claim success */
+ if (vm->cgroup)
+ virCgroupFree(&vm->cgroup);
- rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
- if (rc != 0) {
- if (!quiet)
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to find cgroup for %s"),
- vm->def->name);
- return rc;
+ if (vm->cgroupEmulator)
+ virCgroupFree(&vm->cgroupEmulator);
+
+ if (vm->vcpuCgroups) {
+ for (i = 0; i < priv->nvcpupids; i++) {
+ if (vm->vcpuCgroups[i])
+ virCgroupFree(&vm->vcpuCgroups[i]);
+ }
}
- rc = virCgroupRemove(cgroup);
- virCgroupFree(&cgroup);
- return rc;
+ return 0;
}
-int qemuAddToCgroup(virQEMUDriverPtr driver,
- virDomainDefPtr def)
+int qemuAddToCgroup(virDomainObjPtr vm)
{
- virCgroupPtr cgroup = NULL;
int ret = -1;
- int rc;
- if (driver->cgroup == NULL)
+ if (vm->cgroup == NULL)
return 0; /* Not supported, so claim success */
- rc = virCgroupForDomain(driver->cgroup, def->name, &cgroup, 0);
- if (rc != 0) {
- virReportSystemError(-rc,
- _("unable to find cgroup for domain %s"),
- def->name);
- goto cleanup;
- }
-
- rc = virCgroupAddTask(cgroup, getpid());
- if (rc != 0) {
- virReportSystemError(-rc,
+ ret = virCgroupAddTask(vm->cgroup, getpid());
+ if (ret != 0) {
+ virReportSystemError(-ret,
_("unable to add domain %s task %d to cgroup"),
- def->name, getpid());
- goto cleanup;
+ vm->def->name, getpid());
+ return -1;
}
- ret = 0;
-
-cleanup:
- virCgroupFree(&cgroup);
- return ret;
+ return 0;
}
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
index a677d07..ea6d69f 100644
--- a/src/qemu/qemu_cgroup.h
+++ b/src/qemu/qemu_cgroup.h
@@ -63,7 +63,6 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
int qemuRemoveCgroup(virQEMUDriverPtr driver,
virDomainObjPtr vm,
int quiet);
-int qemuAddToCgroup(virQEMUDriverPtr driver,
- virDomainDefPtr def);
+int qemuAddToCgroup(virDomainObjPtr vm);
#endif /* __QEMU_CGROUP_H__ */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 979a027..fab0b1d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -662,6 +662,7 @@ qemuStartup(bool privileged,
char *membase = NULL;
char *mempath = NULL;
virQEMUDriverConfigPtr cfg;
+ virCgroupPtr appCgroup = NULL;
if (VIR_ALLOC(qemu_driver) < 0)
return -1;
@@ -732,11 +733,18 @@ qemuStartup(bool privileged,
goto error;
}
- rc = virCgroupForDriver("qemu", &qemu_driver->cgroup, privileged,
1);
+ rc = virCgroupGetAppRoot(&appCgroup, privileged);
+ if (rc < 0) {
+ VIR_INFO("Unable to create cgroup for libvirt: %s",
+ virStrerror(-rc, ebuf, sizeof(ebuf)));
+ goto error;
+ }
+ rc = virCgroupNew("qemu", appCgroup, &qemu_driver->cgroup);
if (rc < 0) {
VIR_INFO("Unable to create cgroup for driver: %s",
virStrerror(-rc, ebuf, sizeof(ebuf)));
}
+ virCgroupFree(&appCgroup);
qemu_driver->qemuImgBinary = virFindFileInPath("kvm-img");
if (!qemu_driver->qemuImgBinary)
@@ -3615,9 +3623,8 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
int vcpus = oldvcpus;
pid_t *cpupids = NULL;
int ncpupids;
- virCgroupPtr cgroup = NULL;
virCgroupPtr cgroup_vcpu = NULL;
- bool cgroup_available = false;
+ char *vcpuName = NULL;
qemuDomainObjEnterMonitor(driver, vm);
@@ -3680,15 +3687,14 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
goto cleanup;
}
- cgroup_available = (virCgroupForDomain(driver->cgroup, vm->def->name,
- &cgroup, 0) == 0);
-
if (nvcpus > oldvcpus) {
for (i = oldvcpus; i < nvcpus; i++) {
- if (cgroup_available) {
+ if (vm->cgroup) {
int rv = -1;
/* Create cgroup for the onlined vcpu */
- rv = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 1);
+ if (virAsprintf(&vcpuName, "cpu%d", i) < 0)
+ goto cleanup;
+ rv = virCgroupNew(vcpuName, vm->cgroup,&cgroup_vcpu);
if (rv < 0) {
virReportSystemError(-rv,
_("Unable to create vcpu cgroup for
%s(vcpu:"
@@ -3697,13 +3703,15 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
goto cleanup;
}
+ VIR_FREE(vcpuName);
+
/* Add vcpu thread to the cgroup */
rv = virCgroupAddTask(cgroup_vcpu, cpupids[i]);
if (rv < 0) {
virReportSystemError(-rv,
_("unable to add vcpu %d task %d to
cgroup"),
i, cpupids[i]);
- virCgroupRemove(cgroup_vcpu);
+ virCgroupFree(&cgroup_vcpu);
goto cleanup;
}
}
@@ -3731,7 +3739,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
vcpupin->vcpuid = i;
vm->def->cputune.vcpupin[vm->def->cputune.nvcpupin++] =
vcpupin;
- if (cgroup_available) {
+ if (cgroup_vcpu) {
if (qemuSetupCgroupVcpuPin(cgroup_vcpu,
vm->def->cputune.vcpupin,
vm->def->cputune.nvcpupin, i) <
0) {
@@ -3752,28 +3760,13 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
}
}
}
-
- virCgroupFree(&cgroup_vcpu);
}
} else {
for (i = oldvcpus - 1; i >= nvcpus; i--) {
virDomainVcpuPinDefPtr vcpupin = NULL;
- if (cgroup_available) {
- int rv = -1;
-
- rv = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
- if (rv < 0) {
- virReportSystemError(-rv,
- _("Unable to access vcpu cgroup for
%s(vcpu:"
- " %d)"),
- vm->def->name, i);
- goto cleanup;
- }
-
- /* Remove cgroup for the offlined vcpu */
- virCgroupRemove(cgroup_vcpu);
- virCgroupFree(&cgroup_vcpu);
+ if (vm->cgroup) {
+ /* XXX: remove cgroup for vcpu */
}
/* Free vcpupin setting */
@@ -3793,10 +3786,6 @@ cleanup:
vm->def->vcpus = vcpus;
VIR_FREE(cpupids);
virDomainAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
- if (cgroup)
- virCgroupFree(&cgroup);
- if (cgroup_vcpu)
- virCgroupFree(&cgroup_vcpu);
return ret;
unsupported:
@@ -3996,7 +3985,8 @@ qemuDomainPinVcpuFlags(virDomainPtr dom,
/* 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 &&
+#if 0 /* XXX */
+ if (vm->cgroup &&
virCgroupForVcpu(cgroup_dom, vcpu, &cgroup_vcpu, 0) == 0 &&
qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) <
0) {
virReportError(VIR_ERR_OPERATION_INVALID,
@@ -4004,6 +3994,7 @@ qemuDomainPinVcpuFlags(virDomainPtr dom,
" for vcpu %d"), vcpu);
goto cleanup;
}
+#endif
} else {
if (virProcessSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
@@ -4180,8 +4171,6 @@ qemuDomainPinEmulator(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm;
- virCgroupPtr cgroup_dom = NULL;
- virCgroupPtr cgroup_emulator = NULL;
pid_t pid;
virDomainDefPtr persistentDef = NULL;
int ret = -1;
@@ -4246,16 +4235,13 @@ qemuDomainPinEmulator(virDomainPtr dom,
* Configure the corresponding cpuset cgroup.
* If no cgroup for domain or hypervisor exists, do nothing.
*/
- if (virCgroupForDomain(driver->cgroup, vm->def->name,
- &cgroup_dom, 0) == 0) {
- if (virCgroupForEmulator(cgroup_dom, &cgroup_emulator, 0) == 0)
{
- if (qemuSetupCgroupEmulatorPin(cgroup_emulator,
- newVcpuPin[0]->cpumask) < 0)
{
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("failed to set cpuset.cpus in
cgroup"
- " for emulator threads"));
- goto cleanup;
- }
+ if (vm->cgroupEmulator) {
+ if (qemuSetupCgroupEmulatorPin(vm->cgroupEmulator,
+ newVcpuPin[0]->cpumask) < 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+ goto cleanup;
}
}
} else {
@@ -4317,10 +4303,6 @@ qemuDomainPinEmulator(virDomainPtr dom,
ret = 0;
cleanup:
- if (cgroup_emulator)
- virCgroupFree(&cgroup_emulator);
- if (cgroup_dom)
- virCgroupFree(&cgroup_dom);
virBitmapFree(pcpumap);
if (vm)
@@ -5788,7 +5770,6 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk = dev->data.disk;
- virCgroupPtr cgroup = NULL;
int ret = -1;
if (disk->driverName != NULL && !STREQ(disk->driverName,
"qemu")) {
@@ -5807,13 +5788,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
goto end;
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0))
{
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to find cgroup for %s"),
- vm->def->name);
- goto end;
- }
- if (qemuSetupDiskCgroup(vm, cgroup, disk) < 0)
+ if (vm->cgroup && qemuSetupDiskCgroup(vm, vm->cgroup, disk) <
0)
goto end;
}
switch (disk->device) {
@@ -5848,8 +5823,8 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
break;
}
- if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(vm, cgroup, disk) < 0)
+ if (ret != 0 && vm->cgroup) {
+ if (qemuTeardownDiskCgroup(vm, vm->cgroup, disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(disk->src));
}
@@ -5866,8 +5841,6 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
}
end:
- if (cgroup)
- virCgroupFree(&cgroup);
return ret;
}
@@ -6051,21 +6024,13 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
bool force)
{
virDomainDiskDefPtr disk = dev->data.disk;
- virCgroupPtr cgroup = NULL;
int ret = -1;
if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
goto end;
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
- if (virCgroupForDomain(driver->cgroup,
- vm->def->name, &cgroup, 0) != 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to find cgroup for %s"),
- vm->def->name);
- goto end;
- }
- if (qemuSetupDiskCgroup(vm, cgroup, disk) < 0)
+ if (vm->cgroup && qemuSetupDiskCgroup(vm, vm->cgroup, disk) <
0)
goto end;
}
@@ -6083,14 +6048,12 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
break;
}
- if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(vm, cgroup, disk) < 0)
+ if (ret != 0 && vm->cgroup) {
+ if (qemuTeardownDiskCgroup(vm, vm->cgroup, disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(disk->src));
}
end:
- if (cgroup)
- virCgroupFree(&cgroup);
return ret;
}
@@ -6884,7 +6847,6 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
int ret = -1;
@@ -6920,7 +6882,7 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
@@ -6942,7 +6904,7 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
continue;
}
- rc = virCgroupSetBlkioWeight(group, params[i].value.ui);
+ rc = virCgroupSetBlkioWeight(vm->cgroup, params[i].value.ui);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set blkio weight
tunable"));
@@ -6960,7 +6922,7 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
continue;
}
for (j = 0; j < ndevices; j++) {
- rc = virCgroupSetBlkioDeviceWeight(group,
+ rc = virCgroupSetBlkioDeviceWeight(vm->cgroup,
devices[j].path,
devices[j].weight);
if (rc < 0) {
@@ -7023,7 +6985,6 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
}
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7039,7 +7000,6 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
int i, j;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
unsigned int val;
@@ -7082,7 +7042,7 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -7096,7 +7056,7 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
switch (i) {
case 0: /* fill blkio weight here */
- rc = virCgroupGetBlkioWeight(group, &val);
+ rc = virCgroupGetBlkioWeight(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get blkio weight"));
@@ -7209,8 +7169,6 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
ret = 0;
cleanup:
- if (group)
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7226,7 +7184,6 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
virDomainDefPtr persistentDef = NULL;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virTypedParameterPtr hard_limit = NULL;
virTypedParameterPtr swap_hard_limit = NULL;
@@ -7273,7 +7230,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -7301,7 +7258,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
/* Get current swap hard limit */
- rc = virCgroupGetMemSwapHardLimit(group, &val);
+ rc = virCgroupGetMemSwapHardLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get swap hard limit"));
@@ -7336,7 +7293,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemoryHardLimit(group, param->value.ul);
+ rc = virCgroupSetMemoryHardLimit(vm->cgroup, param->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory hard_limit
tunable"));
@@ -7349,7 +7306,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemorySoftLimit(group, param->value.ul);
+ rc = virCgroupSetMemorySoftLimit(vm->cgroup, param->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory soft_limit
tunable"));
@@ -7362,7 +7319,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemSwapHardLimit(group, param->value.ul);
+ rc = virCgroupSetMemSwapHardLimit(vm->cgroup, param->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set swap_hard_limit
tunable"));
@@ -7381,7 +7338,6 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7397,7 +7353,6 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
int ret = -1;
@@ -7431,7 +7386,7 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
@@ -7491,7 +7446,7 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
switch (i) {
case 0: /* fill memory hard limit here */
- rc = virCgroupGetMemoryHardLimit(group, &val);
+ rc = virCgroupGetMemoryHardLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory hard limit"));
@@ -7504,7 +7459,7 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
break;
case 1: /* fill memory soft limit here */
- rc = virCgroupGetMemorySoftLimit(group, &val);
+ rc = virCgroupGetMemorySoftLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory soft limit"));
@@ -7517,7 +7472,7 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
break;
case 2: /* fill swap hard limit here */
- rc = virCgroupGetMemSwapHardLimit(group, &val);
+ rc = virCgroupGetMemSwapHardLimit(vm->cgroup, &val);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get swap hard limit"));
@@ -7541,8 +7496,6 @@ out:
ret = 0;
cleanup:
- if (group)
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7558,7 +7511,6 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
virDomainDefPtr persistentDef = NULL;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
int ret = -1;
virQEMUDriverConfigPtr cfg = NULL;
@@ -7595,7 +7547,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
@@ -7653,7 +7605,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
continue;
}
- if ((rc = virCgroupSetCpusetMems(group, nodeset_str) != 0)) {
+ if ((rc = virCgroupSetCpusetMems(vm->cgroup, nodeset_str) != 0)) {
virReportSystemError(-rc, "%s",
_("unable to set numa tunable"));
virBitmapFree(nodeset);
@@ -7693,7 +7645,6 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
}
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7709,7 +7660,6 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
char *nodeset = NULL;
@@ -7752,7 +7702,7 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
@@ -7780,7 +7730,7 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
if (!nodeset)
nodeset = strdup("");
} else {
- rc = virCgroupGetCpusetMems(group, &nodeset);
+ rc = virCgroupGetCpusetMems(vm->cgroup, &nodeset);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get numa nodeset"));
@@ -7807,7 +7757,6 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
cleanup:
VIR_FREE(nodeset);
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -7815,13 +7764,11 @@ cleanup:
}
static int
-qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuSetVcpusBWLive(virDomainObjPtr vm,
unsigned long long period, long long quota)
{
int i;
qemuDomainObjPrivatePtr priv = vm->privateData;
- virCgroupPtr cgroup_vcpu = NULL;
- int rc;
if (period == 0 && quota == 0)
return 0;
@@ -7832,36 +7779,23 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
*/
if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
for (i = 0; i < priv->nvcpupids; i++) {
- rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
- if (rc < 0) {
- virReportSystemError(-rc,
- _("Unable to find vcpu cgroup for
%s(vcpu:"
- " %d)"),
- vm->def->name, i);
+ if (vm->vcpuCgroups[i] &&
+ qemuSetupCgroupVcpuBW(vm->vcpuCgroups[i], period, quota) < 0)
goto cleanup;
- }
-
- if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
- goto cleanup;
-
- virCgroupFree(&cgroup_vcpu);
}
}
return 0;
cleanup:
- virCgroupFree(&cgroup_vcpu);
return -1;
}
static int
-qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuSetEmulatorBandwidthLive(virDomainObjPtr vm,
unsigned long long period, long long quota)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- virCgroupPtr cgroup_emulator = NULL;
- int rc;
if (period == 0 && quota == 0)
return 0;
@@ -7870,23 +7804,17 @@ qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr
cgroup,
return 0;
}
- rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 0);
- if (rc < 0) {
- virReportSystemError(-rc,
- _("Unable to find emulator cgroup for %s"),
- vm->def->name);
- goto cleanup;
+ if (!vm->cgroupEmulator) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Unable to find emulator cgroup for %s"),
+ vm->def->name);
+ return -1;
}
- if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
- goto cleanup;
+ if (qemuSetupCgroupVcpuBW(vm->cgroupEmulator, period, quota) < 0)
+ return -1;
- virCgroupFree(&cgroup_emulator);
return 0;
-
-cleanup:
- virCgroupFree(&cgroup_emulator);
- return -1;
}
#define SCHED_RANGE_CHECK(VAR, NAME, MIN, MAX) \
@@ -7906,7 +7834,6 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
int i;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
virDomainDefPtr vmdef = NULL;
unsigned long long value_ul;
@@ -7960,7 +7887,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
"%s", _("cgroup CPU controller is not
mounted"));
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
@@ -7975,7 +7902,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- if ((rc = virCgroupSetCpuShares(group, value_ul))) {
+ if ((rc = virCgroupSetCpuShares(vm->cgroup, value_ul))) {
virReportSystemError(-rc, "%s",
_("unable to set cpu shares
tunable"));
goto cleanup;
@@ -7991,7 +7918,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
- if ((rc = qemuSetVcpusBWLive(vm, group, value_ul, 0)))
+ if ((rc = qemuSetVcpusBWLive(vm, value_ul, 0)))
goto cleanup;
vm->def->cputune.period = value_ul;
@@ -8005,7 +7932,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
- if ((rc = qemuSetVcpusBWLive(vm, group, 0, value_l)))
+ if ((rc = qemuSetVcpusBWLive(vm, 0, value_l)))
goto cleanup;
vm->def->cputune.quota = value_l;
@@ -8019,7 +7946,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
- if ((rc = qemuSetEmulatorBandwidthLive(vm, group, value_ul, 0)))
+ if ((rc = qemuSetEmulatorBandwidthLive(vm, value_ul, 0)))
goto cleanup;
vm->def->cputune.emulator_period = value_ul;
@@ -8033,7 +7960,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
- if ((rc = qemuSetEmulatorBandwidthLive(vm, group, 0, value_l)))
+ if ((rc = qemuSetEmulatorBandwidthLive(vm, 0, value_l)))
goto cleanup;
vm->def->cputune.emulator_quota = value_l;
@@ -8061,7 +7988,6 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
cleanup:
virDomainDefFree(vmdef);
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -8108,52 +8034,39 @@ static int
qemuGetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
unsigned long long *period, long long *quota)
{
- virCgroupPtr cgroup_vcpu = NULL;
qemuDomainObjPrivatePtr priv = NULL;
- int rc;
- int ret = -1;
priv = vm->privateData;
if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
/* We do not create sub dir for each vcpu */
- rc = qemuGetVcpuBWLive(cgroup, period, quota);
- if (rc < 0)
- goto cleanup;
+ if (qemuGetVcpuBWLive(cgroup, period, quota) < 0)
+ return -1;
if (*quota > 0)
*quota /= vm->def->vcpus;
- goto out;
+
+ return 0;
}
/* get period and quota for vcpu0 */
- rc = virCgroupForVcpu(cgroup, 0, &cgroup_vcpu, 0);
- if (!cgroup_vcpu) {
- virReportSystemError(-rc,
- _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
- vm->def->name);
- goto cleanup;
+ if (!vm->vcpuCgroups[0]) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
+ vm->def->name);
+ return -1;
}
- rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
- if (rc < 0)
- goto cleanup;
-
-out:
- ret = 0;
+ if (qemuGetVcpuBWLive(vm->vcpuCgroups[0], period, quota) < 0)
+ return -1;
-cleanup:
- virCgroupFree(&cgroup_vcpu);
- return ret;
+ return 0;
}
static int
-qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuGetEmulatorBandwidthLive(virDomainObjPtr vm,
unsigned long long *period, long long *quota)
{
- virCgroupPtr cgroup_emulator = NULL;
qemuDomainObjPrivatePtr priv = NULL;
- int rc;
- int ret = -1;
priv = vm->privateData;
if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
@@ -8164,23 +8077,17 @@ qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr
cgroup,
}
/* get period and quota for emulator */
- rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 0);
- if (!cgroup_emulator) {
- virReportSystemError(-rc,
- _("Unable to find emulator cgroup for %s"),
- vm->def->name);
- goto cleanup;
+ if (!vm->cgroupEmulator) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Unable to find emulator cgroup for %s"),
+ vm->def->name);
+ return -1;
}
- rc = qemuGetVcpuBWLive(cgroup_emulator, period, quota);
- if (rc < 0)
- goto cleanup;
-
- ret = 0;
+ if (qemuGetVcpuBWLive(vm->cgroupEmulator, period, quota) < 0)
+ return -1;
-cleanup:
- virCgroupFree(&cgroup_emulator);
- return ret;
+ return 0;
}
static int
@@ -8190,7 +8097,6 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
unsigned int flags)
{
virQEMUDriverPtr driver = dom->conn->privateData;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
unsigned long long shares;
unsigned long long period;
@@ -8248,13 +8154,13 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
- rc = virCgroupGetCpuShares(group, &shares);
+ rc = virCgroupGetCpuShares(vm->cgroup, &shares);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to get cpu shares tunable"));
@@ -8262,13 +8168,13 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
}
if (*nparams > 1 && cpu_bw_status) {
- rc = qemuGetVcpusBWLive(vm, group, &period, "a);
+ rc = qemuGetVcpusBWLive(vm, vm->cgroup, &period, "a);
if (rc != 0)
goto cleanup;
}
if (*nparams > 3 && cpu_bw_status) {
- rc = qemuGetEmulatorBandwidthLive(vm, group, &emulator_period,
+ rc = qemuGetEmulatorBandwidthLive(vm, &emulator_period,
&emulator_quota);
if (rc != 0)
goto cleanup;
@@ -8321,7 +8227,6 @@ out:
ret = 0;
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
@@ -11022,7 +10927,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
int i;
bool persist = false;
bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
- virCgroupPtr cgroup = NULL;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
if (!virDomainObjIsActive(vm)) {
@@ -11032,7 +10936,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
}
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
+ !vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -11075,7 +10979,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
}
}
- ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm, cgroup,
+ ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm, vm->cgroup,
&snap->def->disks[i],
vm->def->disks[i],
persistDisk, actions,
@@ -11104,7 +11008,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
persistDisk = vm->newDef->disks[indx];
}
- qemuDomainSnapshotUndoSingleDiskActive(driver, vm, cgroup,
+ qemuDomainSnapshotUndoSingleDiskActive(driver, vm, vm->cgroup,
snap->def->dom->disks[i],
vm->def->disks[i],
persistDisk,
@@ -11115,8 +11019,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
qemuDomainObjExitMonitorWithDriver(driver, vm);
cleanup:
- virCgroupFree(&cgroup);
-
if (ret == 0 || !qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION)) {
if (virDomainSaveStatus(driver->caps, cfg->stateDir, vm) < 0 ||
(persist && virDomainSaveConfig(cfg->configDir, vm->newDef)
< 0))
@@ -12922,7 +12824,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
* we know for sure that there is a backing chain. */
if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW
&&
qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) <
0) {
+ !vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -12943,7 +12845,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW
&&
(virDomainLockDiskAttach(driver->lockManager, cfg->uri,
vm, disk) < 0 ||
- (cgroup && qemuSetupDiskCgroup(vm, cgroup, disk) < 0) ||
+ (cgroup && qemuSetupDiskCgroup(vm, vm->cgroup, disk) < 0) ||
virSecurityManagerSetImageLabel(driver->securityManager, vm->def,
disk) < 0)) {
disk->src = oldsrc;
@@ -12987,8 +12889,6 @@ qemuDomainBlockPivot(virConnectPtr conn,
disk->mirroring = false;
cleanup:
- if (cgroup)
- virCgroupFree(&cgroup);
if (resume && virDomainObjIsActive(vm) &&
qemuProcessStartCPUs(driver, vm, conn,
VIR_DOMAIN_RUNNING_UNPAUSED,
@@ -13220,7 +13120,6 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
struct stat st;
bool need_unlink = false;
char *mirror = NULL;
- virCgroupPtr cgroup = NULL;
virQEMUDriverConfigPtr cfg = NULL;
/* Preliminaries: find the disk we are editing, sanity checks */
@@ -13237,7 +13136,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
goto cleanup;
}
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) <
0) {
+ !vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -13344,9 +13243,9 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
goto endjob;
}
- if (qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+ if (qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk, dest,
VIR_DISK_CHAIN_READ_WRITE) < 0) {
- qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+ qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk, dest,
VIR_DISK_CHAIN_NO_ACCESS);
goto endjob;
}
@@ -13358,7 +13257,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
qemuDomainObjExitMonitor(driver, vm);
if (ret < 0) {
- qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+ qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk, dest,
VIR_DISK_CHAIN_NO_ACCESS);
goto endjob;
}
@@ -13380,8 +13279,6 @@ endjob:
}
cleanup:
- if (cgroup)
- virCgroupFree(&cgroup);
VIR_FREE(device);
if (vm)
virObjectUnlock(vm);
@@ -13437,7 +13334,6 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const
char *base,
virStorageFileMetadataPtr top_meta = NULL;
const char *top_parent = NULL;
const char *base_canon = NULL;
- virCgroupPtr cgroup = NULL;
bool clean_access = false;
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
@@ -13522,17 +13418,17 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const
char *base,
* operation succeeds, but doing that requires tracking the
* operation in XML across libvirtd restarts. */
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) <
0) {
+ !vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
goto endjob;
}
clean_access = true;
- if (qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, base_canon,
+ if (qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk, base_canon,
VIR_DISK_CHAIN_READ_WRITE) < 0 ||
(top_parent && top_parent != disk->src &&
- qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk,
+ qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk,
top_parent,
VIR_DISK_CHAIN_READ_WRITE) < 0))
goto endjob;
@@ -13546,15 +13442,13 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const
char *base,
endjob:
if (ret < 0 && clean_access) {
/* Revert access to read-only, if possible. */
- qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, base_canon,
+ qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk, base_canon,
VIR_DISK_CHAIN_READ_ONLY);
if (top_parent && top_parent != disk->src)
- qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk,
+ qemuDomainPrepareDiskChainElement(driver, vm, vm->cgroup, disk,
top_parent,
VIR_DISK_CHAIN_READ_ONLY);
}
- if (cgroup)
- virCgroupFree(&cgroup);
if (qemuDomainObjEndJob(driver, vm) == 0) {
vm = NULL;
goto cleanup;
@@ -14246,28 +14140,27 @@ qemuDomainGetTotalcpuStats(virCgroupPtr group,
* s3 = t03 + t13
*/
static int
-getSumVcpuPercpuStats(virCgroupPtr group,
- unsigned int nvcpu,
+getSumVcpuPercpuStats(virDomainObjPtr vm,
unsigned long long *sum_cpu_time,
unsigned int num)
{
int ret = -1;
int i;
char *buf = NULL;
- virCgroupPtr group_vcpu = NULL;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
- for (i = 0; i < nvcpu; i++) {
+ for (i = 0; i < priv->nvcpupids; i++) {
char *pos;
unsigned long long tmp;
int j;
- if (virCgroupForVcpu(group, i, &group_vcpu, 0) < 0) {
+ if (!vm->vcpuCgroups[i]) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("error accessing cgroup cpuacct for vcpu"));
goto cleanup;
}
- if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
+ if (virCgroupGetCpuacctPercpuUsage(vm->vcpuCgroups[i], &buf) < 0)
goto cleanup;
pos = buf;
@@ -14280,13 +14173,11 @@ getSumVcpuPercpuStats(virCgroupPtr group,
sum_cpu_time[j] += tmp;
}
- virCgroupFree(&group_vcpu);
VIR_FREE(buf);
}
ret = 0;
cleanup:
- virCgroupFree(&group_vcpu);
VIR_FREE(buf);
return ret;
}
@@ -14306,7 +14197,6 @@ qemuDomainGetPercpuStats(virDomainObjPtr vm,
unsigned long long *sum_cpu_time = NULL;
unsigned long long *sum_cpu_pos;
unsigned int n = 0;
- qemuDomainObjPrivatePtr priv = vm->privateData;
virTypedParameterPtr ent;
int param_idx;
unsigned long long cpu_time;
@@ -14373,7 +14263,7 @@ qemuDomainGetPercpuStats(virDomainObjPtr vm,
virReportOOMError();
goto cleanup;
}
- if (getSumVcpuPercpuStats(group, priv->nvcpupids, sum_cpu_time, n) < 0)
+ if (getSumVcpuPercpuStats(vm, sum_cpu_time, n) < 0)
goto cleanup;
sum_cpu_pos = sum_cpu_time;
@@ -14406,7 +14296,6 @@ qemuDomainGetCPUStats(virDomainPtr domain,
unsigned int flags)
{
virQEMUDriverPtr driver = domain->conn->privateData;
- virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
int ret = -1;
bool isActive;
@@ -14435,19 +14324,18 @@ qemuDomainGetCPUStats(virDomainPtr domain,
goto cleanup;
}
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
if (start_cpu == -1)
- ret = qemuDomainGetTotalcpuStats(group, params, nparams);
+ ret = qemuDomainGetTotalcpuStats(vm->cgroup, params, nparams);
else
- ret = qemuDomainGetPercpuStats(vm, group, params, nparams,
+ ret = qemuDomainGetPercpuStats(vm, vm->cgroup, params, nparams,
start_cpu, ncpus);
cleanup:
- virCgroupFree(&group);
if (vm)
virObjectUnlock(vm);
qemuDriverUnlock(driver);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 98912bf..224ed77 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1117,11 +1117,10 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
}
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
- virCgroupPtr cgroup = NULL;
virUSBDevicePtr usb;
qemuCgroupData data;
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -1134,7 +1133,7 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
goto error;
data.vm = vm;
- data.cgroup = cgroup;
+ data.cgroup = vm->cgroup;
if (virUSBDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup,
&data) < 0) {
virUSBDeviceFree(usb);
@@ -2012,7 +2011,6 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
int i, ret = -1;
virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
- virCgroupPtr cgroup = NULL;
char *drivestr = NULL;
i = qemuFindDisk(vm->def, dev->data.disk->dst);
@@ -2033,7 +2031,7 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
}
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -2094,8 +2092,8 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
vm->def, dev->data.disk) < 0)
VIR_WARN("Unable to restore security label on %s",
dev->data.disk->src);
- if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(vm, cgroup, dev->data.disk) < 0)
+ if (vm->cgroup != NULL) {
+ if (qemuTeardownDiskCgroup(vm, vm->cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -2106,7 +2104,6 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
ret = 0;
cleanup:
- virCgroupFree(&cgroup);
VIR_FREE(drivestr);
return ret;
}
@@ -2118,7 +2115,6 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
int i, ret = -1;
virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
- virCgroupPtr cgroup = NULL;
char *drivestr = NULL;
i = qemuFindDisk(vm->def, dev->data.disk->dst);
@@ -2146,7 +2142,7 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
}
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
- if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=
0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
@@ -2186,8 +2182,8 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
vm->def, dev->data.disk) < 0)
VIR_WARN("Unable to restore security label on %s",
dev->data.disk->src);
- if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(vm, cgroup, dev->data.disk) < 0)
+ if (vm->cgroup != NULL) {
+ if (qemuTeardownDiskCgroup(vm, vm->cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -2199,7 +2195,6 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
cleanup:
VIR_FREE(drivestr);
- virCgroupFree(&cgroup);
return ret;
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index a75fb4e..5d69b71 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3605,7 +3605,6 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
enum qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- virCgroupPtr cgroup = NULL;
int ret = -1;
int rc;
bool restoreLabel = false;
@@ -3641,20 +3640,16 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
* that botches pclose. */
if (qemuCgroupControllerActive(driver,
VIR_CGROUP_CONTROLLER_DEVICES)) {
- if (virCgroupForDomain(driver->cgroup, vm->def->name,
- &cgroup, 0) != 0) {
+ if (!vm->cgroup) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s"),
vm->def->name);
goto cleanup;
}
- rc = virCgroupAllowDevicePath(cgroup, path,
+ rc = virCgroupAllowDevicePath(vm->cgroup, path,
VIR_CGROUP_DEVICE_RW);
- virDomainAuditCgroupPath(vm, cgroup, "allow", path, "rw",
rc);
- if (rc == 1) {
- /* path was not a device, no further need for cgroup */
- virCgroupFree(&cgroup);
- } else if (rc < 0) {
+ virDomainAuditCgroupPath(vm, vm->cgroup, "allow", path,
"rw", rc);
+ if (rc < 0) {
virReportSystemError(-rc,
_("Unable to allow device %s for %s"),
path, vm->def->name);
@@ -3754,14 +3749,13 @@ cleanup:
vm->def, path) < 0)
VIR_WARN("failed to restore save state label on %s", path);
- if (cgroup != NULL) {
- rc = virCgroupDenyDevicePath(cgroup, path,
+ if (vm->cgroup != NULL) {
+ rc = virCgroupDenyDevicePath(vm->cgroup, path,
VIR_CGROUP_DEVICE_RWM);
- virDomainAuditCgroupPath(vm, cgroup, "deny", path, "rwm",
rc);
+ virDomainAuditCgroupPath(vm, vm->cgroup, "deny", path,
"rwm", rc);
if (rc < 0)
VIR_WARN("Unable to deny device %s for %s %d",
path, vm->def->name, rc);
- virCgroupFree(&cgroup);
}
return ret;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 30f923a..84300c1 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2744,7 +2744,7 @@ static int qemuProcessHook(void *data)
* memory allocation is on the correct NUMA node
*/
VIR_DEBUG("Moving process to cgroup");
- if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
+ if (qemuAddToCgroup(h->vm) < 0)
goto cleanup;
/* This must be done after cgroup placement to avoid resetting CPU
@@ -3641,11 +3641,6 @@ int qemuProcessStart(virConnectPtr conn,
}
}
- /* Ensure no historical cgroup for this VM is lying around bogus
- * settings */
- VIR_DEBUG("Ensuring no historical cgroup is lying around");
- qemuRemoveCgroup(driver, vm, 1);
-
for (i = 0 ; i < vm->def->ngraphics; ++i) {
virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 71d46c5..90ff97c 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -37,6 +37,7 @@
#include <libgen.h>
#include <dirent.h>
+#include "virobject.h"
#include "internal.h"
#include "virutil.h"
#include "viralloc.h"
@@ -45,6 +46,7 @@
#include "virfile.h"
#include "virhash.h"
#include "virhashcode.h"
+#include "virthread.h"
#define CGROUP_MAX_VAL 512
@@ -58,12 +60,91 @@ struct virCgroupController {
char *placement;
};
-struct virCgroup {
+struct _virCgroupItem;
+typedef struct _virCgroupItem virCgroupItem;
+typedef virCgroupItem *virCgroupItemPtr;
+
+struct _virCgroupItem {
+ virObjectLockable object;
+
+ char *name;
char *path;
+ bool created; /* the path is created or not */
+
+ virCgroupItemPtr next;
+ virCgroupItemPtr parent;
+ virCgroupItemPtr children;
+
+ int type;
struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
};
+struct virCgroup {
+ virCgroupItemPtr items[VIR_CGROUP_CONTROLLER_LAST];
+};
+
+static virClassPtr cgroupItemClass;
+
+static void cgroupItemDispose(void *obj);
+
+static int virCgroupItemOnceInit(void)
+{
+ if (!(cgroupItemClass = virClassNew(virClassForObjectLockable(),
+ "cgroupItem",
+ sizeof(virCgroupItem),
+ cgroupItemDispose)))
+ return -1;
+
+ return 0;
+}
+VIR_ONCE_GLOBAL_INIT(virCgroupItem);
+
+static virCgroupItemPtr rootCgroupItems[VIR_CGROUP_CONTROLLER_LAST];
+
+static virCgroupItemPtr virCgroupItemRootNew(int type);
+static int virCgroupDetectMounts(struct virCgroupController
(*controllers)[VIR_CGROUP_CONTROLLER_LAST]);
+static int virCgroupDetectPlacement(struct virCgroupController
(*controllers)[VIR_CGROUP_CONTROLLER_LAST]);
+
+static int virCgroupControllersInit(struct virCgroupController
(*controllers)[VIR_CGROUP_CONTROLLER_LAST])
+{
+ int rc;
+ int i;
+
+ rc = virCgroupDetectMounts(controllers);
+ if (rc < 0) {
+ VIR_ERROR(_("Failed to initialize cgroup controllers"));
+ return rc;
+ }
+
+ rc = virCgroupDetectPlacement(controllers);
+
+ if (rc == 0) {
+ /* Check that for every mounted controller, we found our placement */
+ for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
+ if (!(*controllers)[i].mountPoint)
+ continue;
+
+ if (!(*controllers)[i].placement) {
+ VIR_ERROR(_("Could not find placement for controller %s at
%s"),
+ virCgroupControllerTypeToString(i),
+ (*controllers)[i].placement);
+ rc = -ENOENT;
+ break;
+ }
+
+ VIR_DEBUG("Detected mount/mapping %i:%s at %s in %s", i,
+ virCgroupControllerTypeToString(i),
+ (*controllers)[i].mountPoint,
+ (*controllers)[i].placement);
+ }
+ } else {
+ VIR_ERROR(_("Failed to initialize cgroup controllers"));
+ }
+
+ return rc;
+}
+
typedef enum {
VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */
VIR_CGROUP_MEM_HIERACHY = 1 << 0, /* call virCgroupSetMemoryUseHierarchy
@@ -74,25 +155,377 @@ typedef enum {
* cpuacct and cpuset if possible. */
} virCgroupFlags;
+static virCgroupItemPtr virCgroupItemRootNew(int type)
+{
+ virCgroupItemPtr rootItem = NULL;
+
+ if (type >= VIR_CGROUP_CONTROLLER_LAST || type < 0)
+ return NULL;
+
+ if (virCgroupItemInitialize() < 0)
+ return NULL;
+
+ if (!(rootItem = virObjectNew(cgroupItemClass)))
+ return NULL;
+
+ if (virCgroupControllersInit(&rootItem->controllers) != 0) {
+ virObjectUnref(rootItem);
+ rootItem = NULL;
+ return NULL;
+ }
+
+ rootItem->name = strdup("/");
+ rootItem->next = NULL;
+ rootItem->parent = NULL;
+ rootItem->children = NULL;
+ rootItem->created = 1;
+ rootItem->type = type;
+ if (virAsprintf(&rootItem->path, "%s%s",
+ rootItem->controllers[rootItem->type].mountPoint,
+ rootItem->controllers[rootItem->type].placement) < 0) {
+ virObjectUnref(rootItem);
+ rootItem = NULL;
+ }
+
+ return rootItem;
+}
+
+static virCgroupItemPtr virCgroupHasChildByName(virCgroupItemPtr item,
+ const char *name)
+{
+ virCgroupItemPtr child;
+
+ virObjectLock(item);
+
+ child = item->children;
+
+ while (child) {
+ if (STREQ(child->name, name)) {
+ virObjectRef(child);
+ goto out;
+ }
+
+ child = child->next;
+ }
+
+out:
+ virObjectUnlock(item);
+ return child;
+}
+
+static virCgroupItemPtr virCgroupItemNew(const char *name,
+ virCgroupItemPtr parent)
+{
+ virCgroupItemPtr cgroupItem = NULL;
+ virCgroupItemPtr *next = NULL;
+
+ if (!parent)
+ return NULL;
+
+ if (virCgroupItemInitialize() < 0)
+ return NULL;
+
+ cgroupItem = virCgroupHasChildByName(parent, name);
+ if (cgroupItem)
+ return cgroupItem;
+
+ if (!(cgroupItem = virObjectNew(cgroupItemClass)))
+ return NULL;
+
+ cgroupItem->name = strdup(name);
+ cgroupItem->parent = parent;
+ cgroupItem->next = NULL;
+ cgroupItem->children = NULL;
+ cgroupItem->created = false;
+ cgroupItem->type = parent->type;
+
+ if (virAsprintf(&cgroupItem->path, "%s/%s",
+ parent->path,
+ cgroupItem->name) == -1) {
+ virObjectUnref(cgroupItem);
+ cgroupItem = NULL;
+ return NULL;
+ }
+
+ virObjectRef(parent);
+
+ virObjectLock(parent);
+
+ next = &parent->children;
+
+ while (*next)
+ next = &(*next)->next;
+
+ *next = cgroupItem;
+
+ virObjectUnlock(parent);
+
+ return cgroupItem;
+}
+
+static void virCgroupItemFree(virCgroupItemPtr *cgroupItem)
+{
+ if (!virObjectUnref(*cgroupItem))
+ *cgroupItem = NULL;
+}
+
+static void cgroupItemDispose(void *obj)
+{
+ virCgroupItemPtr cgroupItem = obj;
+ virCgroupItemPtr parent = cgroupItem->parent;
+ virCgroupItemPtr *next;
+
+ sa_assert(cgroupItem->children == NULL);
+
+ if (cgroupItem->created &&
+ access(cgroupItem->path, F_OK) == 0)
+ rmdir(cgroupItem->path);
+ VIR_FREE(cgroupItem->path);
+
+ if (parent) {
+ virObjectLock(parent);
+
+ next = &parent->children;
+
+ while (*next && *next != cgroupItem)
+ next = &(*next)->next;
+
+ if (*next == cgroupItem) {
+ *next = cgroupItem->next;
+ cgroupItem->next = NULL;
+ cgroupItem->parent = NULL;
+ } else {
+ /* BUG */
+ }
+
+ virObjectUnlock(parent);
+ virObjectUnref(parent);
+ }
+
+ VIR_FREE(cgroupItem->name);
+}
+
+static int virCgroupItemKeyPath(virCgroupItemPtr cgroupItem,
+ const char *key,
+ char **path);
+
+static int virCgroupItemGetValueStr(virCgroupItemPtr cgroupItem,
+ const char *key,
+ char **value)
+{
+ int rc;
+ char *keypath = NULL;
+
+ *value = NULL;
+
+ rc = virCgroupItemKeyPath(cgroupItem, key, &keypath);
+ if (rc != 0)
+ return rc;
+
+ VIR_DEBUG("Get value %s", keypath);
+
+ rc = virFileReadAll(keypath, 1024*1024, value);
+ if (rc < 0) {
+ rc = -errno;
+ VIR_DEBUG("Failed to read %s: %m\n", keypath);
+ } else {
+ /* Terminated with '\n' has sometimes harmful effects to the caller */
+ if ((*value)[rc - 1] == '\n')
+ (*value)[rc - 1] = '\0';
+
+ rc = 0;
+ }
+
+ VIR_FREE(keypath);
+
+ return rc;
+}
+
+static int virCgroupItemSetValueStr(virCgroupItemPtr cgroupItem,
+ const char *key,
+ const char *value)
+{
+ int rc = 0;
+ char *keypath = NULL;
+
+ rc = virCgroupItemKeyPath(cgroupItem, key, &keypath);
+ if (rc != 0)
+ return rc;
+
+ VIR_DEBUG("Set value '%s' to '%s'", keypath, value);
+ rc = virFileWriteStr(keypath, value, 0);
+ if (rc < 0) {
+ rc = -errno;
+ VIR_DEBUG("Failed to write value '%s': %m", value);
+ } else {
+ rc = 0;
+ }
+
+ VIR_FREE(keypath);
+ return rc;
+}
+
+static int virCgroupRemoveRecursively(char *grppath);
+static int virCgroupItemCpusetInherit(virCgroupItemPtr cgroupItem);
+static int virCgroupItemSetMemoryUseHierarchy(virCgroupItemPtr item);
+
+static int virCgroupItemMakePath(virCgroupItemPtr cgroupItem)
+{
+ int ret = 0;
+
+ if (!cgroupItem->created && access(cgroupItem->path, F_OK) == 0) {
+ VIR_WARN(_("removing historical cgroup directory: %s"),
+ cgroupItem->path);
+
+ if (virCgroupRemoveRecursively(cgroupItem->path) != 0) {
+ VIR_WARN(_("failed to remove historical cgroup directory: %s"),
+ cgroupItem->path);
+ }
+ }
+
+ cgroupItem->created = true;
+
+ if (access(cgroupItem->path, F_OK) != 0) {
+ if (cgroupItem->parent &&
+ (ret = virCgroupItemMakePath(cgroupItem->parent)) < 0)
+ return ret;
+
+ if (mkdir(cgroupItem->path, 0755) < 0) {
+ return -errno;
+ }
+
+ if (cgroupItem->type == VIR_CGROUP_CONTROLLER_CPUSET)
+ virCgroupItemCpusetInherit(cgroupItem);
+
+ if (cgroupItem->type == VIR_CGROUP_CONTROLLER_MEMORY)
+ virCgroupItemSetMemoryUseHierarchy(cgroupItem);
+ }
+
+ return ret;
+}
+
+static int virCgroupItemPath(virCgroupItemPtr cgroupItem,
+ bool create,
+ char **path)
+{
+ if (path) {
+ if (virAsprintf(path, "%s", cgroupItem->path) == -1)
+ return -ENOMEM;
+ }
+
+ if (create && virCgroupItemMakePath(cgroupItem) < 0) {
+ if (path)
+ VIR_FREE(*path);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+static int virCgroupItemKeyPath(virCgroupItemPtr cgroupItem,
+ const char *key,
+ char **path)
+{
+ int ret = 0;
+ char *cgroupItemPath = NULL;
+
+ ret = virCgroupItemPath(cgroupItem, true, &cgroupItemPath);
+ if (ret < 0)
+ return ret;
+
+ if (virAsprintf(path, "%s/%s", cgroupItemPath, key) == -1)
+ ret = -ENOMEM;
+
+ VIR_FREE(cgroupItemPath);
+ return ret;
+}
+
+int virCgroupMakePath(virCgroupPtr cgroup)
+{
+ int i;
+
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ if (virCgroupItemPath(cgroup->items[i], true, NULL) != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int virCgroupNew(const char *name, virCgroupPtr parent, virCgroupPtr *cgroup)
+{
+ virCgroupPtr newCgroup = NULL;
+ virCgroupItemPtr *parentCgroupItems;
+ int ret = -1;
+ int i = 0;
+
+ if (VIR_ALLOC(newCgroup) < 0) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (!parent) {
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ if (!rootCgroupItems[i])
+ rootCgroupItems[i] = virCgroupItemRootNew(i);
+ if (!rootCgroupItems[i])
+ goto error;
+ virObjectRef(rootCgroupItems[i]);
+ }
+
+ parentCgroupItems = rootCgroupItems;
+ } else {
+ parentCgroupItems = parent->items;
+ }
+
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ newCgroup->items[i] = virCgroupItemNew(name, parentCgroupItems[i]);
+ if (!newCgroup->items[i])
+ goto error;
+ }
+
+ *cgroup = newCgroup;
+ newCgroup = NULL;
+ ret = 0;
+
+error:
+ if (!parent) {
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ if (rootCgroupItems[i])
+ virCgroupItemFree(&rootCgroupItems[i]);
+ }
+ }
+
+ if (newCgroup) {
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ if (newCgroup->items[i])
+ virCgroupItemFree(&newCgroup->items[i]);
+ }
+ VIR_FREE(newCgroup);
+ }
+
+ return ret;
+}
+
/**
* virCgroupFree:
*
* @group: The group structure to free
*/
-void virCgroupFree(virCgroupPtr *group)
+void virCgroupFree(virCgroupPtr *cgroup)
{
int i;
- if (*group == NULL)
+ if (!cgroup || !*cgroup)
return;
- for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- VIR_FREE((*group)->controllers[i].mountPoint);
- VIR_FREE((*group)->controllers[i].placement);
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ virCgroupItemFree(&(*cgroup)->items[i]);
}
- VIR_FREE((*group)->path);
- VIR_FREE(*group);
+ VIR_FREE(*cgroup);
+ *cgroup = NULL;
}
/**
@@ -103,12 +536,17 @@ void virCgroupFree(virCgroupPtr *group)
*
* Returns true if a cgroup is subsystem is mounted.
*/
-bool virCgroupMounted(virCgroupPtr cgroup, int controller)
+bool virCgroupMounted(virCgroupPtr cgroup ATTRIBUTE_UNUSED,
+ int controller)
{
- return cgroup->controllers[controller].mountPoint != NULL;
+ if (rootCgroupItems[controller] &&
+ rootCgroupItems[controller]->controllers[controller].mountPoint)
+ return true;
+ return false;
}
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+
/*
* Process /proc/mounts figuring out what controllers are
* mounted and where
@@ -134,6 +572,7 @@ static int virCgroupDetectMounts(struct virCgroupController
(*controllers)[VIR_C
const char *typestr = virCgroupControllerTypeToString(i);
int typelen = strlen(typestr);
char *tmp = entry.mnt_opts;
+ (*controllers)[i].type = i;
while (tmp) {
char *next = strchr(tmp, ',');
int len;
@@ -184,24 +623,24 @@ static int virCgroupDetectPlacement(struct virCgroupController
(*cgroupControlle
}
while (fgets(line, sizeof(line), mapping) != NULL) {
- char *controllers = strchr(line, ':');
- char *path = controllers ? strchr(controllers+1, ':') : NULL;
+ char *controllersStr = strchr(line, ':');
+ char *path = controllersStr ? strchr(controllersStr+1, ':') : NULL;
char *nl = path ? strchr(path, '\n') : NULL;
- if (!controllers || !path)
+ if (!controllersStr || !path)
continue;
if (nl)
*nl = '\0';
*path = '\0';
- controllers++;
+ controllersStr++;
path++;
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
const char *typestr = virCgroupControllerTypeToString(i);
int typelen = strlen(typestr);
- char *tmp = controllers;
+ char *tmp = controllersStr;
while (tmp) {
char *next = strchr(tmp, ',');
int len;
@@ -230,57 +669,8 @@ no_memory:
}
-static int virCgroupDetect(virCgroupPtr group)
-{
- int any = 0;
- int rc;
- int i;
-
- rc = virCgroupDetectMounts(&group->controllers);
- if (rc < 0) {
- VIR_ERROR(_("Failed to detect mounts for %s"), group->path);
- return rc;
- }
-
- /* Check that at least 1 controller is available */
- for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- if (group->controllers[i].mountPoint != NULL)
- any = 1;
- }
- if (!any)
- return -ENXIO;
-
-
- rc = virCgroupDetectPlacement(&group->controllers);
-
- if (rc == 0) {
- /* Check that for every mounted controller, we found our placement */
- for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- if (!group->controllers[i].mountPoint)
- continue;
-
- if (!group->controllers[i].placement) {
- VIR_ERROR(_("Could not find placement for controller %s at
%s"),
- virCgroupControllerTypeToString(i),
- group->controllers[i].placement);
- rc = -ENOENT;
- break;
- }
-
- VIR_DEBUG("Detected mount/mapping %i:%s at %s in %s", i,
- virCgroupControllerTypeToString(i),
- group->controllers[i].mountPoint,
- group->controllers[i].placement);
- }
- } else {
- VIR_ERROR(_("Failed to detect mapping for %s"), group->path);
- }
-
- return rc;
-}
#endif
-
int virCgroupPathOfController(virCgroupPtr group,
int controller,
const char *key,
@@ -289,8 +679,7 @@ int virCgroupPathOfController(virCgroupPtr group,
if (controller == -1) {
int i;
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- if (group->controllers[i].mountPoint &&
- group->controllers[i].placement) {
+ if (virCgroupMounted(group, i)) {
controller = i;
break;
}
@@ -299,47 +688,22 @@ int virCgroupPathOfController(virCgroupPtr group,
if (controller == -1)
return -ENOSYS;
- if (group->controllers[controller].mountPoint == NULL)
- return -ENOENT;
-
- if (group->controllers[controller].placement == NULL)
- return -ENOENT;
-
- if (virAsprintf(path, "%s%s%s/%s",
- group->controllers[controller].mountPoint,
- group->controllers[controller].placement,
- STREQ(group->path, "/") ? "" :
group->path,
+ if (virAsprintf(path, "%s%s%s",
+ group->items[controller]->path,
+ key ? "/" : "",
key ? key : "") == -1)
return -ENOMEM;
return 0;
}
-
static int virCgroupSetValueStr(virCgroupPtr group,
int controller,
const char *key,
const char *value)
{
- int rc = 0;
- char *keypath = NULL;
-
- rc = virCgroupPathOfController(group, controller, key, &keypath);
- if (rc != 0)
- return rc;
-
- VIR_DEBUG("Set value '%s' to '%s'", keypath, value);
- rc = virFileWriteStr(keypath, value, 0);
- if (rc < 0) {
- rc = -errno;
- VIR_DEBUG("Failed to write value '%s': %m", value);
- } else {
- rc = 0;
- }
-
- VIR_FREE(keypath);
-
- return rc;
+ return virCgroupItemSetValueStr(group->items[controller],
+ key, value);
}
static int virCgroupGetValueStr(virCgroupPtr group,
@@ -347,34 +711,8 @@ static int virCgroupGetValueStr(virCgroupPtr group,
const char *key,
char **value)
{
- int rc;
- char *keypath = NULL;
-
- *value = NULL;
-
- rc = virCgroupPathOfController(group, controller, key, &keypath);
- if (rc != 0) {
- VIR_DEBUG("No path of %s, %s", group->path, key);
- return rc;
- }
-
- VIR_DEBUG("Get value %s", keypath);
-
- rc = virFileReadAll(keypath, 1024*1024, value);
- if (rc < 0) {
- rc = -errno;
- VIR_DEBUG("Failed to read %s: %m\n", keypath);
- } else {
- /* Terminated with '\n' has sometimes harmful effects to the caller */
- if ((*value)[rc - 1] == '\n')
- (*value)[rc - 1] = '\0';
-
- rc = 0;
- }
-
- VIR_FREE(keypath);
-
- return rc;
+ return virCgroupItemGetValueStr(group->items[controller],
+ key, value);
}
static int virCgroupSetValueU64(virCgroupPtr group,
@@ -395,8 +733,6 @@ static int virCgroupSetValueU64(virCgroupPtr group,
return rc;
}
-
-
static int virCgroupSetValueI64(virCgroupPtr group,
int controller,
const char *key,
@@ -441,248 +777,88 @@ static int virCgroupGetValueU64(virCgroupPtr group,
unsigned long long int *value)
{
char *strval = NULL;
- int rc = 0;
-
- rc = virCgroupGetValueStr(group, controller, key, &strval);
- if (rc != 0)
- goto out;
-
- if (virStrToLong_ull(strval, NULL, 10, value) < 0)
- rc = -EINVAL;
-out:
- VIR_FREE(strval);
-
- return rc;
-}
-
-
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
-{
- int i;
- int rc = 0;
- const char *inherit_values[] = {
- "cpuset.cpus",
- "cpuset.mems",
- };
-
- VIR_DEBUG("Setting up inheritance %s -> %s", parent->path,
group->path);
- for (i = 0; i < ARRAY_CARDINALITY(inherit_values) ; i++) {
- char *value;
-
- rc = virCgroupGetValueStr(parent,
- VIR_CGROUP_CONTROLLER_CPUSET,
- inherit_values[i],
- &value);
- if (rc != 0) {
- VIR_ERROR(_("Failed to get %s %d"), inherit_values[i], rc);
- break;
- }
-
- VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
-
- rc = virCgroupSetValueStr(group,
- VIR_CGROUP_CONTROLLER_CPUSET,
- inherit_values[i],
- value);
- VIR_FREE(value);
-
- if (rc != 0) {
- VIR_ERROR(_("Failed to set %s %d"), inherit_values[i], rc);
- break;
- }
- }
-
- return rc;
-}
-
-static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
-{
- int rc = 0;
- unsigned long long value;
- const char *filename = "memory.use_hierarchy";
-
- rc = virCgroupGetValueU64(group,
- VIR_CGROUP_CONTROLLER_MEMORY,
- filename, &value);
- if (rc != 0) {
- VIR_ERROR(_("Failed to read %s/%s (%d)"), group->path, filename,
rc);
- return rc;
- }
-
- /* Setting twice causes error, so if already enabled, skip setting */
- if (value == 1)
- return 0;
-
- VIR_DEBUG("Setting up %s/%s", group->path, filename);
- rc = virCgroupSetValueU64(group,
- VIR_CGROUP_CONTROLLER_MEMORY,
- filename, 1);
-
- if (rc != 0) {
- VIR_ERROR(_("Failed to set %s/%s (%d)"), group->path, filename,
rc);
- }
-
- return rc;
-}
-
-static int virCgroupMakeGroup(virCgroupPtr parent,
- virCgroupPtr group,
- bool create,
- unsigned int flags)
-{
- int i;
- int rc = 0;
-
- VIR_DEBUG("Make group %s", group->path);
- for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- char *path = NULL;
-
- /* Skip over controllers that aren't mounted */
- if (!group->controllers[i].mountPoint)
- continue;
-
- /* We need to control cpu bandwidth for each vcpu now */
- if ((flags & VIR_CGROUP_VCPU) &&
- (i != VIR_CGROUP_CONTROLLER_CPU &&
- i != VIR_CGROUP_CONTROLLER_CPUACCT &&
- i != VIR_CGROUP_CONTROLLER_CPUSET)) {
- /* treat it as unmounted and we can use virCgroupAddTask */
- VIR_FREE(group->controllers[i].mountPoint);
- continue;
- }
-
- rc = virCgroupPathOfController(group, i, "", &path);
- if (rc < 0)
- return rc;
- /* As of Feb 2011, clang can't see that the above function
- * call did not modify group. */
- sa_assert(group->controllers[i].mountPoint);
-
- VIR_DEBUG("Make controller %s", path);
- if (access(path, F_OK) != 0) {
- if (!create ||
- mkdir(path, 0755) < 0) {
- /* With a kernel that doesn't support multi-level directory
- * for blkio controller, libvirt will fail and disable all
- * other controllers even though they are available. So
- * treat blkio as unmounted if mkdir fails. */
- if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
- rc = 0;
- VIR_FREE(group->controllers[i].mountPoint);
- VIR_FREE(path);
- continue;
- } else {
- rc = -errno;
- VIR_FREE(path);
- break;
- }
- }
- if (group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint != NULL
&&
- (i == VIR_CGROUP_CONTROLLER_CPUSET ||
- STREQ(group->controllers[i].mountPoint,
group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint))) {
- rc = virCgroupCpuSetInherit(parent, group);
- if (rc != 0) {
- VIR_FREE(path);
- break;
- }
- }
- /*
- * Note that virCgroupSetMemoryUseHierarchy should always be
- * called prior to creating subcgroups and attaching tasks.
- */
- if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
- (group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint != NULL)
&&
- (i == VIR_CGROUP_CONTROLLER_MEMORY ||
- STREQ(group->controllers[i].mountPoint,
group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
- rc = virCgroupSetMemoryUseHierarchy(group);
- if (rc != 0) {
- VIR_FREE(path);
- break;
- }
- }
- }
+ int rc = 0;
- VIR_FREE(path);
- }
+ rc = virCgroupGetValueStr(group, controller, key, &strval);
+ if (rc != 0)
+ goto out;
+
+ if (virStrToLong_ull(strval, NULL, 10, value) < 0)
+ rc = -EINVAL;
+out:
+ VIR_FREE(strval);
return rc;
}
-
-static int virCgroupNew(const char *path,
- virCgroupPtr *group)
+#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+static int virCgroupItemCpusetInherit(virCgroupItemPtr cgroupItem)
{
+ int i;
+ char *value;
int rc = 0;
- char *typpath = NULL;
-
- VIR_DEBUG("New group %s", path);
- *group = NULL;
-
- if (VIR_ALLOC((*group)) != 0) {
- rc = -ENOMEM;
- goto err;
- }
+ const char *inherit_values[] = {
+ "cpuset.cpus",
+ "cpuset.mems",
+ };
- if (!((*group)->path = strdup(path))) {
- rc = -ENOMEM;
- goto err;
- }
+ for (i = 0; i < ARRAY_CARDINALITY(inherit_values) ; i++) {
+ rc = virCgroupItemGetValueStr(cgroupItem->parent,
+ inherit_values[i],
+ &value);
+ if (rc != 0) {
+ VIR_ERROR(_("Failed to get %s %d"), inherit_values[i], rc);
+ break;
+ }
- rc = virCgroupDetect(*group);
- if (rc < 0)
- goto err;
+ VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
- return rc;
-err:
- virCgroupFree(group);
- *group = NULL;
+ rc = virCgroupItemSetValueStr(cgroupItem,
+ inherit_values[i],
+ value);
+ VIR_FREE(value);
- VIR_FREE(typpath);
+ if (rc != 0) {
+ VIR_ERROR(_("Failed to set %s %d"), inherit_values[i], rc);
+ break;
+ }
+ }
return rc;
}
-static int virCgroupAppRoot(bool privileged,
- virCgroupPtr *group,
- bool create)
+static int virCgroupItemSetMemoryUseHierarchy(virCgroupItemPtr item)
{
- virCgroupPtr rootgrp = NULL;
- int rc;
+ int rc = 0;
+ char *value = NULL;
+ const char *filename = "memory.use_hierarchy";
- rc = virCgroupNew("/", &rootgrp);
- if (rc != 0)
+ rc = virCgroupItemGetValueStr(item,
+ filename, &value);
+ if (rc != 0) {
+ VIR_ERROR(_("Failed to read %s/%s (%d)"), item->path, filename,
rc);
return rc;
+ }
- if (privileged) {
- rc = virCgroupNew("/libvirt", group);
- } else {
- char *rootname;
- char *username;
- username = virGetUserName(getuid());
- if (!username) {
- rc = -ENOMEM;
- goto cleanup;
- }
- rc = virAsprintf(&rootname, "/libvirt-%s", username);
- VIR_FREE(username);
- if (rc < 0) {
- rc = -ENOMEM;
- goto cleanup;
- }
-
- rc = virCgroupNew(rootname, group);
- VIR_FREE(rootname);
+ /* Setting twice causes error, so if already enabled, skip setting */
+ if (STREQ(value, "1")) {
+ rc = 0;
+ goto out;
}
- if (rc != 0)
- goto cleanup;
- rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE);
+ VIR_DEBUG("Setting up %s/%s", item->path, filename);
+ rc = virCgroupItemSetValueStr(item,
+ filename, "1");
-cleanup:
- virCgroupFree(&rootgrp);
+ if (rc != 0) {
+ VIR_ERROR(_("Failed to set %s/%s (%d)"), item->path, filename, rc);
+ }
+
+out:
+ VIR_FREE(value);
return rc;
}
+
#endif
#if defined _DIRENT_HAVE_D_TYPE
@@ -743,43 +919,6 @@ static int virCgroupRemoveRecursively(char *grppath
ATTRIBUTE_UNUSED)
#endif
/**
- * virCgroupRemove:
- *
- * @group: The group to be removed
- *
- * It first removes all child groups recursively
- * in depth first order and then removes @group
- * because the presence of the child groups
- * prevents removing @group.
- *
- * Returns: 0 on success
- */
-int virCgroupRemove(virCgroupPtr group)
-{
- int rc = 0;
- int i;
- char *grppath = NULL;
-
- for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
- /* Skip over controllers not mounted */
- if (!group->controllers[i].mountPoint)
- continue;
-
- if (virCgroupPathOfController(group,
- i,
- NULL,
- &grppath) != 0)
- continue;
-
- VIR_DEBUG("Removing cgroup %s and all child cgroups", grppath);
- rc = virCgroupRemoveRecursively(grppath);
- VIR_FREE(grppath);
- }
-
- return rc;
-}
-
-/**
* virCgroupAddTask:
*
* @group: The cgroup to add a task to
@@ -794,7 +933,7 @@ int virCgroupAddTask(virCgroupPtr group, pid_t pid)
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
/* Skip over controllers not mounted */
- if (!group->controllers[i].mountPoint)
+ if (!virCgroupMounted(group, i))
continue;
rc = virCgroupSetValueU64(group, i, "tasks", (unsigned long long)pid);
@@ -819,7 +958,7 @@ int virCgroupAddTaskController(virCgroupPtr group, pid_t pid, int
controller)
if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
return -EINVAL;
- if (!group->controllers[controller].mountPoint)
+ if (!virCgroupMounted(group, controller))
return -EINVAL;
return virCgroupSetValueU64(group, controller, "tasks",
@@ -882,12 +1021,6 @@ int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr
dest_group,
controller > VIR_CGROUP_CONTROLLER_BLKIO)
return -EINVAL;
- if (!src_group->controllers[controller].mountPoint ||
- !dest_group->controllers[controller].mountPoint) {
- VIR_WARN("no vm cgroup in controller %d", controller);
- return 0;
- }
-
rc = virCgroupGetValueStr(src_group, controller, "tasks", &content);
if (rc != 0)
return rc;
@@ -908,226 +1041,39 @@ cleanup:
err = virCgroupAddTaskStrController(src_group, content, controller);
if (err != 0)
VIR_ERROR(_("Cannot recover cgroup %s from %s"),
- src_group->controllers[controller].mountPoint,
- dest_group->controllers[controller].mountPoint);
+ src_group->items[controller]->path,
+ dest_group->items[controller]->path);
VIR_FREE(content);
return rc;
}
-/**
- * virCgroupForDriver:
- *
- * @name: name of this driver (e.g., xen, qemu, lxc)
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForDriver(const char *name,
- virCgroupPtr *group,
- bool privileged,
- bool create)
-{
- int rc;
- char *path = NULL;
- virCgroupPtr rootgrp = NULL;
-
- rc = virCgroupAppRoot(privileged, &rootgrp, create);
- if (rc != 0)
- goto out;
-
- if (virAsprintf(&path, "%s/%s", rootgrp->path, name) < 0) {
- rc = -ENOMEM;
- goto out;
- }
-
- rc = virCgroupNew(path, group);
- VIR_FREE(path);
-
- if (rc == 0) {
- rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE);
- if (rc != 0)
- virCgroupFree(group);
- }
-
-out:
- virCgroupFree(&rootgrp);
-
- return rc;
-}
-#else
-int virCgroupForDriver(const char *name ATTRIBUTE_UNUSED,
- virCgroupPtr *group ATTRIBUTE_UNUSED,
- bool privileged ATTRIBUTE_UNUSED,
- bool create ATTRIBUTE_UNUSED)
-{
- /* Claim no support */
- return -ENXIO;
-}
-#endif
-
-/**
-* virCgroupGetAppRoot:
-*
-* @group: Pointer to returned virCgroupPtr
-*
-* Returns 0 on success
-*/
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupGetAppRoot(virCgroupPtr *group)
-{
- return virCgroupNew("/", group);
-}
-#else
-int virCgroupGetAppRoot(virCgroupPtr *group ATTRIBUTE_UNUSED)
-{
- return -ENXIO;
-}
-#endif
-
-/**
- * virCgroupForDomain:
- *
- * @driver: group for driver owning the domain
- * @name: name of the domain
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForDomain(virCgroupPtr driver,
- const char *name,
- virCgroupPtr *group,
- bool create)
-{
- int rc;
- char *path;
-
- if (driver == NULL)
- return -EINVAL;
-
- if (virAsprintf(&path, "%s/%s", driver->path, name) < 0)
- return -ENOMEM;
-
- rc = virCgroupNew(path, group);
- VIR_FREE(path);
-
- if (rc == 0) {
- /*
- * Create a cgroup with memory.use_hierarchy enabled to
- * surely account memory usage of lxc with ns subsystem
- * enabled. (To be exact, memory and ns subsystems are
- * enabled at the same time.)
- *
- * The reason why doing it here, not a upper group, say
- * a group for driver, is to avoid overhead to track
- * cumulative usage that we don't need.
- */
- rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_MEM_HIERACHY);
- if (rc != 0)
- virCgroupFree(group);
- }
-
- return rc;
-}
-#else
-int virCgroupForDomain(virCgroupPtr driver ATTRIBUTE_UNUSED,
- const char *name ATTRIBUTE_UNUSED,
- virCgroupPtr *group ATTRIBUTE_UNUSED,
- bool create ATTRIBUTE_UNUSED)
-{
- return -ENXIO;
-}
-#endif
-
-/**
- * virCgroupForVcpu:
- *
- * @driver: group for the domain
- * @vcpuid: id of the vcpu
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForVcpu(virCgroupPtr driver,
- int vcpuid,
- virCgroupPtr *group,
- bool create)
+int virCgroupGetAppRoot(virCgroupPtr *cgroup, bool privileged)
{
+ char *name = NULL;
+ char *user = NULL;
int rc;
- char *path;
-
- if (driver == NULL)
- return -EINVAL;
- if (virAsprintf(&path, "%s/vcpu%d", driver->path, vcpuid) < 0)
- return -ENOMEM;
-
- rc = virCgroupNew(path, group);
- VIR_FREE(path);
+ if (privileged)
+ name = strdup("libvirt");
+ else {
+ user = virGetUserName(getuid());
+ if (!user) {
+ return -ENOMEM;
+ }
- if (rc == 0) {
- rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
- if (rc != 0)
- virCgroupFree(group);
+ if (virAsprintf(&name, "libvirt-%s", user) < 0) {
+ VIR_FREE(user);
+ return -ENOMEM;
+ }
}
- return rc;
-}
-#else
-int virCgroupForVcpu(virCgroupPtr driver ATTRIBUTE_UNUSED,
- int vcpuid ATTRIBUTE_UNUSED,
- virCgroupPtr *group ATTRIBUTE_UNUSED,
- bool create ATTRIBUTE_UNUSED)
-{
- return -ENXIO;
-}
-#endif
-
-/**
- * virCgroupForEmulator:
- *
- * @driver: group for the domain
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns: 0 on success or -errno on failure
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForEmulator(virCgroupPtr driver,
- virCgroupPtr *group,
- bool create)
-{
- int rc;
- char *path;
-
- if (driver == NULL)
- return -EINVAL;
-
- if (virAsprintf(&path, "%s/emulator", driver->path) < 0)
- return -ENOMEM;
-
- rc = virCgroupNew(path, group);
- VIR_FREE(path);
-
- if (rc == 0) {
- rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
- if (rc != 0)
- virCgroupFree(group);
- }
+ rc = virCgroupNew(name, NULL, cgroup);
+ VIR_FREE(name);
return rc;
}
-#else
-int virCgroupForEmulator(virCgroupPtr driver ATTRIBUTE_UNUSED,
- virCgroupPtr *group ATTRIBUTE_UNUSED,
- bool create ATTRIBUTE_UNUSED)
-{
- return -ENXIO;
-}
-#endif
/**
* virCgroupSetBlkioWeight:
*
@@ -1861,21 +1807,20 @@ int virCgroupGetFreezerState(virCgroupPtr group, char **state)
#if defined HAVE_KILL && defined HAVE_MNTENT_H && defined
HAVE_GETMNTENT_R
-static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+static int virCgroupItemKillInternal(virCgroupItemPtr item,
+ int signum,
+ virHashTablePtr pids)
{
- int rc;
+ int rc = -1;
int killedAny = 0;
char *keypath = NULL;
bool done = false;
FILE *fp = NULL;
- VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
- group, group->path, signum, pids);
+ VIR_DEBUG("cgroupItem=%p signum=%d pids=%p",
+ item, signum, pids);
- rc = virCgroupPathOfController(group, -1, "tasks", &keypath);
- if (rc != 0) {
- VIR_DEBUG("No path of %s, tasks", group->path);
+ if (virAsprintf(&keypath, "%s/tasks", item->path) < 0)
return rc;
- }
/* PIDs may be forking as we kill them, so loop
* until there are no new PIDs found
@@ -1927,7 +1872,6 @@ cleanup:
return rc;
}
-
static uint32_t virCgroupPidCode(const void *name, uint32_t seed)
{
unsigned long pid_value = (unsigned long)(intptr_t)name;
@@ -1942,15 +1886,8 @@ static void *virCgroupPidCopy(const void *name)
return (void*)name;
}
-/*
- * Returns
- * < 0 : errno that occurred
- * 0 : no PIDs killed
- * 1 : at least one PID killed
- */
-int virCgroupKill(virCgroupPtr group, int signum)
+static int virCgroupItemKill(virCgroupItemPtr item, int signum)
{
- VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
int rc;
/* The 'tasks' file in cgroups can contain duplicated
* pids, so we use a hash to track which we've already
@@ -1963,82 +1900,65 @@ int virCgroupKill(virCgroupPtr group, int signum)
virCgroupPidCopy,
NULL);
- rc = virCgroupKillInternal(group, signum, pids);
+ rc = virCgroupItemKillInternal(item, signum, pids);
virHashFree(pids);
return rc;
}
-
-static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHashTablePtr
pids, bool dormdir)
+/*
+ * Returns
+ * < 0 : errno that occurred
+ * 0 : no PIDs killed
+ * 1 : at least one PID killed
+ */
+int virCgroupKill(virCgroupPtr group, int signum)
{
int rc;
- int killedAny = 0;
- char *keypath = NULL;
- DIR *dp;
- virCgroupPtr subgroup = NULL;
- struct dirent *ent;
- VIR_DEBUG("group=%p path=%s signum=%d pids=%p", group, group->path,
signum, pids);
-
- rc = virCgroupPathOfController(group, -1, "", &keypath);
- if (rc != 0) {
- VIR_DEBUG("No path of %s, tasks", group->path);
- return rc;
- }
+ int i;
- if ((rc = virCgroupKillInternal(group, signum, pids)) != 0)
- return rc;
+ VIR_DEBUG("group=%p signum=%d", group, signum);
- VIR_DEBUG("Iterate over children of %s", keypath);
- if (!(dp = opendir(keypath))) {
- rc = -errno;
- return rc;
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ rc = virCgroupItemKill(group->items[i], signum);
+ if (rc < 0)
+ break;
}
- while ((ent = readdir(dp))) {
- char *subpath;
+ return rc;
+}
- if (STREQ(ent->d_name, "."))
- continue;
- if (STREQ(ent->d_name, ".."))
- continue;
- if (ent->d_type != DT_DIR)
- continue;
+static int virCgroupItemKillRecursiveInternal(virCgroupItemPtr item,
+ int signum,
+ virHashTablePtr pids)
+{
+ int rc;
+ int killedAny = 0;
+ virCgroupItemPtr child = NULL;
- VIR_DEBUG("Process subdir %s", ent->d_name);
- if (virAsprintf(&subpath, "%s/%s", group->path, ent->d_name)
< 0) {
- rc = -ENOMEM;
- goto cleanup;
- }
+ if ((rc = virCgroupItemKillInternal(item, signum, pids)) < 0)
+ return rc;
- if ((rc = virCgroupNew(subpath, &subgroup)) != 0)
- goto cleanup;
+ VIR_DEBUG("Iterate over children of %s", item->path);
- if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0)
- goto cleanup;
+ child = item->children;
+ while (child) {
+ rc = virCgroupItemKillRecursiveInternal(child, signum, pids);
if (rc == 1)
killedAny = 1;
- if (dormdir)
- virCgroupRemove(subgroup);
-
- virCgroupFree(&subgroup);
+ child = child->next;
}
rc = killedAny;
-cleanup:
- virCgroupFree(&subgroup);
- closedir(dp);
-
return rc;
}
-int virCgroupKillRecursive(virCgroupPtr group, int signum)
+static int virCgroupItemKillRecursive(virCgroupItemPtr item, int signum)
{
int rc;
- VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
virHashTablePtr pids = virHashCreateFull(100,
NULL,
virCgroupPidCode,
@@ -2046,19 +1966,30 @@ int virCgroupKillRecursive(virCgroupPtr group, int signum)
virCgroupPidCopy,
NULL);
- rc = virCgroupKillRecursiveInternal(group, signum, pids, false);
+ rc = virCgroupItemKillRecursiveInternal(item, signum, pids);
virHashFree(pids);
return rc;
}
+int virCgroupKillRecursive(virCgroupPtr group, int signum)
+{
+ int rc;
+ int i;
+
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ rc = virCgroupItemKillRecursive(group->items[i], signum);
+ }
+
+ return rc;
+}
int virCgroupKillPainfully(virCgroupPtr group)
{
int i;
int rc;
- VIR_DEBUG("cgroup=%p path=%s", group, group->path);
+ VIR_DEBUG("cgroup=%p", group);
for (i = 0 ; i < 15 ; i++) {
int signum;
if (i == 0)
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index 2ed6ff9..0ccca23 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -49,21 +49,7 @@ int virCgroupForDriver(const char *name,
bool privileged,
bool create);
-int virCgroupGetAppRoot(virCgroupPtr *group);
-
-int virCgroupForDomain(virCgroupPtr driver,
- const char *name,
- virCgroupPtr *group,
- bool create);
-
-int virCgroupForVcpu(virCgroupPtr driver,
- int vcpuid,
- virCgroupPtr *group,
- bool create);
-
-int virCgroupForEmulator(virCgroupPtr driver,
- virCgroupPtr *group,
- bool create);
+int virCgroupGetAppRoot(virCgroupPtr *group, bool privileged);
int virCgroupPathOfController(virCgroupPtr group,
int controller,
@@ -159,6 +145,7 @@ int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus);
int virCgroupRemove(virCgroupPtr group);
+int virCgroupNew(const char *name, virCgroupPtr parent, virCgroupPtr *cgroup);
void virCgroupFree(virCgroupPtr *group);
bool virCgroupMounted(virCgroupPtr cgroup, int controller);
@@ -166,4 +153,6 @@ int virCgroupKill(virCgroupPtr group, int signum);
int virCgroupKillRecursive(virCgroupPtr group, int signum);
int virCgroupKillPainfully(virCgroupPtr group);
+int virCgroupMakePath(virCgroupPtr cgroup);
+
#endif /* __VIR_CGROUP_H__ */
--
1.8.0.1.240.ge8a1f5a