The commit is pushed to "branch-rh7-3.10.0-514.6.1.vz7.28.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.6.1.vz7.28.2
------>
commit 357f6ed81449fdc988771882f1f9b2e1c5455c04
Author: Andrey Ryabinin <aryabi...@virtuozzo.com>
Date:   Fri Jan 20 16:11:39 2017 +0400

    ve/cgroups: Introduce subgroups_limit control
    
    Having a lot memory cgroups on machine may cause significant slowdown.
    So we want to limit number of sub-groups that container can create.
    This patch adds cgroup.subgroups_limit control file for that purpose.
    The file presents only on container's root cgroup.
    
    By default cgroup.subgroups_limit == 0 which means no limit.
    
    https://jira.sw.ru/browse/PSBM-33401
    
    Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com>
    Reviewed-by: Cyrill Gorcunov <gorcu...@openvz.org>
---
 include/linux/cgroup.h |  1 +
 kernel/cgroup.c        | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 816cbac..d99251b 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -284,6 +284,7 @@ struct cgroup {
 
        /* directory xattrs */
        struct simple_xattrs xattrs;
+       u64 subgroups_limit;
 };
 
 #define MAX_CGROUP_ROOT_NAMELEN 64
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 9a39c26..3e2de0b4 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4040,6 +4040,19 @@ static int cgroup_clone_children_write(struct cgroup 
*cgrp,
        return 0;
 }
 
+static u64 cgroup_read_subgroups_limit(struct cgroup *cgrp,
+                               struct cftype *cft)
+{
+       return cgrp->subgroups_limit;
+}
+static int cgroup_write_subgroups_limit(struct cgroup *cgrp,
+                                       struct cftype *cft,
+                                       u64 val)
+{
+       cgrp->subgroups_limit = val;
+       return 0;
+}
+
 /*
  * for the common functions, 'private' gives the type of file
  */
@@ -4090,6 +4103,13 @@ static struct cftype files[] = {
                .write_string = cgroup_release_agent_write,
                .max_write_len = PATH_MAX,
        },
+       {
+               .name = "cgroup.subgroups_limit",
+               .flags = CFTYPE_ONLY_ON_VE_ROOT,
+               .read_u64 = cgroup_read_subgroups_limit,
+               .write_u64 = cgroup_write_subgroups_limit,
+               .mode = S_IRUGO | S_IWUSR,
+       },
        { }     /* terminate */
 };
 
@@ -4205,6 +4225,19 @@ static void offline_css(struct cgroup_subsys *ss, struct 
cgroup *cgrp)
        cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE;
 }
 
+static int subgroups_count(struct cgroup *cgroup)
+{
+       struct cgroup *pos;
+       int cgrps_count = 0;
+
+       rcu_read_lock();
+       cgroup_for_each_descendant_post(pos, cgroup)
+               cgrps_count++;
+       rcu_read_unlock();
+
+       return cgrps_count;
+}
+
 #ifdef CONFIG_VE
 static void cgroup_add_ve_root_files(struct cgroup *cgrp,
                                struct cgroup_subsys *subsys,
@@ -4244,6 +4277,27 @@ void cgroup_mark_ve_root(struct ve_struct *ve)
        mutex_unlock(&cgroup_mutex);
 }
 
+static struct cgroup *cgroup_get_ve_root(struct cgroup *cgrp)
+{
+       struct cgroup *ve_root = NULL;
+
+       rcu_read_lock();
+       do {
+               if (test_bit(CGRP_VE_ROOT, &cgrp->flags)) {
+                       ve_root = cgrp;
+                       break;
+               }
+               cgrp = cgrp->parent;
+       } while (cgrp);
+       rcu_read_unlock();
+
+       return ve_root;
+}
+#else
+static inline struct cgroup *cgroup_get_ve_root(struct cgroup *cgrp)
+{
+       return NULL;
+}
 #endif
 
 /*
@@ -4263,6 +4317,7 @@ static long cgroup_create(struct cgroup *parent, struct 
dentry *dentry,
        int err = 0;
        struct cgroup_subsys *ss;
        struct super_block *sb = root->sb;
+       struct cgroup *ve_root = parent;
 
        /* allocate the cgroup and its ID, 0 is reserved for the root */
        cgrp = kzalloc(sizeof(*cgrp), GFP_KERNEL);
@@ -4278,6 +4333,13 @@ static long cgroup_create(struct cgroup *parent, struct 
dentry *dentry,
        if (cgrp->id < 0)
                goto err_free_name;
 
+       ve_root = cgroup_get_ve_root(parent);
+       if (ve_root && ve_root->subgroups_limit > 0 &&
+                       subgroups_count(ve_root) >= ve_root->subgroups_limit) {
+               err = -EACCES;
+               goto err_free_name;
+       }
+
        /*
         * Only live parents can have children.  Note that the liveliness
         * check isn't strictly necessary because cgroup_mkdir() and
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to