Skip to content

Commit 8353da1

Browse files
committed
cgroup: remove cgroup_tree_mutex
cgroup_tree_mutex was introduced to work around the circular dependency between cgroup_mutex and kernfs active protection - some kernfs file and directory operations needed cgroup_mutex putting cgroup_mutex under active protection but cgroup also needs to be able to access cgroup hierarchies and cftypes to determine which kernfs_nodes need to be removed. cgroup_tree_mutex nested above both cgroup_mutex and kernfs active protection and used to protect the hierarchy and cftypes. While this worked, it added a lot of double lockings and was generally cumbersome. kernfs provides a mechanism to opt out of active protection and cgroup was already using it for removal and subtree_control. There's no reason to mix both methods of avoiding circular locking dependency and the preceding cgroup_kn_lock_live() changes applied it to all relevant cgroup kernfs operations making it unnecessary to nest cgroup_mutex under kernfs active protection. The previous patch reversed the original lock ordering and put cgroup_mutex above kernfs active protection. After these changes, all cgroup_tree_mutex usages are now accompanied by cgroup_mutex making the former completely redundant. This patch removes cgroup_tree_mutex and all its usages. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
1 parent 01f6474 commit 8353da1

1 file changed

Lines changed: 9 additions & 55 deletions

File tree

kernel/cgroup.c

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,6 @@
7070
#define CGROUP_FILE_NAME_MAX (MAX_CGROUP_TYPE_NAMELEN + \
7171
MAX_CFTYPE_NAME + 2)
7272

73-
/*
74-
* cgroup_tree_mutex nests above cgroup_mutex and protects cftypes, file
75-
* creation/removal and hierarchy changing operations including cgroup
76-
* creation, removal, css association and controller rebinding. This outer
77-
* lock is needed mainly to resolve the circular dependency between kernfs
78-
* active ref and cgroup_mutex. cgroup_tree_mutex nests above both.
79-
*/
80-
static DEFINE_MUTEX(cgroup_tree_mutex);
81-
8273
/*
8374
* cgroup_mutex is the master lock. Any modification to cgroup or its
8475
* hierarchy must be performed while holding it.
@@ -111,11 +102,10 @@ static DEFINE_SPINLOCK(cgroup_idr_lock);
111102
*/
112103
static DEFINE_SPINLOCK(release_agent_path_lock);
113104

114-
#define cgroup_assert_mutexes_or_rcu_locked() \
105+
#define cgroup_assert_mutex_or_rcu_locked() \
115106
rcu_lockdep_assert(rcu_read_lock_held() || \
116-
lockdep_is_held(&cgroup_tree_mutex) || \
117107
lockdep_is_held(&cgroup_mutex), \
118-
"cgroup_[tree_]mutex or RCU read lock required");
108+
"cgroup_mutex or RCU read lock required");
119109

120110
/*
121111
* cgroup destruction makes heavy use of work items and there can be a lot
@@ -243,7 +233,6 @@ static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
243233
{
244234
if (ss)
245235
return rcu_dereference_check(cgrp->subsys[ss->id],
246-
lockdep_is_held(&cgroup_tree_mutex) ||
247236
lockdep_is_held(&cgroup_mutex));
248237
else
249238
return &cgrp->dummy_css;
@@ -347,7 +336,6 @@ static int notify_on_release(const struct cgroup *cgrp)
347336
for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \
348337
if (!((css) = rcu_dereference_check( \
349338
(cgrp)->subsys[(ssid)], \
350-
lockdep_is_held(&cgroup_tree_mutex) || \
351339
lockdep_is_held(&cgroup_mutex)))) { } \
352340
else
353341

@@ -381,7 +369,7 @@ static int notify_on_release(const struct cgroup *cgrp)
381369
/* iterate over child cgrps, lock should be held throughout iteration */
382370
#define cgroup_for_each_live_child(child, cgrp) \
383371
list_for_each_entry((child), &(cgrp)->children, sibling) \
384-
if (({ lockdep_assert_held(&cgroup_tree_mutex); \
372+
if (({ lockdep_assert_held(&cgroup_mutex); \
385373
cgroup_is_dead(child); })) \
386374
; \
387375
else
@@ -869,7 +857,6 @@ static void cgroup_destroy_root(struct cgroup_root *root)
869857
struct cgroup *cgrp = &root->cgrp;
870858
struct cgrp_cset_link *link, *tmp_link;
871859

872-
mutex_lock(&cgroup_tree_mutex);
873860
mutex_lock(&cgroup_mutex);
874861

875862
BUG_ON(atomic_read(&root->nr_cgrps));
@@ -899,7 +886,6 @@ static void cgroup_destroy_root(struct cgroup_root *root)
899886
cgroup_exit_root_id(root);
900887

901888
mutex_unlock(&cgroup_mutex);
902-
mutex_unlock(&cgroup_tree_mutex);
903889

904890
kernfs_destroy_root(root->kf_root);
905891
cgroup_free_root(root);
@@ -1096,7 +1082,6 @@ static void cgroup_kn_unlock(struct kernfs_node *kn)
10961082
cgrp = kn->parent->priv;
10971083

10981084
mutex_unlock(&cgroup_mutex);
1099-
mutex_unlock(&cgroup_tree_mutex);
11001085

11011086
kernfs_unbreak_active_protection(kn);
11021087
cgroup_put(cgrp);
@@ -1135,7 +1120,6 @@ static struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn)
11351120
cgroup_get(cgrp);
11361121
kernfs_break_active_protection(kn);
11371122

1138-
mutex_lock(&cgroup_tree_mutex);
11391123
mutex_lock(&cgroup_mutex);
11401124

11411125
if (!cgroup_is_dead(cgrp))
@@ -1149,7 +1133,6 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
11491133
{
11501134
char name[CGROUP_FILE_NAME_MAX];
11511135

1152-
lockdep_assert_held(&cgroup_tree_mutex);
11531136
lockdep_assert_held(&cgroup_mutex);
11541137
kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name));
11551138
}
@@ -1179,7 +1162,6 @@ static int rebind_subsystems(struct cgroup_root *dst_root, unsigned int ss_mask)
11791162
struct cgroup_subsys *ss;
11801163
int ssid, i, ret;
11811164

1182-
lockdep_assert_held(&cgroup_tree_mutex);
11831165
lockdep_assert_held(&cgroup_mutex);
11841166

11851167
for_each_subsys(ss, ssid) {
@@ -1457,7 +1439,6 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
14571439
return -EINVAL;
14581440
}
14591441

1460-
mutex_lock(&cgroup_tree_mutex);
14611442
mutex_lock(&cgroup_mutex);
14621443

14631444
/* See what subsystems are wanted */
@@ -1503,7 +1484,6 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
15031484
kfree(opts.release_agent);
15041485
kfree(opts.name);
15051486
mutex_unlock(&cgroup_mutex);
1506-
mutex_unlock(&cgroup_tree_mutex);
15071487
return ret;
15081488
}
15091489

@@ -1606,7 +1586,6 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned int ss_mask)
16061586
struct css_set *cset;
16071587
int i, ret;
16081588

1609-
lockdep_assert_held(&cgroup_tree_mutex);
16101589
lockdep_assert_held(&cgroup_mutex);
16111590

16121591
ret = cgroup_idr_alloc(&root->cgroup_idr, root_cgrp, 1, 2, GFP_NOWAIT);
@@ -1696,7 +1675,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
16961675
if (!use_task_css_set_links)
16971676
cgroup_enable_task_cg_lists();
16981677

1699-
mutex_lock(&cgroup_tree_mutex);
17001678
mutex_lock(&cgroup_mutex);
17011679

17021680
/* First find the desired set of subsystems */
@@ -1761,9 +1739,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
17611739
*/
17621740
if (!atomic_inc_not_zero(&root->cgrp.refcnt)) {
17631741
mutex_unlock(&cgroup_mutex);
1764-
mutex_unlock(&cgroup_tree_mutex);
17651742
msleep(10);
1766-
mutex_lock(&cgroup_tree_mutex);
17671743
mutex_lock(&cgroup_mutex);
17681744
goto retry;
17691745
}
@@ -1796,7 +1772,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
17961772

17971773
out_unlock:
17981774
mutex_unlock(&cgroup_mutex);
1799-
mutex_unlock(&cgroup_tree_mutex);
18001775

18011776
kfree(opts.release_agent);
18021777
kfree(opts.name);
@@ -2507,7 +2482,6 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
25072482
struct css_set *src_cset;
25082483
int ret;
25092484

2510-
lockdep_assert_held(&cgroup_tree_mutex);
25112485
lockdep_assert_held(&cgroup_mutex);
25122486

25132487
/* look up all csses currently attached to @cgrp's subtree */
@@ -2866,20 +2840,18 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent,
28662840
return -EPERM;
28672841

28682842
/*
2869-
* We're gonna grab cgroup_tree_mutex which nests outside kernfs
2843+
* We're gonna grab cgroup_mutex which nests outside kernfs
28702844
* active_ref. kernfs_rename() doesn't require active_ref
2871-
* protection. Break them before grabbing cgroup_tree_mutex.
2845+
* protection. Break them before grabbing cgroup_mutex.
28722846
*/
28732847
kernfs_break_active_protection(new_parent);
28742848
kernfs_break_active_protection(kn);
28752849

2876-
mutex_lock(&cgroup_tree_mutex);
28772850
mutex_lock(&cgroup_mutex);
28782851

28792852
ret = kernfs_rename(kn, new_parent, new_name_str);
28802853

28812854
mutex_unlock(&cgroup_mutex);
2882-
mutex_unlock(&cgroup_tree_mutex);
28832855

28842856
kernfs_unbreak_active_protection(kn);
28852857
kernfs_unbreak_active_protection(new_parent);
@@ -2944,7 +2916,6 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
29442916
struct cftype *cft;
29452917
int ret;
29462918

2947-
lockdep_assert_held(&cgroup_tree_mutex);
29482919
lockdep_assert_held(&cgroup_mutex);
29492920

29502921
for (cft = cfts; cft->name[0] != '\0'; cft++) {
@@ -2980,7 +2951,6 @@ static int cgroup_apply_cftypes(struct cftype *cfts, bool is_add)
29802951
struct cgroup_subsys_state *css;
29812952
int ret = 0;
29822953

2983-
lockdep_assert_held(&cgroup_tree_mutex);
29842954
lockdep_assert_held(&cgroup_mutex);
29852955

29862956
/* add/rm files for all cgroups created before */
@@ -3049,7 +3019,6 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
30493019

30503020
static int cgroup_rm_cftypes_locked(struct cftype *cfts)
30513021
{
3052-
lockdep_assert_held(&cgroup_tree_mutex);
30533022
lockdep_assert_held(&cgroup_mutex);
30543023

30553024
if (!cfts || !cfts[0].ss)
@@ -3076,11 +3045,9 @@ int cgroup_rm_cftypes(struct cftype *cfts)
30763045
{
30773046
int ret;
30783047

3079-
mutex_lock(&cgroup_tree_mutex);
30803048
mutex_lock(&cgroup_mutex);
30813049
ret = cgroup_rm_cftypes_locked(cfts);
30823050
mutex_unlock(&cgroup_mutex);
3083-
mutex_unlock(&cgroup_tree_mutex);
30843051
return ret;
30853052
}
30863053

@@ -3109,7 +3076,6 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
31093076
if (ret)
31103077
return ret;
31113078

3112-
mutex_lock(&cgroup_tree_mutex);
31133079
mutex_lock(&cgroup_mutex);
31143080

31153081
list_add_tail(&cfts->node, &ss->cfts);
@@ -3118,7 +3084,6 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
31183084
cgroup_rm_cftypes_locked(cfts);
31193085

31203086
mutex_unlock(&cgroup_mutex);
3121-
mutex_unlock(&cgroup_tree_mutex);
31223087
return ret;
31233088
}
31243089

@@ -3158,7 +3123,7 @@ css_next_child(struct cgroup_subsys_state *pos_css,
31583123
struct cgroup *cgrp = parent_css->cgroup;
31593124
struct cgroup *next;
31603125

3161-
cgroup_assert_mutexes_or_rcu_locked();
3126+
cgroup_assert_mutex_or_rcu_locked();
31623127

31633128
/*
31643129
* @pos could already have been removed. Once a cgroup is removed,
@@ -3224,7 +3189,7 @@ css_next_descendant_pre(struct cgroup_subsys_state *pos,
32243189
{
32253190
struct cgroup_subsys_state *next;
32263191

3227-
cgroup_assert_mutexes_or_rcu_locked();
3192+
cgroup_assert_mutex_or_rcu_locked();
32283193

32293194
/* if first iteration, visit @root */
32303195
if (!pos)
@@ -3264,7 +3229,7 @@ css_rightmost_descendant(struct cgroup_subsys_state *pos)
32643229
{
32653230
struct cgroup_subsys_state *last, *tmp;
32663231

3267-
cgroup_assert_mutexes_or_rcu_locked();
3232+
cgroup_assert_mutex_or_rcu_locked();
32683233

32693234
do {
32703235
last = pos;
@@ -3311,7 +3276,7 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
33113276
{
33123277
struct cgroup_subsys_state *next;
33133278

3314-
cgroup_assert_mutexes_or_rcu_locked();
3279+
cgroup_assert_mutex_or_rcu_locked();
33153280

33163281
/* if first iteration, visit leftmost descendant which may be @root */
33173282
if (!pos)
@@ -4178,7 +4143,6 @@ static int online_css(struct cgroup_subsys_state *css)
41784143
struct cgroup_subsys *ss = css->ss;
41794144
int ret = 0;
41804145

4181-
lockdep_assert_held(&cgroup_tree_mutex);
41824146
lockdep_assert_held(&cgroup_mutex);
41834147

41844148
if (ss->css_online)
@@ -4196,7 +4160,6 @@ static void offline_css(struct cgroup_subsys_state *css)
41964160
{
41974161
struct cgroup_subsys *ss = css->ss;
41984162

4199-
lockdep_assert_held(&cgroup_tree_mutex);
42004163
lockdep_assert_held(&cgroup_mutex);
42014164

42024165
if (!(css->flags & CSS_ONLINE))
@@ -4399,7 +4362,6 @@ static void css_killed_work_fn(struct work_struct *work)
43994362
container_of(work, struct cgroup_subsys_state, destroy_work);
44004363
struct cgroup *cgrp = css->cgroup;
44014364

4402-
mutex_lock(&cgroup_tree_mutex);
44034365
mutex_lock(&cgroup_mutex);
44044366

44054367
/*
@@ -4417,7 +4379,6 @@ static void css_killed_work_fn(struct work_struct *work)
44174379
cgroup_destroy_css_killed(cgrp);
44184380

44194381
mutex_unlock(&cgroup_mutex);
4420-
mutex_unlock(&cgroup_tree_mutex);
44214382

44224383
/*
44234384
* Put the css refs from kill_css(). Each css holds an extra
@@ -4450,7 +4411,6 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
44504411
*/
44514412
static void kill_css(struct cgroup_subsys_state *css)
44524413
{
4453-
lockdep_assert_held(&cgroup_tree_mutex);
44544414
lockdep_assert_held(&cgroup_mutex);
44554415

44564416
/*
@@ -4510,7 +4470,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
45104470
bool empty;
45114471
int ssid;
45124472

4513-
lockdep_assert_held(&cgroup_tree_mutex);
45144473
lockdep_assert_held(&cgroup_mutex);
45154474

45164475
/*
@@ -4593,7 +4552,6 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp)
45934552
{
45944553
struct cgroup *parent = cgrp->parent;
45954554

4596-
lockdep_assert_held(&cgroup_tree_mutex);
45974555
lockdep_assert_held(&cgroup_mutex);
45984556

45994557
/* delete this cgroup from parent->children */
@@ -4647,7 +4605,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
46474605

46484606
printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
46494607

4650-
mutex_lock(&cgroup_tree_mutex);
46514608
mutex_lock(&cgroup_mutex);
46524609

46534610
idr_init(&ss->css_idr);
@@ -4685,7 +4642,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
46854642
cgrp_dfl_root.subsys_mask |= 1 << ss->id;
46864643

46874644
mutex_unlock(&cgroup_mutex);
4688-
mutex_unlock(&cgroup_tree_mutex);
46894645
}
46904646

46914647
/**
@@ -4735,7 +4691,6 @@ int __init cgroup_init(void)
47354691

47364692
BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files));
47374693

4738-
mutex_lock(&cgroup_tree_mutex);
47394694
mutex_lock(&cgroup_mutex);
47404695

47414696
/* Add init_css_set to the hash table */
@@ -4745,7 +4700,6 @@ int __init cgroup_init(void)
47454700
BUG_ON(cgroup_setup_root(&cgrp_dfl_root, 0));
47464701

47474702
mutex_unlock(&cgroup_mutex);
4748-
mutex_unlock(&cgroup_tree_mutex);
47494703

47504704
for_each_subsys(ss, ssid) {
47514705
if (ss->early_init) {

0 commit comments

Comments
 (0)