• Zhao Lei's avatar
    btrfs: Fix lockdep warning of btrfs_run_delayed_iputs() · 8a733013
    Zhao Lei authored
    Liu Bo <bo.li.liu@oracle.com> reported a lockdep warning of
    delayed_iput_sem in xfstests generic/241:
      [ 2061.345955] =============================================
      [ 2061.346027] [ INFO: possible recursive locking detected ]
      [ 2061.346027] 4.1.0+ #268 Tainted: G        W
      [ 2061.346027] ---------------------------------------------
      [ 2061.346027] btrfs-cleaner/3045 is trying to acquire lock:
      [ 2061.346027]  (&fs_info->delayed_iput_sem){++++..}, at:
      [<ffffffff814063ab>] btrfs_run_delayed_iputs+0x6b/0x100
      [ 2061.346027] but task is already holding lock:
      [ 2061.346027]  (&fs_info->delayed_iput_sem){++++..}, at: [<ffffffff814063ab>] btrfs_run_delayed_iputs+0x6b/0x100
      [ 2061.346027] other info that might help us debug this:
      [ 2061.346027]  Possible unsafe locking scenario:
      [ 2061.346027]        CPU0
      [ 2061.346027]        ----
      [ 2061.346027]   lock(&fs_info->delayed_iput_sem);
      [ 2061.346027]   lock(&fs_info->delayed_iput_sem);
      [ 2061.346027]
       *** DEADLOCK ***
    It is rarely happened, about 1/400 in my test env.
    The reason is recursion of btrfs_run_delayed_iputs():
      -> btrfs_run_delayed_iputs() *1
      -> get delayed_iput_sem lock *2
      -> iput()
      -> ...
      -> btrfs_commit_transaction()
      -> btrfs_run_delayed_iputs() *1
      -> get delayed_iput_sem lock (dead lock) *2
      *1: recursion of btrfs_run_delayed_iputs()
      *2: warning of lockdep about delayed_iput_sem
    When fs is in high stress, new iputs may added into fs_info->delayed_iputs
    list when btrfs_run_delayed_iputs() is running, which cause
    second btrfs_run_delayed_iputs() run into down_read(&fs_info->delayed_iput_sem)
    again, and cause above lockdep warning.
    Actually, it will not cause real problem because both locks are read lock,
    but to avoid lockdep warning, we can do a fix.
      Don't do btrfs_run_delayed_iputs() in btrfs_commit_transaction() for
      cleaner_kthread thread to break above recursion path.
      cleaner_kthread is calling btrfs_run_delayed_iputs() explicitly in code,
      and don't need to call btrfs_run_delayed_iputs() again in
      btrfs_commit_transaction(), it also give us a bonus to avoid stack overflow.
      No above lockdep warning after patch in 1200 generic/241 tests.
    Reported-by: default avatarLiu Bo <bo.li.liu@oracle.com>
    Signed-off-by: default avatarZhao Lei <zhaolei@cn.fujitsu.com>
    Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>