From: Tejun Heo <tj@kernel.org>
To: Calvin Owens <calvin@wbinvd.org>
Cc: linux-kernel@vger.kernel.org,
Dan Schatzberg <dschatzberg@meta.com>,
Peter Zijlstra <peterz@infradead.org>,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Koutný <mkoutny@suse.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Clark Williams <clrkwllms@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
cgroups@vger.kernel.org, linux-rt-devel@lists.linux.dev
Subject: [PATCH cgroup/for-6.19 2/2] cgroup: Convert css_set_lock locking to use cleanup guards
Date: Tue, 04 Nov 2025 09:32:30 -1000 [thread overview]
Message-ID: <0f56e00692656d09e4b88e2f502ee50f@kernel.org> (raw)
In-Reply-To: <20251104181114.489391-1-calvin@wbinvd.org>
Convert most css_set_lock critical sections to use cleanup guards (guard(),
scoped_guard()) for automatic lock management. This reduces the amount of
manual lock/unlock pairing and eliminates several 'unsigned long flags'
variables.
cgroup_css_links_read() in debug.c is left unconverted as it would require
excessive indentation.
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/cgroup/freezer.c | 38 +-
kernel/cgroup/namespace.c | 8
6 files changed, 302 insertions(+), 346 deletions(-)
--- a/kernel/cgroup/cgroup-internal.h
+++ b/kernel/cgroup/cgroup-internal.h
@@ -198,8 +198,6 @@ void put_css_set_locked(struct css_set *
static inline void put_css_set(struct css_set *cset)
{
- unsigned long flags;
-
/*
* Ensure that the refcount doesn't hit zero while any readers
* can see it. Similar to atomic_dec_and_lock(), but for an
@@ -208,9 +206,9 @@ static inline void put_css_set(struct cs
if (refcount_dec_not_one(&cset->refcount))
return;
- raw_spin_lock_irqsave(&css_set_lock, flags);
+ guard(raw_spinlock_irqsave)(&css_set_lock);
+
put_css_set_locked(cset);
- raw_spin_unlock_irqrestore(&css_set_lock, flags);
}
/*
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -73,9 +73,8 @@ int cgroup_attach_task_all(struct task_s
for_each_root(root) {
struct cgroup *from_cgrp;
- raw_spin_lock_irq(&css_set_lock);
- from_cgrp = task_cgroup_from_root(from, root);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock)
+ from_cgrp = task_cgroup_from_root(from, root);
retval = cgroup_attach_task(from_cgrp, tsk, false);
if (retval)
@@ -121,10 +120,10 @@ int cgroup_transfer_tasks(struct cgroup
cgroup_attach_lock(CGRP_ATTACH_LOCK_GLOBAL, NULL);
/* all tasks in @from are being moved, all csets are source */
- raw_spin_lock_irq(&css_set_lock);
- list_for_each_entry(link, &from->cset_links, cset_link)
- cgroup_migrate_add_src(link->cset, to, &mgctx);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_for_each_entry(link, &from->cset_links, cset_link)
+ cgroup_migrate_add_src(link->cset, to, &mgctx);
+ }
ret = cgroup_migrate_prepare_dst(&mgctx);
if (ret)
@@ -1299,7 +1298,6 @@ struct cgroup *task_get_cgroup1(struct t
{
struct cgroup *cgrp = ERR_PTR(-ENOENT);
struct cgroup_root *root;
- unsigned long flags;
rcu_read_lock();
for_each_root(root) {
@@ -1308,11 +1306,11 @@ struct cgroup *task_get_cgroup1(struct t
continue;
if (root->hierarchy_id != hierarchy_id)
continue;
- raw_spin_lock_irqsave(&css_set_lock, flags);
- cgrp = task_cgroup_from_root(tsk, root);
- if (!cgrp || !cgroup_tryget(cgrp))
- cgrp = ERR_PTR(-ENOENT);
- raw_spin_unlock_irqrestore(&css_set_lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &css_set_lock) {
+ cgrp = task_cgroup_from_root(tsk, root);
+ if (!cgrp || !cgroup_tryget(cgrp))
+ cgrp = ERR_PTR(-ENOENT);
+ }
break;
}
rcu_read_unlock();
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -666,13 +666,9 @@ int __cgroup_task_count(const struct cgr
*/
int cgroup_task_count(const struct cgroup *cgrp)
{
- int count;
+ guard(raw_spinlock_irq)(&css_set_lock);
- raw_spin_lock_irq(&css_set_lock);
- count = __cgroup_task_count(cgrp);
- raw_spin_unlock_irq(&css_set_lock);
-
- return count;
+ return __cgroup_task_count(cgrp);
}
static struct cgroup *kn_priv(struct kernfs_node *kn)
@@ -1238,11 +1234,11 @@ static struct css_set *find_css_set(stru
/* First see if we already have a cgroup group that matches
* the desired set */
- raw_spin_lock_irq(&css_set_lock);
- cset = find_existing_css_set(old_cset, cgrp, template);
- if (cset)
- get_css_set(cset);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ cset = find_existing_css_set(old_cset, cgrp, template);
+ if (cset)
+ get_css_set(cset);
+ }
if (cset)
return cset;
@@ -1274,34 +1270,33 @@ static struct css_set *find_css_set(stru
* find_existing_css_set() */
memcpy(cset->subsys, template, sizeof(cset->subsys));
- raw_spin_lock_irq(&css_set_lock);
- /* Add reference counts and links from the new css_set. */
- list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) {
- struct cgroup *c = link->cgrp;
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ /* Add reference counts and links from the new css_set. */
+ list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) {
+ struct cgroup *c = link->cgrp;
- if (c->root == cgrp->root)
- c = cgrp;
- link_css_set(&tmp_links, cset, c);
- }
+ if (c->root == cgrp->root)
+ c = cgrp;
+ link_css_set(&tmp_links, cset, c);
+ }
- BUG_ON(!list_empty(&tmp_links));
+ BUG_ON(!list_empty(&tmp_links));
- css_set_count++;
+ css_set_count++;
- /* Add @cset to the hash table */
- key = css_set_hash(cset->subsys);
- hash_add(css_set_table, &cset->hlist, key);
+ /* Add @cset to the hash table */
+ key = css_set_hash(cset->subsys);
+ hash_add(css_set_table, &cset->hlist, key);
- for_each_subsys(ss, ssid) {
- struct cgroup_subsys_state *css = cset->subsys[ssid];
+ for_each_subsys(ss, ssid) {
+ struct cgroup_subsys_state *css = cset->subsys[ssid];
- list_add_tail(&cset->e_cset_node[ssid],
- &css->cgroup->e_csets[ssid]);
- css_get(css);
+ list_add_tail(&cset->e_cset_node[ssid],
+ &css->cgroup->e_csets[ssid]);
+ css_get(css);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
-
/*
* If @cset should be threaded, look up the matching dom_cset and
* link them up. We first fully initialize @cset then look for the
@@ -1317,11 +1312,11 @@ static struct css_set *find_css_set(stru
return NULL;
}
- raw_spin_lock_irq(&css_set_lock);
- cset->dom_cset = dcset;
- list_add_tail(&cset->threaded_csets_node,
- &dcset->threaded_csets);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ cset->dom_cset = dcset;
+ list_add_tail(&cset->threaded_csets_node,
+ &dcset->threaded_csets);
+ }
}
return cset;
@@ -1414,16 +1409,14 @@ static void cgroup_destroy_root(struct c
* Release all the links from cset_links to this hierarchy's
* root cgroup
*/
- raw_spin_lock_irq(&css_set_lock);
-
- list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
- list_del(&link->cset_link);
- list_del(&link->cgrp_link);
- kfree(link);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
+ list_del(&link->cset_link);
+ list_del(&link->cgrp_link);
+ kfree(link);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
-
WARN_ON_ONCE(list_empty(&root->root_list));
list_del_rcu(&root->root_list);
cgroup_root_count--;
@@ -1919,25 +1912,27 @@ int rebind_subsystems(struct cgroup_root
rcu_assign_pointer(dcgrp->subsys[ssid], css);
ss->root = dst_root;
- raw_spin_lock_irq(&css_set_lock);
- css->cgroup = dcgrp;
- WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
- list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
- e_cset_node[ss->id]) {
- list_move_tail(&cset->e_cset_node[ss->id],
- &dcgrp->e_csets[ss->id]);
- /*
- * all css_sets of scgrp together in same order to dcgrp,
- * patch in-flight iterators to preserve correct iteration.
- * since the iterator is always advanced right away and
- * finished when it->cset_pos meets it->cset_head, so only
- * update it->cset_head is enough here.
- */
- list_for_each_entry(it, &cset->task_iters, iters_node)
- if (it->cset_head == &scgrp->e_csets[ss->id])
- it->cset_head = &dcgrp->e_csets[ss->id];
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ css->cgroup = dcgrp;
+ WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
+ list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
+ e_cset_node[ss->id]) {
+ list_move_tail(&cset->e_cset_node[ss->id],
+ &dcgrp->e_csets[ss->id]);
+ /*
+ * all css_sets of scgrp together in same order
+ * to dcgrp, patch in-flight iterators to
+ * preserve correct iteration. since the
+ * iterator is always advanced right away and
+ * finished when it->cset_pos meets
+ * it->cset_head, so only update it->cset_head
+ * is enough here.
+ */
+ list_for_each_entry(it, &cset->task_iters, iters_node)
+ if (it->cset_head == &scgrp->e_csets[ss->id])
+ it->cset_head = &dcgrp->e_csets[ss->id];
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
/* default hierarchy doesn't enable controllers by default */
dst_root->subsys_mask |= 1 << ssid;
@@ -1973,10 +1968,10 @@ int cgroup_show_path(struct seq_file *sf
if (!buf)
return -ENOMEM;
- raw_spin_lock_irq(&css_set_lock);
- ns_cgroup = current_cgns_cgroup_from_root(kf_cgroot);
- len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ ns_cgroup = current_cgns_cgroup_from_root(kf_cgroot);
+ len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
+ }
if (len == -E2BIG)
len = -ERANGE;
@@ -2232,13 +2227,13 @@ int cgroup_setup_root(struct cgroup_root
* Link the root cgroup in this hierarchy into all the css_set
* objects.
*/
- raw_spin_lock_irq(&css_set_lock);
- hash_for_each(css_set_table, i, cset, hlist) {
- link_css_set(&tmp_links, cset, root_cgrp);
- if (css_set_populated(cset))
- cgroup_update_populated(root_cgrp, true);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ hash_for_each(css_set_table, i, cset, hlist) {
+ link_css_set(&tmp_links, cset, root_cgrp);
+ if (css_set_populated(cset))
+ cgroup_update_populated(root_cgrp, true);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
BUG_ON(!list_empty(&root_cgrp->self.children));
BUG_ON(atomic_read(&root->nr_cgrps) != 1);
@@ -2282,11 +2277,8 @@ int cgroup_do_get_tree(struct fs_context
struct cgroup *cgrp;
cgroup_lock();
- raw_spin_lock_irq(&css_set_lock);
-
- cgrp = cset_cgroup_from_root(ctx->ns->root_cset, ctx->root);
-
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock)
+ cgrp = cset_cgroup_from_root(ctx->ns->root_cset, ctx->root);
cgroup_unlock();
nsdentry = kernfs_node_dentry(cgrp->kn, sb);
@@ -2498,11 +2490,8 @@ int cgroup_path_ns(struct cgroup *cgrp,
int ret;
cgroup_lock();
- raw_spin_lock_irq(&css_set_lock);
-
- ret = cgroup_path_ns_locked(cgrp, buf, buflen, ns);
-
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock)
+ ret = cgroup_path_ns_locked(cgrp, buf, buflen, ns);
cgroup_unlock();
return ret;
@@ -2721,27 +2710,27 @@ static int cgroup_migrate_execute(struct
* the new cgroup. There are no failure cases after here, so this
* is the commit point.
*/
- raw_spin_lock_irq(&css_set_lock);
- list_for_each_entry(cset, &tset->src_csets, mg_node) {
- list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list) {
- struct css_set *from_cset = task_css_set(task);
- struct css_set *to_cset = cset->mg_dst_cset;
-
- get_css_set(to_cset);
- to_cset->nr_tasks++;
- css_set_move_task(task, from_cset, to_cset, true);
- from_cset->nr_tasks--;
- /*
- * If the source or destination cgroup is frozen,
- * the task might require to change its state.
- */
- cgroup_freezer_migrate_task(task, from_cset->dfl_cgrp,
- to_cset->dfl_cgrp);
- put_css_set_locked(from_cset);
-
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_for_each_entry(cset, &tset->src_csets, mg_node) {
+ list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list) {
+ struct css_set *from_cset = task_css_set(task);
+ struct css_set *to_cset = cset->mg_dst_cset;
+
+ get_css_set(to_cset);
+ to_cset->nr_tasks++;
+ css_set_move_task(task, from_cset, to_cset, true);
+ from_cset->nr_tasks--;
+ /*
+ * If the source or destination cgroup is
+ * frozen, the task might require to change its
+ * state.
+ */
+ cgroup_freezer_migrate_task(task, from_cset->dfl_cgrp,
+ to_cset->dfl_cgrp);
+ put_css_set_locked(from_cset);
+ }
}
}
- raw_spin_unlock_irq(&css_set_lock);
/*
* Migration is committed, all target tasks are now on dst_csets.
@@ -2774,13 +2763,13 @@ out_cancel_attach:
} while_each_subsys_mask();
}
out_release_tset:
- raw_spin_lock_irq(&css_set_lock);
- list_splice_init(&tset->dst_csets, &tset->src_csets);
- list_for_each_entry_safe(cset, tmp_cset, &tset->src_csets, mg_node) {
- list_splice_tail_init(&cset->mg_tasks, &cset->tasks);
- list_del_init(&cset->mg_node);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_splice_init(&tset->dst_csets, &tset->src_csets);
+ list_for_each_entry_safe(cset, tmp_cset, &tset->src_csets, mg_node) {
+ list_splice_tail_init(&cset->mg_tasks, &cset->tasks);
+ list_del_init(&cset->mg_node);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
/*
* Re-initialize the cgroup_taskset structure in case it is reused
@@ -2838,7 +2827,7 @@ void cgroup_migrate_finish(struct cgroup
lockdep_assert_held(&cgroup_mutex);
- raw_spin_lock_irq(&css_set_lock);
+ guard(raw_spinlock_irq)(&css_set_lock);
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
mg_src_preload_node) {
@@ -2857,8 +2846,6 @@ void cgroup_migrate_finish(struct cgroup
list_del_init(&cset->mg_dst_preload_node);
put_css_set_locked(cset);
}
-
- raw_spin_unlock_irq(&css_set_lock);
}
/**
@@ -2994,21 +2981,19 @@ int cgroup_migrate_prepare_dst(struct cg
int cgroup_migrate(struct task_struct *leader, bool threadgroup,
struct cgroup_mgctx *mgctx)
{
- struct task_struct *task;
-
/*
* The following thread iteration should be inside an RCU critical
* section to prevent tasks from being freed while taking the snapshot.
* spin_lock_irq() implies RCU critical section here.
*/
- raw_spin_lock_irq(&css_set_lock);
- task = leader;
- do {
- cgroup_migrate_add_task(task, mgctx);
- if (!threadgroup)
- break;
- } while_each_thread(leader, task);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ struct task_struct *task = leader;
+ do {
+ cgroup_migrate_add_task(task, mgctx);
+ if (!threadgroup)
+ break;
+ } while_each_thread(leader, task);
+ }
return cgroup_migrate_execute(mgctx);
}
@@ -3025,18 +3010,17 @@ int cgroup_attach_task(struct cgroup *ds
bool threadgroup)
{
DEFINE_CGROUP_MGCTX(mgctx);
- struct task_struct *task;
int ret = 0;
/* look up all src csets */
- raw_spin_lock_irq(&css_set_lock);
- task = leader;
- do {
- cgroup_migrate_add_src(task_css_set(task), dst_cgrp, &mgctx);
- if (!threadgroup)
- break;
- } while_each_thread(leader, task);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ struct task_struct *task = leader;
+ do {
+ cgroup_migrate_add_src(task_css_set(task), dst_cgrp, &mgctx);
+ if (!threadgroup)
+ break;
+ } while_each_thread(leader, task);
+ }
/* prepare dst csets and commit */
ret = cgroup_migrate_prepare_dst(&mgctx);
@@ -3193,23 +3177,23 @@ static int cgroup_update_dfl_csses(struc
lockdep_assert_held(&cgroup_mutex);
/* look up all csses currently attached to @cgrp's subtree */
- raw_spin_lock_irq(&css_set_lock);
- cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) {
- struct cgrp_cset_link *link;
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) {
+ struct cgrp_cset_link *link;
- /*
- * As cgroup_update_dfl_csses() is only called by
- * cgroup_apply_control(). The csses associated with the
- * given cgrp will not be affected by changes made to
- * its subtree_control file. We can skip them.
- */
- if (dsct == cgrp)
- continue;
+ /*
+ * As cgroup_update_dfl_csses() is only called by
+ * cgroup_apply_control(). The csses associated with the
+ * given cgrp will not be affected by changes made to
+ * its subtree_control file. We can skip them.
+ */
+ if (dsct == cgrp)
+ continue;
- list_for_each_entry(link, &dsct->cset_links, cset_link)
- cgroup_migrate_add_src(link->cset, dsct, &mgctx);
+ list_for_each_entry(link, &dsct->cset_links, cset_link)
+ cgroup_migrate_add_src(link->cset, dsct, &mgctx);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
/*
* We need to write-lock threadgroup_rwsem while migrating tasks.
@@ -3231,16 +3215,16 @@ static int cgroup_update_dfl_csses(struc
if (ret)
goto out_finish;
- raw_spin_lock_irq(&css_set_lock);
- list_for_each_entry(src_cset, &mgctx.preloaded_src_csets,
- mg_src_preload_node) {
- struct task_struct *task, *ntask;
-
- /* all tasks in src_csets need to be migrated */
- list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
- cgroup_migrate_add_task(task, &mgctx);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_for_each_entry(src_cset, &mgctx.preloaded_src_csets,
+ mg_src_preload_node) {
+ struct task_struct *task, *ntask;
+
+ /* all tasks in src_csets need to be migrated */
+ list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
+ cgroup_migrate_add_task(task, &mgctx);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
ret = cgroup_migrate_execute(&mgctx);
out_finish:
@@ -4188,9 +4172,8 @@ static void __cgroup_kill(struct cgroup
lockdep_assert_held(&cgroup_mutex);
- raw_spin_lock_irq(&css_set_lock);
- cgrp->kill_seq++;
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock)
+ cgrp->kill_seq++;
css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED, &it);
while ((task = css_task_iter_next(&it))) {
@@ -5144,11 +5127,9 @@ repeat:
void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
struct css_task_iter *it)
{
- unsigned long irqflags;
-
memset(it, 0, sizeof(*it));
- raw_spin_lock_irqsave(&css_set_lock, irqflags);
+ guard(raw_spinlock_irqsave)(&css_set_lock);
it->ss = css->ss;
it->flags = flags;
@@ -5161,8 +5142,6 @@ void css_task_iter_start(struct cgroup_s
it->cset_head = it->cset_pos;
css_task_iter_advance(it);
-
- raw_spin_unlock_irqrestore(&css_set_lock, irqflags);
}
/**
@@ -5175,14 +5154,12 @@ void css_task_iter_start(struct cgroup_s
*/
struct task_struct *css_task_iter_next(struct css_task_iter *it)
{
- unsigned long irqflags;
-
if (it->cur_task) {
put_task_struct(it->cur_task);
it->cur_task = NULL;
}
- raw_spin_lock_irqsave(&css_set_lock, irqflags);
+ guard(raw_spinlock_irqsave)(&css_set_lock);
/* @it may be half-advanced by skips, finish advancing */
if (it->flags & CSS_TASK_ITER_SKIPPED)
@@ -5195,8 +5172,6 @@ struct task_struct *css_task_iter_next(s
css_task_iter_advance(it);
}
- raw_spin_unlock_irqrestore(&css_set_lock, irqflags);
-
return it->cur_task;
}
@@ -5208,13 +5183,11 @@ struct task_struct *css_task_iter_next(s
*/
void css_task_iter_end(struct css_task_iter *it)
{
- unsigned long irqflags;
-
if (it->cur_cset) {
- raw_spin_lock_irqsave(&css_set_lock, irqflags);
- list_del(&it->iters_node);
- put_css_set_locked(it->cur_cset);
- raw_spin_unlock_irqrestore(&css_set_lock, irqflags);
+ scoped_guard (raw_spinlock_irqsave, &css_set_lock) {
+ list_del(&it->iters_node);
+ put_css_set_locked(it->cur_cset);
+ }
}
if (it->cur_dcset)
@@ -5380,9 +5353,8 @@ static ssize_t __cgroup_procs_write(stru
goto out_unlock;
/* find the source cgroup */
- raw_spin_lock_irq(&css_set_lock);
- src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock)
+ src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
/*
* Process and thread migrations follow same delegation rule. Check
@@ -5669,11 +5641,11 @@ static void css_release_work_fn(struct w
css_rstat_flush(&cgrp->self);
- raw_spin_lock_irq(&css_set_lock);
- for (tcgrp = cgroup_parent(cgrp); tcgrp;
- tcgrp = cgroup_parent(tcgrp))
- tcgrp->nr_dying_descendants--;
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ for (tcgrp = cgroup_parent(cgrp); tcgrp;
+ tcgrp = cgroup_parent(tcgrp))
+ tcgrp->nr_dying_descendants--;
+ }
/*
* There are two control paths which try to determine
@@ -5924,20 +5896,20 @@ static struct cgroup *cgroup_create(stru
goto out_psi_free;
/* allocation complete, commit to creation */
- raw_spin_lock_irq(&css_set_lock);
- for (i = 0; i < level; i++) {
- tcgrp = cgrp->ancestors[i];
- tcgrp->nr_descendants++;
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ for (i = 0; i < level; i++) {
+ tcgrp = cgrp->ancestors[i];
+ tcgrp->nr_descendants++;
- /*
- * If the new cgroup is frozen, all ancestor cgroups get a new
- * frozen descendant, but their state can't change because of
- * this.
- */
- if (cgrp->freezer.e_freeze)
- tcgrp->freezer.nr_frozen_descendants++;
+ /*
+ * If the new cgroup is frozen, all ancestor cgroups get
+ * a new frozen descendant, but their state can't change
+ * because of this.
+ */
+ if (cgrp->freezer.e_freeze)
+ tcgrp->freezer.nr_frozen_descendants++;
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
list_add_tail_rcu(&cgrp->self.sibling, &cgroup_parent(cgrp)->self.children);
atomic_inc(&root->nr_cgrps);
@@ -6183,10 +6155,10 @@ static int cgroup_destroy_locked(struct
*/
cgrp->self.flags &= ~CSS_ONLINE;
- raw_spin_lock_irq(&css_set_lock);
- list_for_each_entry(link, &cgrp->cset_links, cset_link)
- link->cset->dead = true;
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ list_for_each_entry(link, &cgrp->cset_links, cset_link)
+ link->cset->dead = true;
+ }
/* initiate massacre of all css's */
for_each_css(css, ssid, cgrp)
@@ -6199,18 +6171,18 @@ static int cgroup_destroy_locked(struct
if (cgroup_is_threaded(cgrp))
parent->nr_threaded_children--;
- raw_spin_lock_irq(&css_set_lock);
- for (tcgrp = parent; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
- tcgrp->nr_descendants--;
- tcgrp->nr_dying_descendants++;
- /*
- * If the dying cgroup is frozen, decrease frozen descendants
- * counters of ancestor cgroups.
- */
- if (test_bit(CGRP_FROZEN, &cgrp->flags))
- tcgrp->freezer.nr_frozen_descendants--;
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ for (tcgrp = parent; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
+ tcgrp->nr_descendants--;
+ tcgrp->nr_dying_descendants++;
+ /*
+ * If the dying cgroup is frozen, decrease frozen
+ * descendants counters of ancestor cgroups.
+ */
+ if (test_bit(CGRP_FROZEN, &cgrp->flags))
+ tcgrp->freezer.nr_frozen_descendants--;
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
cgroup1_check_for_release(parent);
@@ -6549,17 +6521,14 @@ EXPORT_SYMBOL_GPL(cgroup_get_from_id);
int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *tsk)
{
- char *buf;
- int retval;
struct cgroup_root *root;
- retval = -ENOMEM;
- buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ char *buf __free(kfree) = kmalloc(PATH_MAX, GFP_KERNEL);
if (!buf)
- goto out;
+ return -ENOMEM;
- rcu_read_lock();
- raw_spin_lock_irq(&css_set_lock);
+ guard(rcu)();
+ guard(raw_spinlock_irq)(&css_set_lock);
for_each_root(root) {
struct cgroup_subsys *ss;
@@ -6594,12 +6563,12 @@ int proc_cgroup_show(struct seq_file *m,
* " (deleted)" is appended to the cgroup path.
*/
if (cgroup_on_dfl(cgrp) || !(tsk->flags & PF_EXITING)) {
- retval = cgroup_path_ns_locked(cgrp, buf, PATH_MAX,
- current->nsproxy->cgroup_ns);
+ int retval = cgroup_path_ns_locked(cgrp, buf, PATH_MAX,
+ current->nsproxy->cgroup_ns);
if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
- goto out_unlock;
+ return retval;
seq_puts(m, buf);
} else {
@@ -6612,13 +6581,7 @@ int proc_cgroup_show(struct seq_file *m,
seq_putc(m, '\n');
}
- retval = 0;
-out_unlock:
- raw_spin_unlock_irq(&css_set_lock);
- rcu_read_unlock();
- kfree(buf);
-out:
- return retval;
+ return 0;
}
/**
@@ -6702,14 +6665,14 @@ static int cgroup_css_set_fork(struct ke
cgroup_threadgroup_change_begin(current);
- raw_spin_lock_irq(&css_set_lock);
- cset = task_css_set(current);
- get_css_set(cset);
- if (kargs->cgrp)
- kargs->kill_seq = kargs->cgrp->kill_seq;
- else
- kargs->kill_seq = cset->dfl_cgrp->kill_seq;
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard(raw_spinlock_irq, &css_set_lock) {
+ cset = task_css_set(current);
+ get_css_set(cset);
+ if (kargs->cgrp)
+ kargs->kill_seq = kargs->cgrp->kill_seq;
+ else
+ kargs->kill_seq = cset->dfl_cgrp->kill_seq;
+ }
if (!(kargs->flags & CLONE_INTO_CGROUP)) {
kargs->cset = cset;
@@ -6899,56 +6862,56 @@ void cgroup_post_fork(struct task_struct
cset = kargs->cset;
kargs->cset = NULL;
- raw_spin_lock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ /* init tasks are special, only link regular threads */
+ if (likely(child->pid)) {
+ if (kargs->cgrp) {
+ cgrp_flags = kargs->cgrp->flags;
+ cgrp_kill_seq = kargs->cgrp->kill_seq;
+ } else {
+ cgrp_flags = cset->dfl_cgrp->flags;
+ cgrp_kill_seq = cset->dfl_cgrp->kill_seq;
+ }
- /* init tasks are special, only link regular threads */
- if (likely(child->pid)) {
- if (kargs->cgrp) {
- cgrp_flags = kargs->cgrp->flags;
- cgrp_kill_seq = kargs->cgrp->kill_seq;
+ WARN_ON_ONCE(!list_empty(&child->cg_list));
+ cset->nr_tasks++;
+ css_set_move_task(child, NULL, cset, false);
} else {
- cgrp_flags = cset->dfl_cgrp->flags;
- cgrp_kill_seq = cset->dfl_cgrp->kill_seq;
+ put_css_set(cset);
+ cset = NULL;
}
- WARN_ON_ONCE(!list_empty(&child->cg_list));
- cset->nr_tasks++;
- css_set_move_task(child, NULL, cset, false);
- } else {
- put_css_set(cset);
- cset = NULL;
- }
-
- if (!(child->flags & PF_KTHREAD)) {
- if (unlikely(test_bit(CGRP_FREEZE, &cgrp_flags))) {
- /*
- * If the cgroup has to be frozen, the new task has
- * too. Let's set the JOBCTL_TRAP_FREEZE jobctl bit to
- * get the task into the frozen state.
- */
- spin_lock(&child->sighand->siglock);
- WARN_ON_ONCE(child->frozen);
- child->jobctl |= JOBCTL_TRAP_FREEZE;
- spin_unlock(&child->sighand->siglock);
+ if (!(child->flags & PF_KTHREAD)) {
+ if (unlikely(test_bit(CGRP_FREEZE, &cgrp_flags))) {
+ /*
+ * If the cgroup has to be frozen, the new task
+ * has too. Let's set the JOBCTL_TRAP_FREEZE
+ * jobctl bit to get the task into the frozen
+ * state.
+ */
+ spin_lock(&child->sighand->siglock);
+ WARN_ON_ONCE(child->frozen);
+ child->jobctl |= JOBCTL_TRAP_FREEZE;
+ spin_unlock(&child->sighand->siglock);
+
+ /*
+ * Calling cgroup_update_frozen() isn't required
+ * here, because it will be called anyway a bit
+ * later from do_freezer_trap(). So we avoid
+ * cgroup's transient switch from the frozen
+ * state and back.
+ */
+ }
/*
- * Calling cgroup_update_frozen() isn't required here,
- * because it will be called anyway a bit later from
- * do_freezer_trap(). So we avoid cgroup's transient
- * switch from the frozen state and back.
+ * If the cgroup is to be killed notice it now and take
+ * the child down right after we finished preparing it
+ * for userspace.
*/
+ kill = kargs->kill_seq != cgrp_kill_seq;
}
-
- /*
- * If the cgroup is to be killed notice it now and take the
- * child down right after we finished preparing it for
- * userspace.
- */
- kill = kargs->kill_seq != cgrp_kill_seq;
}
- raw_spin_unlock_irq(&css_set_lock);
-
/*
* Call ss->fork(). This must happen after @child is linked on
* css_set; otherwise, @child might change state between ->fork()
@@ -6995,9 +6958,8 @@ void cgroup_task_exit(struct task_struct
void cgroup_task_dead(struct task_struct *tsk)
{
struct css_set *cset;
- unsigned long flags;
- raw_spin_lock_irqsave(&css_set_lock, flags);
+ guard(raw_spinlock_irqsave)(&css_set_lock);
WARN_ON_ONCE(list_empty(&tsk->cg_list));
cset = task_css_set(tsk);
@@ -7014,8 +6976,6 @@ void cgroup_task_dead(struct task_struct
if (unlikely(!(tsk->flags & PF_KTHREAD) &&
test_bit(CGRP_FREEZE, &task_dfl_cgroup(tsk)->flags)))
cgroup_update_frozen(task_dfl_cgroup(tsk));
-
- raw_spin_unlock_irqrestore(&css_set_lock, flags);
}
void cgroup_task_release(struct task_struct *task)
@@ -7033,10 +6993,10 @@ void cgroup_task_free(struct task_struct
struct css_set *cset = task_css_set(task);
if (!list_empty(&task->cg_list)) {
- raw_spin_lock_irq(&css_set_lock);
- css_set_skip_task_iters(task_css_set(task), task);
- list_del_init(&task->cg_list);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ css_set_skip_task_iters(task_css_set(task), task);
+ list_del_init(&task->cg_list);
+ }
}
put_css_set(cset);
--- a/kernel/cgroup/debug.c
+++ b/kernel/cgroup/debug.c
@@ -40,33 +40,34 @@ static u64 debug_taskcount_read(struct c
static int current_css_set_read(struct seq_file *seq, void *v)
{
struct kernfs_open_file *of = seq->private;
- struct css_set *cset;
- struct cgroup_subsys *ss;
- struct cgroup_subsys_state *css;
- int i, refcnt;
if (!cgroup_kn_lock_live(of->kn, false))
return -ENODEV;
- raw_spin_lock_irq(&css_set_lock);
- cset = task_css_set(current);
- refcnt = refcount_read(&cset->refcount);
- seq_printf(seq, "css_set %pK %d", cset, refcnt);
- if (refcnt > cset->nr_tasks)
- seq_printf(seq, " +%d", refcnt - cset->nr_tasks);
- seq_puts(seq, "\n");
-
- /*
- * Print the css'es stored in the current css_set.
- */
- for_each_subsys(ss, i) {
- css = cset->subsys[ss->id];
- if (!css)
- continue;
- seq_printf(seq, "%2d: %-4s\t- %p[%d]\n", ss->id, ss->name,
- css, css->id);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ struct css_set *cset = task_css_set(current);
+ struct cgroup_subsys *ss;
+ struct cgroup_subsys_state *css;
+ int i, refcnt;
+
+ refcnt = refcount_read(&cset->refcount);
+ seq_printf(seq, "css_set %pK %d", cset, refcnt);
+ if (refcnt > cset->nr_tasks)
+ seq_printf(seq, " +%d", refcnt - cset->nr_tasks);
+ seq_puts(seq, "\n");
+
+ /*
+ * Print the css'es stored in the current css_set.
+ */
+ for_each_subsys(ss, i) {
+ css = cset->subsys[ss->id];
+ if (!css)
+ continue;
+ seq_printf(seq, "%2d: %-4s\t- %p[%d]\n", ss->id, ss->name,
+ css, css->id);
+ }
}
- raw_spin_unlock_irq(&css_set_lock);
+
cgroup_kn_unlock(of->kn);
return 0;
}
@@ -86,13 +87,13 @@ static int current_css_set_cg_links_read
{
struct cgrp_cset_link *link;
struct css_set *cset;
- char *name_buf;
- name_buf = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+ char *name_buf __free(kfree) = kmalloc(NAME_MAX + 1, GFP_KERNEL);
if (!name_buf)
return -ENOMEM;
- raw_spin_lock_irq(&css_set_lock);
+ guard(raw_spinlock_irq)(&css_set_lock);
+
cset = task_css_set(current);
list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
struct cgroup *c = link->cgrp;
@@ -101,8 +102,7 @@ static int current_css_set_cg_links_read
seq_printf(seq, "Root %d group %s\n",
c->root->hierarchy_id, name_buf);
}
- raw_spin_unlock_irq(&css_set_lock);
- kfree(name_buf);
+
return 0;
}
--- a/kernel/cgroup/freezer.c
+++ b/kernel/cgroup/freezer.c
@@ -108,12 +108,12 @@ void cgroup_enter_frozen(void)
if (current->frozen)
return;
- raw_spin_lock_irq(&css_set_lock);
+ guard (raw_spinlock_irq)(&css_set_lock);
+
current->frozen = true;
cgrp = task_dfl_cgroup(current);
cgroup_inc_frozen_cnt(cgrp);
cgroup_update_frozen(cgrp);
- raw_spin_unlock_irq(&css_set_lock);
}
/*
@@ -129,7 +129,8 @@ void cgroup_leave_frozen(bool always_lea
{
struct cgroup *cgrp;
- raw_spin_lock_irq(&css_set_lock);
+ guard (raw_spinlock_irq)(&css_set_lock);
+
cgrp = task_dfl_cgroup(current);
if (always_leave || !test_bit(CGRP_FREEZE, &cgrp->flags)) {
cgroup_dec_frozen_cnt(cgrp);
@@ -142,7 +143,6 @@ void cgroup_leave_frozen(bool always_lea
set_thread_flag(TIF_SIGPENDING);
spin_unlock(¤t->sighand->siglock);
}
- raw_spin_unlock_irq(&css_set_lock);
}
/*
@@ -178,18 +178,18 @@ static void cgroup_do_freeze(struct cgro
lockdep_assert_held(&cgroup_mutex);
- raw_spin_lock_irq(&css_set_lock);
- write_seqcount_begin(&cgrp->freezer.freeze_seq);
- if (freeze) {
- set_bit(CGRP_FREEZE, &cgrp->flags);
- cgrp->freezer.freeze_start_nsec = ts_nsec;
- } else {
- clear_bit(CGRP_FREEZE, &cgrp->flags);
- cgrp->freezer.frozen_nsec += (ts_nsec -
- cgrp->freezer.freeze_start_nsec);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ write_seqcount_begin(&cgrp->freezer.freeze_seq);
+ if (freeze) {
+ set_bit(CGRP_FREEZE, &cgrp->flags);
+ cgrp->freezer.freeze_start_nsec = ts_nsec;
+ } else {
+ clear_bit(CGRP_FREEZE, &cgrp->flags);
+ cgrp->freezer.frozen_nsec +=
+ (ts_nsec - cgrp->freezer.freeze_start_nsec);
+ }
+ write_seqcount_end(&cgrp->freezer.freeze_seq);
}
- write_seqcount_end(&cgrp->freezer.freeze_seq);
- raw_spin_unlock_irq(&css_set_lock);
if (freeze)
TRACE_CGROUP_PATH(freeze, cgrp);
@@ -212,10 +212,10 @@ static void cgroup_do_freeze(struct cgro
* Cgroup state should be revisited here to cover empty leaf cgroups
* and cgroups which descendants are already in the desired state.
*/
- raw_spin_lock_irq(&css_set_lock);
- if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)
- cgroup_update_frozen(cgrp);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)
+ cgroup_update_frozen(cgrp);
+ }
}
/*
--- a/kernel/cgroup/namespace.c
+++ b/kernel/cgroup/namespace.c
@@ -70,10 +70,10 @@ struct cgroup_namespace *copy_cgroup_ns(
return ERR_PTR(-ENOSPC);
/* It is not safe to take cgroup_mutex here */
- raw_spin_lock_irq(&css_set_lock);
- cset = task_css_set(current);
- get_css_set(cset);
- raw_spin_unlock_irq(&css_set_lock);
+ scoped_guard (raw_spinlock_irq, &css_set_lock) {
+ cset = task_css_set(current);
+ get_css_set(cset);
+ }
new_ns = alloc_cgroup_ns();
if (IS_ERR(new_ns)) {
prev parent reply other threads:[~2025-11-04 19:32 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-04 18:11 DEBUG_ATOMIC_SLEEP spew in cgroup_task_dead() on next-20251104 Calvin Owens
2025-11-04 19:30 ` Tejun Heo
2025-11-05 15:16 ` Calvin Owens
2025-11-05 19:03 ` [PATCH cgroup/for-6.19] cgroup: Fix sleeping from invalid context warning on PREEMPT_RT Tejun Heo
2025-11-06 1:15 ` Calvin Owens
2025-11-06 17:36 ` Tejun Heo
2025-11-06 15:07 ` Sebastian Andrzej Siewior
2025-11-06 17:37 ` Tejun Heo
2025-11-06 17:46 ` Sebastian Andrzej Siewior
2025-11-06 17:55 ` Tejun Heo
2025-11-06 18:06 ` Sebastian Andrzej Siewior
2026-02-19 16:46 ` ~90s reboot delay with v6.19 and PREEMPT_RT Bert Karwatzki
2026-02-19 20:53 ` Calvin Owens
2026-02-19 23:10 ` Bert Karwatzki
2026-02-20 0:58 ` Steven Rostedt
2026-02-20 9:15 ` ~90s shutdown " Bert Karwatzki
2026-02-20 15:44 ` Steven Rostedt
2026-02-23 0:35 ` Bert Karwatzki
2026-02-23 8:22 ` Steven Rostedt
2026-02-23 13:36 ` Bert Karwatzki
2026-02-23 23:36 ` Bert Karwatzki
2026-02-24 12:44 ` Bert Karwatzki
2026-02-24 12:58 ` Bert Karwatzki
2026-02-24 14:20 ` Steven Rostedt
2026-02-24 15:45 ` ~90s reboot " Sebastian Andrzej Siewior
2026-02-25 15:43 ` Sebastian Andrzej Siewior
2026-02-25 16:37 ` Bert Karwatzki
2026-02-25 16:59 ` Sebastian Andrzej Siewior
2026-02-25 22:31 ` Sebastian Andrzej Siewior
2026-02-26 13:24 ` Bert Karwatzki
2026-02-26 13:46 ` Sebastian Andrzej Siewior
2026-02-26 16:37 ` Steven Rostedt
2026-02-27 14:13 ` Sebastian Andrzej Siewior
2026-02-27 22:57 ` Bert Karwatzki
2026-03-02 11:15 ` Sebastian Andrzej Siewior
2025-11-04 19:32 ` [PATCH cgroup/for-6.19 1/2] cgroup: Convert css_set_lock from spinlock_t to raw_spinlock_t Tejun Heo
2025-11-05 7:30 ` Sebastian Andrzej Siewior
2025-11-05 16:19 ` Tejun Heo
2025-11-05 8:50 ` Peter Zijlstra
2025-11-05 16:20 ` Tejun Heo
2025-11-04 19:32 ` Tejun Heo [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0f56e00692656d09e4b88e2f502ee50f@kernel.org \
--to=tj@kernel.org \
--cc=bigeasy@linutronix.de \
--cc=calvin@wbinvd.org \
--cc=cgroups@vger.kernel.org \
--cc=clrkwllms@kernel.org \
--cc=dschatzberg@meta.com \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=mkoutny@suse.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.