mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jemmy Wong <jemmywong512@gmail.com>
To: "Michal Koutný" <mkoutny@suse.com>
Cc: Tejun Heo <tj@kernel.org>, Johannes Weiner <hannes@cmpxchg.org>,
	Waiman Long <longman@redhat.com>,
	cgroups@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v1 2/3] cgroup: add lock guard support for css_set_lock and rcu
Date: Sat,  7 Jun 2025 00:18:40 +0800	[thread overview]
Message-ID: <20250606161841.44354-3-jemmywong512@gmail.com> (raw)
In-Reply-To: <20250606161841.44354-1-jemmywong512@gmail.com>

Signed-off-by: Jemmy Wong <jemmywong512@gmail.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;
+		}
 	}
-	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);
+	}
 
 	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);
+		}
 	}
 
 	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);
 
@@ -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);
+	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) {
+		/* 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(&current->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


  parent reply	other threads:[~2025-06-06 16:18 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-06 16:18 [PATCH v1 0/3] cgroup: Add lock guard support Jemmy Wong
2025-06-06 16:18 ` [PATCH v1 1/3] cgroup: add lock guard support for cgroup_muetx Jemmy Wong
2025-06-17  9:09   ` Michal Koutný
2025-06-06 16:18 ` Jemmy Wong [this message]
2025-06-17  9:09   ` [PATCH v1 2/3] cgroup: add lock guard support for css_set_lock and rcu Michal Koutný
2025-06-06 16:18 ` [PATCH v1 3/3] cgroup: add lock guard support for others Jemmy Wong
2025-06-07 10:50   ` kernel test robot
2025-06-08  8:52     ` Jemmy Wong
2025-06-17  9:10   ` Michal Koutný
2025-06-09 16:34 ` [PATCH v1 0/3] cgroup: Add lock guard support Tejun Heo
2025-06-17  9:08 ` Michal Koutný
2025-06-20 10:45   ` Jemmy Wong
2025-06-21  2:52     ` Tejun Heo
2025-06-23 14:03       ` Johannes Weiner
2025-06-30 17:39         ` Michal Koutný

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=20250606161841.44354-3-jemmywong512@gmail.com \
    --to=jemmywong512@gmail.com \
    --cc=cgroups@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mkoutny@suse.com \
    --cc=tj@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®