On 2019/1/17 上午12:00, Josef Bacik wrote: > qgroups will do the old roots lookup at delayed ref time, which could be > while walking down the extent root while running a delayed ref. This > should be fine, except we specifically lock eb's in the backref walking > code irrespective of path->skip_locking, which deadlocks the system. > Fix up the backref code to honor path->skip_locking, nobody will be > modifying the commit_root when we're searching so it's completely safe > to do. Thanks, > > Signed-off-by: Josef Bacik Reviewed-by: Qu Wenruo Thanks, Qu > --- > fs/btrfs/backref.c | 16 ++++++++++------ > 1 file changed, 10 insertions(+), 6 deletions(-) > > diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c > index 78556447e1d5..973e8251b1bf 100644 > --- a/fs/btrfs/backref.c > +++ b/fs/btrfs/backref.c > @@ -712,7 +712,7 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info, > * read tree blocks and add keys where required. > */ > static int add_missing_keys(struct btrfs_fs_info *fs_info, > - struct preftrees *preftrees) > + struct preftrees *preftrees, bool lock) > { > struct prelim_ref *ref; > struct extent_buffer *eb; > @@ -737,12 +737,14 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info, > free_extent_buffer(eb); > return -EIO; > } > - btrfs_tree_read_lock(eb); > + if (lock) > + btrfs_tree_read_lock(eb); > if (btrfs_header_level(eb) == 0) > btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0); > else > btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0); > - btrfs_tree_read_unlock(eb); > + if (lock) > + btrfs_tree_read_unlock(eb); > free_extent_buffer(eb); > prelim_ref_insert(fs_info, &preftrees->indirect, ref, NULL); > cond_resched(); > @@ -1227,7 +1229,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, > > btrfs_release_path(path); > > - ret = add_missing_keys(fs_info, &preftrees); > + ret = add_missing_keys(fs_info, &preftrees, path->skip_locking == 0); > if (ret) > goto out; > > @@ -1288,11 +1290,13 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, > ret = -EIO; > goto out; > } > - btrfs_tree_read_lock(eb); > + if (!path->skip_locking) > + btrfs_tree_read_lock(eb); > btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); > ret = find_extent_in_eb(eb, bytenr, > *extent_item_pos, &eie, ignore_offset); > - btrfs_tree_read_unlock_blocking(eb); > + if (!path->skip_locking) > + btrfs_tree_read_unlock_blocking(eb); > free_extent_buffer(eb); > if (ret < 0) > goto out; >