diff options
author | Kirill A. Shutemov <kirill.shutemov@linux.intel.com> | 2017-02-24 17:57:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-24 20:46:55 -0500 |
commit | 699fa216808fff47efc9743f92f1b8a9f9bf5321 (patch) | |
tree | 08404eab90540711584c3542f0c267227f5bb432 /mm/page_idle.c | |
parent | 8eaedede825a02dbe2420b9c9be9b5b2d7515496 (diff) |
mm: fix handling PTE-mapped THPs in page_idle_clear_pte_refs()
For PTE-mapped THP page_check_address_transhuge() is not adequate: it
cannot find all relevant PTEs, only the first one.i
Let's switch it to page_vma_mapped_walk().
I don't think it's subject for stable@: it's not fatal.
Link: http://lkml.kernel.org/r/20170129173858.45174-5-kirill.shutemov@linux.intel.com
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_idle.c')
-rw-r--r-- | mm/page_idle.c | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/mm/page_idle.c b/mm/page_idle.c index ae11aa914e55..b0ee56c56b58 100644 --- a/mm/page_idle.c +++ b/mm/page_idle.c | |||
@@ -54,27 +54,27 @@ static int page_idle_clear_pte_refs_one(struct page *page, | |||
54 | struct vm_area_struct *vma, | 54 | struct vm_area_struct *vma, |
55 | unsigned long addr, void *arg) | 55 | unsigned long addr, void *arg) |
56 | { | 56 | { |
57 | struct mm_struct *mm = vma->vm_mm; | 57 | struct page_vma_mapped_walk pvmw = { |
58 | pmd_t *pmd; | 58 | .page = page, |
59 | pte_t *pte; | 59 | .vma = vma, |
60 | spinlock_t *ptl; | 60 | .address = addr, |
61 | }; | ||
61 | bool referenced = false; | 62 | bool referenced = false; |
62 | 63 | ||
63 | if (!page_check_address_transhuge(page, mm, addr, &pmd, &pte, &ptl)) | 64 | while (page_vma_mapped_walk(&pvmw)) { |
64 | return SWAP_AGAIN; | 65 | addr = pvmw.address; |
65 | 66 | if (pvmw.pte) { | |
66 | if (pte) { | 67 | referenced = ptep_clear_young_notify(vma, addr, |
67 | referenced = ptep_clear_young_notify(vma, addr, pte); | 68 | pvmw.pte); |
68 | pte_unmap(pte); | 69 | } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { |
69 | } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { | 70 | referenced = pmdp_clear_young_notify(vma, addr, |
70 | referenced = pmdp_clear_young_notify(vma, addr, pmd); | 71 | pvmw.pmd); |
71 | } else { | 72 | } else { |
72 | /* unexpected pmd-mapped page? */ | 73 | /* unexpected pmd-mapped page? */ |
73 | WARN_ON_ONCE(1); | 74 | WARN_ON_ONCE(1); |
75 | } | ||
74 | } | 76 | } |
75 | 77 | ||
76 | spin_unlock(ptl); | ||
77 | |||
78 | if (referenced) { | 78 | if (referenced) { |
79 | clear_page_idle(page); | 79 | clear_page_idle(page); |
80 | /* | 80 | /* |