*
* This new implementation assumes that cgroup filesystems are mounted
* under /sys/fs/cgroup/clist where clist is either the controller, or
- * a comman-separated list of controllers.
+ * a comma-separated list of controllers.
*/
-#include "config.h"
-
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <grp.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
#include <sys/types.h>
+#include <unistd.h>
#include "caps.h"
#include "cgroup.h"
#include "cgroup_utils.h"
#include "commands.h"
#include "conf.h"
+#include "config.h"
#include "log.h"
#include "macro.h"
#include "storage/storage.h"
free(clist);
}
-/* Allocate a pointer, do not fail. */
-static void *must_alloc(size_t sz)
-{
- return must_realloc(NULL, sz);
-}
-
/* Given a pointer to a null-terminated array of pointers, realloc to add one
* entry, and point the new entry to NULL. Do not fail. Return the index to the
* second-to-last entry - that is, the one which is now available for use
char *prefixed;
len = strlen(entry);
- prefixed = must_alloc(len + 6);
-
+ prefixed = must_realloc(NULL, len + 6);
memcpy(prefixed, "name=", STRLITERALLEN("name="));
memcpy(prefixed + STRLITERALLEN("name="), entry, len);
prefixed[len + 5] = '\0';
+
return prefixed;
}
if (len <= 0)
goto on_error;
- value = must_alloc(len + 1);
+ value = must_realloc(NULL, len + 1);
ret = lxc_read_from_file(fpath, value, len);
if (ret != len)
goto on_error;
struct hierarchy *new;
int newentry;
- new = must_alloc(sizeof(*new));
+ new = must_realloc(NULL, sizeof(*new));
new->controllers = clist;
new->mountpoint = mountpoint;
new->container_base_path = container_base_path;
*p2 = '\0';
len = strlen(p);
- sret = must_alloc(len + 1);
+ sret = must_realloc(NULL, len + 1);
memcpy(sret, p, len);
sret[len] = '\0';
return sret;
return NULL;
len = p2 - p;
- sret = must_alloc(len + 1);
+ sret = must_realloc(NULL, len + 1);
memcpy(sret, p, len);
sret[len] = '\0';
return sret;
for (int i = 0; ops->hierarchies[i]; i++) {
int ret;
+ char *chop;
+ char pivot_cgroup[] = PIVOT_CGROUP;
struct hierarchy *h = ops->hierarchies[i];
if (!h->monitor_full_path)
PIVOT_CGROUP,
"cgroup.procs", NULL);
+ chop = strrchr(pivot_path, '/');
+ if (chop)
+ *chop = '\0';
+
+ /*
+ * Make sure not to pass in the ro string literal PIVOT_CGROUP
+ * here.
+ */
+ if (!cg_legacy_handle_cpuset_hierarchy(h, pivot_cgroup)) {
+ WARN("Failed to handle legacy cpuset controller");
+ goto next;
+ }
+
ret = mkdir_p(pivot_path, 0755);
- if (ret < 0 && errno != EEXIST)
+ if (ret < 0 && errno != EEXIST) {
+ SYSWARN("Failed to create cgroup \"%s\"\n", pivot_path);
goto next;
+ }
+
+ if (chop)
+ *chop = '/';
/* Move ourselves into the pivot cgroup to delete our own
* cgroup.
*/
ret = lxc_write_to_file(pivot_path, pidstr, len, false, 0666);
- if (ret != 0)
+ if (ret != 0) {
+ SYSWARN("Failed to move monitor %s to \"%s\"\n", pidstr, pivot_path);
goto next;
+ }
ret = recursive_destroy(h->monitor_full_path);
if (ret < 0)
return bret;
}
+static int mkdir_eexist_on_last(const char *dir, mode_t mode)
+{
+ const char *tmp = dir;
+ const char *orig = dir;
+ size_t orig_len;
+
+ orig_len = strlen(dir);
+ do {
+ int ret;
+ size_t cur_len;
+ char *makeme;
+
+ dir = tmp + strspn(tmp, "/");
+ tmp = dir + strcspn(dir, "/");
+
+ errno = ENOMEM;
+ cur_len = dir - orig;
+ makeme = strndup(orig, cur_len);
+ if (!makeme)
+ return -1;
+
+ ret = mkdir(makeme, mode);
+ if (ret < 0) {
+ if ((errno != EEXIST) || (orig_len == cur_len)) {
+ SYSERROR("Failed to create directory \"%s\"", makeme);
+ free(makeme);
+ return -1;
+ }
+ }
+ free(makeme);
+
+ } while (tmp != dir);
+
+ return 0;
+}
+
static bool monitor_create_path_for_hierarchy(struct hierarchy *h, char *cgname)
{
int ret;
- h->monitor_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL);
- if (dir_exists(h->monitor_full_path))
- return true;
-
if (!cg_legacy_handle_cpuset_hierarchy(h, cgname)) {
ERROR("Failed to handle legacy cpuset controller");
return false;
}
- ret = mkdir_p(h->monitor_full_path, 0755);
+ h->monitor_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL);
+ ret = mkdir_eexist_on_last(h->monitor_full_path, 0755);
if (ret < 0) {
ERROR("Failed to create cgroup \"%s\"", h->monitor_full_path);
return false;
{
int ret;
- h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL);
- if (dir_exists(h->container_full_path)) {
- ERROR("The cgroup \"%s\" already existed", h->container_full_path);
- return false;
- }
-
if (!cg_legacy_handle_cpuset_hierarchy(h, cgname)) {
ERROR("Failed to handle legacy cpuset controller");
return false;
}
- ret = mkdir_p(h->container_full_path, 0755);
+ h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL);
+ ret = mkdir_eexist_on_last(h->container_full_path, 0755);
if (ret < 0) {
ERROR("Failed to create cgroup \"%s\"", h->container_full_path);
return false;
return bret;
len = strlen(tmp) + 5; /* leave room for -NNN\0 */
- monitor_cgroup = must_alloc(len);
- (void)strlcpy(monitor_cgroup, tmp, len);
- free(tmp);
+ monitor_cgroup = must_realloc(tmp, len);
offset = monitor_cgroup + len - 5;
+ *offset = 0;
do {
if (idx) {
}
} while (ops->hierarchies[i] && idx > 0 && idx < 1000);
- if (idx < 1000)
+ if (idx < 1000) {
bret = true;
+ INFO("The monitor process uses \"%s\" as cgroup", monitor_cgroup);
+ }
on_error:
free(monitor_cgroup);
}
len = strlen(tmp) + 5; /* leave room for -NNN\0 */
- container_cgroup = must_alloc(len);
+ container_cgroup = must_realloc(NULL, len);
(void)strlcpy(container_cgroup, tmp, len);
free(tmp);
offset = container_cgroup + len - 5;
}
ops->container_cgroup = container_cgroup;
+ INFO("The container uses \"%s\" as cgroup", container_cgroup);
return true;
/* After $rootfs/sys/fs/container/controller/the/cg/path has been created,
* remount controller ro if needed and bindmount the cgroupfs onto
- * controll/the/cg/path.
+ * control/the/cg/path.
*/
static int cg_legacy_mount_controllers(int type, struct hierarchy *h,
char *controllerpath, char *cgpath,
len = strlen(base_path) + STRLITERALLEN("/lxc-1000") +
STRLITERALLEN("/cgroup-procs");
- full_path = must_alloc(len + 1);
+ full_path = must_realloc(NULL, len + 1);
do {
if (idx)
ret = snprintf(full_path, len + 1, "%s/lxc-%d",
if (errno != EBUSY)
goto on_error;
- } while (++idx > 0 && idx < 1000);
+ idx++;
+ } while (idx < 1000);
on_success:
if (idx < 1000)