[Devel] [PATCH RH7] cgroup: switch from cgroup_mutex to cgroup_root_mutex in proc_cgroup_show

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Wed Jun 1 11:29:32 MSK 2022


We saw systemd reading /proc/<pid>/cgroup quiet a lot and we also see
that cgroup_mutex is contended enough to make it's waiters wait for
several seconds.

Assuming that cgroup_root_mutex should be less contended as roots change
not so much let's switch /proc/<pid>/cgroup to it.

https://jira.sw.ru/browse/PSBM-139206

Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
Let's build rpm for it, test it on customer test nodes and see if it
helps first.
---
 kernel/cgroup.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 64f4227b2305..1f5d80130070 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -705,13 +705,14 @@ static inline bool css_has_host_cgroups(struct css_set *css_set)
  * Return the cgroup for "task" from the given hierarchy. Must be
  * called with cgroup_mutex held.
  */
-static struct cgroup *task_cgroup_from_root(struct task_struct *task,
-					    struct cgroupfs_root *root)
+static struct cgroup *__task_cgroup_from_root(struct task_struct *task,
+					      struct cgroupfs_root *root,
+					      int nocgmtx)
 {
 	struct css_set *css;
 	struct cgroup *res = NULL;
 
-	BUG_ON(!mutex_is_locked(&cgroup_mutex));
+	BUG_ON(!nocgmtx && !mutex_is_locked(&cgroup_mutex));
 	read_lock(&css_set_lock);
 	/*
 	 * No need to lock the task - since we hold cgroup_mutex the
@@ -736,6 +737,12 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
 	return res;
 }
 
+static struct cgroup *task_cgroup_from_root(struct task_struct *task,
+					      struct cgroupfs_root *root)
+{
+	return __task_cgroup_from_root(task, root, false);
+}
+
 /*
  * There is one global cgroup mutex. We also require taking
  * task_lock() when dereferencing a task's cgroup subsys pointers.
@@ -5578,7 +5585,8 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 
 	retval = 0;
 
-	mutex_lock(&cgroup_mutex);
+	/* without cgroup_mutex we must protect roots list */
+	mutex_lock(&cgroup_root_mutex);
 
 	for_each_active_root(root) {
 		struct cgroup_subsys *ss;
@@ -5594,8 +5602,13 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 			seq_printf(m, "%sname=%s", count ? "," : "",
 				   root->name);
 		seq_putc(m, ':');
-		cgrp = task_cgroup_from_root(tsk, root);
+
+		/* without cgroup_mutex we take rcu to make cgrp valid */
+		rcu_read_lock();
+		cgrp = __task_cgroup_from_root(tsk, root, true);
 		retval = cgroup_path_ve(cgrp, buf, PAGE_SIZE);
+		rcu_read_unlock();
+
 		if (retval < 0)
 			goto out_unlock;
 		seq_puts(m, buf);
@@ -5603,7 +5616,7 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 	}
 
 out_unlock:
-	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_root_mutex);
 	put_task_struct(tsk);
 out_free:
 	kfree(buf);
-- 
2.35.3



More information about the Devel mailing list