On 10/21/26 10:53 AM, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) 
to consider:
- [Low] tracing: fgraph: mix of scoped_guard() and goto in 
alloc_retstack_tasklist()
--

commit 7d59298fba17927bc12b63b0da1c66b0d138332a
Author: Vineet Gupta <[email protected]>

tracing: fgraph: use scoped_guard() for the task list walk

This commit replaces the explicit rcu_read_lock() and rcu_read_unlock() pair
in alloc_retstack_tasklist() with scoped_guard(rcu) and removes the unlock
label by jumping to the free label on the -EAGAIN path.

diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index 4c74f1a15ad48..bbf6e4e2da2d4 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -1057,32 +1057,31 @@ static int alloc_retstack_tasklist(unsigned long 
**ret_stack_list)
                }
        }
- rcu_read_lock();
-       for_each_process_thread(g, t) {
-               unsigned long *rs;
+       scoped_guard (rcu) {
+               for_each_process_thread(g, t) {
+                       unsigned long *rs;
- if (t->ret_stack)
-                       continue;
+                       if (t->ret_stack)
+                               continue;
- rs = kmem_cache_alloc(fgraph_stack_cachep, GFP_NOWAIT);
-               if (!rs) {
-                       if (start == end) {
-                               ret = -EAGAIN;
-                               goto unlock;
+                       rs = kmem_cache_alloc(fgraph_stack_cachep, GFP_NOWAIT);
+                       if (!rs) {
+                               if (start == end) {
+                                       ret = -EAGAIN;
+                                       goto free;
+                               }
+                               rs = ret_stack_list[start++];
                        }
-                       rs = ret_stack_list[start++];
-               }
- atomic_set(&t->trace_overrun, 0);
-               ret_stack_init_task_vars(rs);
-               t->curr_ret_stack = 0;
-               t->curr_ret_depth = -1;
-               /* Make sure the tasks see the 0 first: */
-               smp_store_release(&t->ret_stack, rs);
+                       atomic_set(&t->trace_overrun, 0);
+                       ret_stack_init_task_vars(rs);
+                       t->curr_ret_stack = 0;
+                       t->curr_ret_depth = -1;
+                       /* Make sure the tasks see the 0 first: */
+                       smp_store_release(&t->ret_stack, rs);
+               }
        }
-unlock:
-       rcu_read_unlock();
  free:
        for (i = start; i < end; i++)
                kmem_cache_free(fgraph_stack_cachep, ret_stack_list[i]);
[Severity: Low]
In kernel/trace/fgraph.c, alloc_retstack_tasklist() now uses
scoped_guard(rcu) while still jumping out of the guarded scope via goto free
when kmem_cache_alloc(fgraph_stack_cachep, GFP_NOWAIT) fails and start == end,
as well as jumping to free from the earlier pre-allocation loop:

kernel/trace/fgraph.c:alloc_retstack_tasklist() {
        for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
                ret_stack_list[i] = kmem_cache_alloc(fgraph_stack_cachep, 
GFP_KERNEL);
                if (!ret_stack_list[i]) {
                        start = 0;
                        end = i;
                        ret = -ENOMEM;
                        goto free;
                }
        }
}

The documentation in include/linux/cleanup.h notes that goto-based cleanup
and scope-based cleanup helpers should not be mixed within the same function:

  * Lastly, given that the benefit of cleanup helpers is removal of
  * "goto", and that the "goto" statement can jump between scopes, the
  * expectation is that usage of "goto" and cleanup helpers is never
  * mixed in the same function. I.e. for a given routine, convert all
  * resources that need a "goto" cleanup to scope-based cleanup, or
  * convert none of them.

Also, on the -EAGAIN path inside scoped_guard(rcu), start == end is already
true because all pre-allocated entries in ret_stack_list[] have been consumed,
so the cleanup loop at the free label runs zero iterations on that path.

Should alloc_retstack_tasklist() avoid mixing scoped_guard(rcu) with goto
free?

This has been discussed before and it was agreed this is fine.

Thx,
-Vineet

Reply via email to