aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-03-07 14:22:04 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:18 -0400
commit3173a18f70554fe7880bb2d85c7da566e364eb3c (patch)
tree0a23b42a8d275d3499fac2b90ded76276c64c1c1 /fs/btrfs/extent-tree.c
parentbe283b2e674a09457d4563729015adb637ce7cc1 (diff)
Btrfs: add a incompatible format change for smaller metadata extent refs
We currently store the first key of the tree block inside the reference for the tree block in the extent tree. This takes up quite a bit of space. Make a new key type for metadata which holds the level as the offset and completely removes storing the btrfs_tree_block_info inside the extent ref. This reduces the size from 51 bytes to 33 bytes per extent reference for each tree block. In practice this results in a 30-35% decrease in the size of our extent tree, which means we COW less and can keep more of the extent tree in memory which makes our heavy metadata operations go much faster. This is not an automatic format change, you must enable it at mkfs time or with btrfstune. This patch deals with having metadata stored as either the old format or the new format so it is easy to convert. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c224
1 files changed, 186 insertions, 38 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3d551231caba..7505856df9f3 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -442,11 +442,16 @@ again:
442 block_group->key.offset) 442 block_group->key.offset)
443 break; 443 break;
444 444
445 if (key.type == BTRFS_EXTENT_ITEM_KEY) { 445 if (key.type == BTRFS_EXTENT_ITEM_KEY ||
446 key.type == BTRFS_METADATA_ITEM_KEY) {
446 total_found += add_new_free_space(block_group, 447 total_found += add_new_free_space(block_group,
447 fs_info, last, 448 fs_info, last,
448 key.objectid); 449 key.objectid);
449 last = key.objectid + key.offset; 450 if (key.type == BTRFS_METADATA_ITEM_KEY)
451 last = key.objectid +
452 fs_info->tree_root->leafsize;
453 else
454 last = key.objectid + key.offset;
450 455
451 if (total_found > (1024 * 1024 * 2)) { 456 if (total_found > (1024 * 1024 * 2)) {
452 total_found = 0; 457 total_found = 0;
@@ -718,15 +723,21 @@ int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
718 723
719 key.objectid = start; 724 key.objectid = start;
720 key.offset = len; 725 key.offset = len;
721 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 726 key.type = BTRFS_EXTENT_ITEM_KEY;
722 ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path, 727 ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path,
723 0, 0); 728 0, 0);
729 if (ret > 0) {
730 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
731 if (key.objectid == start &&
732 key.type == BTRFS_METADATA_ITEM_KEY)
733 ret = 0;
734 }
724 btrfs_free_path(path); 735 btrfs_free_path(path);
725 return ret; 736 return ret;
726} 737}
727 738
728/* 739/*
729 * helper function to lookup reference count and flags of extent. 740 * helper function to lookup reference count and flags of a tree block.
730 * 741 *
731 * the head node for delayed ref is used to store the sum of all the 742 * the head node for delayed ref is used to store the sum of all the
732 * reference count modifications queued up in the rbtree. the head 743 * reference count modifications queued up in the rbtree. the head
@@ -736,7 +747,7 @@ int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
736 */ 747 */
737int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, 748int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
738 struct btrfs_root *root, u64 bytenr, 749 struct btrfs_root *root, u64 bytenr,
739 u64 num_bytes, u64 *refs, u64 *flags) 750 u64 offset, int metadata, u64 *refs, u64 *flags)
740{ 751{
741 struct btrfs_delayed_ref_head *head; 752 struct btrfs_delayed_ref_head *head;
742 struct btrfs_delayed_ref_root *delayed_refs; 753 struct btrfs_delayed_ref_root *delayed_refs;
@@ -749,13 +760,29 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
749 u64 extent_flags; 760 u64 extent_flags;
750 int ret; 761 int ret;
751 762
763 /*
764 * If we don't have skinny metadata, don't bother doing anything
765 * different
766 */
767 if (metadata && !btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) {
768 offset = root->leafsize;
769 metadata = 0;
770 }
771
752 path = btrfs_alloc_path(); 772 path = btrfs_alloc_path();
753 if (!path) 773 if (!path)
754 return -ENOMEM; 774 return -ENOMEM;
755 775
756 key.objectid = bytenr; 776 if (metadata) {
757 key.type = BTRFS_EXTENT_ITEM_KEY; 777 key.objectid = bytenr;
758 key.offset = num_bytes; 778 key.type = BTRFS_METADATA_ITEM_KEY;
779 key.offset = offset;
780 } else {
781 key.objectid = bytenr;
782 key.type = BTRFS_EXTENT_ITEM_KEY;
783 key.offset = offset;
784 }
785
759 if (!trans) { 786 if (!trans) {
760 path->skip_locking = 1; 787 path->skip_locking = 1;
761 path->search_commit_root = 1; 788 path->search_commit_root = 1;
@@ -766,6 +793,13 @@ again:
766 if (ret < 0) 793 if (ret < 0)
767 goto out_free; 794 goto out_free;
768 795
796 if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
797 key.type = BTRFS_EXTENT_ITEM_KEY;
798 key.offset = root->leafsize;
799 btrfs_release_path(path);
800 goto again;
801 }
802
769 if (ret == 0) { 803 if (ret == 0) {
770 leaf = path->nodes[0]; 804 leaf = path->nodes[0];
771 item_size = btrfs_item_size_nr(leaf, path->slots[0]); 805 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
@@ -1453,6 +1487,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
1453 int want; 1487 int want;
1454 int ret; 1488 int ret;
1455 int err = 0; 1489 int err = 0;
1490 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
1491 SKINNY_METADATA);
1456 1492
1457 key.objectid = bytenr; 1493 key.objectid = bytenr;
1458 key.type = BTRFS_EXTENT_ITEM_KEY; 1494 key.type = BTRFS_EXTENT_ITEM_KEY;
@@ -1464,11 +1500,46 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
1464 path->keep_locks = 1; 1500 path->keep_locks = 1;
1465 } else 1501 } else
1466 extra_size = -1; 1502 extra_size = -1;
1503
1504 /*
1505 * Owner is our parent level, so we can just add one to get the level
1506 * for the block we are interested in.
1507 */
1508 if (skinny_metadata && owner < BTRFS_FIRST_FREE_OBJECTID) {
1509 key.type = BTRFS_METADATA_ITEM_KEY;
1510 key.offset = owner;
1511 }
1512
1513again:
1467 ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1); 1514 ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1);
1468 if (ret < 0) { 1515 if (ret < 0) {
1469 err = ret; 1516 err = ret;
1470 goto out; 1517 goto out;
1471 } 1518 }
1519
1520 /*
1521 * We may be a newly converted file system which still has the old fat
1522 * extent entries for metadata, so try and see if we have one of those.
1523 */
1524 if (ret > 0 && skinny_metadata) {
1525 skinny_metadata = false;
1526 if (path->slots[0]) {
1527 path->slots[0]--;
1528 btrfs_item_key_to_cpu(path->nodes[0], &key,
1529 path->slots[0]);
1530 if (key.objectid == bytenr &&
1531 key.type == BTRFS_EXTENT_ITEM_KEY &&
1532 key.offset == num_bytes)
1533 ret = 0;
1534 }
1535 if (ret) {
1536 key.type = BTRFS_EXTENT_ITEM_KEY;
1537 key.offset = num_bytes;
1538 btrfs_release_path(path);
1539 goto again;
1540 }
1541 }
1542
1472 if (ret && !insert) { 1543 if (ret && !insert) {
1473 err = -ENOENT; 1544 err = -ENOENT;
1474 goto out; 1545 goto out;
@@ -1504,11 +1575,9 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
1504 ptr = (unsigned long)(ei + 1); 1575 ptr = (unsigned long)(ei + 1);
1505 end = (unsigned long)ei + item_size; 1576 end = (unsigned long)ei + item_size;
1506 1577
1507 if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { 1578 if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK && !skinny_metadata) {
1508 ptr += sizeof(struct btrfs_tree_block_info); 1579 ptr += sizeof(struct btrfs_tree_block_info);
1509 BUG_ON(ptr > end); 1580 BUG_ON(ptr > end);
1510 } else {
1511 BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA));
1512 } 1581 }
1513 1582
1514 err = -ENOENT; 1583 err = -ENOENT;
@@ -1973,10 +2042,8 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
1973 ref_root = ref->root; 2042 ref_root = ref->root;
1974 2043
1975 if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { 2044 if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
1976 if (extent_op) { 2045 if (extent_op)
1977 BUG_ON(extent_op->update_key);
1978 flags |= extent_op->flags_to_set; 2046 flags |= extent_op->flags_to_set;
1979 }
1980 ret = alloc_reserved_file_extent(trans, root, 2047 ret = alloc_reserved_file_extent(trans, root,
1981 parent, ref_root, flags, 2048 parent, ref_root, flags,
1982 ref->objectid, ref->offset, 2049 ref->objectid, ref->offset,
@@ -2029,18 +2096,33 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
2029 u32 item_size; 2096 u32 item_size;
2030 int ret; 2097 int ret;
2031 int err = 0; 2098 int err = 0;
2099 int metadata = (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
2100 node->type == BTRFS_SHARED_BLOCK_REF_KEY);
2032 2101
2033 if (trans->aborted) 2102 if (trans->aborted)
2034 return 0; 2103 return 0;
2035 2104
2105 if (metadata && !btrfs_fs_incompat(root->fs_info, SKINNY_METADATA))
2106 metadata = 0;
2107
2036 path = btrfs_alloc_path(); 2108 path = btrfs_alloc_path();
2037 if (!path) 2109 if (!path)
2038 return -ENOMEM; 2110 return -ENOMEM;
2039 2111
2040 key.objectid = node->bytenr; 2112 key.objectid = node->bytenr;
2041 key.type = BTRFS_EXTENT_ITEM_KEY;
2042 key.offset = node->num_bytes;
2043 2113
2114 if (metadata) {
2115 struct btrfs_delayed_tree_ref *tree_ref;
2116
2117 tree_ref = btrfs_delayed_node_to_tree_ref(node);
2118 key.type = BTRFS_METADATA_ITEM_KEY;
2119 key.offset = tree_ref->level;
2120 } else {
2121 key.type = BTRFS_EXTENT_ITEM_KEY;
2122 key.offset = node->num_bytes;
2123 }
2124
2125again:
2044 path->reada = 1; 2126 path->reada = 1;
2045 path->leave_spinning = 1; 2127 path->leave_spinning = 1;
2046 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, 2128 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key,
@@ -2050,6 +2132,14 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
2050 goto out; 2132 goto out;
2051 } 2133 }
2052 if (ret > 0) { 2134 if (ret > 0) {
2135 if (metadata) {
2136 btrfs_release_path(path);
2137 metadata = 0;
2138
2139 key.offset = node->num_bytes;
2140 key.type = BTRFS_EXTENT_ITEM_KEY;
2141 goto again;
2142 }
2053 err = -EIO; 2143 err = -EIO;
2054 goto out; 2144 goto out;
2055 } 2145 }
@@ -2089,10 +2179,8 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
2089 struct btrfs_key ins; 2179 struct btrfs_key ins;
2090 u64 parent = 0; 2180 u64 parent = 0;
2091 u64 ref_root = 0; 2181 u64 ref_root = 0;
2092 2182 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
2093 ins.objectid = node->bytenr; 2183 SKINNY_METADATA);
2094 ins.offset = node->num_bytes;
2095 ins.type = BTRFS_EXTENT_ITEM_KEY;
2096 2184
2097 ref = btrfs_delayed_node_to_tree_ref(node); 2185 ref = btrfs_delayed_node_to_tree_ref(node);
2098 if (node->type == BTRFS_SHARED_BLOCK_REF_KEY) 2186 if (node->type == BTRFS_SHARED_BLOCK_REF_KEY)
@@ -2100,10 +2188,18 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
2100 else 2188 else
2101 ref_root = ref->root; 2189 ref_root = ref->root;
2102 2190
2191 ins.objectid = node->bytenr;
2192 if (skinny_metadata) {
2193 ins.offset = ref->level;
2194 ins.type = BTRFS_METADATA_ITEM_KEY;
2195 } else {
2196 ins.offset = node->num_bytes;
2197 ins.type = BTRFS_EXTENT_ITEM_KEY;
2198 }
2199
2103 BUG_ON(node->ref_mod != 1); 2200 BUG_ON(node->ref_mod != 1);
2104 if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { 2201 if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
2105 BUG_ON(!extent_op || !extent_op->update_flags || 2202 BUG_ON(!extent_op || !extent_op->update_flags);
2106 !extent_op->update_key);
2107 ret = alloc_reserved_tree_block(trans, root, 2203 ret = alloc_reserved_tree_block(trans, root,
2108 parent, ref_root, 2204 parent, ref_root,
2109 extent_op->flags_to_set, 2205 extent_op->flags_to_set,
@@ -5312,6 +5408,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
5312 int num_to_del = 1; 5408 int num_to_del = 1;
5313 u32 item_size; 5409 u32 item_size;
5314 u64 refs; 5410 u64 refs;
5411 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
5412 SKINNY_METADATA);
5315 5413
5316 path = btrfs_alloc_path(); 5414 path = btrfs_alloc_path();
5317 if (!path) 5415 if (!path)
@@ -5323,6 +5421,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
5323 is_data = owner_objectid >= BTRFS_FIRST_FREE_OBJECTID; 5421 is_data = owner_objectid >= BTRFS_FIRST_FREE_OBJECTID;
5324 BUG_ON(!is_data && refs_to_drop != 1); 5422 BUG_ON(!is_data && refs_to_drop != 1);
5325 5423
5424 if (is_data)
5425 skinny_metadata = 0;
5426
5326 ret = lookup_extent_backref(trans, extent_root, path, &iref, 5427 ret = lookup_extent_backref(trans, extent_root, path, &iref,
5327 bytenr, num_bytes, parent, 5428 bytenr, num_bytes, parent,
5328 root_objectid, owner_objectid, 5429 root_objectid, owner_objectid,
@@ -5339,6 +5440,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
5339 found_extent = 1; 5440 found_extent = 1;
5340 break; 5441 break;
5341 } 5442 }
5443 if (key.type == BTRFS_METADATA_ITEM_KEY &&
5444 key.offset == owner_objectid) {
5445 found_extent = 1;
5446 break;
5447 }
5342 if (path->slots[0] - extent_slot > 5) 5448 if (path->slots[0] - extent_slot > 5)
5343 break; 5449 break;
5344 extent_slot--; 5450 extent_slot--;
@@ -5364,8 +5470,36 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
5364 key.type = BTRFS_EXTENT_ITEM_KEY; 5470 key.type = BTRFS_EXTENT_ITEM_KEY;
5365 key.offset = num_bytes; 5471 key.offset = num_bytes;
5366 5472
5473 if (!is_data && skinny_metadata) {
5474 key.type = BTRFS_METADATA_ITEM_KEY;
5475 key.offset = owner_objectid;
5476 }
5477
5367 ret = btrfs_search_slot(trans, extent_root, 5478 ret = btrfs_search_slot(trans, extent_root,
5368 &key, path, -1, 1); 5479 &key, path, -1, 1);
5480 if (ret > 0 && skinny_metadata && path->slots[0]) {
5481 /*
5482 * Couldn't find our skinny metadata item,
5483 * see if we have ye olde extent item.
5484 */
5485 path->slots[0]--;
5486 btrfs_item_key_to_cpu(path->nodes[0], &key,
5487 path->slots[0]);
5488 if (key.objectid == bytenr &&
5489 key.type == BTRFS_EXTENT_ITEM_KEY &&
5490 key.offset == num_bytes)
5491 ret = 0;
5492 }
5493
5494 if (ret > 0 && skinny_metadata) {
5495 skinny_metadata = false;
5496 key.type = BTRFS_EXTENT_ITEM_KEY;
5497 key.offset = num_bytes;
5498 btrfs_release_path(path);
5499 ret = btrfs_search_slot(trans, extent_root,
5500 &key, path, -1, 1);
5501 }
5502
5369 if (ret) { 5503 if (ret) {
5370 printk(KERN_ERR "umm, got %d back from search" 5504 printk(KERN_ERR "umm, got %d back from search"
5371 ", was looking for %llu\n", ret, 5505 ", was looking for %llu\n", ret,
@@ -5435,7 +5569,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
5435 BUG_ON(item_size < sizeof(*ei)); 5569 BUG_ON(item_size < sizeof(*ei));
5436 ei = btrfs_item_ptr(leaf, extent_slot, 5570 ei = btrfs_item_ptr(leaf, extent_slot,
5437 struct btrfs_extent_item); 5571 struct btrfs_extent_item);
5438 if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { 5572 if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID &&
5573 key.type == BTRFS_EXTENT_ITEM_KEY) {
5439 struct btrfs_tree_block_info *bi; 5574 struct btrfs_tree_block_info *bi;
5440 BUG_ON(item_size < sizeof(*ei) + sizeof(*bi)); 5575 BUG_ON(item_size < sizeof(*ei) + sizeof(*bi));
5441 bi = (struct btrfs_tree_block_info *)(ei + 1); 5576 bi = (struct btrfs_tree_block_info *)(ei + 1);
@@ -6349,7 +6484,12 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
6349 struct btrfs_extent_inline_ref *iref; 6484 struct btrfs_extent_inline_ref *iref;
6350 struct btrfs_path *path; 6485 struct btrfs_path *path;
6351 struct extent_buffer *leaf; 6486 struct extent_buffer *leaf;
6352 u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref); 6487 u32 size = sizeof(*extent_item) + sizeof(*iref);
6488 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
6489 SKINNY_METADATA);
6490
6491 if (!skinny_metadata)
6492 size += sizeof(*block_info);
6353 6493
6354 path = btrfs_alloc_path(); 6494 path = btrfs_alloc_path();
6355 if (!path) 6495 if (!path)
@@ -6370,12 +6510,16 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
6370 btrfs_set_extent_generation(leaf, extent_item, trans->transid); 6510 btrfs_set_extent_generation(leaf, extent_item, trans->transid);
6371 btrfs_set_extent_flags(leaf, extent_item, 6511 btrfs_set_extent_flags(leaf, extent_item,
6372 flags | BTRFS_EXTENT_FLAG_TREE_BLOCK); 6512 flags | BTRFS_EXTENT_FLAG_TREE_BLOCK);
6373 block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
6374 6513
6375 btrfs_set_tree_block_key(leaf, block_info, key); 6514 if (skinny_metadata) {
6376 btrfs_set_tree_block_level(leaf, block_info, level); 6515 iref = (struct btrfs_extent_inline_ref *)(extent_item + 1);
6516 } else {
6517 block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
6518 btrfs_set_tree_block_key(leaf, block_info, key);
6519 btrfs_set_tree_block_level(leaf, block_info, level);
6520 iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
6521 }
6377 6522
6378 iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
6379 if (parent > 0) { 6523 if (parent > 0) {
6380 BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)); 6524 BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
6381 btrfs_set_extent_inline_ref_type(leaf, iref, 6525 btrfs_set_extent_inline_ref_type(leaf, iref,
@@ -6390,7 +6534,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
6390 btrfs_mark_buffer_dirty(leaf); 6534 btrfs_mark_buffer_dirty(leaf);
6391 btrfs_free_path(path); 6535 btrfs_free_path(path);
6392 6536
6393 ret = update_block_group(root, ins->objectid, ins->offset, 1); 6537 ret = update_block_group(root, ins->objectid, root->leafsize, 1);
6394 if (ret) { /* -ENOENT, logic error */ 6538 if (ret) { /* -ENOENT, logic error */
6395 printk(KERN_ERR "btrfs update block group failed for %llu " 6539 printk(KERN_ERR "btrfs update block group failed for %llu "
6396 "%llu\n", (unsigned long long)ins->objectid, 6540 "%llu\n", (unsigned long long)ins->objectid,
@@ -6594,7 +6738,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
6594 struct extent_buffer *buf; 6738 struct extent_buffer *buf;
6595 u64 flags = 0; 6739 u64 flags = 0;
6596 int ret; 6740 int ret;
6597 6741 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
6742 SKINNY_METADATA);
6598 6743
6599 block_rsv = use_block_rsv(trans, root, blocksize); 6744 block_rsv = use_block_rsv(trans, root, blocksize);
6600 if (IS_ERR(block_rsv)) 6745 if (IS_ERR(block_rsv))
@@ -6627,7 +6772,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
6627 else 6772 else
6628 memset(&extent_op->key, 0, sizeof(extent_op->key)); 6773 memset(&extent_op->key, 0, sizeof(extent_op->key));
6629 extent_op->flags_to_set = flags; 6774 extent_op->flags_to_set = flags;
6630 extent_op->update_key = 1; 6775 if (skinny_metadata)
6776 extent_op->update_key = 0;
6777 else
6778 extent_op->update_key = 1;
6631 extent_op->update_flags = 1; 6779 extent_op->update_flags = 1;
6632 extent_op->is_data = 0; 6780 extent_op->is_data = 0;
6633 6781
@@ -6704,8 +6852,9 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
6704 continue; 6852 continue;
6705 6853
6706 /* We don't lock the tree block, it's OK to be racy here */ 6854 /* We don't lock the tree block, it's OK to be racy here */
6707 ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize, 6855 ret = btrfs_lookup_extent_info(trans, root, bytenr,
6708 &refs, &flags); 6856 wc->level - 1, 1, &refs,
6857 &flags);
6709 /* We don't care about errors in readahead. */ 6858 /* We don't care about errors in readahead. */
6710 if (ret < 0) 6859 if (ret < 0)
6711 continue; 6860 continue;
@@ -6772,7 +6921,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
6772 (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag)))) { 6921 (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag)))) {
6773 BUG_ON(!path->locks[level]); 6922 BUG_ON(!path->locks[level]);
6774 ret = btrfs_lookup_extent_info(trans, root, 6923 ret = btrfs_lookup_extent_info(trans, root,
6775 eb->start, eb->len, 6924 eb->start, level, 1,
6776 &wc->refs[level], 6925 &wc->refs[level],
6777 &wc->flags[level]); 6926 &wc->flags[level]);
6778 BUG_ON(ret == -ENOMEM); 6927 BUG_ON(ret == -ENOMEM);
@@ -6870,7 +7019,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
6870 btrfs_tree_lock(next); 7019 btrfs_tree_lock(next);
6871 btrfs_set_lock_blocking(next); 7020 btrfs_set_lock_blocking(next);
6872 7021
6873 ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize, 7022 ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
6874 &wc->refs[level - 1], 7023 &wc->refs[level - 1],
6875 &wc->flags[level - 1]); 7024 &wc->flags[level - 1]);
6876 if (ret < 0) { 7025 if (ret < 0) {
@@ -7001,7 +7150,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
7001 path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 7150 path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
7002 7151
7003 ret = btrfs_lookup_extent_info(trans, root, 7152 ret = btrfs_lookup_extent_info(trans, root,
7004 eb->start, eb->len, 7153 eb->start, level, 1,
7005 &wc->refs[level], 7154 &wc->refs[level],
7006 &wc->flags[level]); 7155 &wc->flags[level]);
7007 if (ret < 0) { 7156 if (ret < 0) {
@@ -7211,8 +7360,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
7211 7360
7212 ret = btrfs_lookup_extent_info(trans, root, 7361 ret = btrfs_lookup_extent_info(trans, root,
7213 path->nodes[level]->start, 7362 path->nodes[level]->start,
7214 path->nodes[level]->len, 7363 level, 1, &wc->refs[level],
7215 &wc->refs[level],
7216 &wc->flags[level]); 7364 &wc->flags[level]);
7217 if (ret < 0) { 7365 if (ret < 0) {
7218 err = ret; 7366 err = ret;