]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
proc: rewrite next_tgid()
authorAlexey Dobriyan <adobriyan@gmail.com>
Wed, 22 Apr 2026 19:17:45 +0000 (22:17 +0300)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 29 May 2026 04:24:39 +0000 (21:24 -0700)
* deduplicate "iter.tgid += 1" line,
  Right now it is done once inside next_tgid() itself and second time
  inside "for" loop.

* deduplicate next_tgid() call itself with different loop style:

auto it = make_tgid_iter();
while (next_tgid(&it)) {
...
}

  gcc seems to inline it twice:

   $ ./scripts/bloat-o-meter ../vmlinux-000 ../obj/vmlinux
add/remove: 0/1 grow/shrink: 1/0 up/down: 100/-245 (-145)
Function                                     old     new   delta
proc_pid_readdir                             531     631    +100
next_tgid                                    245       -    -245

* make tgid_iter.pid_ns const
  it never changes during readdir anyway

[akpm@linux-foundation.org: remove newline]
Link: https://lore.kernel.org/20260422191745.435556-2-adobriyan@gmail.com
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/proc/base.c

index f2db455dbbfd2f48e6a81150e3ea516053401675..49344de1015823a1481bce82f9e33b5ffcc4efbc 100644 (file)
@@ -3543,30 +3543,42 @@ out:
 struct tgid_iter {
        unsigned int tgid;
        struct task_struct *task;
-       struct pid_namespace *pid_ns;
+       struct pid_namespace *const pid_ns;
 };
 
-static struct tgid_iter next_tgid(struct tgid_iter iter)
+static struct tgid_iter
+make_tgid_iter(unsigned int init_tgid, struct pid_namespace *pid_ns)
 {
-       struct pid *pid;
+       return (struct tgid_iter){
+               .tgid = init_tgid - 1,
+               .pid_ns = pid_ns,
+       };
+}
+
+static bool next_tgid(struct tgid_iter *it)
+{
+       if (it->task) {
+               put_task_struct(it->task);
+               it->task = NULL;
+       }
 
-       if (iter.task)
-               put_task_struct(iter.task);
        rcu_read_lock();
-retry:
-       iter.task = NULL;
-       pid = find_ge_pid(iter.tgid, iter.pid_ns);
-       if (pid) {
-               iter.tgid = pid_nr_ns(pid, iter.pid_ns);
-               iter.task = pid_task(pid, PIDTYPE_TGID);
-               if (!iter.task) {
-                       iter.tgid += 1;
-                       goto retry;
+       while (1) {
+               it->tgid += 1;
+               const auto pid = find_ge_pid(it->tgid, it->pid_ns);
+               if (pid) {
+                       it->tgid = pid_nr_ns(pid, it->pid_ns);
+                       it->task = pid_task(pid, PIDTYPE_TGID);
+                       if (it->task) {
+                               get_task_struct(it->task);
+                               rcu_read_unlock();
+                               return true;
+                       }
+               } else {
+                       rcu_read_unlock();
+                       return false;
                }
-               get_task_struct(iter.task);
        }
-       rcu_read_unlock();
-       return iter;
 }
 
 #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 2)
@@ -3574,7 +3586,6 @@ retry:
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 {
-       struct tgid_iter iter;
        struct proc_fs_info *fs_info = proc_sb_info(file_inode(file)->i_sb);
        struct pid_namespace *pid_ns = proc_pid_ns(file_inode(file)->i_sb);
        loff_t pos = ctx->pos;
@@ -3592,12 +3603,9 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
                        return 0;
                ctx->pos = pos = pos + 1;
        }
-       iter.tgid = pos - TGID_OFFSET;
-       iter.task = NULL;
-       iter.pid_ns = pid_ns;
-       for (iter = next_tgid(iter);
-            iter.task;
-            iter.tgid += 1, iter = next_tgid(iter)) {
+
+       auto iter = make_tgid_iter(pos - TGID_OFFSET, pid_ns);
+       while (next_tgid(&iter)) {
                char name[10 + 1];
                unsigned int len;