[PATCH v1 3/3] cgroup: add lock guard support for others

Jemmy Wong posted 3 patches 6 months, 2 weeks ago
[PATCH v1 3/3] cgroup: add lock guard support for others
Posted by Jemmy Wong 6 months, 2 weeks ago
Signed-off-by: Jemmy Wong <jemmywong512@gmail.com>

---
 kernel/cgroup/cgroup-internal.h |  8 ++--
 kernel/cgroup/cgroup-v1.c       | 11 +++--
 kernel/cgroup/cgroup.c          | 73 ++++++++++++---------------------
 3 files changed, 35 insertions(+), 57 deletions(-)

diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h
index b14e61c64a34..5430454d38ca 100644
--- a/kernel/cgroup/cgroup-internal.h
+++ b/kernel/cgroup/cgroup-internal.h
@@ -198,8 +198,6 @@ void put_css_set_locked(struct css_set *cset);
 
 static inline void put_css_set(struct css_set *cset)
 {
-	unsigned long flags;
-
 	/*
 	 * Ensure that the refcount doesn't hit zero while any readers
 	 * can see it. Similar to atomic_dec_and_lock(), but for an
@@ -208,9 +206,9 @@ static inline void put_css_set(struct css_set *cset)
 	if (refcount_dec_not_one(&cset->refcount))
 		return;
 
-	spin_lock_irqsave(&css_set_lock, flags);
-	put_css_set_locked(cset);
-	spin_unlock_irqrestore(&css_set_lock, flags);
+	scoped_guard(spinlock_irqsave, &css_set_lock) {
+		put_css_set_locked(cset);
+	}
 }
 
 /*
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index fcc2d474b470..91c6ba4e441d 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -1291,7 +1291,6 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
 {
 	struct cgroup *cgrp = ERR_PTR(-ENOENT);
 	struct cgroup_root *root;
-	unsigned long flags;
 
 	guard(rcu)();
 	for_each_root(root) {
@@ -1300,11 +1299,11 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
 			continue;
 		if (root->hierarchy_id != hierarchy_id)
 			continue;
-		spin_lock_irqsave(&css_set_lock, flags);
-		cgrp = task_cgroup_from_root(tsk, root);
-		if (!cgrp || !cgroup_tryget(cgrp))
-			cgrp = ERR_PTR(-ENOENT);
-		spin_unlock_irqrestore(&css_set_lock, flags);
+		scoped_guard(spinlock_irqsave, &css_set_lock) {
+			cgrp = task_cgroup_from_root(tsk, root);
+			if (!cgrp || !cgroup_tryget(cgrp))
+				cgrp = ERR_PTR(-ENOENT);
+		}
 		break;
 	}
 
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 46b677a066d1..ea98679b01e1 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -335,28 +335,23 @@ static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end,
 	int ret;
 
 	idr_preload(gfp_mask);
-	spin_lock_bh(&cgroup_idr_lock);
-	ret = idr_alloc(idr, ptr, start, end, gfp_mask & ~__GFP_DIRECT_RECLAIM);
-	spin_unlock_bh(&cgroup_idr_lock);
+	scoped_guard(spinlock_bh, &cgroup_idr_lock) {
+		ret = idr_alloc(idr, ptr, start, end, gfp_mask & ~__GFP_DIRECT_RECLAIM);
+	}
 	idr_preload_end();
 	return ret;
 }
 
 static void *cgroup_idr_replace(struct idr *idr, void *ptr, int id)
 {
-	void *ret;
-
-	spin_lock_bh(&cgroup_idr_lock);
-	ret = idr_replace(idr, ptr, id);
-	spin_unlock_bh(&cgroup_idr_lock);
-	return ret;
+	guard(spinlock_bh)(&cgroup_idr_lock);
+	return idr_replace(idr, ptr, id);
 }
 
 static void cgroup_idr_remove(struct idr *idr, int id)
 {
-	spin_lock_bh(&cgroup_idr_lock);
+	guard(spinlock_bh)(&cgroup_idr_lock);
 	idr_remove(idr, id);
-	spin_unlock_bh(&cgroup_idr_lock);
 }
 
 static bool cgroup_has_tasks(struct cgroup *cgrp)
@@ -583,20 +578,19 @@ struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgrp,
 	if (!CGROUP_HAS_SUBSYS_CONFIG)
 		return NULL;
 
-	rcu_read_lock();
+	guard(rcu)();
 
 	do {
 		css = cgroup_css(cgrp, ss);
 
 		if (css && css_tryget_online(css))
-			goto out_unlock;
+			return css;
 		cgrp = cgroup_parent(cgrp);
 	} while (cgrp);
 
 	css = init_css_set.subsys[ss->id];
 	css_get(css);
-out_unlock:
-	rcu_read_unlock();
+
 	return css;
 }
 EXPORT_SYMBOL_GPL(cgroup_get_e_css);
@@ -1691,9 +1685,9 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
 		struct cgroup_subsys_state *css = cgroup_css(cgrp, cft->ss);
 		struct cgroup_file *cfile = (void *)css + cft->file_offset;
 
-		spin_lock_irq(&cgroup_file_kn_lock);
-		cfile->kn = NULL;
-		spin_unlock_irq(&cgroup_file_kn_lock);
+		scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
+			cfile->kn = NULL;
+		}
 
 		timer_delete_sync(&cfile->notify_timer);
 	}
@@ -4277,9 +4271,9 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
 
 		timer_setup(&cfile->notify_timer, cgroup_file_notify_timer, 0);
 
-		spin_lock_irq(&cgroup_file_kn_lock);
-		cfile->kn = kn;
-		spin_unlock_irq(&cgroup_file_kn_lock);
+		scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
+			cfile->kn = kn;
+		}
 	}
 
 	return 0;
@@ -4534,9 +4528,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
  */
 void cgroup_file_notify(struct cgroup_file *cfile)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&cgroup_file_kn_lock, flags);
+	guard(spinlock_irqsave)(&cgroup_file_kn_lock);
 	if (cfile->kn) {
 		unsigned long last = cfile->notified_at;
 		unsigned long next = last + CGROUP_FILE_NOTIFY_MIN_INTV;
@@ -4548,7 +4540,6 @@ void cgroup_file_notify(struct cgroup_file *cfile)
 			cfile->notified_at = jiffies;
 		}
 	}
-	spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
 }
 
 /**
@@ -4560,10 +4551,10 @@ void cgroup_file_show(struct cgroup_file *cfile, bool show)
 {
 	struct kernfs_node *kn;
 
-	spin_lock_irq(&cgroup_file_kn_lock);
-	kn = cfile->kn;
-	kernfs_get(kn);
-	spin_unlock_irq(&cgroup_file_kn_lock);
+	scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
+		kn = cfile->kn;
+		kernfs_get(kn);
+	}
 
 	if (kn)
 		kernfs_show(kn, show);
@@ -4987,11 +4978,10 @@ static void css_task_iter_advance(struct css_task_iter *it)
 void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
 			 struct css_task_iter *it)
 {
-	unsigned long irqflags;
 
 	memset(it, 0, sizeof(*it));
 
-	spin_lock_irqsave(&css_set_lock, irqflags);
+	guard(spinlock_irqsave)(&css_set_lock);
 
 	it->ss = css->ss;
 	it->flags = flags;
@@ -5004,8 +4994,6 @@ void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
 	it->cset_head = it->cset_pos;
 
 	css_task_iter_advance(it);
-
-	spin_unlock_irqrestore(&css_set_lock, irqflags);
 }
 
 /**
@@ -5018,14 +5006,12 @@ void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
  */
 struct task_struct *css_task_iter_next(struct css_task_iter *it)
 {
-	unsigned long irqflags;
-
 	if (it->cur_task) {
 		put_task_struct(it->cur_task);
 		it->cur_task = NULL;
 	}
 
-	spin_lock_irqsave(&css_set_lock, irqflags);
+	guard(spinlock_irqsave)(&css_set_lock);
 
 	/* @it may be half-advanced by skips, finish advancing */
 	if (it->flags & CSS_TASK_ITER_SKIPPED)
@@ -5038,8 +5024,6 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
 		css_task_iter_advance(it);
 	}
 
-	spin_unlock_irqrestore(&css_set_lock, irqflags);
-
 	return it->cur_task;
 }
 
@@ -5051,13 +5035,10 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
  */
 void css_task_iter_end(struct css_task_iter *it)
 {
-	unsigned long irqflags;
-
 	if (it->cur_cset) {
-		spin_lock_irqsave(&css_set_lock, irqflags);
+		guard(spinlock_irqsave)(&css_set_lock);
 		list_del(&it->iters_node);
 		put_css_set_locked(it->cur_cset);
-		spin_unlock_irqrestore(&css_set_lock, irqflags);
 	}
 
 	if (it->cur_dcset)
@@ -6737,10 +6718,10 @@ void cgroup_post_fork(struct task_struct *child,
 				 * 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);
+				scoped_guard(spinlock, &child->sighand->siglock) {
+					WARN_ON_ONCE(child->frozen);
+					child->jobctl |= JOBCTL_TRAP_FREEZE;
+				}
 
 				/*
 				 * Calling cgroup_update_frozen() isn't required here,
-- 
2.43.0
Re: [PATCH v1 3/3] cgroup: add lock guard support for others
Posted by Michal Koutný 6 months ago
On Sat, Jun 07, 2025 at 12:18:41AM +0800, Jemmy Wong <jemmywong512@gmail.com> wrote:
> Signed-off-by: Jemmy Wong <jemmywong512@gmail.com>
> 
> ---
>  kernel/cgroup/cgroup-internal.h |  8 ++--
>  kernel/cgroup/cgroup-v1.c       | 11 +++--
>  kernel/cgroup/cgroup.c          | 73 ++++++++++++---------------------
>  3 files changed, 35 insertions(+), 57 deletions(-)
> 
> diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h
> index b14e61c64a34..5430454d38ca 100644
> --- a/kernel/cgroup/cgroup-internal.h
> +++ b/kernel/cgroup/cgroup-internal.h
> @@ -198,8 +198,6 @@ void put_css_set_locked(struct css_set *cset);
>  
>  static inline void put_css_set(struct css_set *cset)
>  {
> -	unsigned long flags;
> -
>  	/*
>  	 * Ensure that the refcount doesn't hit zero while any readers
>  	 * can see it. Similar to atomic_dec_and_lock(), but for an
> @@ -208,9 +206,9 @@ static inline void put_css_set(struct css_set *cset)
>  	if (refcount_dec_not_one(&cset->refcount))
>  		return;
>  
> -	spin_lock_irqsave(&css_set_lock, flags);
> -	put_css_set_locked(cset);
> -	spin_unlock_irqrestore(&css_set_lock, flags);
> +	scoped_guard(spinlock_irqsave, &css_set_lock) {
> +		put_css_set_locked(cset);
> +	}
>  }

This should go to the css_set_lock patch.

>  /*
> diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
> index fcc2d474b470..91c6ba4e441d 100644
> --- a/kernel/cgroup/cgroup-v1.c
> +++ b/kernel/cgroup/cgroup-v1.c
> @@ -1291,7 +1291,6 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
>  {
>  	struct cgroup *cgrp = ERR_PTR(-ENOENT);
>  	struct cgroup_root *root;
> -	unsigned long flags;
>  
>  	guard(rcu)();
>  	for_each_root(root) {
> @@ -1300,11 +1299,11 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk, int hierarchy_id)
>  			continue;
>  		if (root->hierarchy_id != hierarchy_id)
>  			continue;
> -		spin_lock_irqsave(&css_set_lock, flags);
> -		cgrp = task_cgroup_from_root(tsk, root);
> -		if (!cgrp || !cgroup_tryget(cgrp))
> -			cgrp = ERR_PTR(-ENOENT);
> -		spin_unlock_irqrestore(&css_set_lock, flags);
> +		scoped_guard(spinlock_irqsave, &css_set_lock) {
> +			cgrp = task_cgroup_from_root(tsk, root);
> +			if (!cgrp || !cgroup_tryget(cgrp))
> +				cgrp = ERR_PTR(-ENOENT);
> +		}

Ditto.

>  		break;
>  	}
>  
> diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
> index 46b677a066d1..ea98679b01e1 100644
> --- a/kernel/cgroup/cgroup.c
> +++ b/kernel/cgroup/cgroup.c
> @@ -335,28 +335,23 @@ static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end,
>  	int ret;
>  
>  	idr_preload(gfp_mask);
> -	spin_lock_bh(&cgroup_idr_lock);
> -	ret = idr_alloc(idr, ptr, start, end, gfp_mask & ~__GFP_DIRECT_RECLAIM);
> -	spin_unlock_bh(&cgroup_idr_lock);
> +	scoped_guard(spinlock_bh, &cgroup_idr_lock) {
> +		ret = idr_alloc(idr, ptr, start, end, gfp_mask & ~__GFP_DIRECT_RECLAIM);
> +	}
>  	idr_preload_end();
>  	return ret;
>  }
>  
>  static void *cgroup_idr_replace(struct idr *idr, void *ptr, int id)
>  {
> -	void *ret;
> -
> -	spin_lock_bh(&cgroup_idr_lock);
> -	ret = idr_replace(idr, ptr, id);
> -	spin_unlock_bh(&cgroup_idr_lock);
> -	return ret;
> +	guard(spinlock_bh)(&cgroup_idr_lock);
> +	return idr_replace(idr, ptr, id);
>  }
>  
>  static void cgroup_idr_remove(struct idr *idr, int id)
>  {
> -	spin_lock_bh(&cgroup_idr_lock);
> +	guard(spinlock_bh)(&cgroup_idr_lock);
>  	idr_remove(idr, id);
> -	spin_unlock_bh(&cgroup_idr_lock);
>  }
>  
>  static bool cgroup_has_tasks(struct cgroup *cgrp)
> @@ -583,20 +578,19 @@ struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgrp,
>  	if (!CGROUP_HAS_SUBSYS_CONFIG)
>  		return NULL;
>  
> -	rcu_read_lock();
> +	guard(rcu)();
>  
>  	do {
>  		css = cgroup_css(cgrp, ss);
>  
>  		if (css && css_tryget_online(css))
> -			goto out_unlock;
> +			return css;
>  		cgrp = cgroup_parent(cgrp);
>  	} while (cgrp);
>  
>  	css = init_css_set.subsys[ss->id];
>  	css_get(css);
> -out_unlock:
> -	rcu_read_unlock();
> +
>  	return css;
>  }
>  EXPORT_SYMBOL_GPL(cgroup_get_e_css);

This should go to the RCU patch.

> @@ -1691,9 +1685,9 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
>  		struct cgroup_subsys_state *css = cgroup_css(cgrp, cft->ss);
>  		struct cgroup_file *cfile = (void *)css + cft->file_offset;
>  
> -		spin_lock_irq(&cgroup_file_kn_lock);
> -		cfile->kn = NULL;
> -		spin_unlock_irq(&cgroup_file_kn_lock);
> +		scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
> +			cfile->kn = NULL;
> +		}
>  
>  		timer_delete_sync(&cfile->notify_timer);
>  	}
> @@ -4277,9 +4271,9 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
>  
>  		timer_setup(&cfile->notify_timer, cgroup_file_notify_timer, 0);
>  
> -		spin_lock_irq(&cgroup_file_kn_lock);
> -		cfile->kn = kn;
> -		spin_unlock_irq(&cgroup_file_kn_lock);
> +		scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
> +			cfile->kn = kn;
> +		}
>  	}
>  
>  	return 0;
> @@ -4534,9 +4528,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
>   */
>  void cgroup_file_notify(struct cgroup_file *cfile)
>  {
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&cgroup_file_kn_lock, flags);
> +	guard(spinlock_irqsave)(&cgroup_file_kn_lock);
>  	if (cfile->kn) {
>  		unsigned long last = cfile->notified_at;
>  		unsigned long next = last + CGROUP_FILE_NOTIFY_MIN_INTV;
> @@ -4548,7 +4540,6 @@ void cgroup_file_notify(struct cgroup_file *cfile)
>  			cfile->notified_at = jiffies;
>  		}
>  	}
> -	spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
>  }
>  
>  /**
> @@ -4560,10 +4551,10 @@ void cgroup_file_show(struct cgroup_file *cfile, bool show)
>  {
>  	struct kernfs_node *kn;
>  
> -	spin_lock_irq(&cgroup_file_kn_lock);
> -	kn = cfile->kn;
> -	kernfs_get(kn);
> -	spin_unlock_irq(&cgroup_file_kn_lock);
> +	scoped_guard(spinlock_irq, &cgroup_file_kn_lock) {
> +		kn = cfile->kn;
> +		kernfs_get(kn);
> +	}
>  
>  	if (kn)
>  		kernfs_show(kn, show);
> @@ -4987,11 +4978,10 @@ static void css_task_iter_advance(struct css_task_iter *it)
>  void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
>  			 struct css_task_iter *it)
>  {
> -	unsigned long irqflags;
>  
>  	memset(it, 0, sizeof(*it));
>  
> -	spin_lock_irqsave(&css_set_lock, irqflags);
> +	guard(spinlock_irqsave)(&css_set_lock);
>  
>  	it->ss = css->ss;
>  	it->flags = flags;
> @@ -5004,8 +4994,6 @@ void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
>  	it->cset_head = it->cset_pos;
>  
>  	css_task_iter_advance(it);
> -
> -	spin_unlock_irqrestore(&css_set_lock, irqflags);
>  }
>  

css_set_lock

>  /**
> @@ -5018,14 +5006,12 @@ void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
>   */
>  struct task_struct *css_task_iter_next(struct css_task_iter *it)
>  {
> -	unsigned long irqflags;
> -
>  	if (it->cur_task) {
>  		put_task_struct(it->cur_task);
>  		it->cur_task = NULL;
>  	}
>  
> -	spin_lock_irqsave(&css_set_lock, irqflags);
> +	guard(spinlock_irqsave)(&css_set_lock);
>  
>  	/* @it may be half-advanced by skips, finish advancing */
>  	if (it->flags & CSS_TASK_ITER_SKIPPED)
> @@ -5038,8 +5024,6 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
>  		css_task_iter_advance(it);
>  	}
>  
> -	spin_unlock_irqrestore(&css_set_lock, irqflags);
> -
>  	return it->cur_task;
>  }
>  

css_set_lock

> @@ -5051,13 +5035,10 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
>   */
>  void css_task_iter_end(struct css_task_iter *it)
>  {
> -	unsigned long irqflags;
> -
>  	if (it->cur_cset) {
> -		spin_lock_irqsave(&css_set_lock, irqflags);
> +		guard(spinlock_irqsave)(&css_set_lock);
>  		list_del(&it->iters_node);
>  		put_css_set_locked(it->cur_cset);
> -		spin_unlock_irqrestore(&css_set_lock, irqflags);
>  	}
>  
>  	if (it->cur_dcset)

css_set_lock

> @@ -6737,10 +6718,10 @@ void cgroup_post_fork(struct task_struct *child,
>  				 * 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);
> +				scoped_guard(spinlock, &child->sighand->siglock) {
> +					WARN_ON_ONCE(child->frozen);
> +					child->jobctl |= JOBCTL_TRAP_FREEZE;
> +				}
>  
>  				/*
>  				 * Calling cgroup_update_frozen() isn't required here,
> -- 
> 2.43.0
> 
Re: [PATCH v1 3/3] cgroup: add lock guard support for others
Posted by kernel test robot 6 months, 2 weeks ago
Hi Jemmy,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tj-cgroup/for-next]
[also build test WARNING on linus/master next-20250606]
[cannot apply to v6.15]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jemmy-Wong/cgroup-add-lock-guard-support-for-cgroup_muetx/20250607-002109
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
patch link:    https://lore.kernel.org/r/20250606161841.44354-4-jemmywong512%40gmail.com
patch subject: [PATCH v1 3/3] cgroup: add lock guard support for others
config: sparc-randconfig-r121-20250607 (https://download.01.org/0day-ci/archive/20250607/202506071822.ERv4i34r-lkp@intel.com/config)
compiler: sparc-linux-gcc (GCC) 8.5.0
reproduce: (https://download.01.org/0day-ci/archive/20250607/202506071822.ERv4i34r-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506071822.ERv4i34r-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> kernel/cgroup/cgroup.c:6721:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *l @@     got struct spinlock [noderef] __rcu * @@
   kernel/cgroup/cgroup.c:6721:33: sparse:     expected struct spinlock [usertype] *l
   kernel/cgroup/cgroup.c:6721:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/cgroup/cgroup.c:345:13: sparse: sparse: context imbalance in 'cgroup_idr_replace' - wrong count at exit
   kernel/cgroup/cgroup.c:351:13: sparse: sparse: context imbalance in 'cgroup_idr_remove' - wrong count at exit
   kernel/cgroup/cgroup.c:626:5: sparse: sparse: context imbalance in 'cgroup_task_count' - wrong count at exit
   kernel/cgroup/cgroup.c:2225:9: sparse: sparse: context imbalance in 'cgroup_do_get_tree' - different lock contexts for basic block
   kernel/cgroup/cgroup.c:2418:5: sparse: sparse: context imbalance in 'cgroup_path_ns' - wrong count at exit
   kernel/cgroup/cgroup.c:2734:9: sparse: sparse: context imbalance in 'cgroup_migrate_finish' - wrong count at exit
   kernel/cgroup/cgroup.c:3131:9: sparse: sparse: context imbalance in 'cgroup_lock_and_drain_offline' - wrong count at exit
   kernel/cgroup/cgroup.c:4532:9: sparse: sparse: context imbalance in 'cgroup_file_notify' - wrong count at exit
   kernel/cgroup/cgroup.c:4994:9: sparse: sparse: context imbalance in 'css_task_iter_start' - wrong count at exit
   kernel/cgroup/cgroup.c:5027:9: sparse: sparse: context imbalance in 'css_task_iter_next' - wrong count at exit
   kernel/cgroup/cgroup.c:5047:9: sparse: sparse: context imbalance in 'css_task_iter_end' - wrong count at exit
   kernel/cgroup/cgroup.c:6485:12: sparse: sparse: context imbalance in 'cgroup_css_set_fork' - wrong count at exit
   kernel/cgroup/cgroup.c:6601:9: sparse: sparse: context imbalance in 'cgroup_css_set_put_fork' - wrong count at exit
   kernel/cgroup/cgroup.c:6621:5: sparse: sparse: context imbalance in 'cgroup_can_fork' - wrong count at exit
   kernel/cgroup/cgroup.c:6670:9: sparse: sparse: context imbalance in 'cgroup_cancel_fork' - unexpected unlock
   kernel/cgroup/cgroup.c:6813:9: sparse: sparse: context imbalance in 'cgroup_release' - different lock contexts for basic block

vim +6721 kernel/cgroup/cgroup.c

  6672	
  6673	/**
  6674	 * cgroup_post_fork - finalize cgroup setup for the child process
  6675	 * @child: the child process
  6676	 * @kargs: the arguments passed to create the child process
  6677	 *
  6678	 * Attach the child process to its css_set calling the subsystem fork()
  6679	 * callbacks.
  6680	 */
  6681	void cgroup_post_fork(struct task_struct *child,
  6682			      struct kernel_clone_args *kargs)
  6683		__releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex)
  6684	{
  6685		unsigned int cgrp_kill_seq = 0;
  6686		unsigned long cgrp_flags = 0;
  6687		bool kill = false;
  6688		struct cgroup_subsys *ss;
  6689		struct css_set *cset;
  6690		int i;
  6691	
  6692		cset = kargs->cset;
  6693		kargs->cset = NULL;
  6694	
  6695		scoped_guard(spinlock_irq, &css_set_lock) {
  6696			/* init tasks are special, only link regular threads */
  6697			if (likely(child->pid)) {
  6698				if (kargs->cgrp) {
  6699					cgrp_flags = kargs->cgrp->flags;
  6700					cgrp_kill_seq = kargs->cgrp->kill_seq;
  6701				} else {
  6702					cgrp_flags = cset->dfl_cgrp->flags;
  6703					cgrp_kill_seq = cset->dfl_cgrp->kill_seq;
  6704				}
  6705	
  6706				WARN_ON_ONCE(!list_empty(&child->cg_list));
  6707				cset->nr_tasks++;
  6708				css_set_move_task(child, NULL, cset, false);
  6709			} else {
  6710				put_css_set(cset);
  6711				cset = NULL;
  6712			}
  6713	
  6714			if (!(child->flags & PF_KTHREAD)) {
  6715				if (unlikely(test_bit(CGRP_FREEZE, &cgrp_flags))) {
  6716					/*
  6717					 * If the cgroup has to be frozen, the new task has
  6718					 * too. Let's set the JOBCTL_TRAP_FREEZE jobctl bit to
  6719					 * get the task into the frozen state.
  6720					 */
> 6721					scoped_guard(spinlock, &child->sighand->siglock) {
  6722						WARN_ON_ONCE(child->frozen);
  6723						child->jobctl |= JOBCTL_TRAP_FREEZE;
  6724					}
  6725	
  6726					/*
  6727					 * Calling cgroup_update_frozen() isn't required here,
  6728					 * because it will be called anyway a bit later from
  6729					 * do_freezer_trap(). So we avoid cgroup's transient
  6730					 * switch from the frozen state and back.
  6731					 */
  6732				}
  6733	
  6734				/*
  6735				 * If the cgroup is to be killed notice it now and take the
  6736				 * child down right after we finished preparing it for
  6737				 * userspace.
  6738				 */
  6739				kill = kargs->kill_seq != cgrp_kill_seq;
  6740			}
  6741		}
  6742		/*
  6743		 * Call ss->fork().  This must happen after @child is linked on
  6744		 * css_set; otherwise, @child might change state between ->fork()
  6745		 * and addition to css_set.
  6746		 */
  6747		do_each_subsys_mask(ss, i, have_fork_callback) {
  6748			ss->fork(child);
  6749		} while_each_subsys_mask();
  6750	
  6751		/* Make the new cset the root_cset of the new cgroup namespace. */
  6752		if (kargs->flags & CLONE_NEWCGROUP) {
  6753			struct css_set *rcset = child->nsproxy->cgroup_ns->root_cset;
  6754	
  6755			get_css_set(cset);
  6756			child->nsproxy->cgroup_ns->root_cset = cset;
  6757			put_css_set(rcset);
  6758		}
  6759	
  6760		/* Cgroup has to be killed so take down child immediately. */
  6761		if (unlikely(kill))
  6762			do_send_sig_info(SIGKILL, SEND_SIG_NOINFO, child, PIDTYPE_TGID);
  6763	
  6764		cgroup_css_set_put_fork(kargs);
  6765	}
  6766	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v1 3/3] cgroup: add lock guard support for others
Posted by Jemmy Wong 6 months, 1 week ago
Hi Peter, Dam, Ingo,

Do you have any recommendations to eliminate this false positive, given that sparse recognizes scoped_guard but not guard?

Looks like false positives. Some of these warnings were already present 
due to asymmetric lock/unlock behavior in a specific function,

while others were introduced by the use of guard, 
which can be resolved by replacing it with scoped_guard, 
but I don’t like this solution which could add additional indentation.

——

Previous warnings - caused by asymmetric lock/unlock:

kernel/cgroup/cgroup.c:3161:9: sparse: warning: context imbalance in 'cgroup_lock_and_drain_offline' - wrong count at exit
kernel/cgroup/cgroup.c:6530:12: sparse: warning: context imbalance in 'cgroup_css_set_fork' - wrong count at exit
kernel/cgroup/cgroup.c:6646:9: sparse: warning: context imbalance in 'cgroup_css_set_put_fork' - wrong count at exit
kernel/cgroup/cgroup.c:6666:5: sparse: warning: context imbalance in 'cgroup_can_fork' - wrong count at exit
kernel/cgroup/cgroup.c:6715:9: sparse: warning: context imbalance in 'cgroup_cancel_fork' - unexpected unlock

New warnings - caused by guard:

kernel/cgroup/cgroup.c:345:13: sparse: sparse: context imbalance in 'cgroup_idr_replace' - wrong count at exit
kernel/cgroup/cgroup.c:351:13: sparse: sparse: context imbalance in 'cgroup_idr_remove' - wrong count at exit
kernel/cgroup/cgroup.c:626:5: sparse: sparse: context imbalance in 'cgroup_task_count' - wrong count at exit
kernel/cgroup/cgroup.c:2225:9: sparse: sparse: context imbalance in 'cgroup_do_get_tree' - different lock contexts for basic block
kernel/cgroup/cgroup.c:2418:5: sparse: sparse: context imbalance in 'cgroup_path_ns' - wrong count at exit
kernel/cgroup/cgroup.c:2734:9: sparse: sparse: context imbalance in 'cgroup_migrate_finish' - wrong count at exit
kernel/cgroup/cgroup.c:4532:9: sparse: sparse: context imbalance in 'cgroup_file_notify' - wrong count at exit
kernel/cgroup/cgroup.c:4994:9: sparse: sparse: context imbalance in 'css_task_iter_start' - wrong count at exit
kernel/cgroup/cgroup.c:5027:9: sparse: sparse: context imbalance in 'css_task_iter_next' - wrong count at exit
kernel/cgroup/cgroup.c:5047:9: sparse: sparse: context imbalance in 'css_task_iter_end' - wrong count at exit

Best,
Jemmy

> On Jun 7, 2025, at 6:50 PM, kernel test robot <lkp@intel.com> wrote:
> 
> Hi Jemmy,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on tj-cgroup/for-next]
> [also build test WARNING on linus/master next-20250606]
> [cannot apply to v6.15]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Jemmy-Wong/cgroup-add-lock-guard-support-for-cgroup_muetx/20250607-002109
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
> patch link:    https://lore.kernel.org/r/20250606161841.44354-4-jemmywong512%40gmail.com
> patch subject: [PATCH v1 3/3] cgroup: add lock guard support for others
> config: sparc-randconfig-r121-20250607 (https://download.01.org/0day-ci/archive/20250607/202506071822.ERv4i34r-lkp@intel.com/config)
> compiler: sparc-linux-gcc (GCC) 8.5.0
> reproduce: (https://download.01.org/0day-ci/archive/20250607/202506071822.ERv4i34r-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202506071822.ERv4i34r-lkp@intel.com/
> 
> sparse warnings: (new ones prefixed by >>)
>>> kernel/cgroup/cgroup.c:6721:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *l @@     got struct spinlock [noderef] __rcu * @@
>   kernel/cgroup/cgroup.c:6721:33: sparse:     expected struct spinlock [usertype] *l
>   kernel/cgroup/cgroup.c:6721:33: sparse:     got struct spinlock [noderef] __rcu *
>   kernel/cgroup/cgroup.c:345:13: sparse: sparse: context imbalance in 'cgroup_idr_replace' - wrong count at exit
>   kernel/cgroup/cgroup.c:351:13: sparse: sparse: context imbalance in 'cgroup_idr_remove' - wrong count at exit
>   kernel/cgroup/cgroup.c:626:5: sparse: sparse: context imbalance in 'cgroup_task_count' - wrong count at exit
>   kernel/cgroup/cgroup.c:2225:9: sparse: sparse: context imbalance in 'cgroup_do_get_tree' - different lock contexts for basic block
>   kernel/cgroup/cgroup.c:2418:5: sparse: sparse: context imbalance in 'cgroup_path_ns' - wrong count at exit
>   kernel/cgroup/cgroup.c:2734:9: sparse: sparse: context imbalance in 'cgroup_migrate_finish' - wrong count at exit
>   kernel/cgroup/cgroup.c:3131:9: sparse: sparse: context imbalance in 'cgroup_lock_and_drain_offline' - wrong count at exit
>   kernel/cgroup/cgroup.c:4532:9: sparse: sparse: context imbalance in 'cgroup_file_notify' - wrong count at exit
>   kernel/cgroup/cgroup.c:4994:9: sparse: sparse: context imbalance in 'css_task_iter_start' - wrong count at exit
>   kernel/cgroup/cgroup.c:5027:9: sparse: sparse: context imbalance in 'css_task_iter_next' - wrong count at exit
>   kernel/cgroup/cgroup.c:5047:9: sparse: sparse: context imbalance in 'css_task_iter_end' - wrong count at exit
>   kernel/cgroup/cgroup.c:6485:12: sparse: sparse: context imbalance in 'cgroup_css_set_fork' - wrong count at exit
>   kernel/cgroup/cgroup.c:6601:9: sparse: sparse: context imbalance in 'cgroup_css_set_put_fork' - wrong count at exit
>   kernel/cgroup/cgroup.c:6621:5: sparse: sparse: context imbalance in 'cgroup_can_fork' - wrong count at exit
>   kernel/cgroup/cgroup.c:6670:9: sparse: sparse: context imbalance in 'cgroup_cancel_fork' - unexpected unlock
>   kernel/cgroup/cgroup.c:6813:9: sparse: sparse: context imbalance in 'cgroup_release' - different lock contexts for basic block
> 
> vim +6721 kernel/cgroup/cgroup.c
> 
>  6672 
>  6673 /**
>  6674 * cgroup_post_fork - finalize cgroup setup for the child process
>  6675 * @child: the child process
>  6676 * @kargs: the arguments passed to create the child process
>  6677 *
>  6678 * Attach the child process to its css_set calling the subsystem fork()
>  6679 * callbacks.
>  6680 */
>  6681 void cgroup_post_fork(struct task_struct *child,
>  6682      struct kernel_clone_args *kargs)
>  6683 __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex)
>  6684 {
>  6685 unsigned int cgrp_kill_seq = 0;
>  6686 unsigned long cgrp_flags = 0;
>  6687 bool kill = false;
>  6688 struct cgroup_subsys *ss;
>  6689 struct css_set *cset;
>  6690 int i;
>  6691 
>  6692 cset = kargs->cset;
>  6693 kargs->cset = NULL;
>  6694 
>  6695 scoped_guard(spinlock_irq, &css_set_lock) {
>  6696 /* init tasks are special, only link regular threads */
>  6697 if (likely(child->pid)) {
>  6698 if (kargs->cgrp) {
>  6699 cgrp_flags = kargs->cgrp->flags;
>  6700 cgrp_kill_seq = kargs->cgrp->kill_seq;
>  6701 } else {
>  6702 cgrp_flags = cset->dfl_cgrp->flags;
>  6703 cgrp_kill_seq = cset->dfl_cgrp->kill_seq;
>  6704 }
>  6705 
>  6706 WARN_ON_ONCE(!list_empty(&child->cg_list));
>  6707 cset->nr_tasks++;
>  6708 css_set_move_task(child, NULL, cset, false);
>  6709 } else {
>  6710 put_css_set(cset);
>  6711 cset = NULL;
>  6712 }
>  6713 
>  6714 if (!(child->flags & PF_KTHREAD)) {
>  6715 if (unlikely(test_bit(CGRP_FREEZE, &cgrp_flags))) {
>  6716 /*
>  6717 * If the cgroup has to be frozen, the new task has
>  6718 * too. Let's set the JOBCTL_TRAP_FREEZE jobctl bit to
>  6719 * get the task into the frozen state.
>  6720 */
>> 6721 scoped_guard(spinlock, &child->sighand->siglock) {
>  6722 WARN_ON_ONCE(child->frozen);
>  6723 child->jobctl |= JOBCTL_TRAP_FREEZE;
>  6724 }
>  6725 
>  6726 /*
>  6727 * Calling cgroup_update_frozen() isn't required here,
>  6728 * because it will be called anyway a bit later from
>  6729 * do_freezer_trap(). So we avoid cgroup's transient
>  6730 * switch from the frozen state and back.
>  6731 */
>  6732 }
>  6733 
>  6734 /*
>  6735 * If the cgroup is to be killed notice it now and take the
>  6736 * child down right after we finished preparing it for
>  6737 * userspace.
>  6738 */
>  6739 kill = kargs->kill_seq != cgrp_kill_seq;
>  6740 }
>  6741 }
>  6742 /*
>  6743 * Call ss->fork().  This must happen after @child is linked on
>  6744 * css_set; otherwise, @child might change state between ->fork()
>  6745 * and addition to css_set.
>  6746 */
>  6747 do_each_subsys_mask(ss, i, have_fork_callback) {
>  6748 ss->fork(child);
>  6749 } while_each_subsys_mask();
>  6750 
>  6751 /* Make the new cset the root_cset of the new cgroup namespace. */
>  6752 if (kargs->flags & CLONE_NEWCGROUP) {
>  6753 struct css_set *rcset = child->nsproxy->cgroup_ns->root_cset;
>  6754 
>  6755 get_css_set(cset);
>  6756 child->nsproxy->cgroup_ns->root_cset = cset;
>  6757 put_css_set(rcset);
>  6758 }
>  6759 
>  6760 /* Cgroup has to be killed so take down child immediately. */
>  6761 if (unlikely(kill))
>  6762 do_send_sig_info(SIGKILL, SEND_SIG_NOINFO, child, PIDTYPE_TGID);
>  6763 
>  6764 cgroup_css_set_put_fork(kargs);
>  6765 }
>  6766 
> 
> -- 
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki