lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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(&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
> 

Download attachment "signature.asc" of type "application/pgp-signature" (229 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ