diff options
-rw-r--r-- | fs/btrfs/backref.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 431ea9211bc1..eaf133384a8f 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -597,6 +597,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
597 | int slot; | 597 | int slot; |
598 | struct extent_buffer *leaf; | 598 | struct extent_buffer *leaf; |
599 | struct btrfs_key key; | 599 | struct btrfs_key key; |
600 | struct btrfs_key found_key; | ||
600 | unsigned long ptr; | 601 | unsigned long ptr; |
601 | unsigned long end; | 602 | unsigned long end; |
602 | struct btrfs_extent_item *ei; | 603 | struct btrfs_extent_item *ei; |
@@ -614,17 +615,21 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
614 | 615 | ||
615 | ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); | 616 | ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); |
616 | flags = btrfs_extent_flags(leaf, ei); | 617 | flags = btrfs_extent_flags(leaf, ei); |
618 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
617 | 619 | ||
618 | ptr = (unsigned long)(ei + 1); | 620 | ptr = (unsigned long)(ei + 1); |
619 | end = (unsigned long)ei + item_size; | 621 | end = (unsigned long)ei + item_size; |
620 | 622 | ||
621 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | 623 | if (found_key.type == BTRFS_EXTENT_ITEM_KEY && |
624 | flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | ||
622 | struct btrfs_tree_block_info *info; | 625 | struct btrfs_tree_block_info *info; |
623 | 626 | ||
624 | info = (struct btrfs_tree_block_info *)ptr; | 627 | info = (struct btrfs_tree_block_info *)ptr; |
625 | *info_level = btrfs_tree_block_level(leaf, info); | 628 | *info_level = btrfs_tree_block_level(leaf, info); |
626 | ptr += sizeof(struct btrfs_tree_block_info); | 629 | ptr += sizeof(struct btrfs_tree_block_info); |
627 | BUG_ON(ptr > end); | 630 | BUG_ON(ptr > end); |
631 | } else if (found_key.type == BTRFS_METADATA_ITEM_KEY) { | ||
632 | *info_level = found_key.offset; | ||
628 | } else { | 633 | } else { |
629 | BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA)); | 634 | BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA)); |
630 | } | 635 | } |
@@ -796,8 +801,11 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |||
796 | INIT_LIST_HEAD(&prefs_delayed); | 801 | INIT_LIST_HEAD(&prefs_delayed); |
797 | 802 | ||
798 | key.objectid = bytenr; | 803 | key.objectid = bytenr; |
799 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
800 | key.offset = (u64)-1; | 804 | key.offset = (u64)-1; |
805 | if (btrfs_fs_incompat(fs_info, SKINNY_METADATA)) | ||
806 | key.type = BTRFS_METADATA_ITEM_KEY; | ||
807 | else | ||
808 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
801 | 809 | ||
802 | path = btrfs_alloc_path(); | 810 | path = btrfs_alloc_path(); |
803 | if (!path) | 811 | if (!path) |
@@ -862,7 +870,8 @@ again: | |||
862 | slot = path->slots[0]; | 870 | slot = path->slots[0]; |
863 | btrfs_item_key_to_cpu(leaf, &key, slot); | 871 | btrfs_item_key_to_cpu(leaf, &key, slot); |
864 | if (key.objectid == bytenr && | 872 | if (key.objectid == bytenr && |
865 | key.type == BTRFS_EXTENT_ITEM_KEY) { | 873 | (key.type == BTRFS_EXTENT_ITEM_KEY || |
874 | key.type == BTRFS_METADATA_ITEM_KEY)) { | ||
866 | ret = __add_inline_refs(fs_info, path, bytenr, | 875 | ret = __add_inline_refs(fs_info, path, bytenr, |
867 | &info_level, &prefs); | 876 | &info_level, &prefs); |
868 | if (ret) | 877 | if (ret) |
@@ -1276,12 +1285,16 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
1276 | { | 1285 | { |
1277 | int ret; | 1286 | int ret; |
1278 | u64 flags; | 1287 | u64 flags; |
1288 | u64 size = 0; | ||
1279 | u32 item_size; | 1289 | u32 item_size; |
1280 | struct extent_buffer *eb; | 1290 | struct extent_buffer *eb; |
1281 | struct btrfs_extent_item *ei; | 1291 | struct btrfs_extent_item *ei; |
1282 | struct btrfs_key key; | 1292 | struct btrfs_key key; |
1283 | 1293 | ||
1284 | key.type = BTRFS_EXTENT_ITEM_KEY; | 1294 | if (btrfs_fs_incompat(fs_info, SKINNY_METADATA)) |
1295 | key.type = BTRFS_METADATA_ITEM_KEY; | ||
1296 | else | ||
1297 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
1285 | key.objectid = logical; | 1298 | key.objectid = logical; |
1286 | key.offset = (u64)-1; | 1299 | key.offset = (u64)-1; |
1287 | 1300 | ||
@@ -1294,9 +1307,15 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
1294 | return ret; | 1307 | return ret; |
1295 | 1308 | ||
1296 | btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); | 1309 | btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); |
1297 | if (found_key->type != BTRFS_EXTENT_ITEM_KEY || | 1310 | if (found_key->type == BTRFS_METADATA_ITEM_KEY) |
1311 | size = fs_info->extent_root->leafsize; | ||
1312 | else if (found_key->type == BTRFS_EXTENT_ITEM_KEY) | ||
1313 | size = found_key->offset; | ||
1314 | |||
1315 | if ((found_key->type != BTRFS_EXTENT_ITEM_KEY && | ||
1316 | found_key->type != BTRFS_METADATA_ITEM_KEY) || | ||
1298 | found_key->objectid > logical || | 1317 | found_key->objectid > logical || |
1299 | found_key->objectid + found_key->offset <= logical) { | 1318 | found_key->objectid + size <= logical) { |
1300 | pr_debug("logical %llu is not within any extent\n", | 1319 | pr_debug("logical %llu is not within any extent\n", |
1301 | (unsigned long long)logical); | 1320 | (unsigned long long)logical); |
1302 | return -ENOENT; | 1321 | return -ENOENT; |