aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2019-08-08 21:24:23 -0400
committerDavid Sterba <dsterba@suse.com>2019-09-09 08:59:12 -0400
commite2406a6f13bdc7df43bf7e4e66cb06348daef618 (patch)
treee1e6afcec2d3b385010a0b261dfc676578ef4064
parentf82d1c7ca8ae1bf89e8d78c5ecb56b6b228c1a75 (diff)
btrfs: tree-checker: Add simple keyed refs check
For TREE_BLOCK_REF, SHARED_DATA_REF and SHARED_BLOCK_REF we need to check: | TREE_BLOCK_REF | SHARED_BLOCK_REF | SHARED_BLOCK_REF --------------+----------------+-----------------+------------------ key->objectid | Alignment | Alignment | Alignment key->offset | Any value | Alignment | Alignment item_size | 0 | 0 | sizeof(le32) (*) *: sizeof(struct btrfs_shared_data_ref) So introduce a check to check all these 3 key types together. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/tree-checker.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 7eee0bbd8c37..0a56616bef9a 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -923,7 +923,9 @@ static void extent_err(const struct extent_buffer *eb, int slot,
923 923
924 btrfs_item_key_to_cpu(eb, &key, slot); 924 btrfs_item_key_to_cpu(eb, &key, slot);
925 bytenr = key.objectid; 925 bytenr = key.objectid;
926 if (key.type == BTRFS_METADATA_ITEM_KEY) 926 if (key.type == BTRFS_METADATA_ITEM_KEY ||
927 key.type == BTRFS_TREE_BLOCK_REF_KEY ||
928 key.type == BTRFS_SHARED_BLOCK_REF_KEY)
927 len = eb->fs_info->nodesize; 929 len = eb->fs_info->nodesize;
928 else 930 else
929 len = key.offset; 931 len = key.offset;
@@ -1154,6 +1156,37 @@ static int check_extent_item(struct extent_buffer *leaf,
1154 return 0; 1156 return 0;
1155} 1157}
1156 1158
1159static int check_simple_keyed_refs(struct extent_buffer *leaf,
1160 struct btrfs_key *key, int slot)
1161{
1162 u32 expect_item_size = 0;
1163
1164 if (key->type == BTRFS_SHARED_DATA_REF_KEY)
1165 expect_item_size = sizeof(struct btrfs_shared_data_ref);
1166
1167 if (btrfs_item_size_nr(leaf, slot) != expect_item_size) {
1168 generic_err(leaf, slot,
1169 "invalid item size, have %u expect %u for key type %u",
1170 btrfs_item_size_nr(leaf, slot),
1171 expect_item_size, key->type);
1172 return -EUCLEAN;
1173 }
1174 if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) {
1175 generic_err(leaf, slot,
1176"invalid key objectid for shared block ref, have %llu expect aligned to %u",
1177 key->objectid, leaf->fs_info->sectorsize);
1178 return -EUCLEAN;
1179 }
1180 if (key->type != BTRFS_TREE_BLOCK_REF_KEY &&
1181 !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) {
1182 extent_err(leaf, slot,
1183 "invalid tree parent bytenr, have %llu expect aligned to %u",
1184 key->offset, leaf->fs_info->sectorsize);
1185 return -EUCLEAN;
1186 }
1187 return 0;
1188}
1189
1157/* 1190/*
1158 * Common point to switch the item-specific validation. 1191 * Common point to switch the item-specific validation.
1159 */ 1192 */
@@ -1196,6 +1229,11 @@ static int check_leaf_item(struct extent_buffer *leaf,
1196 case BTRFS_METADATA_ITEM_KEY: 1229 case BTRFS_METADATA_ITEM_KEY:
1197 ret = check_extent_item(leaf, key, slot); 1230 ret = check_extent_item(leaf, key, slot);
1198 break; 1231 break;
1232 case BTRFS_TREE_BLOCK_REF_KEY:
1233 case BTRFS_SHARED_DATA_REF_KEY:
1234 case BTRFS_SHARED_BLOCK_REF_KEY:
1235 ret = check_simple_keyed_refs(leaf, key, slot);
1236 break;
1199 } 1237 }
1200 return ret; 1238 return ret;
1201} 1239}