|
Michal Koutný |
249c98 |
From: Shakeel Butt <shakeelb@google.com>
|
|
Michal Koutný |
249c98 |
Date: Sun, 24 Oct 2021 23:19:14 -0700
|
|
Michal Koutný |
249c98 |
Subject: cgroup: reduce dependency on cgroup_mutex
|
|
Michal Koutný |
249c98 |
Git-commit: be288169712f3dea0bc6b50c00b3ab53d85f1435
|
|
Michal Koutný |
249c98 |
Patch-mainline: v5.16-rc1
|
|
Michal Koutný |
249c98 |
References: bsc#1205650
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
Currently cgroup_get_from_path() and cgroup_get_from_id() grab
|
|
Michal Koutný |
249c98 |
cgroup_mutex before traversing the default hierarchy to find the
|
|
Michal Koutný |
249c98 |
kernfs_node corresponding to the path/id and then extract the linked
|
|
Michal Koutný |
249c98 |
cgroup. Since cgroup_mutex is still held, it is guaranteed that the
|
|
Michal Koutný |
249c98 |
cgroup will be alive and the reference can be taken on it.
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
However similar guarantee can be provided without depending on the
|
|
Michal Koutný |
249c98 |
cgroup_mutex and potentially reducing avenues of cgroup_mutex contentions.
|
|
Michal Koutný |
249c98 |
The kernfs_node's priv pointer is RCU protected pointer and with just
|
|
Michal Koutný |
249c98 |
rcu read lock we can grab the reference on the cgroup without
|
|
Michal Koutný |
249c98 |
cgroup_mutex. So, remove cgroup_mutex from them.
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
Signed-off-by: Shakeel Butt <shakeelb@google.com>
|
|
Michal Koutný |
249c98 |
Signed-off-by: Tejun Heo <tj@kernel.org>
|
|
Michal Koutný |
249c98 |
Acked-by: Michal Koutný <mkoutny@suse.com>
|
|
Michal Koutný |
249c98 |
---
|
|
Michal Koutný |
249c98 |
kernel/cgroup/cgroup.c | 51 ++++++++++++++++++++++++++++----------------------
|
|
Michal Koutný |
249c98 |
1 file changed, 29 insertions(+), 22 deletions(-)
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
|
|
Michal Koutný |
249c98 |
index 2e98db4558f2..003204c85893 100644
|
|
Michal Koutný |
249c98 |
--- a/kernel/cgroup/cgroup.c
|
|
Michal Koutný |
249c98 |
+++ b/kernel/cgroup/cgroup.c
|
|
Michal Koutný |
249c98 |
@@ -5932,17 +5932,20 @@ struct cgroup *cgroup_get_from_id(u64 id)
|
|
Michal Koutný |
249c98 |
struct kernfs_node *kn;
|
|
Michal Koutný |
249c98 |
struct cgroup *cgrp = NULL;
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
- mutex_lock(&cgroup_mutex);
|
|
Michal Koutný |
249c98 |
kn = kernfs_find_and_get_node_by_id(cgrp_dfl_root.kf_root, id);
|
|
Michal Koutný |
249c98 |
if (!kn)
|
|
Michal Koutný |
249c98 |
- goto out_unlock;
|
|
Michal Koutný |
249c98 |
+ goto out;
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+ rcu_read_lock();
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
- cgrp = kn->priv;
|
|
Michal Koutný |
249c98 |
- if (cgroup_is_dead(cgrp) || !cgroup_tryget(cgrp))
|
|
Michal Koutný |
249c98 |
+ cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
|
|
Michal Koutný |
249c98 |
+ if (cgrp && !cgroup_tryget(cgrp))
|
|
Michal Koutný |
249c98 |
cgrp = NULL;
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+ rcu_read_unlock();
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
kernfs_put(kn);
|
|
Michal Koutný |
249c98 |
-out_unlock:
|
|
Michal Koutný |
249c98 |
- mutex_unlock(&cgroup_mutex);
|
|
Michal Koutný |
249c98 |
+out:
|
|
Michal Koutný |
249c98 |
return cgrp;
|
|
Michal Koutný |
249c98 |
}
|
|
Michal Koutný |
249c98 |
EXPORT_SYMBOL_GPL(cgroup_get_from_id);
|
|
Michal Koutný |
249c98 |
@@ -6495,30 +6498,34 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
|
|
Michal Koutný |
249c98 |
*
|
|
Michal Koutný |
249c98 |
* Find the cgroup at @path on the default hierarchy, increment its
|
|
Michal Koutný |
249c98 |
* reference count and return it. Returns pointer to the found cgroup on
|
|
Michal Koutný |
249c98 |
- * success, ERR_PTR(-ENOENT) if @path doesn't exist and ERR_PTR(-ENOTDIR)
|
|
Michal Koutný |
249c98 |
- * if @path points to a non-directory.
|
|
Michal Koutný |
249c98 |
+ * success, ERR_PTR(-ENOENT) if @path doesn't exist or if the cgroup has already
|
|
Michal Koutný |
249c98 |
+ * been released and ERR_PTR(-ENOTDIR) if @path points to a non-directory.
|
|
Michal Koutný |
249c98 |
*/
|
|
Michal Koutný |
249c98 |
struct cgroup *cgroup_get_from_path(const char *path)
|
|
Michal Koutný |
249c98 |
{
|
|
Michal Koutný |
249c98 |
struct kernfs_node *kn;
|
|
Michal Koutný |
249c98 |
- struct cgroup *cgrp;
|
|
Michal Koutný |
249c98 |
-
|
|
Michal Koutný |
249c98 |
- mutex_lock(&cgroup_mutex);
|
|
Michal Koutný |
249c98 |
+ struct cgroup *cgrp = ERR_PTR(-ENOENT);
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
kn = kernfs_walk_and_get(cgrp_dfl_root.cgrp.kn, path);
|
|
Michal Koutný |
249c98 |
- if (kn) {
|
|
Michal Koutný |
249c98 |
- if (kernfs_type(kn) == KERNFS_DIR) {
|
|
Michal Koutný |
249c98 |
- cgrp = kn->priv;
|
|
Michal Koutný |
249c98 |
- cgroup_get_live(cgrp);
|
|
Michal Koutný |
249c98 |
- } else {
|
|
Michal Koutný |
249c98 |
- cgrp = ERR_PTR(-ENOTDIR);
|
|
Michal Koutný |
249c98 |
- }
|
|
Michal Koutný |
249c98 |
- kernfs_put(kn);
|
|
Michal Koutný |
249c98 |
- } else {
|
|
Michal Koutný |
249c98 |
- cgrp = ERR_PTR(-ENOENT);
|
|
Michal Koutný |
249c98 |
+ if (!kn)
|
|
Michal Koutný |
249c98 |
+ goto out;
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+ if (kernfs_type(kn) != KERNFS_DIR) {
|
|
Michal Koutný |
249c98 |
+ cgrp = ERR_PTR(-ENOTDIR);
|
|
Michal Koutný |
249c98 |
+ goto out_kernfs;
|
|
Michal Koutný |
249c98 |
}
|
|
Michal Koutný |
249c98 |
|
|
Michal Koutný |
249c98 |
- mutex_unlock(&cgroup_mutex);
|
|
Michal Koutný |
249c98 |
+ rcu_read_lock();
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+ cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
|
|
Michal Koutný |
249c98 |
+ if (!cgrp || !cgroup_tryget(cgrp))
|
|
Michal Koutný |
249c98 |
+ cgrp = ERR_PTR(-ENOENT);
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+ rcu_read_unlock();
|
|
Michal Koutný |
249c98 |
+
|
|
Michal Koutný |
249c98 |
+out_kernfs:
|
|
Michal Koutný |
249c98 |
+ kernfs_put(kn);
|
|
Michal Koutný |
249c98 |
+out:
|
|
Michal Koutný |
249c98 |
return cgrp;
|
|
Michal Koutný |
249c98 |
}
|
|
Michal Koutný |
249c98 |
EXPORT_SYMBOL_GPL(cgroup_get_from_path);
|
|
Michal Koutný |
249c98 |
|