diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-08-21 19:49:55 -0400 |
|---|---|---|
| committer | Georg Veichtlbauer <georg@vware.at> | 2023-07-16 12:47:43 +0200 |
| commit | 46c6fbdd185a7005fac895c5cfa7896b9329324f (patch) | |
| tree | 3f29778ea9abd4cca355b6d5fd7fb8e54cf636fc /mm/memory.c | |
| parent | 90dccbae4c0410e209049e22eaae9cd2718e1aa5 (diff) | |
BACKPORT: mm: do_wp_page() simplification
How about we just make sure we're the only possible valid user fo the
page before we bother to reuse it?
Simplify, simplify, simplify.
And get rid of the nasty serialization on the page lock at the same time.
[peterx: add subject prefix]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Change-Id: I25c2cf9a3afebc19aaeda29ffbfcb82edb7fcb7c
Diffstat (limited to 'mm/memory.c')
| -rw-r--r-- | mm/memory.c | 49 |
1 files changed, 14 insertions, 35 deletions
diff --git a/mm/memory.c b/mm/memory.c index ccb04d3f9bab..8e44f5d2d5f4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2400,45 +2400,24 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, * not dirty accountable. */ if (PageAnon(old_page)) { - if (PageKsm(old_page) && (PageSwapCache(old_page) || - page_count(old_page) != 1)) + /* PageKsm() doesn't necessarily raise the page refcount */ + if (PageKsm(old_page) || page_count(old_page) != 1) goto copy; - if (!trylock_page(old_page)) { - page_cache_get(old_page); - pte_unmap_unlock(page_table, ptl); - lock_page(old_page); - page_table = pte_offset_map_lock(mm, pmd, address, - &ptl); - if (!pte_same(*page_table, orig_pte)) { - unlock_page(old_page); - pte_unmap_unlock(page_table, ptl); - page_cache_release(old_page); - return 0; - } - page_cache_release(old_page); - } - if (PageKsm(old_page)) { - bool reused = reuse_ksm_page(old_page, vma, - address); - unlock_page(old_page); - if (!reused) - goto copy; - wp_page_reuse(mm, vma, address, page_table, ptl, - orig_pte, old_page, 0, 0); - return VM_FAULT_WRITE; - } - if (reuse_swap_page(old_page)) { - /* - * The page is all ours. Move it to our anon_vma so - * the rmap code will not search our parent or siblings. - * Protected against the rmap code by the page lock. - */ - page_move_anon_rmap(old_page, vma, address); + if (!trylock_page(old_page)) + goto copy; + if (PageKsm(old_page) || page_mapcount(old_page) != 1 || page_count(old_page) != 1) { unlock_page(old_page); - return wp_page_reuse(mm, vma, address, page_table, ptl, - orig_pte, old_page, 0, 0); + goto copy; } + /* + * Ok, we've got the only map reference, and the only + * page count reference, and the page is locked, + * it's dark out, and we're wearing sunglasses. Hit it. + */ + wp_page_reuse(mm, vma, address, page_table, ptl, + orig_pte, old_page, 0, 0); unlock_page(old_page); + return VM_FAULT_WRITE; } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))) { return wp_page_shared(mm, vma, address, page_table, pmd, |
