From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Morton Subject: Re: [PATCH] -mm/linux-next: procfs: Mark thread stack correctly in proc//maps Date: Tue, 13 Mar 2012 13:16:16 -0700 Message-ID: <20120313131616.f66dbdad.akpm@linux-foundation.org> References: <4F57A3EC.7070101@gmail.com> <1331660076-32766-1-git-send-email-siddhesh.poyarekar@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Return-path: Received: from mail.linuxfoundation.org ([140.211.169.12]:48746 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752577Ab2CMUQS (ORCPT ); Tue, 13 Mar 2012 16:16:18 -0400 In-Reply-To: <1331660076-32766-1-git-send-email-siddhesh.poyarekar@gmail.com> Sender: linux-next-owner@vger.kernel.org List-ID: To: Siddhesh Poyarekar Cc: linux-kernel@vger.kernel.org, linux-next , Alexander Viro , Alexey Dobriyan , Jamie Lokier , KOSAKI Motohiro , Matt Mackall , Mike Frysinger , Oleg Nesterov , Paul Gortmaker , Mark Salter On Tue, 13 Mar 2012 23:04:36 +0530 Siddhesh Poyarekar wrote: > 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(-) diff -puN Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/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 diff -puN fs/proc/task_mmu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 fs/proc/task_mmu.c --- a/fs/proc/task_mmu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/fs/proc/task_mmu.c @@ -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) { + /* + * 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); + } } if (is_vm_hugetlb_page(vma)) diff -puN fs/proc/task_nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 fs/proc/task_nommu.c --- a/fs/proc/task_nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/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); } } diff -puN mm/memory.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/memory.c --- a/mm/memory.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/mm/memory.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include @@ -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(¤t->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) { diff -puN mm/nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/nommu.c --- a/mm/nommu.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/mm/nommu.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -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; -} diff -puN mm/util.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 mm/util.c --- a/mm/util.c~procfs-mark-thread-stack-correctly-in-proc-pid-maps-v3 +++ a/mm/util.c @@ -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) { _