summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-checker.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-checker.c')
-rw-r--r--fs/btrfs/tree-checker.c48
1 files changed, 48 insertions, 0 deletions
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
1190static 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}