summaryrefslogtreecommitdiff
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2015-11-19 10:57:20 (GMT)
committerChris Mason <clm@fb.com>2015-11-25 13:19:51 (GMT)
commit020d5b7366fc03e4bf84142ae6f63031ac504e33 (patch)
tree8f2c36c78f0d213d379e172f3a824c9d90ab1b2b /fs/btrfs/file.c
parent31388ab2edac833defa4193172edc1d409868bfb (diff)
downloadlinux-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