Skip to content

Commit bff7dc9

Browse files
laoarmehmetb0
authored andcommitted
cgroup: Make operations on the cgroup root_list RCU safe
BugLink: https://bugs.launchpad.net/bugs/2086242 [ Upstream commit d23b5c5 ] At present, when we perform operations on the cgroup root_list, we must hold the cgroup_mutex, which is a relatively heavyweight lock. In reality, we can make operations on this list RCU-safe, eliminating the need to hold the cgroup_mutex during traversal. Modifications to the list only occur in the cgroup root setup and destroy paths, which should be infrequent in a production environment. In contrast, traversal may occur frequently. Therefore, making it RCU-safe would be beneficial. Signed-off-by: Yafang Shao <[email protected]> Signed-off-by: Tejun Heo <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Koichiro Den <[email protected]> Signed-off-by: Roxana Nicolescu <[email protected]>
1 parent 7e36985 commit bff7dc9

File tree

3 files changed

+10
-8
lines changed

3 files changed

+10
-8
lines changed

include/linux/cgroup-defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ struct cgroup_root {
516516

517517
/* A list running through the active hierarchies */
518518
struct list_head root_list;
519+
struct rcu_head rcu;
519520

520521
/* Hierarchy-specific flags */
521522
unsigned int flags;

kernel/cgroup/cgroup-internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ extern struct list_head cgroup_roots;
172172

173173
/* iterate across the hierarchies */
174174
#define for_each_root(root) \
175-
list_for_each_entry((root), &cgroup_roots, root_list)
175+
list_for_each_entry_rcu((root), &cgroup_roots, root_list, \
176+
lockdep_is_held(&cgroup_mutex))
176177

177178
/**
178179
* for_each_subsys - iterate all enabled cgroup subsystems

kernel/cgroup/cgroup.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,7 @@ static void cgroup_exit_root_id(struct cgroup_root *root)
13321332

13331333
void cgroup_free_root(struct cgroup_root *root)
13341334
{
1335-
kfree(root);
1335+
kfree_rcu(root, rcu);
13361336
}
13371337

13381338
static void cgroup_destroy_root(struct cgroup_root *root)
@@ -1365,7 +1365,7 @@ static void cgroup_destroy_root(struct cgroup_root *root)
13651365
spin_unlock_irq(&css_set_lock);
13661366

13671367
if (!list_empty(&root->root_list)) {
1368-
list_del(&root->root_list);
1368+
list_del_rcu(&root->root_list);
13691369
cgroup_root_count--;
13701370
}
13711371

@@ -1411,7 +1411,6 @@ current_cgns_cgroup_from_root(struct cgroup_root *root)
14111411
}
14121412
rcu_read_unlock();
14131413

1414-
BUG_ON(!res);
14151414
return res;
14161415
}
14171416

@@ -1421,7 +1420,6 @@ static struct cgroup *cset_cgroup_from_root(struct css_set *cset,
14211420
{
14221421
struct cgroup *res = NULL;
14231422

1424-
lockdep_assert_held(&cgroup_mutex);
14251423
lockdep_assert_held(&css_set_lock);
14261424

14271425
if (cset == &init_css_set) {
@@ -1447,7 +1445,9 @@ static struct cgroup *cset_cgroup_from_root(struct css_set *cset,
14471445

14481446
/*
14491447
* Return the cgroup for "task" from the given hierarchy. Must be
1450-
* called with cgroup_mutex and css_set_lock held.
1448+
* called with css_set_lock held to prevent task's groups from being modified.
1449+
* Must be called with either cgroup_mutex or rcu read lock to prevent the
1450+
* cgroup root from being destroyed.
14511451
*/
14521452
struct cgroup *task_cgroup_from_root(struct task_struct *task,
14531453
struct cgroup_root *root)
@@ -1986,7 +1986,7 @@ void init_cgroup_root(struct cgroup_fs_context *ctx)
19861986
struct cgroup_root *root = ctx->root;
19871987
struct cgroup *cgrp = &root->cgrp;
19881988

1989-
INIT_LIST_HEAD(&root->root_list);
1989+
INIT_LIST_HEAD_RCU(&root->root_list);
19901990
atomic_set(&root->nr_cgrps, 1);
19911991
cgrp->root = root;
19921992
init_cgroup_housekeeping(cgrp);
@@ -2068,7 +2068,7 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
20682068
* care of subsystems' refcounts, which are explicitly dropped in
20692069
* the failure exit path.
20702070
*/
2071-
list_add(&root->root_list, &cgroup_roots);
2071+
list_add_rcu(&root->root_list, &cgroup_roots);
20722072
cgroup_root_count++;
20732073

20742074
/*

0 commit comments

Comments
 (0)