diff options
author | Qu Wenruo <wqu@suse.com> | 2019-08-08 21:24:23 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2019-09-09 08:59:12 -0400 |
commit | e2406a6f13bdc7df43bf7e4e66cb06348daef618 (patch) | |
tree | e1e6afcec2d3b385010a0b261dfc676578ef4064 | |
parent | f82d1c7ca8ae1bf89e8d78c5ecb56b6b228c1a75 (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.c | 40 |
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 | ||
1159 | static 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 | } |