aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/proc.txt5
-rw-r--r--fs/exec.c2
-rw-r--r--fs/proc/array.c85
-rw-r--r--fs/proc/task_mmu.c19
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/fork.c2
-rw-r--r--mm/Makefile4
7 files changed, 114 insertions, 4 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 75988ba26a51..b5aee7838a00 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -176,6 +176,7 @@ read the file /proc/PID/status:
176 CapBnd: ffffffffffffffff 176 CapBnd: ffffffffffffffff
177 voluntary_ctxt_switches: 0 177 voluntary_ctxt_switches: 0
178 nonvoluntary_ctxt_switches: 1 178 nonvoluntary_ctxt_switches: 1
179 Stack usage: 12 kB
179 180
180This shows you nearly the same information you would get if you viewed it with 181This shows you nearly the same information you would get if you viewed it with
181the ps command. In fact, ps uses the proc file system to obtain its 182the ps command. In fact, ps uses the proc file system to obtain its
@@ -229,6 +230,7 @@ Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
229 Mems_allowed_list Same as previous, but in "list format" 230 Mems_allowed_list Same as previous, but in "list format"
230 voluntary_ctxt_switches number of voluntary context switches 231 voluntary_ctxt_switches number of voluntary context switches
231 nonvoluntary_ctxt_switches number of non voluntary context switches 232 nonvoluntary_ctxt_switches number of non voluntary context switches
233 Stack usage: stack usage high water mark (round up to page size)
232.............................................................................. 234..............................................................................
233 235
234Table 1-3: Contents of the statm files (as of 2.6.8-rc3) 236Table 1-3: Contents of the statm files (as of 2.6.8-rc3)
@@ -307,7 +309,7 @@ address perms offset dev inode pathname
30708049000-0804a000 rw-p 00001000 03:00 8312 /opt/test 30908049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
3080804a000-0806b000 rw-p 00000000 00:00 0 [heap] 3100804a000-0806b000 rw-p 00000000 00:00 0 [heap]
309a7cb1000-a7cb2000 ---p 00000000 00:00 0 311a7cb1000-a7cb2000 ---p 00000000 00:00 0
310a7cb2000-a7eb2000 rw-p 00000000 00:00 0 312a7cb2000-a7eb2000 rw-p 00000000 00:00 0 [threadstack:001ff4b4]
311a7eb2000-a7eb3000 ---p 00000000 00:00 0 313a7eb2000-a7eb3000 ---p 00000000 00:00 0
312a7eb3000-a7ed5000 rw-p 00000000 00:00 0 314a7eb3000-a7ed5000 rw-p 00000000 00:00 0
313a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 315a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
@@ -343,6 +345,7 @@ is not associated with a file:
343 [stack] = the stack of the main process 345 [stack] = the stack of the main process
344 [vdso] = the "virtual dynamic shared object", 346 [vdso] = the "virtual dynamic shared object",
345 the kernel system call handler 347 the kernel system call handler
348 [threadstack:xxxxxxxx] = the stack of the thread, xxxxxxxx is the stack size
346 349
347 or if empty, the mapping is anonymous. 350 or if empty, the mapping is anonymous.
348 351
diff --git a/fs/exec.c b/fs/exec.c
index 69bb9d899791..5c833c18d0d4 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1357,6 +1357,8 @@ int do_execve(char * filename,
1357 if (retval < 0) 1357 if (retval < 0)
1358 goto out; 1358 goto out;
1359 1359
1360 current->stack_start = current->mm->start_stack;
1361
1360 /* execve succeeded */ 1362 /* execve succeeded */
1361 current->fs->in_exec = 0; 1363 current->fs->in_exec = 0;
1362 current->in_execve = 0; 1364 current->in_execve = 0;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 725a650bbbb8..0c6bc602e6c4 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -82,6 +82,7 @@
82#include <linux/pid_namespace.h> 82#include <linux/pid_namespace.h>
83#include <linux/ptrace.h> 83#include <linux/ptrace.h>
84#include <linux/tracehook.h> 84#include <linux/tracehook.h>
85#include <linux/swapops.h>
85 86
86#include <asm/pgtable.h> 87#include <asm/pgtable.h>
87#include <asm/processor.h> 88#include <asm/processor.h>
@@ -321,6 +322,87 @@ static inline void task_context_switch_counts(struct seq_file *m,
321 p->nivcsw); 322 p->nivcsw);
322} 323}
323 324
325struct stack_stats {
326 struct vm_area_struct *vma;
327 unsigned long startpage;
328 unsigned long usage;
329};
330
331static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr,
332 unsigned long end, struct mm_walk *walk)
333{
334 struct stack_stats *ss = walk->private;
335 struct vm_area_struct *vma = ss->vma;
336 pte_t *pte, ptent;
337 spinlock_t *ptl;
338 int ret = 0;
339
340 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
341 for (; addr != end; pte++, addr += PAGE_SIZE) {
342 ptent = *pte;
343
344#ifdef CONFIG_STACK_GROWSUP
345 if (pte_present(ptent) || is_swap_pte(ptent))
346 ss->usage = addr - ss->startpage + PAGE_SIZE;
347#else
348 if (pte_present(ptent) || is_swap_pte(ptent)) {
349 ss->usage = ss->startpage - addr + PAGE_SIZE;
350 pte++;
351 ret = 1;
352 break;
353 }
354#endif
355 }
356 pte_unmap_unlock(pte - 1, ptl);
357 cond_resched();
358 return ret;
359}
360
361static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma,
362 struct task_struct *task)
363{
364 struct stack_stats ss;
365 struct mm_walk stack_walk = {
366 .pmd_entry = stack_usage_pte_range,
367 .mm = vma->vm_mm,
368 .private = &ss,
369 };
370
371 if (!vma->vm_mm || is_vm_hugetlb_page(vma))
372 return 0;
373
374 ss.vma = vma;
375 ss.startpage = task->stack_start & PAGE_MASK;
376 ss.usage = 0;
377
378#ifdef CONFIG_STACK_GROWSUP
379 walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end,
380 &stack_walk);
381#else
382 walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE,
383 &stack_walk);
384#endif
385 return ss.usage;
386}
387
388static inline void task_show_stack_usage(struct seq_file *m,
389 struct task_struct *task)
390{
391 struct vm_area_struct *vma;
392 struct mm_struct *mm = get_task_mm(task);
393
394 if (mm) {
395 down_read(&mm->mmap_sem);
396 vma = find_vma(mm, task->stack_start);
397 if (vma)
398 seq_printf(m, "Stack usage:\t%lu kB\n",
399 get_stack_usage_in_bytes(vma, task) >> 10);
400
401 up_read(&mm->mmap_sem);
402 mmput(mm);
403 }
404}
405
324int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, 406int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
325 struct pid *pid, struct task_struct *task) 407 struct pid *pid, struct task_struct *task)
326{ 408{
@@ -340,6 +422,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
340 task_show_regs(m, task); 422 task_show_regs(m, task);
341#endif 423#endif
342 task_context_switch_counts(m, task); 424 task_context_switch_counts(m, task);
425 task_show_stack_usage(m, task);
343 return 0; 426 return 0;
344} 427}
345 428
@@ -481,7 +564,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
481 rsslim, 564 rsslim,
482 mm ? mm->start_code : 0, 565 mm ? mm->start_code : 0,
483 mm ? mm->end_code : 0, 566 mm ? mm->end_code : 0,
484 (permitted && mm) ? mm->start_stack : 0, 567 (permitted) ? task->stack_start : 0,
485 esp, 568 esp,
486 eip, 569 eip,
487 /* The signal information here is obsolete. 570 /* The signal information here is obsolete.
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 366b1017a4f1..2a1bef9203c6 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -243,6 +243,25 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
243 } else if (vma->vm_start <= mm->start_stack && 243 } else if (vma->vm_start <= mm->start_stack &&
244 vma->vm_end >= mm->start_stack) { 244 vma->vm_end >= mm->start_stack) {
245 name = "[stack]"; 245 name = "[stack]";
246 } else {
247 unsigned long stack_start;
248 struct proc_maps_private *pmp;
249
250 pmp = m->private;
251 stack_start = pmp->task->stack_start;
252
253 if (vma->vm_start <= stack_start &&
254 vma->vm_end >= stack_start) {
255 pad_len_spaces(m, len);
256 seq_printf(m,
257 "[threadstack:%08lx]",
258#ifdef CONFIG_STACK_GROWSUP
259 vma->vm_end - stack_start
260#else
261 stack_start - vma->vm_start
262#endif
263 );
264 }
246 } 265 }
247 } else { 266 } else {
248 name = "[vdso]"; 267 name = "[vdso]";
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6448bbc6406b..3cbc6c0be666 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1529,6 +1529,7 @@ struct task_struct {
1529 /* bitmask of trace recursion */ 1529 /* bitmask of trace recursion */
1530 unsigned long trace_recursion; 1530 unsigned long trace_recursion;
1531#endif /* CONFIG_TRACING */ 1531#endif /* CONFIG_TRACING */
1532 unsigned long stack_start;
1532}; 1533};
1533 1534
1534/* Future-safe accessor for struct task_struct's cpus_allowed. */ 1535/* Future-safe accessor for struct task_struct's cpus_allowed. */
diff --git a/kernel/fork.c b/kernel/fork.c
index 7cf45812ce84..8f45b0ebdda7 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1095,6 +1095,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1095 1095
1096 p->bts = NULL; 1096 p->bts = NULL;
1097 1097
1098 p->stack_start = stack_start;
1099
1098 /* Perform scheduler related setup. Assign this task to a CPU. */ 1100 /* Perform scheduler related setup. Assign this task to a CPU. */
1099 sched_fork(p, clone_flags); 1101 sched_fork(p, clone_flags);
1100 1102
diff --git a/mm/Makefile b/mm/Makefile
index 728a9fde49d1..88193d73cd1a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -11,10 +11,10 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
11 maccess.o page_alloc.o page-writeback.o \ 11 maccess.o page_alloc.o page-writeback.o \
12 readahead.o swap.o truncate.o vmscan.o shmem.o \ 12 readahead.o swap.o truncate.o vmscan.o shmem.o \
13 prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ 13 prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
14 page_isolation.o mm_init.o mmu_context.o $(mmu-y) 14 page_isolation.o mm_init.o mmu_context.o \
15 pagewalk.o $(mmu-y)
15obj-y += init-mm.o 16obj-y += init-mm.o
16 17
17obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
18obj-$(CONFIG_BOUNCE) += bounce.o 18obj-$(CONFIG_BOUNCE) += bounce.o
19obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o 19obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
20obj-$(CONFIG_HAS_DMA) += dmapool.o 20obj-$(CONFIG_HAS_DMA) += dmapool.o