#include "cgroup.h"
#include "cgroup_utils.h"
#include "commands.h"
-#include "conf.h"
#include "log.h"
-#include "storage/storage.h"
+#include "storage.h"
#include "utils.h"
lxc_log_define(lxc_cgfsng, lxc);
c2 = c1;
else if (c1 < c2)
c1 = c2;
- else if (!c1 && c2) /* The reverse case is obvs. not needed. */
+ else if (!c1 && c2) // The reverse case is obvs. not needed.
c1 = c2;
/* If the above logic is correct, c1 should always hold a valid string
bool bret = false, flipped_bit = false;
lastslash = strrchr(path, '/');
- if (!lastslash) { /* bug... this shouldn't be possible */
+ if (!lastslash) { // bug... this shouldn't be possible
ERROR("Invalid path: %s.", path);
return bret;
}
int ret;
lastslash = strrchr(path, '/');
- if (!lastslash) { /* bug... this shouldn't be possible */
+ if (!lastslash) { // bug... this shouldn't be possible
ERROR("cgfsng:copy_parent_file: bad path %s", path);
return false;
}
printf("Cgroup information:\n");
printf(" container name: %s\n", d->name ? d->name : "(null)");
printf(" lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(null)");
- printf(" lxc.cgroup.pattern: %s\n",
- d->cgroup_pattern ? d->cgroup_pattern : "(null)");
- printf(" cgroup: %s\n",
- d->container_cgroup ? d->container_cgroup : "(null)");
+ printf(" lxc.cgroup.pattern: %s\n", d->cgroup_pattern ? d->cgroup_pattern : "(null)");
+ printf(" cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(null)");
}
static void lxc_cgfsng_print_hierarchies()
const char *tmp;
errno = 0;
tmp = lxc_global_config_value("lxc.cgroup.use");
+
if (!cgroup_use && errno != 0) { /* lxc.cgroup.use can be NULL */
CGFSNG_DEBUG("Failed to retrieve list of cgroups to use\n");
return false;
return parse_hierarchies();
}
-static void *cgfsng_init(struct lxc_handler *handler)
+static void *cgfsng_init(const char *name)
{
- const char *cgroup_pattern;
struct cgfsng_handler_data *d;
+ const char *cgroup_pattern;
d = must_alloc(sizeof(*d));
memset(d, 0, sizeof(*d));
- /* copy container name */
- d->name = must_copy_string(handler->name);
+ d->name = must_copy_string(name);
- /* copy system-wide cgroup information */
cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
- if (!cgroup_pattern) {
- /* lxc.cgroup.pattern is only NULL on error. */
+ if (!cgroup_pattern) { // lxc.cgroup.pattern is only NULL on error
ERROR("Error getting cgroup pattern");
goto out_free;
}
static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
{
h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
- if (dir_exists(h->fullcgpath)) { /* it must not already exist */
+ if (dir_exists(h->fullcgpath)) { // it must not already exist
ERROR("Path \"%s\" already existed.", h->fullcgpath);
return false;
}
*/
static inline bool cgfsng_create(void *hdata)
{
+ struct cgfsng_handler_data *d = hdata;
+ char *tmp, *cgname, *offset;
int i;
- size_t len;
- char *cgname, *offset, *tmp;
int idx = 0;
- struct cgfsng_handler_data *d = hdata;
+ size_t len;
if (!d)
return false;
-
if (d->container_cgroup) {
WARN("cgfsng_create called a second time");
return false;
ERROR("Failed expanding cgroup name pattern");
return false;
}
- len = strlen(tmp) + 5; /* leave room for -NNN\0 */
+ len = strlen(tmp) + 5; // leave room for -NNN\0
cgname = must_alloc(len);
strcpy(cgname, tmp);
free(tmp);
for (i = 0; hierarchies[i]; i++) {
if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
int j;
- ERROR("Failed to create \"%s\"", hierarchies[i]->fullcgpath);
+ SYSERROR("Failed to create %s: %s", hierarchies[i]->fullcgpath, strerror(errno));
free(hierarchies[i]->fullcgpath);
hierarchies[i]->fullcgpath = NULL;
for (j = 0; j < i; j++)
return true;
}
+struct chown_data {
+ struct cgfsng_handler_data *d;
+ uid_t origuid; // target uid in parent namespace
+};
+
/*
* chgrp the container cgroups to container group. We leave
* the container owner as cgroup owner. So we must make the
const char *inpath,
const char *filename)
{
+ /*
+ * XXX Remove this case after 2.0 release. It's for dealing with
+ * containers spawned under the old buggy cgfsng which wasn't around
+ * for long.
+ */
+ if (strncmp(inpath, "/sys/fs/cgroup/", 15) == 0)
+ return must_make_path(inpath, filename, NULL);
return must_make_path(h->mountpoint, inpath, filename, NULL);
}
struct hierarchy *h = hierarchies[i];
path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
- if (!path) /* not running */
+ if (!path) // not running
continue;
fullpath = build_full_cgpath_from_monitorpath(h, path, "cgroup.procs");
*p = '\0';
path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem);
- if (!path) /* not running */
+ if (!path) // not running
return -1;
h = get_hierarchy(subsystem);
*p = '\0';
path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem);
- if (!path) /* not running */
+ if (!path) // not running
return -1;
h = get_hierarchy(subsystem);
return ret;
}
-/*
- * take devices cgroup line
- * /dev/foo rwx
- * and convert it to a valid
- * type major:minor mode
- * line. Return <0 on error. Dest is a preallocated buffer
- * long enough to hold the output.
- */
-static int convert_devpath(const char *invalue, char *dest)
-{
- int n_parts;
- char *p, *path, type;
- struct stat sb;
- unsigned long minor, major;
- int ret = -EINVAL;
- char *mode = NULL;
-
- path = must_copy_string(invalue);
-
- /*
- * read path followed by mode; ignore any trailing text.
- * A ' # comment' would be legal. Technically other text
- * is not legal, we could check for that if we cared to
- */
- for (n_parts = 1, p = path; *p && n_parts < 3; p++) {
- if (*p != ' ')
- continue;
- *p = '\0';
- if (n_parts != 1)
- break;
- p++;
- n_parts++;
- while (*p == ' ')
- p++;
- mode = p;
- if (*p == '\0')
- goto out;
- }
-
- if (n_parts == 1)
- goto out;
-
- ret = stat(path, &sb);
- if (ret < 0)
- goto out;
-
- mode_t m = sb.st_mode & S_IFMT;
- switch (m) {
- case S_IFBLK:
- type = 'b';
- break;
- case S_IFCHR:
- type = 'c';
- break;
- default:
- ERROR("Unsupported device type %i for %s", m, path);
- ret = -EINVAL;
- goto out;
- }
-
- major = MAJOR(sb.st_rdev);
- minor = MINOR(sb.st_rdev);
- ret = snprintf(dest, 50, "%c %lu:%lu %s", type, major, minor, mode);
- if (ret < 0 || ret >= 50) {
- ERROR("Error on configuration value \"%c %lu:%lu %s\" (max 50 "
- "chars)", type, major, minor, mode);
- ret = -ENAMETOOLONG;
- goto out;
- }
- ret = 0;
-
-out:
- free(path);
- return ret;
-}
-
/*
* Called from setup_limits - here we have the container's cgroup_data because
* we created the cgroups
static int lxc_cgroup_set_data(const char *filename, const char *value, struct cgfsng_handler_data *d)
{
char *fullpath, *p;
- /* "b|c <2^64-1>:<2^64-1> r|w|m" = 47 chars max */
- char converted_value[50];
struct hierarchy *h;
int ret = 0;
char *controller = NULL;
if ((p = strchr(controller, '.')) != NULL)
*p = '\0';
- if (strcmp("devices.allow", filename) == 0 && value[0] == '/') {
- ret = convert_devpath(value, converted_value);
- if (ret < 0)
- return ret;
- value = converted_value;
-
- }
-
h = get_hierarchy(controller);
if (!h) {
ERROR("Failed to setup limits for the \"%s\" controller. "