Skip to contentSkip to conversation

-mm/linux-next: procfs: Mark thread stack correctly in proc/<pid>/maps

PATCH Andrew Morton 4 participants 6 messages Mar 13, 2012 – Mar 26, 2012 2 messages not in the archive

Subsystems (6)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

Andrew Morton

author maintainer
#2 lore raw
Quoted 1 line · On Tue, 13 Mar 2012 23:04:36 +0530 Siddhesh Poyarekar…

Following is the updated patch with requested changes incorporated.

Boy, that's a lot of changes (below). What does it all do?

Why did the sched.h inclusions get taken out again?

 Documentation/filesystems/proc.txt |   36 +++++++++++++---
 fs/proc/task_mmu.c                 |   59 ++++++++++++++++++---------
 fs/proc/task_nommu.c               |   11 ++++-
 mm/memory.c                        |   38 -----------------
 mm/nommu.c                         |   40 ------------------
 mm/util.c                          |   41 ++++++++++++++++++
 6 files changed, 121 insertions(+), 104 deletions(-)
Documentation/filesystems/proc.txt renamed from Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +29 -7
diff -puN Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 Documentation/filesystems/proc.txt
@@ -325,7 +325,7 @@ address           perms offset  dev   in
 a7cb1000-a7cb2000 ---p 00000000 00:00 0
 a7cb2000-a7eb2000 rw-p 00000000 00:00 0
 a7eb2000-a7eb3000 ---p 00000000 00:00 0
-a7eb3000-a7ed5000 rw-p 00000000 00:00 0
+a7eb3000-a7ed5000 rw-p 00000000 00:00 0          [stack:1001]
 a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
 a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
 a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6
@@ -337,7 +337,7 @@ a8024000-a8027000 rw-p 00000000 00:00 0
 a8027000-a8043000 r-xp 00000000 03:00 8317       /lib/ld-linux.so.2
 a8043000-a8044000 r--p 0001b000 03:00 8317       /lib/ld-linux.so.2
 a8044000-a8045000 rw-p 0001c000 03:00 8317       /lib/ld-linux.so.2
-aff35000-aff4a000 rw-p 00000000 00:00 0          [stack:1001]
+aff35000-aff4a000 rw-p 00000000 00:00 0          [stack]
 ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
 
 where "address" is the address space in the process that it occupies, "perms"
@@ -356,8 +356,8 @@ The "pathname" shows the name associated
 is not associated with a file:
 
  [heap]                   = the heap of the program
- [stack:1001]             = the mapping is used as a stack by the thread
-                            with tid 1001
+ [stack]                  = the stack of the main process
+ [stack:1001]             = the stack of the thread with tid 1001
  [vdso]                   = the "virtual dynamic shared object",
                             the kernel system call handler
 
@@ -365,9 +365,31 @@ is not associated with a file:
 
 The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
 of the individual tasks of a process. In this file you will see a mapping marked
-as [stack:TID] only if that task sees it as a stack. This is a key difference
-from the content of /proc/PID/maps, where you will see all mappings that are
-being used as stack by all of those tasks.
+as [stack] if that task sees it as a stack. This is a key difference from the
+content of /proc/PID/maps, where you will see all mappings that are being used
+as stack by all of those tasks. Hence, for the example above, the task-level
+map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
+
+08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
+08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
+0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
+a7cb1000-a7cb2000 ---p 00000000 00:00 0
+a7cb2000-a7eb2000 rw-p 00000000 00:00 0
+a7eb2000-a7eb3000 ---p 00000000 00:00 0
+a7eb3000-a7ed5000 rw-p 00000000 00:00 0          [stack]
+a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
+a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
+a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6
+a800b000-a800e000 rw-p 00000000 00:00 0
+a800e000-a8022000 r-xp 00000000 03:00 14462      /lib/libpthread.so.0
+a8022000-a8023000 r--p 00013000 03:00 14462      /lib/libpthread.so.0
+a8023000-a8024000 rw-p 00014000 03:00 14462      /lib/libpthread.so.0
+a8024000-a8027000 rw-p 00000000 00:00 0
+a8027000-a8043000 r-xp 00000000 03:00 8317       /lib/ld-linux.so.2
+a8043000-a8044000 r--p 0001b000 03:00 8317       /lib/ld-linux.so.2
+a8044000-a8045000 rw-p 0001c000 03:00 8317       /lib/ld-linux.so.2
+aff35000-aff4a000 rw-p 00000000 00:00 0
+ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
 
 The /proc/PID/smaps is an extension based on maps, showing the memory
 consumption for each of the process's mappings. For each of mappings there
fs/proc/task_mmu.c renamed from fs/proc/task_mmu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +41 -18

89 lines not on this page · raw message

fs/proc/task_nommu.c renamed from fs/proc/task_nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +10 -1
diff -puN fs/proc/task_nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 fs/proc/task_nommu.c
@@ -171,9 +171,18 @@ static int nommu_vma_show(struct seq_fil
 		seq_path(m, &file->f_path, "");
 	} else if (mm) {
 		pid_t tid = vm_is_stack(priv->task, vma, is_pid);
+
 		if (tid != 0) {
 			pad_len_spaces(m, len);
-			seq_printf(m, "[stack:%d]", tid);
+			/*
+			 * Thread stack in /proc/PID/task/TID/maps or
+			 * the main process stack.
+			 */
+			if (!is_pid || (vma->vm_start <= mm->start_stack &&
+			    vma->vm_end >= mm->start_stack))
+				seq_printf(m, "[stack]");
+			else
+				seq_printf(m, "[stack:%d]", tid);
 		}
 	}
 
mm/memory.c renamed from mm/memory.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +0 -38
diff -puN mm/memory.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/memory.c
@@ -57,7 +57,6 @@
 #include <linux/swapops.h>
 #include <linux/elf.h>
 #include <linux/gfp.h>
-#include <linux/sched.h>
 
 #include <asm/io.h>
 #include <asm/pgalloc.h>
@@ -113,13 +112,6 @@ __setup("norandmaps", disable_randmaps);
 unsigned long zero_pfn __read_mostly;
 unsigned long highest_memmap_pfn __read_mostly;
 
-/* Check if the vma is being used as a stack by this task */
-static int vm_is_stack_for_task(struct task_struct *t,
-				struct vm_area_struct *vma)
-{
-	return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
-}
-
 /*
  * CONFIG_MMU architectures set up ZERO_PAGE in their paging_init()
  */
@@ -3899,36 +3891,6 @@ void print_vma_addr(char *prefix, unsign
 	up_read(&current->mm->mmap_sem);
 }
 
-/*
- * Check if the vma is being used as a stack.
- * If is_group is non-zero, check in the entire thread group or else
- * just check in the current task. Returns the pid of the task that
- * the vma is stack for.
- */
-pid_t vm_is_stack(struct task_struct *task,
-		  struct vm_area_struct *vma, int in_group)
-{
-	pid_t ret = 0;
-
-	if (vm_is_stack_for_task(task, vma))
-		return task->pid;
-
-	if (in_group) {
-		struct task_struct *t = task;
-		rcu_read_lock();
-		while_each_thread(task, t) {
-			if (vm_is_stack_for_task(t, vma)) {
-				ret = t->pid;
-				goto done;
-			}
-		}
-	}
-
-done:
-	rcu_read_unlock();
-	return ret;
-}
-
 #ifdef CONFIG_PROVE_LOCKING
 void might_fault(void)
 {
mm/nommu.c renamed from mm/nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +0 -40
diff -puN mm/nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/nommu.c
@@ -29,7 +29,6 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
-#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
@@ -2095,42 +2094,3 @@ int nommu_shrink_inode_mappings(struct i
 	up_write(&nommu_region_sem);
 	return 0;
 }
-
-/* Check if the vma is being used as a stack by this task */
-static int vm_is_stack_for_task(struct task_struct *t,
-				struct vm_area_struct *vma)
-{
-	return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
-}
-
-/*
- * Check if the vma is being used as a stack.
- * If is_group is non-zero, check in the entire thread group or else
- * just check in the current task. Returns the pid of the task that
- * the vma is stack for.
- */
-pid_t vm_is_stack(struct task_struct *task,
-		  struct vm_area_struct *vma, int in_group)
-{
-	pid_t ret = 0;
-
-	if (vm_is_stack_for_task(task, vma))
-		return task->pid;
-
-	if (in_group) {
-		struct task_struct *t;
-		rcu_read_lock();
-		t = list_first_entry_rcu(&task->thread_group,
-					 struct task_struct, thread_group);
-		do {
-			if (vm_is_stack_for_task(t, vma)) {
-				ret = t->pid;
-				goto done;
-			}
-		} while_each_thread(task, t);
-done:
-		rcu_read_unlock();
-	}
-
-	return ret;
-}
mm/util.c renamed from mm/util.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +41 -0

47 lines not on this page · raw message

_

#3 lore raw
Quoted 4 lines · Andrew Morton

Boy, that's a lot of changes (below).  What does it all do?

Why did the sched.h inclusions get taken out again?

Most of it is code shuffling in addition to the feature change I mentioned earlier. I've elaborated on the changes inline.

Quoted 3 lines

diff -puN Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 Documentation/filesystems/proc.txt

Documentation/filesystems/proc.txt renamed from Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +0 -0

<snip>

Quoted 21 lines

 The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint of the individual tasks of a process. In this file you will see a mapping marked

Documentation/filesystems/proc.txt renamed from Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +15 -3
-as [stack:TID] only if that task sees it as a stack. This is a key difference
-from the content of /proc/PID/maps, where you will see all mappings that are
-being used as stack by all of those tasks.
+as [stack] if that task sees it as a stack. This is a key difference from the
+content of /proc/PID/maps, where you will see all mappings that are being used
+as stack by all of those tasks. Hence, for the example above, the task-level
+map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
+
+08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
+08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
+0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
+a7cb1000-a7cb2000 ---p 00000000 00:00 0
+a7cb2000-a7eb2000 rw-p 00000000 00:00 0
+a7eb2000-a7eb3000 ---p 00000000 00:00 0
+a7eb3000-a7ed5000 rw-p 00000000 00:00 0          [stack]
+a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
+a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
+a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6

Documentation/filesystems/proc.txt is not associated with a file: · line 392

Quoted 10 lines
Documentation/filesystems/proc.txt renamed from Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +10 -0
+a800b000-a800e000 rw-p 00000000 00:00 0
+a800e000-a8022000 r-xp 00000000 03:00 14462      /lib/libpthread.so.0
+a8022000-a8023000 r--p 00013000 03:00 14462      /lib/libpthread.so.0
+a8023000-a8024000 rw-p 00014000 03:00 14462      /lib/libpthread.so.0
+a8024000-a8027000 rw-p 00000000 00:00 0
+a8027000-a8043000 r-xp 00000000 03:00 8317       /lib/ld-linux.so.2
+a8043000-a8044000 r--p 0001b000 03:00 8317       /lib/ld-linux.so.2
+a8044000-a8045000 rw-p 0001c000 03:00 8317       /lib/ld-linux.so.2
+aff35000-aff4a000 rw-p 00000000 00:00 0
+ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]

I extended the documentation a bit to give an example of how /proc/PID/task/TID/maps would look like. This reflects the feature change that KOSAKI-san requested (keeping process stack as [stack] in /proc/PID/maps).

Quoted 82 lines
fs/proc/task_mmu.c renamed from fs/proc/task_mmu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +32 -18
@@ -222,7 +222,7 @@ show_map_vma(struct seq_file *m, struct
        unsigned long start, end;
        dev_t dev = 0;
        int len;
-       const char *name;
+       const char *name = NULL;
 
        if (file) {
                struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
@@ -256,33 +256,47 @@ show_map_vma(struct seq_file *m, struct
        if (file) {
                pad_len_spaces(m, len);
                seq_path(m, &file->f_path, "\n");
-               goto out;
+               goto done;
        }
 
        name = arch_vma_name(vma);
        if (!name) {
-               if (mm) {
-                       if (vma->vm_start <= mm->brk &&
-                                       vma->vm_end >= mm->start_brk) {
-                               name = "[heap]";
-                       } else {
-                               pid_t tid;
+               pid_t tid;
 
-                               tid = vm_is_stack(task, vma, is_pid);
-                               if (tid != 0) {
-                                       pad_len_spaces(m, len);
-                                       seq_printf(m, "[stack:%d]", tid);
-                               }
-                       }
-               } else {
+               if (!mm) {
                        name = "[vdso]";
+                       goto done;
+               }
+
+               if (vma->vm_start <= mm->brk &&
+                   vma->vm_end >= mm->start_brk) {
+                       name = "[heap]";
+                       goto done;
+               }
+
+               tid = vm_is_stack(task, vma, is_pid);
+
+               if (tid !=0) {
+                       /*
+                        * Thread stack in /proc/PID/task/TID/maps or
+                        * the main process stack.
+                        */
+                       if (!is_pid || (vma->vm_start <= mm->start_stack &&
+                           vma->vm_end >= mm->start_stack)) {
+                               name = "[stack]";
+                       } else {
+                               /* Thread stack in /proc/PID/maps */
+                               pad_len_spaces(m, len);
+                               seq_printf(m, "[stack:%d]", tid);
+                       }
                }
        }
+
+done:
        if (name) {
                pad_len_spaces(m, len);
                seq_puts(m, name);
        }
-out:
        seq_putc(m, '\n');
  }
 
@@ -1134,8 +1148,17 @@ static int show_numa_map(struct seq_file
                seq_printf(m, " heap");
        } else {
                pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid);
-               if (tid != 0)
-                       seq_printf(m, " stack:%d", tid);
+               if (tid !=0) {
+                       /*

fs/proc/task_mmu.c static int show_numa_map(struct seq_file · line 1162

Quoted 10 lines
fs/proc/task_mmu.c renamed from fs/proc/task_mmu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +9 -0
+                        * Thread stack in /proc/PID/task/TID/maps or
+                        * the main process stack.
+                        */
+                       if (!is_pid || (vma->vm_start <= mm->start_stack &&
+                           vma->vm_end >= mm->start_stack))
+                               seq_printf(m, " stack");
+                       else
+                               seq_printf(m, " stack:%d", tid);
+               }
        }

The request to keep process stack marked as [stack] meant an additional nested condition, so I cleaned up the code like you had suggested earlier.

Quoted 51 lines

diff -puN mm/util.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/util.c

mm/util.c renamed from mm/util.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +41 -0
@@ -239,6 +239,47 @@ void __vma_link_list(struct mm_struct *m
                next->vm_prev = vma;
  }
 
+/* Check if the vma is being used as a stack by this task */
+static int vm_is_stack_for_task(struct task_struct *t,
+                               struct vm_area_struct *vma)
+{
+       return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
+}
+
+/*
+ * Check if the vma is being used as a stack.
+ * If is_group is non-zero, check in the entire thread group or else
+ * just check in the current task. Returns the pid of the task that
+ * the vma is stack for.
+ */
+pid_t vm_is_stack(struct task_struct *task,
+                 struct vm_area_struct *vma, int in_group)
+{
+       pid_t ret = 0;
+
+       if (vm_is_stack_for_task(task, vma))
+               return task->pid;
+
+       if (in_group) {
+               struct task_struct *t;
+               rcu_read_lock();
+               if (!pid_alive(task))
+                       goto done;
+
+               t = task;
+               do {
+                       if (vm_is_stack_for_task(t, vma)) {
+                               ret = t->pid;
+                               goto done;
+                       }
+               } while_each_thread(task, t);
+done:
+               rcu_read_unlock();
+       }
+
+       return ret;
+}
+
  #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
  void arch_pick_mmap_layout(struct mm_struct *mm)
  {
Quoted 2 lines

_

I had duplicated the vm_is_stack functions for mmu and nommu in memory.c and nommu.c, which I unified and moved to util.c (above), which is built in both mmu and nommu and also seemed like a good enough place for it since it is a utility function. util.c already includes sched.h, which is why the sched.h inclusions are not needed anymore.

I forgot to mention how I have tested this:

* Build and functionality test on x86_64
* Build test for i386
* Build test for nommu with a bit of a hack; removing mmu code in x86 and building it as if it were nommu.

Signature · 2 lines
Siddhesh Poyarekar
http://siddhesh.in
#4 lore raw
In reply to Andrew Morton
Quoted 7 lines · Andrew Morton
Quoted 1 line · On Tue, 13 Mar 2012 23:04:36 +0530 Siddhesh Poyarekar…

Following is the updated patch with requested changes incorporated.

Boy, that's a lot of changes (below).  What does it all do?

Hi,

Since this patch was included in the -mm tree on March 14th, I assumed that linux-next would get the patch in today's merge, but it hasn't. Is there something I am missing? Does the patch need additional review/acks that I need to request for?

Thanks,
Siddhesh

Thanks,
Siddhesh

Signature · 2 lines
Siddhesh Poyarekar
http://siddhesh.in
#5 lore raw
Quoted 10 lines · Siddhesh Poyarekar
Quoted 7 lines · Andrew Morton
Quoted 1 line · On Tue, 13 Mar 2012 23:04:36 +0530 Siddhesh Poyarekar…

Following is the updated patch with requested changes incorporated.

Boy, that's a lot of changes (below).  What does it all do?

Quoted 6 lines

Hi,

Since this patch was included in the -mm tree on March 14th, I assumed that linux-next would get the patch in today's merge, but it hasn't. Is there something I am missing? Does the patch need additional review/acks that I need to request for?

Hi Siddhesh,

It looks like this still fails. The original failure was:

super.c:(.text+0x3ffd8): undefined reference to `vm_is_stack'

Now it is:

mm/nommu.o: In function `vm_is_stack':
nommu.c:(.text+0x2178): multiple definition of `vm_is_stack' mm/util.o:util.c:(.text+0x2bc): first defined here make[2]: *** [mm/built-in.o] Error 1

http://kisskb.ellerman.id.au/kisskb/buildresult/5941188/

Can you include in your testing for v3, the ARM at91x40_defconfig please?

Thanks,
Paul.

Quoted 15 lines

Thanks,
Siddhesh

Thanks,
Siddhesh

--
Siddhesh Poyarekar
http://siddhesh.in
--
To unsubscribe from this list: send the line "unsubscribe linux-next" in the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

#6 lore raw
Quoted 8 lines · Paul Gortmaker

Now it is:

mm/nommu.o: In function `vm_is_stack':
nommu.c:(.text+0x2178): multiple definition of `vm_is_stack' mm/util.o:util.c:(.text+0x2bc): first defined here make[2]: *** [mm/built-in.o] Error 1

http://kisskb.ellerman.id.au/kisskb/buildresult/5941188/

Looks like the problem is because this patch got included in linux-next 2 days ago:

http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=47d1ab583408e5b8e900c5080aec9bbcf210df22

When I had consolidated all of these changes into what Andrew got the v3 patch from, this patch should have been removed since I moved this function definition from memory.c and nommu.c into util.c, but it looks like the patch got merged in once again, causing the build error above. Dropping this patch should be sufficient to fix the build problem. This is also the reason why the March 22 build was successful (with my final changes) and the March 24 build wasn't (with this additional patch).

Signature · 2 lines
Siddhesh Poyarekar
http://siddhesh.in
#7 lore raw

Hi Siddhesh,

Quoted 10 lines · On Mon, 26 Mar 2012 08:32:35 +0530 Siddhesh Poyarekar…
Quoted 7 lines · Paul Gortmaker

Now it is:

mm/nommu.o: In function `vm_is_stack':
nommu.c:(.text+0x2178): multiple definition of `vm_is_stack' mm/util.o:util.c:(.text+0x2bc): first defined here make[2]: *** [mm/built-in.o] Error 1

Quoted 6 lines
Quoted 1 line

http://kisskb.ellerman.id.au/kisskb/buildresult/5941188/

Looks like the problem is because this patch got included in linux-next 2 days ago:

http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=47d1ab583408e5b8e900c5080aec9bbcf210df22

I will remove that patch today.

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/