]> git.proxmox.com Git - mirror_lxc.git/commitdiff
confile: add lxc.cgroup2.[controller].[property]
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 31 Jan 2018 15:44:30 +0000 (16:44 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 31 Jan 2018 15:44:30 +0000 (16:44 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
doc/lxc.container.conf.sgml.in
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c

index 3ae4bfd1898e59c65f761755e444ce9c3d417107..dfb7ba05d4c55551fec3f0feaa9509d7f50202e8 100644 (file)
@@ -1330,17 +1330,31 @@ dev/null proc/kcore none bind,relative 0 0
       <variablelist>
         <varlistentry>
           <term>
-            <option>lxc.cgroup.[subsystem name]</option>
+            <option>lxc.cgroup.[controller name]</option>
           </term>
           <listitem>
             <para>
-              specify the control group value to be set.  The
-              subsystem name is the literal name of the control group
-              subsystem.  The permitted names and the syntax of their
-              values is not dictated by LXC, instead it depends on the
-              features of the Linux kernel running at the time the
-              container is started,
-              eg. <option>lxc.cgroup.cpuset.cpus</option>
+              Specify the control group value to be set on a legacy cgroup
+              hierarchy. The controller name is the literal name of the control
+              group. The permitted names and the syntax of their values is not
+              dictated by LXC, instead it depends on the features of the Linux
+              kernel running at the time the container is started, eg.
+              <option>lxc.cgroup.cpuset.cpus</option>
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.cgroup2.[controller name]</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the control group value to be set on the unified cgroup
+              shierarchy. The controller name is the literal name of the control
+              group. The permitted names and the syntax of their values is not
+              dictated by LXC, instead it depends on the features of the Linux
+              kernel running at the time the container is started, eg.
+              <option>lxc.cgroup2.memory.high</option>
             </para>
           </listitem>
         </varlistentry>
index a080bbd7e08d98003c7a79a75e3b1389e3b14622..9b6868940ed51c04a48b8b88271f02a77562858d 100644 (file)
@@ -2555,6 +2555,7 @@ struct lxc_conf *lxc_conf_init(void)
        }
        new->logfd = -1;
        lxc_list_init(&new->cgroup);
+       lxc_list_init(&new->cgroup2);
        lxc_list_init(&new->network);
        lxc_list_init(&new->mount_list);
        lxc_list_init(&new->caps);
@@ -3446,23 +3447,38 @@ int lxc_clear_config_keepcaps(struct lxc_conf *c)
        return 0;
 }
 
-int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
+int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
 {
-       struct lxc_list *it,*next;
-       bool all = false;
+       char *global_token, *namespaced_token;
+       struct lxc_list *it, *next, *list;
        const char *k = NULL;
+       bool all = false;
 
-       if (strcmp(key, "lxc.cgroup") == 0)
+       if (version == CGROUP2_SUPER_MAGIC) {
+               global_token = "lxc.cgroup2";
+               namespaced_token = "lxc.cgroup2.";
+               list = &c->cgroup2;
+       } else if (version == CGROUP_SUPER_MAGIC) {
+               global_token = "lxc.cgroup";
+               namespaced_token = "lxc.cgroup.";
+               list = &c->cgroup;
+       } else {
+               return -1;
+       }
+
+       if (strcmp(key, global_token) == 0)
                all = true;
-       else if (strncmp(key, "lxc.cgroup.", sizeof("lxc.cgroup.") - 1) == 0)
-               k = key + sizeof("lxc.cgroup.") - 1;
+       else if (strncmp(key, namespaced_token, sizeof(namespaced_token) - 1) == 0)
+               k = key + sizeof(namespaced_token) - 1;
        else
                return -1;
 
-       lxc_list_for_each_safe(it, &c->cgroup, next) {
+       lxc_list_for_each_safe(it, list, next) {
                struct lxc_cgroup *cg = it->elem;
+
                if (!all && strcmp(cg->subsystem, k) != 0)
                        continue;
+
                lxc_list_del(it);
                free(cg->subsystem);
                free(cg->value);
@@ -3680,7 +3696,8 @@ void lxc_conf_free(struct lxc_conf *conf)
        lxc_seccomp_free(conf);
        lxc_clear_config_caps(conf);
        lxc_clear_config_keepcaps(conf);
-       lxc_clear_cgroups(conf, "lxc.cgroup");
+       lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC);
+       lxc_clear_cgroups(conf, "lxc.cgroup2", CGROUP2_SUPER_MAGIC);
        lxc_clear_hooks(conf, "lxc.hook");
        lxc_clear_mount_entries(conf);
        lxc_clear_idmaps(conf);
index 1146a1d4f67cbf6ee721d772b0d58ea12c0e5d8b..2346b717fd7de793da5241980a3cc98eafafd495 100644 (file)
@@ -52,6 +52,8 @@ typedef void * scmp_filter_ctx;
  * programmer to specify the right subsystem.
  * @subsystem : the targeted subsystem
  * @value     : the value to set
+ * @version   : The version of the cgroup filesystem on which the controller
+ *              resides.
  *
  * @controllers : The controllers to use for this container.
  * @dir         : The name of the directory containing the container's cgroup.
@@ -61,6 +63,7 @@ struct lxc_cgroup {
        union {
                /* information about a specific controller */
                struct /* controller */ {
+                       int version;
                        char *subsystem;
                        char *value;
                };
@@ -282,7 +285,10 @@ struct lxc_conf {
        int reboot;
        signed long personality;
        struct utsname *utsname;
-       struct lxc_list cgroup;
+       struct {
+               struct lxc_list cgroup;
+               struct lxc_list cgroup2;
+       };
        struct {
                struct lxc_list id_map;
 
@@ -433,7 +439,7 @@ extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
 extern void lxc_delete_tty(struct lxc_tty_info *tty_info);
 extern int lxc_clear_config_caps(struct lxc_conf *c);
 extern int lxc_clear_config_keepcaps(struct lxc_conf *c);
-extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key);
+extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version);
 extern int lxc_clear_mount_entries(struct lxc_conf *c);
 extern int lxc_clear_automounts(struct lxc_conf *c);
 extern int lxc_clear_hooks(struct lxc_conf *c, const char *key);
index 3deec58bf92793ea1f209e9ef3794e81f33f24a7..fa4f84da9e516382ce1384ccb80db1b92ba45a66 100644 (file)
@@ -81,6 +81,7 @@ lxc_config_define(apparmor_profile);
 lxc_config_define(cap_drop);
 lxc_config_define(cap_keep);
 lxc_config_define(cgroup_controller);
+lxc_config_define(cgroup2_controller);
 lxc_config_define(cgroup_dir);
 lxc_config_define(console_logfile);
 lxc_config_define(console_rotate);
@@ -153,6 +154,7 @@ static struct lxc_config_t config[] = {
        { "lxc.autodev",                   false,                  set_config_autodev,                     get_config_autodev,                     clr_config_autodev,                   },
        { "lxc.cap.drop",                  false,                  set_config_cap_drop,                    get_config_cap_drop,                    clr_config_cap_drop,                  },
        { "lxc.cap.keep",                  false,                  set_config_cap_keep,                    get_config_cap_keep,                    clr_config_cap_keep,                  },
+       { "lxc.cgroup2",                   false,                  set_config_cgroup2_controller,          get_config_cgroup2_controller,          clr_config_cgroup2_controller,        },
        { "lxc.cgroup.dir",                false,                  set_config_cgroup_dir,                  get_config_cgroup_dir,                  clr_config_cgroup_dir,                },
        { "lxc.cgroup",                    false,                  set_config_cgroup_controller,           get_config_cgroup_controller,           clr_config_cgroup_controller,         },
        { "lxc.console.buffer.logfile",    false,                  set_config_console_buffer_logfile,      get_config_console_buffer_logfile,      clr_config_console_buffer_logfile,    },
@@ -1374,28 +1376,33 @@ static int set_config_signal_stop(const char *key, const char *value,
        return 0;
 }
 
-static int set_config_cgroup_controller(const char *key, const char *value,
-                                       struct lxc_conf *lxc_conf, void *data)
+static int __set_config_cgroup_controller(const char *key, const char *value,
+                                         struct lxc_conf *lxc_conf, int version)
 {
-       char *subkey;
-       char *token = "lxc.cgroup.";
+       const char *subkey, *token;
+       size_t token_len;
        struct lxc_list *cglist = NULL;
        struct lxc_cgroup *cgelem = NULL;
 
        if (lxc_config_value_empty(value))
-               return lxc_clear_cgroups(lxc_conf, key);
-
-       subkey = strstr(key, token);
-       if (!subkey)
-               return -1;
-
-       if (!strlen(subkey))
-               return -1;
+               return lxc_clear_cgroups(lxc_conf, key, version);
+
+       if (version == CGROUP2_SUPER_MAGIC) {
+               token = "lxc.cgroup2.";
+               token_len = 12;
+       } else if (version == CGROUP_SUPER_MAGIC) {
+               token = "lxc.cgroup.";
+               token_len = 11;
+       } else {
+               return -EINVAL;
+       }
 
-       if (strlen(subkey) == strlen(token))
-               return -1;
+       if (strncmp(key, token, token_len) != 0)
+               return -EINVAL;
 
-       subkey += strlen(token);
+       subkey = key + token_len;
+       if (*subkey == '\0')
+               return -EINVAL;
 
        cglist = malloc(sizeof(*cglist));
        if (!cglist)
@@ -1407,14 +1414,21 @@ static int set_config_cgroup_controller(const char *key, const char *value,
        memset(cgelem, 0, sizeof(*cgelem));
 
        cgelem->subsystem = strdup(subkey);
-       cgelem->value = strdup(value);
+       if (!cgelem->subsystem)
+               goto out;
 
-       if (!cgelem->subsystem || !cgelem->value)
+       cgelem->value = strdup(value);
+       if (!cgelem->value)
                goto out;
 
-       cglist->elem = cgelem;
+       cgelem->version = version;
+
+       lxc_list_add_elem(cglist, cgelem);
 
-       lxc_list_add_tail(&lxc_conf->cgroup, cglist);
+       if (version == CGROUP2_SUPER_MAGIC)
+               lxc_list_add_tail(&lxc_conf->cgroup2, cglist);
+       else
+               lxc_list_add_tail(&lxc_conf->cgroup, cglist);
 
        return 0;
 
@@ -1429,6 +1443,21 @@ out:
        return -1;
 }
 
+static int set_config_cgroup_controller(const char *key, const char *value,
+                                       struct lxc_conf *lxc_conf, void *data)
+{
+       return __set_config_cgroup_controller(key, value, lxc_conf,
+                                             CGROUP_SUPER_MAGIC);
+}
+
+static int set_config_cgroup2_controller(const char *key, const char *value,
+                                        struct lxc_conf *lxc_conf, void *data)
+{
+       return __set_config_cgroup_controller(key, value, lxc_conf,
+                                             CGROUP2_SUPER_MAGIC);
+}
+
+
 static int set_config_cgroup_dir(const char *key, const char *value,
                                 struct lxc_conf *lxc_conf, void *data)
 {
@@ -2910,11 +2939,14 @@ static int get_config_selinux_context(const char *key, char *retv, int inlen,
  * If you ask for 'lxc.cgroup", then all cgroup entries will be printed, in
  * 'lxc.cgroup.subsystem.key = value' format.
  */
-static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
-                                       struct lxc_conf *c, void *data)
+static int __get_config_cgroup_controller(const char *key, char *retv,
+                                         int inlen, struct lxc_conf *c,
+                                         int version)
 {
-       struct lxc_list *it;
        int len;
+       size_t namespaced_token_len;
+       char *global_token, *namespaced_token;
+       struct lxc_list *it;
        int fulllen = 0;
        bool get_all = false;
 
@@ -2923,10 +2955,22 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
        else
                memset(retv, 0, inlen);
 
-       if (!strcmp(key, "lxc.cgroup"))
+       if (version == CGROUP2_SUPER_MAGIC) {
+               global_token = "lxc.cgroup2";
+               namespaced_token = "lxc.cgroup2.";
+               namespaced_token_len = sizeof("lxc.cgroup2.") - 1;;
+       } else if (version == CGROUP_SUPER_MAGIC) {
+               global_token = "lxc.cgroup";
+               namespaced_token = "lxc.cgroup.";
+               namespaced_token_len = sizeof("lxc.cgroup.") - 1;;
+       } else {
+               return -1;
+       }
+
+       if (strcmp(key, global_token) == 0)
                get_all = true;
-       else if (!strncmp(key, "lxc.cgroup.", 11))
-               key += 11;
+       else if (strncmp(key, namespaced_token, namespaced_token_len) == 0)
+               key += namespaced_token_len;
        else
                return -1;
 
@@ -2934,8 +2978,11 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
                struct lxc_cgroup *cg = it->elem;
 
                if (get_all) {
-                       strprint(retv, inlen, "lxc.cgroup.%s = %s\n",
-                                cg->subsystem, cg->value);
+                       if (version != cg->version)
+                               continue;
+
+                       strprint(retv, inlen, "%s.%s = %s\n",
+                                global_token, cg->subsystem, cg->value);
                } else if (!strcmp(cg->subsystem, key)) {
                        strprint(retv, inlen, "%s\n", cg->value);
                }
@@ -2944,6 +2991,20 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
        return fulllen;
 }
 
+static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
+                                       struct lxc_conf *c, void *data)
+{
+       return __get_config_cgroup_controller(key, retv, inlen, c,
+                                             CGROUP_SUPER_MAGIC);
+}
+
+static int get_config_cgroup2_controller(const char *key, char *retv, int inlen,
+                                        struct lxc_conf *c, void *data)
+{
+       return __get_config_cgroup_controller(key, retv, inlen, c,
+                                             CGROUP2_SUPER_MAGIC);
+}
+
 static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
                                 struct lxc_conf *lxc_conf, void *data)
 {
@@ -3632,7 +3693,13 @@ static inline int clr_config_selinux_context(const char *key,
 static inline int clr_config_cgroup_controller(const char *key,
                                               struct lxc_conf *c, void *data)
 {
-       return lxc_clear_cgroups(c, key);
+       return lxc_clear_cgroups(c, key, CGROUP_SUPER_MAGIC);
+}
+
+static inline int clr_config_cgroup2_controller(const char *key,
+                                               struct lxc_conf *c, void *data)
+{
+       return lxc_clear_cgroups(c, key, CGROUP2_SUPER_MAGIC);
 }
 
 static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,