diff options
author | Omar Sandoval <osandov@fb.com> | 2016-05-20 13:50:33 -0700 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2016-06-25 06:20:10 -0700 |
commit | 02dbfc99b424dde3cf0a492ed3bec4f222441754 (patch) | |
tree | d08f267bac15ea5939185424bbe73306b7f11cb6 /fs/btrfs/delayed-inode.h | |
parent | 33688abb2802ff3a230bd2441f765477b94cc89e (diff) | |
download | linux-stable-02dbfc99b424dde3cf0a492ed3bec4f222441754.tar.gz linux-stable-02dbfc99b424dde3cf0a492ed3bec4f222441754.tar.bz2 linux-stable-02dbfc99b424dde3cf0a492ed3bec4f222441754.zip |
Btrfs: fix ->iterate_shared() by upgrading i_rwsem for delayed nodes
Commit fe742fd4f90f ("Revert "btrfs: switch to ->iterate_shared()"")
backed out the conversion to ->iterate_shared() for Btrfs because the
delayed inode handling in btrfs_real_readdir() is racy. However, we can
still do readdir in parallel if there are no delayed nodes.
This is a temporary fix which upgrades the shared inode lock to an
exclusive lock only when we have delayed items until we come up with a
more complete solution. While we're here, rename the
btrfs_{get,put}_delayed_items functions to make it very clear that
they're just for readdir.
Tested with xfstests and by doing a parallel kernel build:
while make tinyconfig && make -j4 && git clean dqfx; do
:
done
along with a bunch of parallel finds in another shell:
while true; do
for ((i=0; i<4; i++)); do
find . >/dev/null &
done
wait
done
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/delayed-inode.h')
-rw-r--r-- | fs/btrfs/delayed-inode.h | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 0167853c84ae..2495b3d4075f 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -137,10 +137,12 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); void btrfs_destroy_delayed_inodes(struct btrfs_root *root); /* Used for readdir() */ -void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, - struct list_head *del_list); -void btrfs_put_delayed_items(struct list_head *ins_list, - struct list_head *del_list); +bool btrfs_readdir_get_delayed_items(struct inode *inode, + struct list_head *ins_list, + struct list_head *del_list); +void btrfs_readdir_put_delayed_items(struct inode *inode, + struct list_head *ins_list, + struct list_head *del_list); int btrfs_should_delete_dir_index(struct list_head *del_list, u64 index); int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, |