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/task_mmu.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/task_mmu.c')
-rw-r--r-- | fs/proc/task_mmu.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 9bd8be1d235c..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]"; |
@@ -465,23 +484,28 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | |||
465 | return 0; | 484 | return 0; |
466 | } | 485 | } |
467 | 486 | ||
487 | #define CLEAR_REFS_ALL 1 | ||
488 | #define CLEAR_REFS_ANON 2 | ||
489 | #define CLEAR_REFS_MAPPED 3 | ||
490 | |||
468 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, | 491 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, |
469 | size_t count, loff_t *ppos) | 492 | size_t count, loff_t *ppos) |
470 | { | 493 | { |
471 | struct task_struct *task; | 494 | struct task_struct *task; |
472 | char buffer[PROC_NUMBUF], *end; | 495 | char buffer[PROC_NUMBUF]; |
473 | struct mm_struct *mm; | 496 | struct mm_struct *mm; |
474 | struct vm_area_struct *vma; | 497 | struct vm_area_struct *vma; |
498 | long type; | ||
475 | 499 | ||
476 | memset(buffer, 0, sizeof(buffer)); | 500 | memset(buffer, 0, sizeof(buffer)); |
477 | if (count > sizeof(buffer) - 1) | 501 | if (count > sizeof(buffer) - 1) |
478 | count = sizeof(buffer) - 1; | 502 | count = sizeof(buffer) - 1; |
479 | if (copy_from_user(buffer, buf, count)) | 503 | if (copy_from_user(buffer, buf, count)) |
480 | return -EFAULT; | 504 | return -EFAULT; |
481 | if (!simple_strtol(buffer, &end, 0)) | 505 | if (strict_strtol(strstrip(buffer), 10, &type)) |
506 | return -EINVAL; | ||
507 | if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) | ||
482 | return -EINVAL; | 508 | return -EINVAL; |
483 | if (*end == '\n') | ||
484 | end++; | ||
485 | task = get_proc_task(file->f_path.dentry->d_inode); | 509 | task = get_proc_task(file->f_path.dentry->d_inode); |
486 | if (!task) | 510 | if (!task) |
487 | return -ESRCH; | 511 | return -ESRCH; |
@@ -494,18 +518,31 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, | |||
494 | down_read(&mm->mmap_sem); | 518 | down_read(&mm->mmap_sem); |
495 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | 519 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
496 | clear_refs_walk.private = vma; | 520 | clear_refs_walk.private = vma; |
497 | if (!is_vm_hugetlb_page(vma)) | 521 | if (is_vm_hugetlb_page(vma)) |
498 | walk_page_range(vma->vm_start, vma->vm_end, | 522 | continue; |
499 | &clear_refs_walk); | 523 | /* |
524 | * Writing 1 to /proc/pid/clear_refs affects all pages. | ||
525 | * | ||
526 | * Writing 2 to /proc/pid/clear_refs only affects | ||
527 | * Anonymous pages. | ||
528 | * | ||
529 | * Writing 3 to /proc/pid/clear_refs only affects file | ||
530 | * mapped pages. | ||
531 | */ | ||
532 | if (type == CLEAR_REFS_ANON && vma->vm_file) | ||
533 | continue; | ||
534 | if (type == CLEAR_REFS_MAPPED && !vma->vm_file) | ||
535 | continue; | ||
536 | walk_page_range(vma->vm_start, vma->vm_end, | ||
537 | &clear_refs_walk); | ||
500 | } | 538 | } |
501 | flush_tlb_mm(mm); | 539 | flush_tlb_mm(mm); |
502 | up_read(&mm->mmap_sem); | 540 | up_read(&mm->mmap_sem); |
503 | mmput(mm); | 541 | mmput(mm); |
504 | } | 542 | } |
505 | put_task_struct(task); | 543 | put_task_struct(task); |
506 | if (end - buffer == 0) | 544 | |
507 | return -EIO; | 545 | return count; |
508 | return end - buffer; | ||
509 | } | 546 | } |
510 | 547 | ||
511 | const struct file_operations proc_clear_refs_operations = { | 548 | const struct file_operations proc_clear_refs_operations = { |