Skip to content

Commit 7bf3a99

Browse files
adam900710kdave
authored andcommitted
btrfs: subpage: reject tree blocks which are not nodesize aligned
When btrfs subpage support (fs block < page size) was introduced, a subpage filesystem will only reject tree blocks which cross page boundaries. This used to be a compromise to simplify the tree block handling and still allowing subpage cases to read some old converted filesystems which did not have proper chunk alignment. But in practice, suppose we have the following unaligned tree block on a 64K page sized system: 0 32K 44K 60K 64K | |///////////////| | Although btrfs has no problem reading the tree block at [44K, 60K), if extent allocator is allocating another tree block, it may choose the range [60K, 74K), as extent allocator has no awareness if it's a subpage metadata request or not. Then we'd get -EINVAL from the following sequence: btrfs_alloc_tree_block() |- btrfs_reserve_extent() | Which returned range [60K, 74K) |- btrfs_init_new_buffer() |- btrfs_find_create_tree_block() |- alloc_extent_buffer() |- check_eb_alignment() Which returned -EINVAL, because the range crosses page boundary. This situation will not fix itself and should mostly mark the fs read-only. Thankfully we didn't really get such reports in the real world because: - The original unaligned tree block is only caused by older btrfs-convert It's before the btrfs-convert rework was done in v4.6, where converted btrfs filesystem can have metadata block groups which are not aligned to nodesize nor stripe size (64K). But after btrfs-progs v4.6, all chunks allocated will be stripe (64K) aligned, thus no more such problem. Considering how old the fix is (v4.6 was released almost 10 years ago), subpage support for btrfs was introduced in v5.15, it should be safe to reject those unaligned tree blocks. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 5b97870 commit 7bf3a99

File tree

1 file changed

+2
-3
lines changed

1 file changed

+2
-3
lines changed

fs/btrfs/extent_io.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,10 +3083,9 @@ static bool check_eb_alignment(struct btrfs_fs_info *fs_info, u64 start)
30833083
return true;
30843084
}
30853085

3086-
if (fs_info->nodesize < PAGE_SIZE &&
3087-
offset_in_page(start) + fs_info->nodesize > PAGE_SIZE) {
3086+
if (fs_info->nodesize < PAGE_SIZE && !IS_ALIGNED(start, fs_info->nodesize)) {
30883087
btrfs_err(fs_info,
3089-
"tree block crosses page boundary, start %llu nodesize %u",
3088+
"tree block is not nodesize aligned, start %llu nodesize %u",
30903089
start, fs_info->nodesize);
30913090
return true;
30923091
}

0 commit comments

Comments
 (0)