diff options
| author | Moussa A. Ba <moussa.a.ba@gmail.com> | 2009-09-21 20:02:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-22 10:17:33 -0400 |
| commit | 398499d5f3613c47f2143b8c54a04efb5d7a6da9 (patch) | |
| tree | 0b337ca1d0e20caa2295c159d5c0deadf362e4a0 /fs/proc | |
| parent | 7103ad323b1ae32bedc3267402117e2f8b45e48d (diff) | |
pagemap clear_refs: modify to specify anon or mapped vma clearing
The patch makes the clear_refs more versatile in adding the option to
select anonymous pages or file backed pages for clearing. This addition
has a measurable impact on user space application performance as it
decreases the number of pagewalks in scenarios where one is only
interested in a specific type of page (anonymous or file mapped).
The patch adds anonymous and file backed filters to the clear_refs interface.
echo 1 > /proc/PID/clear_refs resets the bits on all pages
echo 2 > /proc/PID/clear_refs resets the bits on anonymous pages only
echo 3 > /proc/PID/clear_refs resets the bits on file backed pages only
Any other value is ignored
Signed-off-by: Moussa A. Ba <moussa.a.ba@gmail.com>
Signed-off-by: Jared E. Hulbert <jaredeh@gmail.com>
Acked-by: David Rientjes <rientjes@google.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.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 9bd8be1d235c..59e98fea34a4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -465,6 +465,10 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | |||
| 465 | return 0; | 465 | return 0; |
| 466 | } | 466 | } |
| 467 | 467 | ||
| 468 | #define CLEAR_REFS_ALL 1 | ||
| 469 | #define CLEAR_REFS_ANON 2 | ||
| 470 | #define CLEAR_REFS_MAPPED 3 | ||
| 471 | |||
| 468 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, | 472 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, |
| 469 | size_t count, loff_t *ppos) | 473 | size_t count, loff_t *ppos) |
| 470 | { | 474 | { |
| @@ -472,13 +476,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, | |||
| 472 | char buffer[PROC_NUMBUF], *end; | 476 | char buffer[PROC_NUMBUF], *end; |
| 473 | struct mm_struct *mm; | 477 | struct mm_struct *mm; |
| 474 | struct vm_area_struct *vma; | 478 | struct vm_area_struct *vma; |
| 479 | int type; | ||
| 475 | 480 | ||
| 476 | memset(buffer, 0, sizeof(buffer)); | 481 | memset(buffer, 0, sizeof(buffer)); |
| 477 | if (count > sizeof(buffer) - 1) | 482 | if (count > sizeof(buffer) - 1) |
| 478 | count = sizeof(buffer) - 1; | 483 | count = sizeof(buffer) - 1; |
| 479 | if (copy_from_user(buffer, buf, count)) | 484 | if (copy_from_user(buffer, buf, count)) |
| 480 | return -EFAULT; | 485 | return -EFAULT; |
| 481 | if (!simple_strtol(buffer, &end, 0)) | 486 | type = simple_strtol(buffer, &end, 0); |
| 487 | if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) | ||
| 482 | return -EINVAL; | 488 | return -EINVAL; |
| 483 | if (*end == '\n') | 489 | if (*end == '\n') |
| 484 | end++; | 490 | end++; |
| @@ -494,9 +500,23 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, | |||
| 494 | down_read(&mm->mmap_sem); | 500 | down_read(&mm->mmap_sem); |
| 495 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | 501 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
| 496 | clear_refs_walk.private = vma; | 502 | clear_refs_walk.private = vma; |
| 497 | if (!is_vm_hugetlb_page(vma)) | 503 | if (is_vm_hugetlb_page(vma)) |
| 498 | walk_page_range(vma->vm_start, vma->vm_end, | 504 | continue; |
| 499 | &clear_refs_walk); | 505 | /* |
| 506 | * Writing 1 to /proc/pid/clear_refs affects all pages. | ||
| 507 | * | ||
| 508 | * Writing 2 to /proc/pid/clear_refs only affects | ||
| 509 | * Anonymous pages. | ||
| 510 | * | ||
| 511 | * Writing 3 to /proc/pid/clear_refs only affects file | ||
| 512 | * mapped pages. | ||
| 513 | */ | ||
| 514 | if (type == CLEAR_REFS_ANON && vma->vm_file) | ||
| 515 | continue; | ||
| 516 | if (type == CLEAR_REFS_MAPPED && !vma->vm_file) | ||
| 517 | continue; | ||
| 518 | walk_page_range(vma->vm_start, vma->vm_end, | ||
| 519 | &clear_refs_walk); | ||
| 500 | } | 520 | } |
| 501 | flush_tlb_mm(mm); | 521 | flush_tlb_mm(mm); |
| 502 | up_read(&mm->mmap_sem); | 522 | up_read(&mm->mmap_sem); |
