diff options
author | Filipe Manana <fdmanana@suse.com> | 2015-11-19 10:57:20 (GMT) |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-11-25 13:19:51 (GMT) |
commit | 020d5b7366fc03e4bf84142ae6f63031ac504e33 (patch) | |
tree | 8f2c36c78f0d213d379e172f3a824c9d90ab1b2b /fs/btrfs/file.c | |
parent | 31388ab2edac833defa4193172edc1d409868bfb (diff) | |
download | linux-020d5b7366fc03e4bf84142ae6f63031ac504e33.tar.xz |
Btrfs: fix race between scrub and block group deletion
Scrub can race with the cleaner kthread deleting block groups that are
unused (and with relocation too) leading to a failure with error -EINVAL
that gets returned to user space.
The following diagram illustrates how it happens:
CPU 1 CPU 2
cleaner kthread
btrfs_delete_unused_bgs()
gets block group X from
fs_info->unused_bgs
sets block group to RO
btrfs_remove_chunk(bg X)
deletes device extents
scrub_enumerate_chunks()
searches device tree using
its commit root
finds device extent for
block group X
gets block group X from the tree
fs_info->block_group_cache_tree
(via btrfs_lookup_block_group())
sets bg X to RO (again)
btrfs_remove_block_group(bg X)
deletes block group from
fs_info->block_group_cache_tree
removes extent map from
fs_info->mapping_tree
scrub_chunk(offset X)
searches fs_info->mapping_tree
for extent map starting at
offset X
--> doesn't find any such
extent map
--> returns -EINVAL and scrub
errors out to userspace
with -EINVAL
Fix this by dealing with an extent map lookup failure as an indicator of
block group deletion.
Issue reproduced with fstest btrfs/071.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/file.c')
0 files changed, 0 insertions, 0 deletions