Commit 28766805 authored by Shachar Raindel's avatar Shachar Raindel Committed by Linus Torvalds

mm: refactor do_wp_page - rewrite the unlock flow

When do_wp_page is ending, in several cases it needs to unlock the pages
and ptls it was accessing.

Currently, this logic was "called" by using a goto jump.  This makes
following the control flow of the function harder.  Readability was
further hampered by the unlock case containing large amount of logic
needed only in one of the 3 cases.

Using goto for cleanup is generally allowed.  However, moving the
trivial unlocking flows to the relevant call sites allow deeper
refactoring in the next patch.
Signed-off-by: default avatarShachar Raindel <raindel@mellanox.com>
Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Acked-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: default avatarRik van Riel <riel@redhat.com>
Acked-by: default avatarAndi Kleen <ak@linux.intel.com>
Acked-by: default avatarHaggai Eran <haggaie@mellanox.com>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Peter Feiner <pfeiner@google.com>
Cc: Michel Lespinasse <walken@google.com>
Reviewed-by: default avatarMichal Hocko <mhocko@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4e047f89
...@@ -2066,7 +2066,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -2066,7 +2066,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
{ {
struct page *old_page, *new_page = NULL; struct page *old_page, *new_page = NULL;
pte_t entry; pte_t entry;
int ret = 0; int page_copied = 0;
unsigned long mmun_start = 0; /* For mmu_notifiers */ unsigned long mmun_start = 0; /* For mmu_notifiers */
unsigned long mmun_end = 0; /* For mmu_notifiers */ unsigned long mmun_end = 0; /* For mmu_notifiers */
struct mem_cgroup *memcg; struct mem_cgroup *memcg;
...@@ -2101,7 +2101,9 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -2101,7 +2101,9 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
&ptl); &ptl);
if (!pte_same(*page_table, orig_pte)) { if (!pte_same(*page_table, orig_pte)) {
unlock_page(old_page); unlock_page(old_page);
goto unlock; pte_unmap_unlock(page_table, ptl);
page_cache_release(old_page);
return 0;
} }
page_cache_release(old_page); page_cache_release(old_page);
} }
...@@ -2148,7 +2150,9 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -2148,7 +2150,9 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
&ptl); &ptl);
if (!pte_same(*page_table, orig_pte)) { if (!pte_same(*page_table, orig_pte)) {
unlock_page(old_page); unlock_page(old_page);
goto unlock; pte_unmap_unlock(page_table, ptl);
page_cache_release(old_page);
return 0;
} }
page_mkwrite = 1; page_mkwrite = 1;
} }
...@@ -2246,29 +2250,28 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -2246,29 +2250,28 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
/* Free the old page.. */ /* Free the old page.. */
new_page = old_page; new_page = old_page;
ret |= VM_FAULT_WRITE; page_copied = 1;
} else } else
mem_cgroup_cancel_charge(new_page, memcg); mem_cgroup_cancel_charge(new_page, memcg);
if (new_page) if (new_page)
page_cache_release(new_page); page_cache_release(new_page);
unlock:
pte_unmap_unlock(page_table, ptl); pte_unmap_unlock(page_table, ptl);
if (mmun_end > mmun_start) mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
if (old_page) { if (old_page) {
/* /*
* Don't let another task, with possibly unlocked vma, * Don't let another task, with possibly unlocked vma,
* keep the mlocked page. * keep the mlocked page.
*/ */
if ((ret & VM_FAULT_WRITE) && (vma->vm_flags & VM_LOCKED)) { if (page_copied && (vma->vm_flags & VM_LOCKED)) {
lock_page(old_page); /* LRU manipulation */ lock_page(old_page); /* LRU manipulation */
munlock_vma_page(old_page); munlock_vma_page(old_page);
unlock_page(old_page); unlock_page(old_page);
} }
page_cache_release(old_page); page_cache_release(old_page);
} }
return ret; return page_copied ? VM_FAULT_WRITE : 0;
oom_free_new: oom_free_new:
page_cache_release(new_page); page_cache_release(new_page);
oom: oom:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment