From efdc3feadb493ae7f24c573c8b863d7a51117391 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 13 Oct 2020 10:22:00 -0700 Subject: [PATCH 1/3] mm: move final page locking out of __do_fault() helper into callers The old semantics of our __do_fault() helper was that it always locked the page unless there was an error (or unless the faulting had already handled a COW event). That turns out to be a mistake. Not all callers actually want the page locked at all, and they might as well check the same VM_FAULT_LOCKED bit that __do_fault() itself checked whether the page is already locked or not. This change only moves that final page locking out into the callers, but intentionally does not actually change any of the locking semantics: the callers will not just do that final page locking themselves instead. That means that future patches may then decide to not lock the page after all, but this is just preparation for any such future change. Signed-off-by: Linus Torvalds --- mm/memory.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 5efa07fb6cdc..1e2796d68e43 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3647,11 +3647,6 @@ static vm_fault_t __do_fault(struct vm_fault *vmf) return VM_FAULT_HWPOISON; } - if (unlikely(!(ret & VM_FAULT_LOCKED))) - lock_page(vmf->page); - else - VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); - return ret; } @@ -3940,6 +3935,11 @@ static vm_fault_t do_read_fault(struct vm_fault *vmf) if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY))) return ret; + if (unlikely(!(ret & VM_FAULT_LOCKED))) + lock_page(vmf->page); + else + VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); + ret |= finish_fault(vmf); unlock_page(vmf->page); if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY))) @@ -3971,6 +3971,11 @@ static vm_fault_t do_cow_fault(struct vm_fault *vmf) if (ret & VM_FAULT_DONE_COW) return ret; + if (unlikely(!(ret & VM_FAULT_LOCKED))) + lock_page(vmf->page); + else + VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); + copy_user_highpage(vmf->cow_page, vmf->page, vmf->address, vma); __SetPageUptodate(vmf->cow_page); @@ -3994,6 +3999,11 @@ static vm_fault_t do_shared_fault(struct vm_fault *vmf) if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY))) return ret; + if (unlikely(!(ret & VM_FAULT_LOCKED))) + lock_page(vmf->page); + else + VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); + /* * Check if the backing address space wants to know that the page is * about to become writable -- 2.30.0.352.gf6a05684e6