Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

btrfs: tree-checker: introduce checks for FREE_SPACE_INFO

Introduce checks for FREE_SPACE_INFO item, which include:

- Key alignment check
The objectid is the logical bytenr of the chunk/bg, and offset is the
length of the chunk/bg, thus they should all be aligned to the fs
block size.

- Item size check
The FREE_SPACE_INFO should a fix size.

- Flags check
The flags member should have no other flags than
BTRFS_FREE_SPACE_USING_BITMAPS.

For future expansion, introduce a new macro
BTRFS_FREE_SPACE_FLAGS_MASK for such checks.

And since we're here, the BTRFS_FREE_SPACE_USING_BITMAPS should not
use unsigned long long, as the flags is only 32 bits wide.
So fix that to use unsigned long.

- Extent count check
That member shows how many free space bitmap/extent items there are
inside the chunk/bg.

We know the chunk size (from key->offset), thus there should be at
most (key->offset >> sectorsize_bits) blocks inside the chunk.
Use that value as the upper limit and if that counter is larger than
that, there is a high chance it's a bitflip in high bits.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Qu Wenruo and committed by
David Sterba
52e71eb9 ad0c23c9

+52 -1
+50
fs/btrfs/tree-checker.c
··· 1945 1945 return 0; 1946 1946 } 1947 1947 1948 + static int check_free_space_info(struct extent_buffer *leaf, struct btrfs_key *key, 1949 + int slot) 1950 + { 1951 + struct btrfs_fs_info *fs_info = leaf->fs_info; 1952 + struct btrfs_free_space_info *fsi; 1953 + const u32 blocksize = fs_info->sectorsize; 1954 + u32 flags; 1955 + 1956 + if (unlikely(!IS_ALIGNED(key->objectid, blocksize))) { 1957 + generic_err(leaf, slot, 1958 + "free space info key objectid is not aligned to %u, has " BTRFS_KEY_FMT, 1959 + blocksize, BTRFS_KEY_FMT_VALUE(key)); 1960 + return -EUCLEAN; 1961 + } 1962 + if (unlikely(!IS_ALIGNED(key->offset, blocksize))) { 1963 + generic_err(leaf, slot, 1964 + "free space info key offset is not aligned to %u, has " BTRFS_KEY_FMT, 1965 + blocksize, BTRFS_KEY_FMT_VALUE(key)); 1966 + return -EUCLEAN; 1967 + } 1968 + if (unlikely(btrfs_item_size(leaf, slot) != 1969 + sizeof(struct btrfs_free_space_info))) { 1970 + generic_err(leaf, slot, 1971 + "invalid item size for free space info, has %u expect %zu", 1972 + btrfs_item_size(leaf, slot), 1973 + sizeof(struct btrfs_free_space_info)); 1974 + return -EUCLEAN; 1975 + } 1976 + fsi = btrfs_item_ptr(leaf, slot, struct btrfs_free_space_info); 1977 + flags = btrfs_free_space_flags(leaf, fsi); 1978 + if (unlikely(flags & ~BTRFS_FREE_SPACE_FLAGS_MASK)) { 1979 + generic_err(leaf, slot, 1980 + "unknown flags for free space info, has 0x%x valid mask 0x%lx", 1981 + flags, BTRFS_FREE_SPACE_FLAGS_MASK); 1982 + return -EUCLEAN; 1983 + } 1984 + if (unlikely(btrfs_free_space_extent_count(leaf, fsi) > 1985 + key->offset >> fs_info->sectorsize_bits)) { 1986 + generic_err(leaf, slot, 1987 + "suspicious extent count, has %u max valid %llu", 1988 + btrfs_free_space_extent_count(leaf, fsi), 1989 + key->offset >> fs_info->sectorsize_bits); 1990 + return -EUCLEAN; 1991 + } 1992 + return 0; 1993 + } 1994 + 1948 1995 /* 1949 1996 * Common point to switch the item-specific validation. 1950 1997 */ ··· 2054 2007 break; 2055 2008 case BTRFS_RAID_STRIPE_KEY: 2056 2009 ret = check_raid_stripe_extent(leaf, key, slot); 2010 + break; 2011 + case BTRFS_FREE_SPACE_INFO_KEY: 2012 + ret = check_free_space_info(leaf, key, slot); 2057 2013 break; 2058 2014 } 2059 2015
+2 -1
include/uapi/linux/btrfs_tree.h
··· 1245 1245 __le32 flags; 1246 1246 } __attribute__ ((__packed__)); 1247 1247 1248 - #define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) 1248 + #define BTRFS_FREE_SPACE_USING_BITMAPS (1UL << 0) 1249 + #define BTRFS_FREE_SPACE_FLAGS_MASK (BTRFS_FREE_SPACE_USING_BITMAPS) 1249 1250 1250 1251 #define BTRFS_QGROUP_LEVEL_SHIFT 48 1251 1252 static inline __u16 btrfs_qgroup_level(__u64 qgroupid)