On Fri, Jun 01, 2007 at 03:53:49AM +0200, Nick Piggin wrote:
Ok. So how about the attached patch? It's a bit different than discussed,
but I think it's much cleaner because it preserves the current behavior of
the callback and keeps that bit of page locking inside core code. Not tested
as of yet, but I can run it tommorrow.
--Mark
--
Mark Fasheh
Senior Software Developer, Oracle
mark.fasheh@oracle.com
From: Mark Fasheh <mark.fasheh@oracle.com>
[PATCH] Release page lock before calling ->page_mkwrite
__do_fault() was calling ->page_mkwrite() with the page lock held, which
violates the locking rules for that callback. Release and retake the page
lock around the callback to avoid deadlocking file systems which manually
take it.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
---
mm/memory.c | 14 +++++++++-----
1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 7221618..491cc27 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2378,11 +2378,14 @@ static int __do_fault(struct mm_struct *
* address space wants to know that the page is about
* to become writable
*/
- if (vma->vm_ops->page_mkwrite &&
- vma->vm_ops->page_mkwrite(vma, page) < 0) {
- fdata.type = VM_FAULT_SIGBUS;
- anon = 1; /* no anon but release faulted_page */
- goto out;
+ if (vma->vm_ops->page_mkwrite) {
+ unlock_page(page);
+ if (vma->vm_ops->page_mkwrite(vma, page) < 0) {
+ fdata.type = VM_FAULT_SIGBUS;
+ anon = 1; /* no anon but release faulted_page */
+ goto out_unlocked;
+ }
+ lock_page(page);
}
}
@@ -2434,6 +2437,7 @@ static int __do_fault(struct mm_struct *
out:
unlock_page(faulted_page);
+out_unlocked:
if (anon)
page_cache_release(faulted_page);
else if (dirty_page) {
--
1.4.2.3
-