]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/cgroups/cgfsng.c
cgfs: remove redundancy utils
[mirror_lxc.git] / src / lxc / cgroups / cgfsng.c
index e083ad6d61b80c038cdf09a01a61c0d36bbd3061..1631319ec8abdfccb1fed72fe9842f966526b16a 100644 (file)
  *
  * 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"
@@ -82,12 +84,6 @@ static void free_string_list(char **clist)
        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
@@ -132,12 +128,12 @@ static char *cg_legacy_must_prefix_named(char *entry)
        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;
 }
 
@@ -539,7 +535,7 @@ static bool copy_parent_file(char *path, char *file)
        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;
@@ -822,7 +818,7 @@ static struct hierarchy *add_hierarchy(struct hierarchy ***h, char **clist, char
        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;
@@ -861,7 +857,7 @@ static char *cg_hybrid_get_mountpoint(char *line)
        *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;
@@ -877,7 +873,7 @@ static char *copy_to_eol(char *p)
                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;
@@ -1150,6 +1146,8 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
 
        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)
@@ -1167,16 +1165,36 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
                                                    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)
@@ -1255,20 +1273,53 @@ on_error:
        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;
@@ -1281,18 +1332,13 @@ static bool container_create_path_for_hierarchy(struct hierarchy *h, char *cgnam
 {
        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;
@@ -1347,10 +1393,9 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
                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) {
@@ -1374,8 +1419,10 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
                }
        } 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);
@@ -1413,7 +1460,7 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
        }
 
        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;
@@ -1452,6 +1499,7 @@ again:
        }
 
        ops->container_cgroup = container_cgroup;
+       INFO("The container uses \"%s\" as cgroup", container_cgroup);
 
        return true;
 
@@ -1635,7 +1683,7 @@ static bool cg_mount_needs_subdirs(int type)
 
 /* 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,
@@ -2056,7 +2104,7 @@ static int __cg_unified_attach(const struct hierarchy *h, const char *name,
 
        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",
@@ -2079,7 +2127,8 @@ static int __cg_unified_attach(const struct hierarchy *h, const char *name,
                if (errno != EBUSY)
                        goto on_error;
 
-       } while (++idx > 0 && idx < 1000);
+               idx++;
+       } while (idx < 1000);
 
 on_success:
        if (idx < 1000)