diff options
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-checker.c | 48 |
3 files changed, 50 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b161224b5a0b..20793742c9d3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2447,6 +2447,7 @@ enum btrfs_inline_ref_type { | |||
2447 | int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, | 2447 | int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, |
2448 | struct btrfs_extent_inline_ref *iref, | 2448 | struct btrfs_extent_inline_ref *iref, |
2449 | enum btrfs_inline_ref_type is_data); | 2449 | enum btrfs_inline_ref_type is_data); |
2450 | u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset); | ||
2450 | 2451 | ||
2451 | u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); | 2452 | u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); |
2452 | 2453 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cd210550a349..5e8c6a0bac4b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -438,7 +438,7 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, | |||
438 | return BTRFS_REF_TYPE_INVALID; | 438 | return BTRFS_REF_TYPE_INVALID; |
439 | } | 439 | } |
440 | 440 | ||
441 | static u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset) | 441 | u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset) |
442 | { | 442 | { |
443 | u32 high_crc = ~(u32)0; | 443 | u32 high_crc = ~(u32)0; |
444 | u32 low_crc = ~(u32)0; | 444 | u32 low_crc = ~(u32)0; |
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 0a56616bef9a..9645389a1187 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c | |||
@@ -1187,6 +1187,51 @@ static int check_simple_keyed_refs(struct extent_buffer *leaf, | |||
1187 | return 0; | 1187 | return 0; |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | static int check_extent_data_ref(struct extent_buffer *leaf, | ||
1191 | struct btrfs_key *key, int slot) | ||
1192 | { | ||
1193 | struct btrfs_extent_data_ref *dref; | ||
1194 | unsigned long ptr = btrfs_item_ptr_offset(leaf, slot); | ||
1195 | const unsigned long end = ptr + btrfs_item_size_nr(leaf, slot); | ||
1196 | |||
1197 | if (btrfs_item_size_nr(leaf, slot) % sizeof(*dref) != 0) { | ||
1198 | generic_err(leaf, slot, | ||
1199 | "invalid item size, have %u expect aligned to %zu for key type %u", | ||
1200 | btrfs_item_size_nr(leaf, slot), | ||
1201 | sizeof(*dref), key->type); | ||
1202 | } | ||
1203 | if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { | ||
1204 | generic_err(leaf, slot, | ||
1205 | "invalid key objectid for shared block ref, have %llu expect aligned to %u", | ||
1206 | key->objectid, leaf->fs_info->sectorsize); | ||
1207 | return -EUCLEAN; | ||
1208 | } | ||
1209 | for (; ptr < end; ptr += sizeof(*dref)) { | ||
1210 | u64 root_objectid; | ||
1211 | u64 owner; | ||
1212 | u64 offset; | ||
1213 | u64 hash; | ||
1214 | |||
1215 | dref = (struct btrfs_extent_data_ref *)ptr; | ||
1216 | root_objectid = btrfs_extent_data_ref_root(leaf, dref); | ||
1217 | owner = btrfs_extent_data_ref_objectid(leaf, dref); | ||
1218 | offset = btrfs_extent_data_ref_offset(leaf, dref); | ||
1219 | hash = hash_extent_data_ref(root_objectid, owner, offset); | ||
1220 | if (hash != key->offset) { | ||
1221 | extent_err(leaf, slot, | ||
1222 | "invalid extent data ref hash, item has 0x%016llx key has 0x%016llx", | ||
1223 | hash, key->offset); | ||
1224 | return -EUCLEAN; | ||
1225 | } | ||
1226 | if (!IS_ALIGNED(offset, leaf->fs_info->sectorsize)) { | ||
1227 | extent_err(leaf, slot, | ||
1228 | "invalid extent data backref offset, have %llu expect aligned to %u", | ||
1229 | offset, leaf->fs_info->sectorsize); | ||
1230 | } | ||
1231 | } | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1190 | /* | 1235 | /* |
1191 | * Common point to switch the item-specific validation. | 1236 | * Common point to switch the item-specific validation. |
1192 | */ | 1237 | */ |
@@ -1234,6 +1279,9 @@ static int check_leaf_item(struct extent_buffer *leaf, | |||
1234 | case BTRFS_SHARED_BLOCK_REF_KEY: | 1279 | case BTRFS_SHARED_BLOCK_REF_KEY: |
1235 | ret = check_simple_keyed_refs(leaf, key, slot); | 1280 | ret = check_simple_keyed_refs(leaf, key, slot); |
1236 | break; | 1281 | break; |
1282 | case BTRFS_EXTENT_DATA_REF_KEY: | ||
1283 | ret = check_extent_data_ref(leaf, key, slot); | ||
1284 | break; | ||
1237 | } | 1285 | } |
1238 | return ret; | 1286 | return ret; |
1239 | } | 1287 | } |