/* * Make sure the 'cgroup group' exists, so that we don't have to worry about * that later. * * @lxcgroup: the cgroup group, i.e. 'lxc' by default. * * See detailed comments at lxc_cgroup_path_create for more information. * * Returns 0 on success, -1 on error. */ static int create_lxcgroups(const char *lxcgroup) { FILE *file = NULL; struct mntent *mntent; int ret, retv = -1; char path[MAXPATHLEN]; file = setmntent(MTAB, "r"); if (!file) { SYSERROR("failed to open %s", MTAB); return -1; } while ((mntent = getmntent(file))) { if (strcmp(mntent->mnt_type, "cgroup")) continue; if (!mount_has_subsystem(mntent)) continue; /* * TODO - handle case where lxcgroup has subdirs? (i.e. build/l1) * We probably only want to support that for /users/joe */ ret = snprintf(path, MAXPATHLEN, "%s/%s", mntent->mnt_dir, lxcgroup ? lxcgroup : "lxc"); if (ret < 0 || ret >= MAXPATHLEN) goto fail; if (access(path, F_OK)) { set_clone_children(mntent->mnt_dir); ret = mkdir(path, 0755); if (ret == -1 && errno != EEXIST) { SYSERROR("failed to create '%s' directory", path); goto fail; } } } retv = 0; fail: endmntent(file); return retv; }
/** * Mount the cgroup filesystems and record the information. * This should take configuration data from /etc. For now, * Just mount all controllers, separately just as cgroup-lite * does, and set the use_hierarchy and clone_children options. * * Things which should go into configuration file: * . which controllers to mount * . which controllers to co-mount * . any mount options (per-controller) * . values for sane_behavior, use_hierarchy, and clone_children */ int setup_cgroup_mounts(void) { FILE *cgf; int ret; char line[400]; if (unshare(CLONE_NEWNS) < 0) { nih_fatal("Failed to unshare a private mount ns: %s", strerror(errno)); return -1; } if (!setup_base_path()) { nih_fatal("Error setting up base cgroup path"); return -1; } if ((cgf = fopen("/proc/cgroups", "r")) == NULL) { nih_fatal ("Error opening /proc/cgroups: %s", strerror(errno)); return -1; } while (fgets(line, 400, cgf)) { char *p; struct controller_mounts *tmp; char dest[MAXPATHLEN]; unsigned long h; if (line[0] == '#') continue; p = index(line, '\t'); if (!p) continue; *p = '\0'; h = strtoul(p+1, NULL, 10); if (h) { nih_info("%s was already mounted!", line); #if STRICT ret = -1; goto out; #endif } ret = snprintf(dest, MAXPATHLEN, "%s/%s", base_path, line); if (ret < 0 || ret >= MAXPATHLEN) { nih_fatal("Error calculating pathname for %s and %s", base_path, line); goto out; } if (mkdir(dest, 0755) < 0 && errno != EEXIST) { nih_fatal("Failed to create %s: %s", dest, strerror(errno)); ret = -1; goto out; } if ((ret = mount(line, dest, "cgroup", 0, line)) < 0) { nih_fatal("Failed mounting %s: %s", line, strerror(errno)); goto out; } ret = -1; tmp = realloc(all_mounts, (num_controllers+1) * sizeof(*all_mounts)); if (!tmp) { nih_fatal("Out of memory mounting controllers"); goto out; } all_mounts = tmp; all_mounts[num_controllers].controller = strdup(line); if (!all_mounts[num_controllers].controller) { nih_fatal("Out of memory mounting controllers"); goto out; } all_mounts[num_controllers].options = NULL; all_mounts[num_controllers].path = strdup(dest); if (!all_mounts[num_controllers].path) { nih_fatal("Out of memory mounting controllers"); goto out; } nih_info("Mounted %s onto %s", all_mounts[num_controllers].controller, all_mounts[num_controllers].path); if (strcmp(all_mounts[num_controllers].controller, "cpuset") == 0) { set_clone_children(dest); // TODO make this optional? nih_info("set clone_children"); } else if (strcmp(all_mounts[num_controllers].controller, "memory") == 0) { set_use_hierarchy(dest); // TODO make this optional? nih_info("set memory.use_hierarchy"); } num_controllers++; } nih_info("mounted %d controllers", num_controllers); ret = 0; out: fclose(cgf); return ret; }