aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2016-02-02 19:57:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-03 11:28:43 -0500
commit65376df582174ffcec9e6471bf5b0dd79ba05e4a (patch)
tree60c4841a00605605bf8c315783ed48648333e865 /fs/proc
parent5c2ff95e41c9290d16556cd02e35b25d81be8fe0 (diff)
proc: revert /proc/<pid>/maps [stack:TID] annotation
Commit b76437579d13 ("procfs: mark thread stack correctly in proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps. Finding the task of a stack VMA requires walking the entire thread list, turning this into quadratic behavior: a thousand threads means a thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a million combinations. The cost is not in proportion to the usefulness as described in the patch. Drop the [stack:TID] annotation to make /proc/<pid>/maps (and /proc/<pid>/numa_maps) usable again for higher thread counts. The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as identifying the stack VMA there is an O(1) operation. Siddesh said: "The end users needed a way to identify thread stacks programmatically and there wasn't a way to do that. I'm afraid I no longer remember (or have access to the resources that would aid my memory since I changed employers) the details of their requirement. However, I did do this on my own time because I thought it was an interesting project for me and nobody really gave any feedback then as to its utility, so as far as I am concerned you could roll back the main thread maps information since the information is available in the thread-specific files" Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Cc: "Kirill A. Shutemov" <kirill@shutemov.name> Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com> Cc: Shaohua Li <shli@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/task_mmu.c66
-rw-r--r--fs/proc/task_nommu.c49
2 files changed, 43 insertions, 72 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 4a0c31f904a6..fa95ab2d3674 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -259,23 +259,29 @@ static int do_maps_open(struct inode *inode, struct file *file,
259 sizeof(struct proc_maps_private)); 259 sizeof(struct proc_maps_private));
260} 260}
261 261
262static pid_t pid_of_stack(struct proc_maps_private *priv, 262/*
263 struct vm_area_struct *vma, bool is_pid) 263 * Indicate if the VMA is a stack for the given task; for
264 * /proc/PID/maps that is the stack of the main task.
265 */
266static int is_stack(struct proc_maps_private *priv,
267 struct vm_area_struct *vma, int is_pid)
264{ 268{
265 struct inode *inode = priv->inode; 269 int stack = 0;
266 struct task_struct *task; 270
267 pid_t ret = 0; 271 if (is_pid) {
272 stack = vma->vm_start <= vma->vm_mm->start_stack &&
273 vma->vm_end >= vma->vm_mm->start_stack;
274 } else {
275 struct inode *inode = priv->inode;
276 struct task_struct *task;
268 277
269 rcu_read_lock(); 278 rcu_read_lock();
270 task = pid_task(proc_pid(inode), PIDTYPE_PID); 279 task = pid_task(proc_pid(inode), PIDTYPE_PID);
271 if (task) {
272 task = task_of_stack(task, vma, is_pid);
273 if (task) 280 if (task)
274 ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info); 281 stack = vma_is_stack_for_task(vma, task);
282 rcu_read_unlock();
275 } 283 }
276 rcu_read_unlock(); 284 return stack;
277
278 return ret;
279} 285}
280 286
281static void 287static void
@@ -335,8 +341,6 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
335 341
336 name = arch_vma_name(vma); 342 name = arch_vma_name(vma);
337 if (!name) { 343 if (!name) {
338 pid_t tid;
339
340 if (!mm) { 344 if (!mm) {
341 name = "[vdso]"; 345 name = "[vdso]";
342 goto done; 346 goto done;
@@ -348,21 +352,8 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
348 goto done; 352 goto done;
349 } 353 }
350 354
351 tid = pid_of_stack(priv, vma, is_pid); 355 if (is_stack(priv, vma, is_pid))
352 if (tid != 0) { 356 name = "[stack]";
353 /*
354 * Thread stack in /proc/PID/task/TID/maps or
355 * the main process stack.
356 */
357 if (!is_pid || (vma->vm_start <= mm->start_stack &&
358 vma->vm_end >= mm->start_stack)) {
359 name = "[stack]";
360 } else {
361 /* Thread stack in /proc/PID/maps */
362 seq_pad(m, ' ');
363 seq_printf(m, "[stack:%d]", tid);
364 }
365 }
366 } 357 }
367 358
368done: 359done:
@@ -1618,19 +1609,8 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
1618 seq_file_path(m, file, "\n\t= "); 1609 seq_file_path(m, file, "\n\t= ");
1619 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { 1610 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
1620 seq_puts(m, " heap"); 1611 seq_puts(m, " heap");
1621 } else { 1612 } else if (is_stack(proc_priv, vma, is_pid)) {
1622 pid_t tid = pid_of_stack(proc_priv, vma, is_pid); 1613 seq_puts(m, " stack");
1623 if (tid != 0) {
1624 /*
1625 * Thread stack in /proc/PID/task/TID/maps or
1626 * the main process stack.
1627 */
1628 if (!is_pid || (vma->vm_start <= mm->start_stack &&
1629 vma->vm_end >= mm->start_stack))
1630 seq_puts(m, " stack");
1631 else
1632 seq_printf(m, " stack:%d", tid);
1633 }
1634 } 1614 }
1635 1615
1636 if (is_vm_hugetlb_page(vma)) 1616 if (is_vm_hugetlb_page(vma))
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index e0d64c92e4f6..faacb0c0d857 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -123,23 +123,26 @@ unsigned long task_statm(struct mm_struct *mm,
123 return size; 123 return size;
124} 124}
125 125
126static pid_t pid_of_stack(struct proc_maps_private *priv, 126static int is_stack(struct proc_maps_private *priv,
127 struct vm_area_struct *vma, bool is_pid) 127 struct vm_area_struct *vma, int is_pid)
128{ 128{
129 struct inode *inode = priv->inode; 129 struct mm_struct *mm = vma->vm_mm;
130 struct task_struct *task; 130 int stack = 0;
131 pid_t ret = 0; 131
132 132 if (is_pid) {
133 rcu_read_lock(); 133 stack = vma->vm_start <= mm->start_stack &&
134 task = pid_task(proc_pid(inode), PIDTYPE_PID); 134 vma->vm_end >= mm->start_stack;
135 if (task) { 135 } else {
136 task = task_of_stack(task, vma, is_pid); 136 struct inode *inode = priv->inode;
137 struct task_struct *task;
138
139 rcu_read_lock();
140 task = pid_task(proc_pid(inode), PIDTYPE_PID);
137 if (task) 141 if (task)
138 ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info); 142 stack = vma_is_stack_for_task(vma, task);
143 rcu_read_unlock();
139 } 144 }
140 rcu_read_unlock(); 145 return stack;
141
142 return ret;
143} 146}
144 147
145/* 148/*
@@ -181,21 +184,9 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
181 if (file) { 184 if (file) {
182 seq_pad(m, ' '); 185 seq_pad(m, ' ');
183 seq_file_path(m, file, ""); 186 seq_file_path(m, file, "");
184 } else if (mm) { 187 } else if (mm && is_stack(priv, vma, is_pid)) {
185 pid_t tid = pid_of_stack(priv, vma, is_pid); 188 seq_pad(m, ' ');
186 189 seq_printf(m, "[stack]");
187 if (tid != 0) {
188 seq_pad(m, ' ');
189 /*
190 * Thread stack in /proc/PID/task/TID/maps or
191 * the main process stack.
192 */
193 if (!is_pid || (vma->vm_start <= mm->start_stack &&
194 vma->vm_end >= mm->start_stack))
195 seq_printf(m, "[stack]");
196 else
197 seq_printf(m, "[stack:%d]", tid);
198 }
199 } 190 }
200 191
201 seq_putc(m, '\n'); 192 seq_putc(m, '\n');