aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-07-19 04:47:00 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:41 -0400
commit6967614761fd305b3414d9485d89dc2e0a407410 (patch)
tree498bd41e9cf8795535f597696dd2c834d79ffb44 /mm/memory.c
parent54cb8821de07f2ffcd28c380ce9b93d5784b40d7 (diff)
ocfs2: 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> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/mm/memory.c b/mm/memory.c
index eee7fec3ab54..7abd3899848b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2369,11 +2369,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
2369 * address space wants to know that the page is about 2369 * address space wants to know that the page is about
2370 * to become writable 2370 * to become writable
2371 */ 2371 */
2372 if (vma->vm_ops->page_mkwrite && 2372 if (vma->vm_ops->page_mkwrite) {
2373 vma->vm_ops->page_mkwrite(vma, page) < 0) { 2373 unlock_page(page);
2374 fdata.type = VM_FAULT_SIGBUS; 2374 if (vma->vm_ops->page_mkwrite(vma, page) < 0) {
2375 anon = 1; /* no anon but release faulted_page */ 2375 fdata.type = VM_FAULT_SIGBUS;
2376 goto out; 2376 anon = 1; /* no anon but release faulted_page */
2377 goto out_unlocked;
2378 }
2379 lock_page(page);
2377 } 2380 }
2378 } 2381 }
2379 2382
@@ -2425,6 +2428,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
2425 2428
2426out: 2429out:
2427 unlock_page(faulted_page); 2430 unlock_page(faulted_page);
2431out_unlocked:
2428 if (anon) 2432 if (anon)
2429 page_cache_release(faulted_page); 2433 page_cache_release(faulted_page);
2430 else if (dirty_page) { 2434 else if (dirty_page) {