aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/backref.c31
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;