History

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.

Qu Wenruo committed 8 months ago

Commit 52e71eb1 parent ad0c23c2 files · +52 −1Browse files

Unified · Split

2 files
  1. fs/btrfs/tree-checker.c +50 −0
  2. include/uapi/linux/btrfs_tree.h +2 −1
fs/btrfs/tree-checker.c+50−0
@@ -1945,6 +1945,53 @@ static int check_dev_extent_item(const struct extent_buffer *leaf, · 1944 unmodified lines
1945 return 0;1945 return 0;
1946}1946}
1947 1947
1948static 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 * Common point to switch the item-specific validation.1996 * Common point to switch the item-specific validation.
1950 */1997 */
@@ -2008,6 +2055,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf, · 57 unmodified lines
2008 case BTRFS_RAID_STRIPE_KEY:2055 case BTRFS_RAID_STRIPE_KEY:
2009 ret = check_raid_stripe_extent(leaf, key, slot);2056 ret = check_raid_stripe_extent(leaf, key, slot);
2010 break;2057 break;
2058 case BTRFS_FREE_SPACE_INFO_KEY:
2059 ret = check_free_space_info(leaf, key, slot);
2060 break;
2011 }2061 }
2012 2062
2013 if (unlikely(ret))2063 if (unlikely(ret))
include/uapi/linux/btrfs_tree.h+2−1
@@ -1245,7 +1245,8 @@ struct btrfs_free_space_info { · 1244 unmodified lines
1245 __le32 flags;1245 __le32 flags;
1246} __attribute__ ((__packed__));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#define BTRFS_QGROUP_LEVEL_SHIFT 481251#define BTRFS_QGROUP_LEVEL_SHIFT 48
1251static inline __u16 btrfs_qgroup_level(__u64 qgroupid)1252static inline __u16 btrfs_qgroup_level(__u64 qgroupid)