Skip to content
  • Qu Wenruo's avatar
    btrfs: Don't call btrfs_start_transaction() on frozen fs to avoid deadlock. · a53f4f8e
    Qu Wenruo authored
    Commit 6b5fe46d
    
     (btrfs: do commit in sync_fs if there are pending
    changes) will call btrfs_start_transaction() in sync_fs(), to handle
    some operations needed to be done in next transaction.
    
    However this can cause deadlock if the filesystem is frozen, with the
    following sys_r+w output:
    [  143.255932] Call Trace:
    [  143.255936]  [<ffffffff816c0e09>] schedule+0x29/0x70
    [  143.255939]  [<ffffffff811cb7f3>] __sb_start_write+0xb3/0x100
    [  143.255971]  [<ffffffffa040ec06>] start_transaction+0x2e6/0x5a0
    [btrfs]
    [  143.255992]  [<ffffffffa040f1eb>] btrfs_start_transaction+0x1b/0x20
    [btrfs]
    [  143.256003]  [<ffffffffa03dc0ba>] btrfs_sync_fs+0xca/0xd0 [btrfs]
    [  143.256007]  [<ffffffff811f7be0>] sync_fs_one_sb+0x20/0x30
    [  143.256011]  [<ffffffff811cbd01>] iterate_supers+0xe1/0xf0
    [  143.256014]  [<ffffffff811f7d75>] sys_sync+0x55/0x90
    [  143.256017]  [<ffffffff816c49d2>] system_call_fastpath+0x12/0x17
    [  143.256111] Call Trace:
    [  143.256114]  [<ffffffff816c0e09>] schedule+0x29/0x70
    [  143.256119]  [<ffffffff816c3405>] rwsem_down_write_failed+0x1c5/0x2d0
    [  143.256123]  [<ffffffff8133f013>] call_rwsem_down_write_failed+0x13/0x20
    [  143.256131]  [<ffffffff811caae8>] thaw_super+0x28/0xc0
    [  143.256135]  [<ffffffff811db3e5>] do_vfs_ioctl+0x3f5/0x540
    [  143.256187]  [<ffffffff811db5c1>] SyS_ioctl+0x91/0xb0
    [  143.256213]  [<ffffffff816c49d2>] system_call_fastpath+0x12/0x17
    
    The reason is like the following:
    (Holding s_umount)
    VFS sync_fs staff:
    |- btrfs_sync_fs()
       |- btrfs_start_transaction()
          |- sb_start_intwrite()
          (Waiting thaw_fs to unfreeze)
    					VFS thaw_fs staff:
    					thaw_fs()
    					(Waiting sync_fs to release
    					 s_umount)
    
    So deadlock happens.
    This can be easily triggered by fstest/generic/068 with inode_cache
    mount option.
    
    The fix is to check if the fs is frozen, if the fs is frozen, just
    return and waiting for the next transaction.
    
    Cc: David Sterba <dsterba@suse.cz>
    Reported-by: default avatarGui Hecheng <guihc.fnst@cn.fujitsu.com>
    Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
    [enhanced comment, changed to SB_FREEZE_WRITE]
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.cz>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    a53f4f8e