1 From 65376df582174ffcec9e6471bf5b0dd79ba05e4a Mon Sep 17 00:00:00 2001
2 From: Johannes Weiner <hannes@cmpxchg.org>
3 Date: Tue, 2 Feb 2016 16:57:29 -0800
4 Subject: proc: revert /proc/<pid>/maps [stack:TID] annotation
6 From: Johannes Weiner <hannes@cmpxchg.org>
8 commit 65376df582174ffcec9e6471bf5b0dd79ba05e4a upstream.
10 Commit b76437579d13 ("procfs: mark thread stack correctly in
11 proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps.
13 Finding the task of a stack VMA requires walking the entire thread list,
14 turning this into quadratic behavior: a thousand threads means a
15 thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a
18 The cost is not in proportion to the usefulness as described in the
21 Drop the [stack:TID] annotation to make /proc/<pid>/maps (and
22 /proc/<pid>/numa_maps) usable again for higher thread counts.
24 The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as
25 identifying the stack VMA there is an O(1) operation.
28 "The end users needed a way to identify thread stacks programmatically and
29 there wasn't a way to do that. I'm afraid I no longer remember (or have
30 access to the resources that would aid my memory since I changed
31 employers) the details of their requirement. However, I did do this on my
32 own time because I thought it was an interesting project for me and nobody
33 really gave any feedback then as to its utility, so as far as I am
34 concerned you could roll back the main thread maps information since the
35 information is available in the thread-specific files"
37 Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
38 Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
39 Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
40 Cc: Shaohua Li <shli@fb.com>
41 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
42 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
43 Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
44 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
47 Documentation/filesystems/proc.txt | 9 +----
48 fs/proc/task_mmu.c | 66 ++++++++++++-------------------------
49 fs/proc/task_nommu.c | 49 +++++++++++----------------
50 include/linux/mm.h | 3 -
51 mm/util.c | 27 ---------------
52 5 files changed, 48 insertions(+), 106 deletions(-)
54 --- a/Documentation/filesystems/proc.txt
55 +++ b/Documentation/filesystems/proc.txt
56 @@ -334,7 +334,7 @@ address perms offset dev in
57 a7cb1000-a7cb2000 ---p 00000000 00:00 0
58 a7cb2000-a7eb2000 rw-p 00000000 00:00 0
59 a7eb2000-a7eb3000 ---p 00000000 00:00 0
60 -a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001]
61 +a7eb3000-a7ed5000 rw-p 00000000 00:00 0
62 a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
63 a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
64 a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
65 @@ -366,7 +366,6 @@ is not associated with a file:
67 [heap] = the heap of the program
68 [stack] = the stack of the main process
69 - [stack:1001] = the stack of the thread with tid 1001
70 [vdso] = the "virtual dynamic shared object",
71 the kernel system call handler
73 @@ -374,10 +373,8 @@ is not associated with a file:
75 The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
76 of the individual tasks of a process. In this file you will see a mapping marked
77 -as [stack] if that task sees it as a stack. This is a key difference from the
78 -content of /proc/PID/maps, where you will see all mappings that are being used
79 -as stack by all of those tasks. Hence, for the example above, the task-level
80 -map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
81 +as [stack] if that task sees it as a stack. Hence, for the example above, the
82 +task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
84 08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
85 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
86 --- a/fs/proc/task_mmu.c
87 +++ b/fs/proc/task_mmu.c
88 @@ -243,23 +243,29 @@ static int do_maps_open(struct inode *in
89 sizeof(struct proc_maps_private));
92 -static pid_t pid_of_stack(struct proc_maps_private *priv,
93 - struct vm_area_struct *vma, bool is_pid)
95 + * Indicate if the VMA is a stack for the given task; for
96 + * /proc/PID/maps that is the stack of the main task.
98 +static int is_stack(struct proc_maps_private *priv,
99 + struct vm_area_struct *vma, int is_pid)
101 - struct inode *inode = priv->inode;
102 - struct task_struct *task;
107 + stack = vma->vm_start <= vma->vm_mm->start_stack &&
108 + vma->vm_end >= vma->vm_mm->start_stack;
110 + struct inode *inode = priv->inode;
111 + struct task_struct *task;
114 - task = pid_task(proc_pid(inode), PIDTYPE_PID);
116 - task = task_of_stack(task, vma, is_pid);
118 + task = pid_task(proc_pid(inode), PIDTYPE_PID);
120 - ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
121 + stack = vma_is_stack_for_task(vma, task);
131 @@ -315,8 +321,6 @@ show_map_vma(struct seq_file *m, struct
133 name = arch_vma_name(vma);
140 @@ -328,21 +332,8 @@ show_map_vma(struct seq_file *m, struct
144 - tid = pid_of_stack(priv, vma, is_pid);
147 - * Thread stack in /proc/PID/task/TID/maps or
148 - * the main process stack.
150 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
151 - vma->vm_end >= mm->start_stack)) {
154 - /* Thread stack in /proc/PID/maps */
156 - seq_printf(m, "[stack:%d]", tid);
159 + if (is_stack(priv, vma, is_pid))
164 @@ -1510,19 +1501,8 @@ static int show_numa_map(struct seq_file
165 seq_path(m, &file->f_path, "\n\t= ");
166 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
167 seq_puts(m, " heap");
169 - pid_t tid = pid_of_stack(proc_priv, vma, is_pid);
172 - * Thread stack in /proc/PID/task/TID/maps or
173 - * the main process stack.
175 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
176 - vma->vm_end >= mm->start_stack))
177 - seq_puts(m, " stack");
179 - seq_printf(m, " stack:%d", tid);
181 + } else if (is_stack(proc_priv, vma, is_pid)) {
182 + seq_puts(m, " stack");
185 if (is_vm_hugetlb_page(vma))
186 --- a/fs/proc/task_nommu.c
187 +++ b/fs/proc/task_nommu.c
188 @@ -123,23 +123,26 @@ unsigned long task_statm(struct mm_struc
192 -static pid_t pid_of_stack(struct proc_maps_private *priv,
193 - struct vm_area_struct *vma, bool is_pid)
194 +static int is_stack(struct proc_maps_private *priv,
195 + struct vm_area_struct *vma, int is_pid)
197 - struct inode *inode = priv->inode;
198 - struct task_struct *task;
202 - task = pid_task(proc_pid(inode), PIDTYPE_PID);
204 - task = task_of_stack(task, vma, is_pid);
205 + struct mm_struct *mm = vma->vm_mm;
209 + stack = vma->vm_start <= mm->start_stack &&
210 + vma->vm_end >= mm->start_stack;
212 + struct inode *inode = priv->inode;
213 + struct task_struct *task;
216 + task = pid_task(proc_pid(inode), PIDTYPE_PID);
218 - ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
219 + stack = vma_is_stack_for_task(vma, task);
229 @@ -181,21 +184,9 @@ static int nommu_vma_show(struct seq_fil
232 seq_path(m, &file->f_path, "");
234 - pid_t tid = pid_of_stack(priv, vma, is_pid);
239 - * Thread stack in /proc/PID/task/TID/maps or
240 - * the main process stack.
242 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
243 - vma->vm_end >= mm->start_stack))
244 - seq_printf(m, "[stack]");
246 - seq_printf(m, "[stack:%d]", tid);
248 + } else if (mm && is_stack(priv, vma, is_pid)) {
250 + seq_printf(m, "[stack]");
254 --- a/include/linux/mm.h
255 +++ b/include/linux/mm.h
256 @@ -1242,8 +1242,7 @@ int set_page_dirty_lock(struct page *pag
257 int clear_page_dirty_for_io(struct page *page);
258 int get_cmdline(struct task_struct *task, char *buffer, int buflen);
260 -extern struct task_struct *task_of_stack(struct task_struct *task,
261 - struct vm_area_struct *vma, bool in_group);
262 +int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t);
264 extern unsigned long move_page_tables(struct vm_area_struct *vma,
265 unsigned long old_addr, struct vm_area_struct *new_vma,
268 @@ -185,36 +185,11 @@ void __vma_link_list(struct mm_struct *m
271 /* Check if the vma is being used as a stack by this task */
272 -static int vm_is_stack_for_task(struct task_struct *t,
273 - struct vm_area_struct *vma)
274 +int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t)
276 return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
280 - * Check if the vma is being used as a stack.
281 - * If is_group is non-zero, check in the entire thread group or else
282 - * just check in the current task. Returns the task_struct of the task
283 - * that the vma is stack for. Must be called under rcu_read_lock().
285 -struct task_struct *task_of_stack(struct task_struct *task,
286 - struct vm_area_struct *vma, bool in_group)
288 - if (vm_is_stack_for_task(task, vma))
292 - struct task_struct *t;
294 - for_each_thread(task, t) {
295 - if (vm_is_stack_for_task(t, vma))
303 #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
304 void arch_pick_mmap_layout(struct mm_struct *mm)