From 1b2b061f622ea60924eba886975183306aa56972 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 13 Oct 2020 10:43:05 -0700 Subject: [PATCH 2/3] mm: don't lock the page, only to immediately unlock it again for do_page_mkwrite() Our page locking during fault handling a bit messy, and the shared fault code in particular was locking the page only to immediately unlock it again because do_page_mkwrite() wanted it unlocked. We keep the "did we lock it" state around in the VM_FAULT_LOCKED bit, so let's just use that knowledge, and not first lock it if it wasn't locked, only to then unlock it again. It would be even better to transfer the "did we already lock this page" information into do_page_mkwrite(), because that function will actually want to lock it eventually anyway, but let's just clean up one thing at a time. Signed-off-by: Linus Torvalds --- mm/memory.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 1e2796d68e43..d7e30273bef1 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3999,25 +3999,33 @@ 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 */ if (vma->vm_ops->page_mkwrite) { - unlock_page(vmf->page); + /* do_page_mkwrite() wants the page unlocked */ + if (ret & VM_FAULT_LOCKED) { + unlock_page(vmf->page); + ret &= ~VM_FAULT_LOCKED; + } + tmp = do_page_mkwrite(vmf); if (unlikely(!tmp || (tmp & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))) { put_page(vmf->page); return tmp; } + + /* Did do_page_mkwrite() lock the page again? */ + ret |= tmp & VM_FAULT_LOCKED; } + if (unlikely(!(ret & VM_FAULT_LOCKED))) + lock_page(vmf->page); + else + VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); + ret |= finish_fault(vmf); if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY))) { -- 2.30.0.352.gf6a05684e6