aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-06-28 13:11:22 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-07-02 11:51:02 -0400
commit261c84b662f93e0eb75bccd6cd732391d005060a (patch)
tree8a982a07457895d119993e878405cf635a966157 /fs/btrfs/backref.c
parent35f0399db6658f465b00893bdd13b992a0acfef0 (diff)
Btrfs: make backref walking code handle skinny metadata
I missed fixing the backref stuff when I introduced the skinny metadata. If you try and do things like snapshot aware defrag with skinny metadata you are going to see tons of warnings related to the backref count being less than 0. This is because the delayed refs will be found for stuff just fine, but it won't find the skinny metadata extent refs. With this patch I'm not seeing warnings anymore. Thanks, Reviewed-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/backref.c')
-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;