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 is present only on container's root cgroup.
https://jira.sw.ru/browse/PSBM-33401
Signed-off-by: Andrey Ryabinin
---
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
--
2.10.2
___
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel