aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/proc.txt9
-rw-r--r--fs/proc/task_mmu.c66
-rw-r--r--fs/proc/task_nommu.c49
-rw-r--r--include/linux/mm.h3
-rw-r--r--mm/util.c27
5 files changed, 48 insertions, 106 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index fde9fd06fa98..eaebf27539f5 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -356,7 +356,7 @@ address perms offset dev inode pathname
356a7cb1000-a7cb2000 ---p 00000000 00:00 0 356a7cb1000-a7cb2000 ---p 00000000 00:00 0
357a7cb2000-a7eb2000 rw-p 00000000 00:00 0 357a7cb2000-a7eb2000 rw-p 00000000 00:00 0
358a7eb2000-a7eb3000 ---p 00000000 00:00 0 358a7eb2000-a7eb3000 ---p 00000000 00:00 0
359a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001] 359a7eb3000-a7ed5000 rw-p 00000000 00:00 0
360a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 360a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
361a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6 361a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
362a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6 362a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
@@ -388,7 +388,6 @@ is not associated with a file:
388 388
389 [heap] = the heap of the program 389 [heap] = the heap of the program
390 [stack] = the stack of the main process 390 [stack] = the stack of the main process
391 [stack:1001] = the stack of the thread with tid 1001
392 [vdso] = the "virtual dynamic shared object", 391 [vdso] = the "virtual dynamic shared object",
393 the kernel system call handler 392 the kernel system call handler
394 393
@@ -396,10 +395,8 @@ is not associated with a file:
396 395
397The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint 396The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
398of the individual tasks of a process. In this file you will see a mapping marked 397of the individual tasks of a process. In this file you will see a mapping marked
399as [stack] if that task sees it as a stack. This is a key difference from the 398as [stack] if that task sees it as a stack. Hence, for the example above, the
400content of /proc/PID/maps, where you will see all mappings that are being used 399task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
401as stack by all of those tasks. Hence, for the example above, the task-level
402map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
403 400
40408048000-08049000 r-xp 00000000 03:00 8312 /opt/test 40108048000-08049000 r-xp 00000000 03:00 8312 /opt/test
40508049000-0804a000 rw-p 00001000 03:00 8312 /opt/test 40208049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
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');
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f1cd22f2df1a..0b50d7848e3a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1341,8 +1341,7 @@ static inline int stack_guard_page_end(struct vm_area_struct *vma,
1341 !vma_growsup(vma->vm_next, addr); 1341 !vma_growsup(vma->vm_next, addr);
1342} 1342}
1343 1343
1344extern struct task_struct *task_of_stack(struct task_struct *task, 1344int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t);
1345 struct vm_area_struct *vma, bool in_group);
1346 1345
1347extern unsigned long move_page_tables(struct vm_area_struct *vma, 1346extern unsigned long move_page_tables(struct vm_area_struct *vma,
1348 unsigned long old_addr, struct vm_area_struct *new_vma, 1347 unsigned long old_addr, struct vm_area_struct *new_vma,
diff --git a/mm/util.c b/mm/util.c
index c108a6542d05..4fb14ca5a419 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -230,36 +230,11 @@ void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
230} 230}
231 231
232/* Check if the vma is being used as a stack by this task */ 232/* Check if the vma is being used as a stack by this task */
233static int vm_is_stack_for_task(struct task_struct *t, 233int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t)
234 struct vm_area_struct *vma)
235{ 234{
236 return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); 235 return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
237} 236}
238 237
239/*
240 * Check if the vma is being used as a stack.
241 * If is_group is non-zero, check in the entire thread group or else
242 * just check in the current task. Returns the task_struct of the task
243 * that the vma is stack for. Must be called under rcu_read_lock().
244 */
245struct task_struct *task_of_stack(struct task_struct *task,
246 struct vm_area_struct *vma, bool in_group)
247{
248 if (vm_is_stack_for_task(task, vma))
249 return task;
250
251 if (in_group) {
252 struct task_struct *t;
253
254 for_each_thread(task, t) {
255 if (vm_is_stack_for_task(t, vma))
256 return t;
257 }
258 }
259
260 return NULL;
261}
262
263#if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT) 238#if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
264void arch_pick_mmap_layout(struct mm_struct *mm) 239void arch_pick_mmap_layout(struct mm_struct *mm)
265{ 240{