static int lxc_one_cgroup_attach(const char *name, struct mntent *mntent, pid_t pid) { FILE *f; char tasks[MAXPATHLEN], initcgroup[MAXPATHLEN]; char *cgmnt = mntent->mnt_dir; int flags, ret = 0; int rc; flags = get_cgroup_flags(mntent); rc = snprintf(tasks, MAXPATHLEN, "%s%s%s/%s/tasks", cgmnt, get_init_cgroup(NULL, mntent, initcgroup), (flags & CGROUP_NS_CGROUP) ? "" : "/lxc", name); if (rc < 0 || rc >= MAXPATHLEN) { ERROR("pathname too long"); return -1; } f = fopen(tasks, "w"); if (!f) { SYSERROR("failed to open '%s'", tasks); return -1; } if (fprintf(f, "%d", pid) <= 0) { SYSERROR("failed to write pid '%d' to '%s'", pid, tasks); ret = -1; } fclose(f); return ret; }
static int get_cgroup_mount(const char *subsystem, char *mnt) { struct mntent *mntent; char initcgroup[MAXPATHLEN]; FILE *file = NULL; int ret, flags, err = -1; 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 (subsystem) { if (!hasmntopt(mntent, subsystem)) continue; } else { if (!mount_has_subsystem(mntent)) continue; } flags = get_cgroup_flags(mntent); ret = snprintf(mnt, MAXPATHLEN, "%s%s%s", mntent->mnt_dir, get_init_cgroup(subsystem, NULL, initcgroup), (flags & CGROUP_NS_CGROUP) ? "" : "/lxc"); if (ret < 0 || ret >= MAXPATHLEN) goto fail; DEBUG("using cgroup mounted at '%s'", mnt); err = 0; goto out; }; fail: DEBUG("Failed to find cgroup for %s\n", subsystem ? subsystem : "(NULL)"); out: endmntent(file); return err; }
int lxc_one_cgroup_destroy(struct mntent *mntent, const char *name) { char cgname[MAXPATHLEN], initcgroup[MAXPATHLEN]; char *cgmnt = mntent->mnt_dir; int flags = get_cgroup_flags(mntent); int rc; rc = snprintf(cgname, MAXPATHLEN, "%s%s%s/%s", cgmnt, get_init_cgroup(NULL, mntent, initcgroup), (flags & CGROUP_NS_CGROUP) ? "" : "/lxc", name); if (rc < 0 || rc >= MAXPATHLEN) { ERROR("name too long"); return -1; } DEBUG("destroying %s\n", cgname); if (recursive_rmdir(cgname)) { SYSERROR("failed to remove cgroup '%s'", cgname); return -1; } DEBUG("'%s' unlinked", cgname); return 0; }
int lxc_cgroup_create(const char *name, pid_t pid) { char cgmnt[MAXPATHLEN]; char cgname[MAXPATHLEN]; char clonechild[MAXPATHLEN]; int flags; if (get_cgroup_mount(MTAB, cgmnt)) { ERROR("cgroup is not mounted"); return -1; } snprintf(cgname, MAXPATHLEN, "%s/%s", cgmnt, name); /* * There is a previous cgroup, assume it is empty, * otherwise that fails */ if (!access(cgname, F_OK) && rmdir(cgname)) { SYSERROR("failed to remove previous cgroup '%s'", cgname); return -1; } if (get_cgroup_flags(MTAB, &flags)) { SYSERROR("failed to get cgroup flags"); return -1; } /* We have the deprecated ns_cgroup subsystem */ if (flags & CGROUP_NS_CGROUP) { WARN("using deprecated ns_cgroup"); return cgroup_rename_nsgroup(cgmnt, cgname, pid); } snprintf(clonechild, MAXPATHLEN, "%s/cgroup.clone_children", cgmnt); /* we check if the kernel has clone_children, at this point if there * no clone_children neither ns_cgroup, that means the cgroup is mounted * without the ns_cgroup and it has not the compatibility flag */ if (access(clonechild, F_OK)) { ERROR("no ns_cgroup option specified"); return -1; } /* we enable the clone_children flag of the cgroup */ if (cgroup_enable_clone_children(clonechild)) { SYSERROR("failed to enable 'clone_children flag"); return -1; } /* Let's create the cgroup */ if (mkdir(cgname, 0700)) { SYSERROR("failed to create '%s' directory", cgname); return -1; } /* Let's add the pid to the 'tasks' file */ if (cgroup_attach(cgname, pid)) { SYSERROR("failed to attach pid '%d' to '%s'", pid, cgname); rmdir(cgname); return -1; } return 0; }
/* * create a cgroup for the container in a particular subsystem. */ static int lxc_one_cgroup_create(const char *name, struct mntent *mntent, pid_t pid) { char cginit[MAXPATHLEN], cgname[MAXPATHLEN], cgparent[MAXPATHLEN]; char clonechild[MAXPATHLEN]; char initcgroup[MAXPATHLEN]; int flags, ret; /* cgparent is the parent dir, e.g., /sys/fs/cgroup/<cgroup>/<init-cgroup>/lxc */ /* (remember get_init_cgroup() returns a path starting with '/') */ /* cgname is the full name, e.g., /sys/fs/cgroup/<cgroup>/<init-cgroup>/lxc/name */ ret = snprintf(cginit, MAXPATHLEN, "%s%s", mntent->mnt_dir, get_init_cgroup(NULL, mntent, initcgroup)); if (ret < 0 || ret >= MAXPATHLEN) { SYSERROR("Failed creating pathname for init's cgroup (%d)\n", ret); return -1; } flags = get_cgroup_flags(mntent); ret = snprintf(cgparent, MAXPATHLEN, "%s%s", cginit, (flags & CGROUP_NS_CGROUP) ? "" : "/lxc"); if (ret < 0 || ret >= MAXPATHLEN) { SYSERROR("Failed creating pathname for cgroup parent (%d)\n", ret); return -1; } ret = snprintf(cgname, MAXPATHLEN, "%s/%s", cgparent, name); if (ret < 0 || ret >= MAXPATHLEN) { SYSERROR("Failed creating pathname for cgroup (%d)\n", ret); return -1; } /* Do we have the deprecated ns_cgroup subsystem? */ if (flags & CGROUP_NS_CGROUP) { WARN("using deprecated ns_cgroup"); return cgroup_rename_nsgroup(cginit, name, pid); } ret = snprintf(clonechild, MAXPATHLEN, "%s/cgroup.clone_children", cginit); if (ret < 0 || ret >= MAXPATHLEN) { SYSERROR("Failed creating pathname for clone_children (%d)\n", ret); return -1; } /* we check if the kernel has clone_children, at this point if there * no clone_children neither ns_cgroup, that means the cgroup is mounted * without the ns_cgroup and it has not the compatibility flag */ if (access(clonechild, F_OK)) { ERROR("no ns_cgroup option specified"); return -1; } /* enable the clone_children flag of the cgroup */ if (cgroup_enable_clone_children(clonechild)) { SYSERROR("failed to enable 'clone_children flag"); return -1; } /* if cgparent does not exist, create it */ if (access(cgparent, F_OK) && mkdir(cgparent, 0755)) { SYSERROR("failed to create '%s' directory", cgparent); return -1; } /* * There is a previous cgroup. Try to delete it. If that fails * (i.e. it is not empty) try to move it out of the way. */ if (!access(cgname, F_OK) && rmdir(cgname)) { if (try_to_move_cgname(cgparent, cgname)) { SYSERROR("failed to remove previous cgroup '%s'", cgname); return -1; } } /* Let's create the cgroup */ if (mkdir(cgname, 0755)) { SYSERROR("failed to create '%s' directory", cgname); return -1; } INFO("created cgroup '%s'", cgname); return 0; }