• Chao Yu's avatar
    f2fs: fix to avoid potential deadlock · 34415099
    Chao Yu authored
    Quoted from Jing Xia's report, there is a potential deadlock may happen
    between kworker and checkpoint as below:
    
    [T:writeback]				[T:checkpoint]
    - wb_writeback
     - blk_start_plug
    bio contains NodeA was plugged in writeback threads
    					- do_writepages  -- sync write inodeB, inc wb_sync_req[DATA]
    					 - f2fs_write_data_pages
    					  - f2fs_write_single_data_page -- write last dirty page
    					   - f2fs_do_write_data_page
    					    - set_page_writeback  -- clear page dirty flag and
    					    PAGECACHE_TAG_DIRTY tag in radix tree
    					    - f2fs_outplace_write_data
    					     - f2fs_update_data_blkaddr
    					      - f2fs_wait_on_page_writeback -- wait NodeA to writeback here
    					   - inode_dec_dirty_pages
     - writeback_sb_inodes
      - writeback_single_inode
       - do_writepages
        - f2fs_write_data_pages -- skip writepages due to wb_sync_req[DATA]
         - wbc->pages_skipped += get_dirty_pages() -- PAGECACHE_TAG_DIRTY is not set but get_dirty_pages() returns one
      - requeue_inode -- requeue inode to wb->b_dirty queue due to non-zero.pages_skipped
     - blk_finish_plug
    
    Let's try to avoid deadlock condition by forcing unplugging previous bio via
    blk_finish_plug(current->plug) once we'v skipped writeback in writepages()
    due to valid sbi->wb_sync_req[DATA/NODE].
    
    Fixes: 687de7f1
    
     ("f2fs: avoid IO split due to mixed WB_SYNC_ALL and WB_SYNC_NONE")
    Signed-off-by: default avatarZhiguo Niu <zhiguo.niu@unisoc.com>
    Signed-off-by: default avatarJing Xia <jing.xia@unisoc.com>
    Signed-off-by: default avatarChao Yu <chao@kernel.org>
    Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
    34415099
node.c 81.4 KB