diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 224 |
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 | */ |
737 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | 748 | int 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 | |||
1513 | again: | ||
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 | |||
2125 | again: | ||
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; |