diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-10-25 12:30:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-25 12:30:53 -0400 |
commit | 0b9e31e9264f1bad89856afb96da1688292f13b4 (patch) | |
tree | 7a9e9b6456dce993efeed8734de0a15a1f16ae94 /fs/proc/array.c | |
parent | cf82ff7ea7695b0e82ba07bc5e9f1bd03a74e1aa (diff) | |
parent | 964fe080d94db82a3268443e9b9ece4c60246414 (diff) |
Merge branch 'linus' into sched/core
Conflicts:
fs/proc/array.c
Merge reason: resolve conflict and queue up dependent patch.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/proc/array.c')
-rw-r--r-- | fs/proc/array.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 762aea9c9c71..e209f64ab27b 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,94 @@ static inline void task_context_switch_counts(struct seq_file *m, | |||
321 | p->nivcsw); | 322 | p->nivcsw); |
322 | } | 323 | } |
323 | 324 | ||
325 | #ifdef CONFIG_MMU | ||
326 | |||
327 | struct stack_stats { | ||
328 | struct vm_area_struct *vma; | ||
329 | unsigned long startpage; | ||
330 | unsigned long usage; | ||
331 | }; | ||
332 | |||
333 | static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr, | ||
334 | unsigned long end, struct mm_walk *walk) | ||
335 | { | ||
336 | struct stack_stats *ss = walk->private; | ||
337 | struct vm_area_struct *vma = ss->vma; | ||
338 | pte_t *pte, ptent; | ||
339 | spinlock_t *ptl; | ||
340 | int ret = 0; | ||
341 | |||
342 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | ||
343 | for (; addr != end; pte++, addr += PAGE_SIZE) { | ||
344 | ptent = *pte; | ||
345 | |||
346 | #ifdef CONFIG_STACK_GROWSUP | ||
347 | if (pte_present(ptent) || is_swap_pte(ptent)) | ||
348 | ss->usage = addr - ss->startpage + PAGE_SIZE; | ||
349 | #else | ||
350 | if (pte_present(ptent) || is_swap_pte(ptent)) { | ||
351 | ss->usage = ss->startpage - addr + PAGE_SIZE; | ||
352 | pte++; | ||
353 | ret = 1; | ||
354 | break; | ||
355 | } | ||
356 | #endif | ||
357 | } | ||
358 | pte_unmap_unlock(pte - 1, ptl); | ||
359 | cond_resched(); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma, | ||
364 | struct task_struct *task) | ||
365 | { | ||
366 | struct stack_stats ss; | ||
367 | struct mm_walk stack_walk = { | ||
368 | .pmd_entry = stack_usage_pte_range, | ||
369 | .mm = vma->vm_mm, | ||
370 | .private = &ss, | ||
371 | }; | ||
372 | |||
373 | if (!vma->vm_mm || is_vm_hugetlb_page(vma)) | ||
374 | return 0; | ||
375 | |||
376 | ss.vma = vma; | ||
377 | ss.startpage = task->stack_start & PAGE_MASK; | ||
378 | ss.usage = 0; | ||
379 | |||
380 | #ifdef CONFIG_STACK_GROWSUP | ||
381 | walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end, | ||
382 | &stack_walk); | ||
383 | #else | ||
384 | walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE, | ||
385 | &stack_walk); | ||
386 | #endif | ||
387 | return ss.usage; | ||
388 | } | ||
389 | |||
390 | static inline void task_show_stack_usage(struct seq_file *m, | ||
391 | struct task_struct *task) | ||
392 | { | ||
393 | struct vm_area_struct *vma; | ||
394 | struct mm_struct *mm = get_task_mm(task); | ||
395 | |||
396 | if (mm) { | ||
397 | down_read(&mm->mmap_sem); | ||
398 | vma = find_vma(mm, task->stack_start); | ||
399 | if (vma) | ||
400 | seq_printf(m, "Stack usage:\t%lu kB\n", | ||
401 | get_stack_usage_in_bytes(vma, task) >> 10); | ||
402 | |||
403 | up_read(&mm->mmap_sem); | ||
404 | mmput(mm); | ||
405 | } | ||
406 | } | ||
407 | #else | ||
408 | static void task_show_stack_usage(struct seq_file *m, struct task_struct *task) | ||
409 | { | ||
410 | } | ||
411 | #endif /* CONFIG_MMU */ | ||
412 | |||
324 | static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) | 413 | static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) |
325 | { | 414 | { |
326 | seq_printf(m, "Cpus_allowed:\t"); | 415 | seq_printf(m, "Cpus_allowed:\t"); |
@@ -351,6 +440,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, | |||
351 | task_show_regs(m, task); | 440 | task_show_regs(m, task); |
352 | #endif | 441 | #endif |
353 | task_context_switch_counts(m, task); | 442 | task_context_switch_counts(m, task); |
443 | task_show_stack_usage(m, task); | ||
354 | return 0; | 444 | return 0; |
355 | } | 445 | } |
356 | 446 | ||
@@ -492,7 +582,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, | |||
492 | rsslim, | 582 | rsslim, |
493 | mm ? mm->start_code : 0, | 583 | mm ? mm->start_code : 0, |
494 | mm ? mm->end_code : 0, | 584 | mm ? mm->end_code : 0, |
495 | (permitted && mm) ? mm->start_stack : 0, | 585 | (permitted) ? task->stack_start : 0, |
496 | esp, | 586 | esp, |
497 | eip, | 587 | eip, |
498 | /* The signal information here is obsolete. | 588 | /* The signal information here is obsolete. |