aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorHillf Danton <dhillf@gmail.com>2012-01-20 17:34:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-23 11:38:48 -0500
commit409eb8c2611b4310947a150af988111f7f52ab15 (patch)
treea410c7c9c5a58643da7b4c2abdb7796d1255f048 /mm
parent6568d4a9c9ff16d6c4f0b14dfea567806ce579e4 (diff)
mm/hugetlb.c: undo change to page mapcount in fault handler
Page mapcount should be updated only if we are sure that the page ends up in the page table otherwise we would leak if we couldn't COW due to reservations or if idx is out of bounds. Signed-off-by: Hillf Danton <dhillf@gmail.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/hugetlb.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ea8c3a4cd2ae..5f34bd8dda34 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2508,6 +2508,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
2508{ 2508{
2509 struct hstate *h = hstate_vma(vma); 2509 struct hstate *h = hstate_vma(vma);
2510 int ret = VM_FAULT_SIGBUS; 2510 int ret = VM_FAULT_SIGBUS;
2511 int anon_rmap = 0;
2511 pgoff_t idx; 2512 pgoff_t idx;
2512 unsigned long size; 2513 unsigned long size;
2513 struct page *page; 2514 struct page *page;
@@ -2562,14 +2563,13 @@ retry:
2562 spin_lock(&inode->i_lock); 2563 spin_lock(&inode->i_lock);
2563 inode->i_blocks += blocks_per_huge_page(h); 2564 inode->i_blocks += blocks_per_huge_page(h);
2564 spin_unlock(&inode->i_lock); 2565 spin_unlock(&inode->i_lock);
2565 page_dup_rmap(page);
2566 } else { 2566 } else {
2567 lock_page(page); 2567 lock_page(page);
2568 if (unlikely(anon_vma_prepare(vma))) { 2568 if (unlikely(anon_vma_prepare(vma))) {
2569 ret = VM_FAULT_OOM; 2569 ret = VM_FAULT_OOM;
2570 goto backout_unlocked; 2570 goto backout_unlocked;
2571 } 2571 }
2572 hugepage_add_new_anon_rmap(page, vma, address); 2572 anon_rmap = 1;
2573 } 2573 }
2574 } else { 2574 } else {
2575 /* 2575 /*
@@ -2582,7 +2582,6 @@ retry:
2582 VM_FAULT_SET_HINDEX(h - hstates); 2582 VM_FAULT_SET_HINDEX(h - hstates);
2583 goto backout_unlocked; 2583 goto backout_unlocked;
2584 } 2584 }
2585 page_dup_rmap(page);
2586 } 2585 }
2587 2586
2588 /* 2587 /*
@@ -2606,6 +2605,10 @@ retry:
2606 if (!huge_pte_none(huge_ptep_get(ptep))) 2605 if (!huge_pte_none(huge_ptep_get(ptep)))
2607 goto backout; 2606 goto backout;
2608 2607
2608 if (anon_rmap)
2609 hugepage_add_new_anon_rmap(page, vma, address);
2610 else
2611 page_dup_rmap(page);
2609 new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE) 2612 new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
2610 && (vma->vm_flags & VM_SHARED))); 2613 && (vma->vm_flags & VM_SHARED)));
2611 set_huge_pte_at(mm, address, ptep, new_pte); 2614 set_huge_pte_at(mm, address, ptep, new_pte);