* before creating subcgroups and
* attaching tasks
*/
- VIR_CGROUP_VCPU = 1 << 1, /* create subdir only under the cgroup cpu,
- * cpuacct and cpuset if possible. */
} virCgroupFlags;
/**
}
-static int virCgroupDetect(virCgroupPtr group)
+static int virCgroupDetect(virCgroupPtr group,
+ int controllers)
{
- int any = 0;
int rc;
int i;
+ int j;
rc = virCgroupDetectMounts(group);
if (rc < 0) {
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 (controllers >= 0) {
+ VIR_DEBUG("Validating controllers %d", controllers);
+ for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
+ VIR_DEBUG("Controller '%s' wanted=%s",
+ virCgroupControllerTypeToString(i),
+ (1 << i) & controllers ? "yes" : "no");
+ if (((1 << i) & controllers)) {
+ /* Ensure requested controller is present */
+ if (!group->controllers[i].mountPoint) {
+ VIR_DEBUG("Requested controlled '%s' not mounted",
+ virCgroupControllerTypeToString(i));
+ return -ENOENT;
+ }
+ } else {
+ /* Check whether a request to disable a controller
+ * clashes with co-mounting of controllers */
+ for (j = 0 ; j < VIR_CGROUP_CONTROLLER_LAST ; j++) {
+ if (j == i)
+ continue;
+ if (!((1 << j) & controllers))
+ continue;
+
+ if (STREQ_NULLABLE(group->controllers[i].mountPoint,
+ group->controllers[j].mountPoint)) {
+ VIR_DEBUG("Controller '%s' is not wanted, but '%s' is co-mounted",
+ virCgroupControllerTypeToString(i),
+ virCgroupControllerTypeToString(j));
+ return -EINVAL;
+ }
+ }
+ VIR_FREE(group->controllers[i].mountPoint);
+ }
+ }
+ } else {
+ VIR_DEBUG("Auto-detecting controllers");
+ controllers = 0;
+ for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
+ VIR_DEBUG("Controller '%s' present=%s",
+ virCgroupControllerTypeToString(i),
+ group->controllers[i].mountPoint ? "yes" : "no");
+ if (group->controllers[i].mountPoint == NULL)
+ continue;
+ controllers |= (1 << i);
+ }
}
- if (!any)
- return -ENXIO;
+ /* Check that at least 1 controller is available */
+ if (!controllers)
+ return -ENXIO;
rc = virCgroupDetectPlacement(group);
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;
static int virCgroupNew(const char *path,
+ int controllers,
virCgroupPtr *group)
{
int rc = 0;
char *typpath = NULL;
- VIR_DEBUG("New group %s", path);
+ VIR_DEBUG("path=%s controllers=%d", path, controllers);
*group = NULL;
if (VIR_ALLOC((*group)) != 0) {
goto err;
}
- rc = virCgroupDetect(*group);
+ rc = virCgroupDetect(*group, controllers);
if (rc < 0)
goto err;
static int virCgroupAppRoot(bool privileged,
virCgroupPtr *group,
- bool create)
+ bool create,
+ int controllers)
{
virCgroupPtr rootgrp = NULL;
int rc;
- rc = virCgroupNew("/", &rootgrp);
+ rc = virCgroupNew("/", controllers, &rootgrp);
if (rc != 0)
return rc;
if (privileged) {
- rc = virCgroupNew("/libvirt", group);
+ rc = virCgroupNew("/libvirt", controllers, group);
} else {
char *rootname;
char *username;
goto cleanup;
}
- rc = virCgroupNew(rootname, group);
+ rc = virCgroupNew(rootname, controllers, group);
VIR_FREE(rootname);
}
if (rc != 0)
return rc;
}
+
/**
* virCgroupAddTask:
*
*
* Returns: 0 on success or -errno on failure
*/
-int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr dest_group,
- int controller)
+int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr dest_group)
{
- int rc = 0, err = 0;
+ int rc = 0;
char *content = NULL;
+ int i;
- if (controller < VIR_CGROUP_CONTROLLER_CPU ||
- controller > VIR_CGROUP_CONTROLLER_BLKIO)
- return -EINVAL;
-
- if (!src_group->controllers[controller].mountPoint ||
- !dest_group->controllers[controller].mountPoint) {
- return -EINVAL;
- }
-
- rc = virCgroupGetValueStr(src_group, controller, "tasks", &content);
- if (rc != 0)
- return rc;
+ for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
+ if (!src_group->controllers[i].mountPoint ||
+ !dest_group->controllers[i].mountPoint)
+ continue;
- rc = virCgroupAddTaskStrController(dest_group, content, controller);
- if (rc != 0)
- goto cleanup;
+ rc = virCgroupGetValueStr(src_group, i, "tasks", &content);
+ if (rc != 0)
+ return rc;
- VIR_FREE(content);
+ rc = virCgroupAddTaskStrController(dest_group, content, i);
+ if (rc != 0)
+ goto cleanup;
- return 0;
+ VIR_FREE(content);
+ }
cleanup:
- /*
- * We don't need to recover dest_cgroup because cgroup will make sure
- * that one task only resides in one cgroup of the same controller.
- */
- 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);
VIR_FREE(content);
-
return rc;
}
int virCgroupForDriver(const char *name,
virCgroupPtr *group,
bool privileged,
- bool create)
+ bool create,
+ int controllers)
{
int rc;
char *path = NULL;
virCgroupPtr rootgrp = NULL;
- rc = virCgroupAppRoot(privileged, &rootgrp, create);
+ rc = virCgroupAppRoot(privileged, &rootgrp,
+ create, controllers);
if (rc != 0)
goto out;
goto out;
}
- rc = virCgroupNew(path, group);
+ rc = virCgroupNew(path, controllers, group);
VIR_FREE(path);
if (rc == 0) {
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
int virCgroupForSelf(virCgroupPtr *group)
{
- return virCgroupNew("/", group);
+ return virCgroupNew("/", -1, group);
}
#else
int virCgroupForSelf(virCgroupPtr *group ATTRIBUTE_UNUSED)
if (virAsprintf(&path, "%s/%s", driver->path, name) < 0)
return -ENOMEM;
- rc = virCgroupNew(path, group);
+ rc = virCgroupNew(path, -1, group);
VIR_FREE(path);
if (rc == 0) {
{
int rc;
char *path;
+ int controllers;
if (driver == NULL)
return -EINVAL;
if (virAsprintf(&path, "%s/vcpu%d", driver->path, vcpuid) < 0)
return -ENOMEM;
- rc = virCgroupNew(path, group);
+ controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUSET));
+
+ rc = virCgroupNew(path, controllers, group);
VIR_FREE(path);
if (rc == 0) {
- rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
+ rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_NONE);
if (rc != 0)
virCgroupFree(group);
}
{
int rc;
char *path;
+ int controllers;
if (driver == NULL)
return -EINVAL;
if (virAsprintf(&path, "%s/emulator", driver->path) < 0)
return -ENOMEM;
- rc = virCgroupNew(path, group);
+ controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUSET));
+
+ rc = virCgroupNew(path, controllers, group);
VIR_FREE(path);
if (rc == 0) {
- rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
+ rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_NONE);
if (rc != 0)
virCgroupFree(group);
}
goto cleanup;
}
- if ((rc = virCgroupNew(subpath, &subgroup)) != 0)
+ if ((rc = virCgroupNew(subpath, -1, &subgroup)) != 0)
goto cleanup;
if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0)