[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <ufzmhgkxfs2mms2a7rm3ikefpjq3kcae72nhdzepfilggteqvl@cbtfuy3nmxtm>
Date: Tue, 17 Jun 2025 11:09:55 +0200
From: Michal Koutný <mkoutny@...e.com>
To: Jemmy Wong <jemmywong512@...il.com>
Cc: Tejun Heo <tj@...nel.org>, Johannes Weiner <hannes@...xchg.org>,
Waiman Long <longman@...hat.com>, cgroups@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v1 2/3] cgroup: add lock guard support for css_set_lock
and rcu
I'd separate css_set_lock and RCU here, they're very different species.
On Sat, Jun 07, 2025 at 12:18:40AM +0800, Jemmy Wong <jemmywong512@...il.com> wrote:
> Signed-off-by: Jemmy Wong <jemmywong512@...il.com>
>
> ---
> kernel/cgroup/cgroup-v1.c | 29 +-
> kernel/cgroup/cgroup.c | 580 ++++++++++++++++++--------------------
> kernel/cgroup/cpuset-v1.c | 16 +-
> kernel/cgroup/debug.c | 185 ++++++------
> kernel/cgroup/freezer.c | 28 +-
> kernel/cgroup/namespace.c | 8 +-
> 6 files changed, 401 insertions(+), 445 deletions(-)
>
> diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
> index f4658eda4445..fcc2d474b470 100644
> --- a/kernel/cgroup/cgroup-v1.c
> +++ b/kernel/cgroup/cgroup-v1.c
> @@ -70,9 +70,9 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
> for_each_root(root) {
> struct cgroup *from_cgrp;
>
> - spin_lock_irq(&css_set_lock);
> - from_cgrp = task_cgroup_from_root(from, root);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + from_cgrp = task_cgroup_from_root(from, root);
> + }
>
> retval = cgroup_attach_task(from_cgrp, tsk, false);
> if (retval)
> @@ -117,10 +117,10 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
> cgroup_attach_lock(true);
>
> /* all tasks in @from are being moved, all csets are source */
> - spin_lock_irq(&css_set_lock);
> - list_for_each_entry(link, &from->cset_links, cset_link)
> - cgroup_migrate_add_src(link->cset, to, &mgctx);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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)
> @@ -728,13 +728,12 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
> * @kn->priv's validity. For this and css_tryget_online_from_dir(),
> * @kn->priv is RCU safe. Let's do the RCU dancing.
> */
> - rcu_read_lock();
> - cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> - if (!cgrp || !cgroup_tryget(cgrp)) {
> - rcu_read_unlock();
> - return -ENOENT;
> + scoped_guard(rcu) {
> + cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> + if (!cgrp || !cgroup_tryget(cgrp)) {
> + return -ENOENT;
> + }
As this became a single statement, braces are unnecessary.
> }
> - rcu_read_unlock();
>
> css_task_iter_start(&cgrp->self, 0, &it);
> while ((tsk = css_task_iter_next(&it))) {
> @@ -1294,7 +1293,7 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
> struct cgroup_root *root;
> unsigned long flags;
>
> - rcu_read_lock();
> + guard(rcu)();
> for_each_root(root) {
> /* cgroup1 only*/
> if (root == &cgrp_dfl_root)
> @@ -1308,7 +1307,7 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
> spin_unlock_irqrestore(&css_set_lock, flags);
> break;
> }
> - rcu_read_unlock();
> +
> return cgrp;
> }
>
> diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
> index 54f80afe4f65..46b677a066d1 100644
> --- a/kernel/cgroup/cgroup.c
> +++ b/kernel/cgroup/cgroup.c
> @@ -631,13 +631,8 @@ int __cgroup_task_count(const struct cgroup *cgrp)
> */
> int cgroup_task_count(const struct cgroup *cgrp)
> {
> - int count;
> -
> - spin_lock_irq(&css_set_lock);
> - count = __cgroup_task_count(cgrp);
> - spin_unlock_irq(&css_set_lock);
> -
> - return count;
> + guard(spinlock_irq)(&css_set_lock);
> + return __cgroup_task_count(cgrp);
> }
>
> static struct cgroup *kn_priv(struct kernfs_node *kn)
> @@ -1202,11 +1197,11 @@ static struct css_set *find_css_set(struct css_set *old_cset,
>
> /* First see if we already have a cgroup group that matches
> * the desired set */
> - spin_lock_irq(&css_set_lock);
> - cset = find_existing_css_set(old_cset, cgrp, template);
> - if (cset)
> - get_css_set(cset);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + cset = find_existing_css_set(old_cset, cgrp, template);
> + if (cset)
> + get_css_set(cset);
> + }
Here it could work to add a guard() into find_existing_css_set()
instead.
>
> if (cset)
> return cset;
> @@ -1238,34 +1233,33 @@ static struct css_set *find_css_set(struct css_set *old_cset,
> * find_existing_css_set() */
> memcpy(cset->subsys, template, sizeof(cset->subsys));
>
> - 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(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);
> + }
> }
>
> - 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
> @@ -1281,11 +1275,11 @@ static struct css_set *find_css_set(struct css_set *old_cset,
> return NULL;
> }
>
> - spin_lock_irq(&css_set_lock);
> - cset->dom_cset = dcset;
> - list_add_tail(&cset->threaded_csets_node,
> - &dcset->threaded_csets);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + cset->dom_cset = dcset;
> + list_add_tail(&cset->threaded_csets_node,
> + &dcset->threaded_csets);
> + }
> }
I admit this part of find_css_set() is less nice after rework :-/
>
> return cset;
> @@ -1362,16 +1356,14 @@ static void cgroup_destroy_root(struct cgroup_root *root)
> * Release all the links from cset_links to this hierarchy's
> * root cgroup
> */
> - 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(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);
> + }
> }
>
> - spin_unlock_irq(&css_set_lock);
> -
> WARN_ON_ONCE(list_empty(&root->root_list));
> list_del_rcu(&root->root_list);
> cgroup_root_count--;
> @@ -1437,13 +1429,10 @@ current_cgns_cgroup_from_root(struct cgroup_root *root)
>
> lockdep_assert_held(&css_set_lock);
>
> - rcu_read_lock();
> -
> - cset = current->nsproxy->cgroup_ns->root_cset;
> - res = __cset_cgroup_from_root(cset, root);
> -
> - rcu_read_unlock();
> -
> + scoped_guard(rcu) {
> + cset = current->nsproxy->cgroup_ns->root_cset;
> + res = __cset_cgroup_from_root(cset, root);
> + }
> /*
> * The namespace_sem is held by current, so the root cgroup can't
> * be umounted. Therefore, we can ensure that the res is non-NULL.
> @@ -1867,25 +1856,25 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
> rcu_assign_pointer(dcgrp->subsys[ssid], css);
> ss->root = dst_root;
>
> - 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(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];
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> /* default hierarchy doesn't enable controllers by default */
> dst_root->subsys_mask |= 1 << ssid;
> @@ -1921,10 +1910,10 @@ int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
> if (!buf)
> return -ENOMEM;
>
> - 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);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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;
> @@ -2175,13 +2164,13 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
> * Link the root cgroup in this hierarchy into all the css_set
> * objects.
> */
> - 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(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);
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> BUG_ON(!list_empty(&root_cgrp->self.children));
> BUG_ON(atomic_read(&root->nr_cgrps) != 1);
> @@ -2225,11 +2214,8 @@ int cgroup_do_get_tree(struct fs_context *fc)
> struct cgroup *cgrp;
>
> scoped_guard(cgroup_mutex) {
> - spin_lock_irq(&css_set_lock);
> -
> + guard(spinlock_irq)(&css_set_lock);
> cgrp = cset_cgroup_from_root(ctx->ns->root_cset, ctx->root);
> -
> - spin_unlock_irq(&css_set_lock);
> }
>
> nsdentry = kernfs_node_dentry(cgrp->kn, sb);
> @@ -2438,16 +2424,10 @@ int cgroup_path_ns_locked(struct cgroup *cgrp, char *buf, size_t buflen,
> int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
> struct cgroup_namespace *ns)
> {
> - int ret;
> -
> guard(cgroup_mutex)();
> - spin_lock_irq(&css_set_lock);
> -
> - ret = cgroup_path_ns_locked(cgrp, buf, buflen, ns);
> -
> - spin_unlock_irq(&css_set_lock);
> + guard(spinlock_irq)(&css_set_lock);
>
> - return ret;
> + return cgroup_path_ns_locked(cgrp, buf, buflen, ns);
> }
> EXPORT_SYMBOL_GPL(cgroup_path_ns);
This is an example of good condensation.
>
> @@ -2629,27 +2609,27 @@ static int cgroup_migrate_execute(struct cgroup_mgctx *mgctx)
> * the new cgroup. There are no failure cases after here, so this
> * is the commit point.
> */
> - 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(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);
>
> + }
> }
> }
> - spin_unlock_irq(&css_set_lock);
>
> /*
> * Migration is committed, all target tasks are now on dst_csets.
> @@ -2682,13 +2662,13 @@ static int cgroup_migrate_execute(struct cgroup_mgctx *mgctx)
> } while_each_subsys_mask();
> }
> out_release_tset:
> - 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(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);
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> /*
> * Re-initialize the cgroup_taskset structure in case it is reused
> @@ -2746,7 +2726,7 @@ void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
>
> lockdep_assert_held(&cgroup_mutex);
>
> - spin_lock_irq(&css_set_lock);
> + guard(spinlock_irq)(&css_set_lock);
>
> list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
> mg_src_preload_node) {
> @@ -2765,8 +2745,6 @@ void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
> list_del_init(&cset->mg_dst_preload_node);
> put_css_set_locked(cset);
> }
> -
> - spin_unlock_irq(&css_set_lock);
> }
>
> /**
> @@ -2909,14 +2887,14 @@ int cgroup_migrate(struct task_struct *leader, bool threadgroup,
> * section to prevent tasks from being freed while taking the snapshot.
> * spin_lock_irq() implies RCU critical section here.
> */
> - spin_lock_irq(&css_set_lock);
> - task = leader;
> - do {
> - cgroup_migrate_add_task(task, mgctx);
> - if (!threadgroup)
> - break;
> - } while_each_thread(leader, task);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + task = leader;
> + do {
> + cgroup_migrate_add_task(task, mgctx);
> + if (!threadgroup)
> + break;
> + } while_each_thread(leader, task);
> + }
>
> return cgroup_migrate_execute(mgctx);
> }
> @@ -2937,16 +2915,15 @@ int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader,
> int ret = 0;
>
> /* look up all src csets */
> - spin_lock_irq(&css_set_lock);
> - rcu_read_lock();
> - task = leader;
> - do {
> - cgroup_migrate_add_src(task_css_set(task), dst_cgrp, &mgctx);
> - if (!threadgroup)
> - break;
> - } while_each_thread(leader, task);
> - rcu_read_unlock();
> - spin_unlock_irq(&css_set_lock);
As I look at it now, the RCU lock seems pointless here.
That'd deserve a separate patch (independent of this guard series).
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + guard(rcu)();
> + 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);
> @@ -3088,23 +3065,23 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
> lockdep_assert_held(&cgroup_mutex);
>
> /* look up all csses currently attached to @cgrp's subtree */
> - spin_lock_irq(&css_set_lock);
> - cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) {
> - struct cgrp_cset_link *link;
> + scoped_guard(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);
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> /*
> * We need to write-lock threadgroup_rwsem while migrating tasks.
> @@ -3120,16 +3097,16 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
> if (ret)
> goto out_finish;
>
> - 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;
> + scoped_guard(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);
> + /* 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);
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> ret = cgroup_migrate_execute(&mgctx);
> out_finish:
> @@ -3734,7 +3711,8 @@ static int cgroup_stat_show(struct seq_file *seq, void *v)
> * Without proper lock protection, racing is possible. So the
> * numbers may not be consistent when that happens.
> */
> - rcu_read_lock();
> + guard(rcu)();
> +
> for (ssid = 0; ssid < CGROUP_SUBSYS_COUNT; ssid++) {
> dying_cnt[ssid] = -1;
> if ((BIT(ssid) & cgrp_dfl_inhibit_ss_mask) ||
> @@ -3753,7 +3731,6 @@ static int cgroup_stat_show(struct seq_file *seq, void *v)
> seq_printf(seq, "nr_dying_subsys_%s %d\n",
> cgroup_subsys[ssid]->name, dying_cnt[ssid]);
> }
> - rcu_read_unlock();
> return 0;
> }
>
> @@ -3771,11 +3748,10 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp,
> {
> struct cgroup_subsys_state *css;
>
> - rcu_read_lock();
> + guard(rcu)();
> css = cgroup_css(cgrp, ss);
> if (css && !css_tryget_online(css))
> css = NULL;
> - rcu_read_unlock();
>
> return css;
> }
> @@ -4056,9 +4032,9 @@ static void __cgroup_kill(struct cgroup *cgrp)
>
> lockdep_assert_held(&cgroup_mutex);
>
> - spin_lock_irq(&css_set_lock);
> - cgrp->kill_seq++;
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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))) {
> @@ -4187,9 +4163,9 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
> * doesn't need to be pinned. The RCU locking is not necessary
> * either. It's just for the convenience of using cgroup_css().
> */
> - rcu_read_lock();
> - css = cgroup_css(cgrp, cft->ss);
> - rcu_read_unlock();
> + scoped_guard(rcu) {
> + css = cgroup_css(cgrp, cft->ss);
> + }
>
> if (cft->write_u64) {
> unsigned long long v;
> @@ -4815,14 +4791,14 @@ bool css_has_online_children(struct cgroup_subsys_state *css)
> struct cgroup_subsys_state *child;
> bool ret = false;
>
> - rcu_read_lock();
> + guard(rcu)();
> css_for_each_child(child, css) {
> if (child->flags & CSS_ONLINE) {
> ret = true;
> break;
> }
> }
> - rcu_read_unlock();
> +
> return ret;
> }
>
> @@ -5247,9 +5223,9 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
> goto out_unlock;
>
> /* find the source cgroup */
> - spin_lock_irq(&css_set_lock);
> - src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
> + }
>
> /*
> * Process and thread migrations follow same delegation rule. Check
> @@ -5531,11 +5507,11 @@ static inline void css_release_work_fn_locked(struct work_struct *work)
>
> css_rstat_flush(&cgrp->self);
>
> - spin_lock_irq(&css_set_lock);
> - for (tcgrp = cgroup_parent(cgrp); tcgrp;
> - tcgrp = cgroup_parent(tcgrp))
> - tcgrp->nr_dying_descendants--;
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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
> @@ -5790,20 +5766,20 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
> goto out_psi_free;
>
> /* allocation complete, commit to creation */
> - spin_lock_irq(&css_set_lock);
> - for (i = 0; i < level; i++) {
> - tcgrp = cgrp->ancestors[i];
> - tcgrp->nr_descendants++;
> + scoped_guard(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++;
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> list_add_tail_rcu(&cgrp->self.sibling, &cgroup_parent(cgrp)->self.children);
> atomic_inc(&root->nr_cgrps);
> @@ -6047,10 +6023,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
> */
> cgrp->self.flags &= ~CSS_ONLINE;
>
> - spin_lock_irq(&css_set_lock);
> - list_for_each_entry(link, &cgrp->cset_links, cset_link)
> - link->cset->dead = true;
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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)
> @@ -6063,18 +6039,18 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
> if (cgroup_is_threaded(cgrp))
> parent->nr_threaded_children--;
>
> - 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(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--;
> + }
> }
> - spin_unlock_irq(&css_set_lock);
>
> cgroup1_check_for_release(parent);
>
> @@ -6356,13 +6332,12 @@ struct cgroup *cgroup_get_from_id(u64 id)
> return ERR_PTR(-ENOENT);
> }
>
> - rcu_read_lock();
> -
> - cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> - if (cgrp && !cgroup_tryget(cgrp))
> - cgrp = NULL;
> + scoped_guard(rcu) {
> + cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> + if (cgrp && !cgroup_tryget(cgrp))
> + cgrp = NULL;
> + }
>
> - rcu_read_unlock();
> kernfs_put(kn);
>
> if (!cgrp)
> @@ -6539,14 +6514,14 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
>
> cgroup_threadgroup_change_begin(current);
>
> - 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;
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(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;
> @@ -6736,56 +6711,53 @@ void cgroup_post_fork(struct task_struct *child,
> cset = kargs->cset;
> kargs->cset = NULL;
>
> - spin_lock_irq(&css_set_lock);
> + scoped_guard(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;
> }
> -
> - 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()
> @@ -6824,25 +6796,23 @@ void cgroup_exit(struct task_struct *tsk)
> struct css_set *cset;
> int i;
>
> - spin_lock_irq(&css_set_lock);
> -
> - WARN_ON_ONCE(list_empty(&tsk->cg_list));
> - cset = task_css_set(tsk);
> - css_set_move_task(tsk, cset, NULL, false);
> - cset->nr_tasks--;
> - /* matches the signal->live check in css_task_iter_advance() */
> - if (thread_group_leader(tsk) && atomic_read(&tsk->signal->live))
> - list_add_tail(&tsk->cg_list, &cset->dying_tasks);
> -
> - if (dl_task(tsk))
> - dec_dl_tasks_cs(tsk);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + WARN_ON_ONCE(list_empty(&tsk->cg_list));
> + cset = task_css_set(tsk);
> + css_set_move_task(tsk, cset, NULL, false);
> + cset->nr_tasks--;
> + /* matches the signal->live check in css_task_iter_advance() */
> + if (thread_group_leader(tsk) && atomic_read(&tsk->signal->live))
> + list_add_tail(&tsk->cg_list, &cset->dying_tasks);
>
> - WARN_ON_ONCE(cgroup_task_frozen(tsk));
> - if (unlikely(!(tsk->flags & PF_KTHREAD) &&
> - test_bit(CGRP_FREEZE, &task_dfl_cgroup(tsk)->flags)))
> - cgroup_update_frozen(task_dfl_cgroup(tsk));
> + if (dl_task(tsk))
> + dec_dl_tasks_cs(tsk);
>
> - spin_unlock_irq(&css_set_lock);
> + WARN_ON_ONCE(cgroup_task_frozen(tsk));
> + if (unlikely(!(tsk->flags & PF_KTHREAD) &&
> + test_bit(CGRP_FREEZE, &task_dfl_cgroup(tsk)->flags)))
> + cgroup_update_frozen(task_dfl_cgroup(tsk));
> + }
>
> /* see cgroup_post_fork() for details */
> do_each_subsys_mask(ss, i, have_exit_callback) {
> @@ -6860,10 +6830,9 @@ void cgroup_release(struct task_struct *task)
> } while_each_subsys_mask();
>
> if (!list_empty(&task->cg_list)) {
> - spin_lock_irq(&css_set_lock);
> + guard(spinlock_irq)(&css_set_lock);
> css_set_skip_task_iters(task_css_set(task), task);
> list_del_init(&task->cg_list);
> - spin_unlock_irq(&css_set_lock);
> }
> }
>
> @@ -6944,7 +6913,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
> !kn || kernfs_type(kn) != KERNFS_DIR)
> return ERR_PTR(-EBADF);
>
> - rcu_read_lock();
> + guard(rcu)();
>
> /*
> * This path doesn't originate from kernfs and @kn could already
> @@ -6958,7 +6927,6 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
> if (!css || !css_tryget_online(css))
> css = ERR_PTR(-ENOENT);
>
> - rcu_read_unlock();
> return css;
> }
>
> @@ -7001,13 +6969,11 @@ struct cgroup *cgroup_get_from_path(const char *path)
> goto out_kernfs;
> }
>
> - rcu_read_lock();
> -
> - cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> - if (!cgrp || !cgroup_tryget(cgrp))
> - cgrp = ERR_PTR(-ENOENT);
> -
> - rcu_read_unlock();
> + scoped_guard(rcu) {
> + cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
> + if (!cgrp || !cgroup_tryget(cgrp))
> + cgrp = ERR_PTR(-ENOENT);
> + }
>
> out_kernfs:
> kernfs_put(kn);
> @@ -7106,28 +7072,28 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
> {
> struct cgroup *cgroup;
>
> - rcu_read_lock();
> - /* Don't associate the sock with unrelated interrupted task's cgroup. */
> - if (in_interrupt()) {
> - cgroup = &cgrp_dfl_root.cgrp;
> - cgroup_get(cgroup);
> - goto out;
> - }
> + scoped_guard(rcu) {
Here could be unscoped guard()(rcu)?
> + /* Don't associate the sock with unrelated interrupted task's cgroup. */
> + if (in_interrupt()) {
> + cgroup = &cgrp_dfl_root.cgrp;
> + cgroup_get(cgroup);
> + break;
> + }
>
> - while (true) {
> - struct css_set *cset;
> + while (true) {
> + struct css_set *cset;
>
> - cset = task_css_set(current);
> - if (likely(cgroup_tryget(cset->dfl_cgrp))) {
> - cgroup = cset->dfl_cgrp;
> - break;
> + cset = task_css_set(current);
> + if (likely(cgroup_tryget(cset->dfl_cgrp))) {
> + cgroup = cset->dfl_cgrp;
> + break;
> + }
> + cpu_relax();
> }
> - cpu_relax();
> +
> + skcd->cgroup = cgroup;
> + cgroup_bpf_get(cgroup);
> }
> -out:
> - skcd->cgroup = cgroup;
> - cgroup_bpf_get(cgroup);
> - rcu_read_unlock();
> }
>
> void cgroup_sk_clone(struct sock_cgroup_data *skcd)
> diff --git a/kernel/cgroup/cpuset-v1.c b/kernel/cgroup/cpuset-v1.c
> index b69a7db67090..114a63432d23 100644
> --- a/kernel/cgroup/cpuset-v1.c
> +++ b/kernel/cgroup/cpuset-v1.c
> @@ -140,9 +140,8 @@ int cpuset_memory_pressure_enabled __read_mostly;
>
> void __cpuset_memory_pressure_bump(void)
> {
> - rcu_read_lock();
> + guard(rcu)();
> fmeter_markevent(&task_cs(current)->fmeter);
> - rcu_read_unlock();
> }
>
> static int update_relax_domain_level(struct cpuset *cs, s64 val)
> @@ -393,13 +392,12 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
> if (!buf)
> goto out;
>
> - rcu_read_lock();
> - spin_lock_irq(&css_set_lock);
> - css = task_css(tsk, cpuset_cgrp_id);
> - retval = cgroup_path_ns_locked(css->cgroup, buf, PATH_MAX,
> - current->nsproxy->cgroup_ns);
> - spin_unlock_irq(&css_set_lock);
> - rcu_read_unlock();
> + scoped_guard(rcu) {
> + guard(spinlock_irq)(&css_set_lock);
> + css = task_css(tsk, cpuset_cgrp_id);
> + retval = cgroup_path_ns_locked(css->cgroup, buf, PATH_MAX,
> + current->nsproxy->cgroup_ns);
> + }
>
> if (retval == -E2BIG)
> retval = -ENAMETOOLONG;
> diff --git a/kernel/cgroup/debug.c b/kernel/cgroup/debug.c
> index 80aa3f027ac3..2f04db56c8ac 100644
> --- a/kernel/cgroup/debug.c
> +++ b/kernel/cgroup/debug.c
> @@ -48,27 +48,26 @@ static int current_css_set_read(struct seq_file *seq, void *v)
> if (!cgroup_kn_lock_live(of->kn, false))
> return -ENODEV;
>
> - spin_lock_irq(&css_set_lock);
> - rcu_read_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");
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + guard(rcu)();
> + 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);
> + /*
> + * 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);
> + }
> }
> - rcu_read_unlock();
> - spin_unlock_irq(&css_set_lock);
> cgroup_kn_unlock(of->kn);
> return 0;
> }
> @@ -76,12 +75,8 @@ static int current_css_set_read(struct seq_file *seq, void *v)
> static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
> struct cftype *cft)
> {
> - u64 count;
> -
> - rcu_read_lock();
> - count = refcount_read(&task_css_set(current)->refcount);
> - rcu_read_unlock();
> - return count;
> + guard(rcu)();
> + return refcount_read(&task_css_set(current)->refcount);
> }
>
> static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
> @@ -94,18 +89,17 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
> if (!name_buf)
> return -ENOMEM;
>
> - spin_lock_irq(&css_set_lock);
> - rcu_read_lock();
> - cset = task_css_set(current);
> - list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
> - struct cgroup *c = link->cgrp;
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + guard(rcu)();
> + cset = task_css_set(current);
> + list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
> + struct cgroup *c = link->cgrp;
>
> - cgroup_name(c, name_buf, NAME_MAX + 1);
> - seq_printf(seq, "Root %d group %s\n",
> - c->root->hierarchy_id, name_buf);
> + cgroup_name(c, name_buf, NAME_MAX + 1);
> + seq_printf(seq, "Root %d group %s\n",
> + c->root->hierarchy_id, name_buf);
> + }
> }
> - rcu_read_unlock();
> - spin_unlock_irq(&css_set_lock);
> kfree(name_buf);
> return 0;
> }
> @@ -117,74 +111,73 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
> struct cgrp_cset_link *link;
> int dead_cnt = 0, extra_refs = 0, threaded_csets = 0;
>
> - spin_lock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
> + struct css_set *cset = link->cset;
> + struct task_struct *task;
> + int count = 0;
> + int refcnt = refcount_read(&cset->refcount);
> +
> + /*
> + * Print out the proc_cset and threaded_cset relationship
> + * and highlight difference between refcount and task_count.
> + */
> + seq_printf(seq, "css_set %pK", cset);
> + if (rcu_dereference_protected(cset->dom_cset, 1) != cset) {
> + threaded_csets++;
> + seq_printf(seq, "=>%pK", cset->dom_cset);
> + }
> + if (!list_empty(&cset->threaded_csets)) {
> + struct css_set *tcset;
> + int idx = 0;
> +
> + list_for_each_entry(tcset, &cset->threaded_csets,
> + threaded_csets_node) {
> + seq_puts(seq, idx ? "," : "<=");
> + seq_printf(seq, "%pK", tcset);
> + idx++;
> + }
> + } else {
> + seq_printf(seq, " %d", refcnt);
> + if (refcnt - cset->nr_tasks > 0) {
> + int extra = refcnt - cset->nr_tasks;
> +
> + seq_printf(seq, " +%d", extra);
> + /*
> + * Take out the one additional reference in
> + * init_css_set.
> + */
> + if (cset == &init_css_set)
> + extra--;
> + extra_refs += extra;
> + }
> + }
> + seq_puts(seq, "\n");
>
> - list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
> - struct css_set *cset = link->cset;
> - struct task_struct *task;
> - int count = 0;
> - int refcnt = refcount_read(&cset->refcount);
> + list_for_each_entry(task, &cset->tasks, cg_list) {
> + if (count++ <= MAX_TASKS_SHOWN_PER_CSS)
> + seq_printf(seq, " task %d\n",
> + task_pid_vnr(task));
> + }
>
> - /*
> - * Print out the proc_cset and threaded_cset relationship
> - * and highlight difference between refcount and task_count.
> - */
> - seq_printf(seq, "css_set %pK", cset);
> - if (rcu_dereference_protected(cset->dom_cset, 1) != cset) {
> - threaded_csets++;
> - seq_printf(seq, "=>%pK", cset->dom_cset);
> - }
> - if (!list_empty(&cset->threaded_csets)) {
> - struct css_set *tcset;
> - int idx = 0;
> -
> - list_for_each_entry(tcset, &cset->threaded_csets,
> - threaded_csets_node) {
> - seq_puts(seq, idx ? "," : "<=");
> - seq_printf(seq, "%pK", tcset);
> - idx++;
> + list_for_each_entry(task, &cset->mg_tasks, cg_list) {
> + if (count++ <= MAX_TASKS_SHOWN_PER_CSS)
> + seq_printf(seq, " task %d\n",
> + task_pid_vnr(task));
> }
> - } else {
> - seq_printf(seq, " %d", refcnt);
> - if (refcnt - cset->nr_tasks > 0) {
> - int extra = refcnt - cset->nr_tasks;
> -
> - seq_printf(seq, " +%d", extra);
> - /*
> - * Take out the one additional reference in
> - * init_css_set.
> - */
> - if (cset == &init_css_set)
> - extra--;
> - extra_refs += extra;
> + /* show # of overflowed tasks */
> + if (count > MAX_TASKS_SHOWN_PER_CSS)
> + seq_printf(seq, " ... (%d)\n",
> + count - MAX_TASKS_SHOWN_PER_CSS);
> +
> + if (cset->dead) {
> + seq_puts(seq, " [dead]\n");
> + dead_cnt++;
> }
> - }
> - seq_puts(seq, "\n");
> -
> - list_for_each_entry(task, &cset->tasks, cg_list) {
> - if (count++ <= MAX_TASKS_SHOWN_PER_CSS)
> - seq_printf(seq, " task %d\n",
> - task_pid_vnr(task));
> - }
>
> - list_for_each_entry(task, &cset->mg_tasks, cg_list) {
> - if (count++ <= MAX_TASKS_SHOWN_PER_CSS)
> - seq_printf(seq, " task %d\n",
> - task_pid_vnr(task));
> + WARN_ON(count != cset->nr_tasks);
> }
> - /* show # of overflowed tasks */
> - if (count > MAX_TASKS_SHOWN_PER_CSS)
> - seq_printf(seq, " ... (%d)\n",
> - count - MAX_TASKS_SHOWN_PER_CSS);
> -
> - if (cset->dead) {
> - seq_puts(seq, " [dead]\n");
> - dead_cnt++;
> - }
> -
> - WARN_ON(count != cset->nr_tasks);
> }
> - spin_unlock_irq(&css_set_lock);
>
> if (!dead_cnt && !extra_refs && !threaded_csets)
> return 0;
> diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
> index bf1690a167dd..01134b3af176 100644
> --- a/kernel/cgroup/freezer.c
> +++ b/kernel/cgroup/freezer.c
> @@ -108,12 +108,12 @@ void cgroup_enter_frozen(void)
> if (current->frozen)
> return;
>
> - spin_lock_irq(&css_set_lock);
> + guard(spinlock_irq)(&css_set_lock);
> +
> current->frozen = true;
> cgrp = task_dfl_cgroup(current);
> cgroup_inc_frozen_cnt(cgrp);
> cgroup_update_frozen(cgrp);
> - spin_unlock_irq(&css_set_lock);
> }
>
> /*
> @@ -129,7 +129,8 @@ void cgroup_leave_frozen(bool always_leave)
> {
> struct cgroup *cgrp;
>
> - spin_lock_irq(&css_set_lock);
> + guard(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_leave)
> set_thread_flag(TIF_SIGPENDING);
> spin_unlock(¤t->sighand->siglock);
> }
> - spin_unlock_irq(&css_set_lock);
> }
>
> /*
> @@ -178,12 +178,12 @@ static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze)
>
> lockdep_assert_held(&cgroup_mutex);
>
> - spin_lock_irq(&css_set_lock);
> - if (freeze)
> - set_bit(CGRP_FREEZE, &cgrp->flags);
> - else
> - clear_bit(CGRP_FREEZE, &cgrp->flags);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + if (freeze)
> + set_bit(CGRP_FREEZE, &cgrp->flags);
> + else
> + clear_bit(CGRP_FREEZE, &cgrp->flags);
> + }
>
> if (freeze)
> TRACE_CGROUP_PATH(freeze, cgrp);
> @@ -206,10 +206,10 @@ static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze)
> * Cgroup state should be revisited here to cover empty leaf cgroups
> * and cgroups which descendants are already in the desired state.
> */
> - spin_lock_irq(&css_set_lock);
> - if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)
> - cgroup_update_frozen(cgrp);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)
> + cgroup_update_frozen(cgrp);
> + }
> }
>
> /*
> diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c
> index 144a464e45c6..3e2454a106aa 100644
> --- a/kernel/cgroup/namespace.c
> +++ b/kernel/cgroup/namespace.c
> @@ -71,10 +71,10 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
> return ERR_PTR(-ENOSPC);
>
> /* It is not safe to take cgroup_mutex here */
> - spin_lock_irq(&css_set_lock);
> - cset = task_css_set(current);
> - get_css_set(cset);
> - spin_unlock_irq(&css_set_lock);
> + scoped_guard(spinlock_irq, &css_set_lock) {
> + cset = task_css_set(current);
> + get_css_set(cset);
> + }
>
> new_ns = alloc_cgroup_ns();
> if (IS_ERR(new_ns)) {
> --
> 2.43.0
>
Download attachment "signature.asc" of type "application/pgp-signature" (229 bytes)
Powered by blists - more mailing lists