From 969e62f9784dcd3083ba3fe32b87bdea8319aba9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 13 Oct 2020 11:00:33 -0700 Subject: [PATCH 3/4] mm: do_cow_fault() does not need the source page to be locked This removes the "lock if it wasn't locked" logic from do_cow_fault(), since we're not even going to install that page into the destination address space (finish_fault() will use ->cow_page rather than ->page), and copying the source page does not need the source to be locked. So instead of doing "lock if it wasn't locked" followed by an unconditional unlock of the page, just do "unlock if it was locked". Of course, since all the normal file mapping ->fault() handlers currently lock the page they return (see filemap_fault() for details), all of this is pretty much theoretical. But this is the right thing to do - making sure we hold the page lock when we really don't is just confusing and wrong. And this prepares the way for any future changes to filemap_fault() where we go "Oh, we actually _don't_ need to lock the page for this case at all". Signed-off-by: Linus Torvalds --- mm/memory.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 5c93b4bec063..d4d32d0c33c7 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4031,16 +4031,13 @@ 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); + if (ret & VM_FAULT_LOCKED) + unlock_page(vmf->page); + ret |= finish_fault(vmf); - unlock_page(vmf->page); put_page(vmf->page); if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY))) goto uncharge_out; -- 2.28.0.218.gc12ef3d349