As Dinosaur Huang reported, there is a potential deadlock in between
GC and mkwrite():

Thread A                        Thread B
- do_page_mkwrite
 - f2fs_vm_page_mkwrite
  - lock_page
                                - f2fs_balance_fs
                                 - mutex_lock(gc_mutex)
                                 - f2fs_gc
                                  - do_garbage_collect
                                   - ra_data_block
                                    - grab_cache_page
  - f2fs_balance_fs
   - mutex_lock(gc_mutex)

In order to fix this, we just move f2fs_balance_fs() out of page lock's
coverage in f2fs_vm_page_mkwrite().

Reported-by: Dinosaur Huang <dinosaur.hu...@unisoc.com>
Signed-off-by: Chao Yu <yuch...@huawei.com>
---
 fs/f2fs/file.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index c0560d62dbee..ed3290225506 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -67,6 +67,8 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
 
        f2fs_bug_on(sbi, f2fs_has_inline_data(inode));
 
+       f2fs_balance_fs(sbi, true);
+
        file_update_time(vmf->vma->vm_file);
        down_read(&F2FS_I(inode)->i_mmap_sem);
        lock_page(page);
@@ -120,8 +122,6 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
 out_sem:
        up_read(&F2FS_I(inode)->i_mmap_sem);
 
-       f2fs_balance_fs(sbi, dn.node_changed);
-
        sb_end_pagefault(inode->i_sb);
 err:
        return block_page_mkwrite_return(err);
-- 
2.18.0.rc1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to