diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 22 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 224 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 2 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 73 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 30 |
7 files changed, 290 insertions, 67 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index ca9d8f1a3bb6..fe032ab6bd8a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -867,7 +867,8 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
867 | 867 | ||
868 | if (btrfs_block_can_be_shared(root, buf)) { | 868 | if (btrfs_block_can_be_shared(root, buf)) { |
869 | ret = btrfs_lookup_extent_info(trans, root, buf->start, | 869 | ret = btrfs_lookup_extent_info(trans, root, buf->start, |
870 | buf->len, &refs, &flags); | 870 | btrfs_header_level(buf), 1, |
871 | &refs, &flags); | ||
871 | if (ret) | 872 | if (ret) |
872 | return ret; | 873 | return ret; |
873 | if (refs == 0) { | 874 | if (refs == 0) { |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index e2f14b5258b6..efb2feb7cd4a 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -509,6 +509,7 @@ struct btrfs_super_block { | |||
509 | 509 | ||
510 | #define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) | 510 | #define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) |
511 | #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) | 511 | #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) |
512 | #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) | ||
512 | 513 | ||
513 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL | 514 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL |
514 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL | 515 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL |
@@ -519,7 +520,8 @@ struct btrfs_super_block { | |||
519 | BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ | 520 | BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ |
520 | BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \ | 521 | BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \ |
521 | BTRFS_FEATURE_INCOMPAT_RAID56 | \ | 522 | BTRFS_FEATURE_INCOMPAT_RAID56 | \ |
522 | BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF) | 523 | BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF | \ |
524 | BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) | ||
523 | 525 | ||
524 | /* | 526 | /* |
525 | * A leaf is full of items. offset and size tell us where to find | 527 | * A leaf is full of items. offset and size tell us where to find |
@@ -1809,6 +1811,12 @@ struct btrfs_ioctl_defrag_range_args { | |||
1809 | */ | 1811 | */ |
1810 | #define BTRFS_EXTENT_ITEM_KEY 168 | 1812 | #define BTRFS_EXTENT_ITEM_KEY 168 |
1811 | 1813 | ||
1814 | /* | ||
1815 | * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know | ||
1816 | * the length, so we save the level in key->offset instead of the length. | ||
1817 | */ | ||
1818 | #define BTRFS_METADATA_ITEM_KEY 169 | ||
1819 | |||
1812 | #define BTRFS_TREE_BLOCK_REF_KEY 176 | 1820 | #define BTRFS_TREE_BLOCK_REF_KEY 176 |
1813 | 1821 | ||
1814 | #define BTRFS_EXTENT_DATA_REF_KEY 178 | 1822 | #define BTRFS_EXTENT_DATA_REF_KEY 178 |
@@ -3006,7 +3014,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
3006 | int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len); | 3014 | int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len); |
3007 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | 3015 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, |
3008 | struct btrfs_root *root, u64 bytenr, | 3016 | struct btrfs_root *root, u64 bytenr, |
3009 | u64 num_bytes, u64 *refs, u64 *flags); | 3017 | u64 offset, int metadata, u64 *refs, u64 *flags); |
3010 | int btrfs_pin_extent(struct btrfs_root *root, | 3018 | int btrfs_pin_extent(struct btrfs_root *root, |
3011 | u64 bytenr, u64 num, int reserved); | 3019 | u64 bytenr, u64 num, int reserved); |
3012 | int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, | 3020 | int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, |
@@ -3669,6 +3677,16 @@ static inline void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, | |||
3669 | } | 3677 | } |
3670 | } | 3678 | } |
3671 | 3679 | ||
3680 | #define btrfs_fs_incompat(fs_info, opt) \ | ||
3681 | __btrfs_fs_incompat((fs_info), BTRFS_FEATURE_INCOMPAT_##opt) | ||
3682 | |||
3683 | static inline int __btrfs_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag) | ||
3684 | { | ||
3685 | struct btrfs_super_block *disk_super; | ||
3686 | disk_super = fs_info->super_copy; | ||
3687 | return !!(btrfs_super_incompat_flags(disk_super) & flag); | ||
3688 | } | ||
3689 | |||
3672 | /* | 3690 | /* |
3673 | * Call btrfs_abort_transaction as early as possible when an error condition is | 3691 | * Call btrfs_abort_transaction as early as possible when an error condition is |
3674 | * detected, that way the exact line number is reported. | 3692 | * detected, that way the exact line number is reported. |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e0665488e512..f47754a2fee4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2290,6 +2290,9 @@ int open_ctree(struct super_block *sb, | |||
2290 | if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO) | 2290 | if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO) |
2291 | features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; | 2291 | features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; |
2292 | 2292 | ||
2293 | if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) | ||
2294 | printk(KERN_ERR "btrfs: has skinny extents\n"); | ||
2295 | |||
2293 | /* | 2296 | /* |
2294 | * flag our filesystem as having big metadata blocks if | 2297 | * flag our filesystem as having big metadata blocks if |
2295 | * they are bigger than the page size | 2298 | * they are bigger than the page size |
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; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 24e8a356a36c..c69145b66ea4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3660,7 +3660,7 @@ static int check_path_shared(struct btrfs_root *root, | |||
3660 | eb = path->nodes[level]; | 3660 | eb = path->nodes[level]; |
3661 | if (!btrfs_block_can_be_shared(root, eb)) | 3661 | if (!btrfs_block_can_be_shared(root, eb)) |
3662 | continue; | 3662 | continue; |
3663 | ret = btrfs_lookup_extent_info(NULL, root, eb->start, eb->len, | 3663 | ret = btrfs_lookup_extent_info(NULL, root, eb->start, level, 1, |
3664 | &refs, NULL); | 3664 | &refs, NULL); |
3665 | if (refs > 1) | 3665 | if (refs > 1) |
3666 | return 1; | 3666 | return 1; |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b67171e6d688..86f192ffc212 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -619,10 +619,13 @@ static noinline_for_stack | |||
619 | int find_inline_backref(struct extent_buffer *leaf, int slot, | 619 | int find_inline_backref(struct extent_buffer *leaf, int slot, |
620 | unsigned long *ptr, unsigned long *end) | 620 | unsigned long *ptr, unsigned long *end) |
621 | { | 621 | { |
622 | struct btrfs_key key; | ||
622 | struct btrfs_extent_item *ei; | 623 | struct btrfs_extent_item *ei; |
623 | struct btrfs_tree_block_info *bi; | 624 | struct btrfs_tree_block_info *bi; |
624 | u32 item_size; | 625 | u32 item_size; |
625 | 626 | ||
627 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
628 | |||
626 | item_size = btrfs_item_size_nr(leaf, slot); | 629 | item_size = btrfs_item_size_nr(leaf, slot); |
627 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 | 630 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 |
628 | if (item_size < sizeof(*ei)) { | 631 | if (item_size < sizeof(*ei)) { |
@@ -634,13 +637,18 @@ int find_inline_backref(struct extent_buffer *leaf, int slot, | |||
634 | WARN_ON(!(btrfs_extent_flags(leaf, ei) & | 637 | WARN_ON(!(btrfs_extent_flags(leaf, ei) & |
635 | BTRFS_EXTENT_FLAG_TREE_BLOCK)); | 638 | BTRFS_EXTENT_FLAG_TREE_BLOCK)); |
636 | 639 | ||
637 | if (item_size <= sizeof(*ei) + sizeof(*bi)) { | 640 | if (key.type == BTRFS_EXTENT_ITEM_KEY && |
641 | item_size <= sizeof(*ei) + sizeof(*bi)) { | ||
638 | WARN_ON(item_size < sizeof(*ei) + sizeof(*bi)); | 642 | WARN_ON(item_size < sizeof(*ei) + sizeof(*bi)); |
639 | return 1; | 643 | return 1; |
640 | } | 644 | } |
641 | 645 | ||
642 | bi = (struct btrfs_tree_block_info *)(ei + 1); | 646 | if (key.type == BTRFS_EXTENT_ITEM_KEY) { |
643 | *ptr = (unsigned long)(bi + 1); | 647 | bi = (struct btrfs_tree_block_info *)(ei + 1); |
648 | *ptr = (unsigned long)(bi + 1); | ||
649 | } else { | ||
650 | *ptr = (unsigned long)(ei + 1); | ||
651 | } | ||
644 | *end = (unsigned long)ei + item_size; | 652 | *end = (unsigned long)ei + item_size; |
645 | return 0; | 653 | return 0; |
646 | } | 654 | } |
@@ -708,7 +716,7 @@ again: | |||
708 | end = 0; | 716 | end = 0; |
709 | ptr = 0; | 717 | ptr = 0; |
710 | key.objectid = cur->bytenr; | 718 | key.objectid = cur->bytenr; |
711 | key.type = BTRFS_EXTENT_ITEM_KEY; | 719 | key.type = BTRFS_METADATA_ITEM_KEY; |
712 | key.offset = (u64)-1; | 720 | key.offset = (u64)-1; |
713 | 721 | ||
714 | path1->search_commit_root = 1; | 722 | path1->search_commit_root = 1; |
@@ -766,7 +774,8 @@ again: | |||
766 | break; | 774 | break; |
767 | } | 775 | } |
768 | 776 | ||
769 | if (key.type == BTRFS_EXTENT_ITEM_KEY) { | 777 | if (key.type == BTRFS_EXTENT_ITEM_KEY || |
778 | key.type == BTRFS_METADATA_ITEM_KEY) { | ||
770 | ret = find_inline_backref(eb, path1->slots[0], | 779 | ret = find_inline_backref(eb, path1->slots[0], |
771 | &ptr, &end); | 780 | &ptr, &end); |
772 | if (ret) | 781 | if (ret) |
@@ -2768,8 +2777,13 @@ static int reada_tree_block(struct reloc_control *rc, | |||
2768 | struct tree_block *block) | 2777 | struct tree_block *block) |
2769 | { | 2778 | { |
2770 | BUG_ON(block->key_ready); | 2779 | BUG_ON(block->key_ready); |
2771 | readahead_tree_block(rc->extent_root, block->bytenr, | 2780 | if (block->key.type == BTRFS_METADATA_ITEM_KEY) |
2772 | block->key.objectid, block->key.offset); | 2781 | readahead_tree_block(rc->extent_root, block->bytenr, |
2782 | block->key.objectid, | ||
2783 | rc->extent_root->leafsize); | ||
2784 | else | ||
2785 | readahead_tree_block(rc->extent_root, block->bytenr, | ||
2786 | block->key.objectid, block->key.offset); | ||
2773 | return 0; | 2787 | return 0; |
2774 | } | 2788 | } |
2775 | 2789 | ||
@@ -3176,12 +3190,17 @@ static int add_tree_block(struct reloc_control *rc, | |||
3176 | eb = path->nodes[0]; | 3190 | eb = path->nodes[0]; |
3177 | item_size = btrfs_item_size_nr(eb, path->slots[0]); | 3191 | item_size = btrfs_item_size_nr(eb, path->slots[0]); |
3178 | 3192 | ||
3179 | if (item_size >= sizeof(*ei) + sizeof(*bi)) { | 3193 | if (extent_key->type == BTRFS_METADATA_ITEM_KEY || |
3194 | item_size >= sizeof(*ei) + sizeof(*bi)) { | ||
3180 | ei = btrfs_item_ptr(eb, path->slots[0], | 3195 | ei = btrfs_item_ptr(eb, path->slots[0], |
3181 | struct btrfs_extent_item); | 3196 | struct btrfs_extent_item); |
3182 | bi = (struct btrfs_tree_block_info *)(ei + 1); | 3197 | if (extent_key->type == BTRFS_EXTENT_ITEM_KEY) { |
3198 | bi = (struct btrfs_tree_block_info *)(ei + 1); | ||
3199 | level = btrfs_tree_block_level(eb, bi); | ||
3200 | } else { | ||
3201 | level = (int)extent_key->offset; | ||
3202 | } | ||
3183 | generation = btrfs_extent_generation(eb, ei); | 3203 | generation = btrfs_extent_generation(eb, ei); |
3184 | level = btrfs_tree_block_level(eb, bi); | ||
3185 | } else { | 3204 | } else { |
3186 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 | 3205 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 |
3187 | u64 ref_owner; | 3206 | u64 ref_owner; |
@@ -3210,7 +3229,7 @@ static int add_tree_block(struct reloc_control *rc, | |||
3210 | return -ENOMEM; | 3229 | return -ENOMEM; |
3211 | 3230 | ||
3212 | block->bytenr = extent_key->objectid; | 3231 | block->bytenr = extent_key->objectid; |
3213 | block->key.objectid = extent_key->offset; | 3232 | block->key.objectid = rc->extent_root->leafsize; |
3214 | block->key.offset = generation; | 3233 | block->key.offset = generation; |
3215 | block->level = level; | 3234 | block->level = level; |
3216 | block->key_ready = 0; | 3235 | block->key_ready = 0; |
@@ -3252,9 +3271,15 @@ static int __add_tree_block(struct reloc_control *rc, | |||
3252 | ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0); | 3271 | ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0); |
3253 | if (ret < 0) | 3272 | if (ret < 0) |
3254 | goto out; | 3273 | goto out; |
3255 | BUG_ON(ret); | ||
3256 | 3274 | ||
3257 | btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); | 3275 | btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); |
3276 | if (ret > 0) { | ||
3277 | if (key.objectid == bytenr && | ||
3278 | key.type == BTRFS_METADATA_ITEM_KEY) | ||
3279 | ret = 0; | ||
3280 | } | ||
3281 | BUG_ON(ret); | ||
3282 | |||
3258 | ret = add_tree_block(rc, &key, path, blocks); | 3283 | ret = add_tree_block(rc, &key, path, blocks); |
3259 | out: | 3284 | out: |
3260 | btrfs_free_path(path); | 3285 | btrfs_free_path(path); |
@@ -3275,7 +3300,8 @@ static int block_use_full_backref(struct reloc_control *rc, | |||
3275 | return 1; | 3300 | return 1; |
3276 | 3301 | ||
3277 | ret = btrfs_lookup_extent_info(NULL, rc->extent_root, | 3302 | ret = btrfs_lookup_extent_info(NULL, rc->extent_root, |
3278 | eb->start, eb->len, NULL, &flags); | 3303 | eb->start, btrfs_header_level(eb), 1, |
3304 | NULL, &flags); | ||
3279 | BUG_ON(ret); | 3305 | BUG_ON(ret); |
3280 | 3306 | ||
3281 | if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) | 3307 | if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) |
@@ -3644,12 +3670,25 @@ next: | |||
3644 | break; | 3670 | break; |
3645 | } | 3671 | } |
3646 | 3672 | ||
3647 | if (key.type != BTRFS_EXTENT_ITEM_KEY || | 3673 | if (key.type != BTRFS_EXTENT_ITEM_KEY && |
3674 | key.type != BTRFS_METADATA_ITEM_KEY) { | ||
3675 | path->slots[0]++; | ||
3676 | goto next; | ||
3677 | } | ||
3678 | |||
3679 | if (key.type == BTRFS_EXTENT_ITEM_KEY && | ||
3648 | key.objectid + key.offset <= rc->search_start) { | 3680 | key.objectid + key.offset <= rc->search_start) { |
3649 | path->slots[0]++; | 3681 | path->slots[0]++; |
3650 | goto next; | 3682 | goto next; |
3651 | } | 3683 | } |
3652 | 3684 | ||
3685 | if (key.type == BTRFS_METADATA_ITEM_KEY && | ||
3686 | key.objectid + rc->extent_root->leafsize <= | ||
3687 | rc->search_start) { | ||
3688 | path->slots[0]++; | ||
3689 | goto next; | ||
3690 | } | ||
3691 | |||
3653 | ret = find_first_extent_bit(&rc->processed_blocks, | 3692 | ret = find_first_extent_bit(&rc->processed_blocks, |
3654 | key.objectid, &start, &end, | 3693 | key.objectid, &start, &end, |
3655 | EXTENT_DIRTY, NULL); | 3694 | EXTENT_DIRTY, NULL); |
@@ -3658,7 +3697,11 @@ next: | |||
3658 | btrfs_release_path(path); | 3697 | btrfs_release_path(path); |
3659 | rc->search_start = end + 1; | 3698 | rc->search_start = end + 1; |
3660 | } else { | 3699 | } else { |
3661 | rc->search_start = key.objectid + key.offset; | 3700 | if (key.type == BTRFS_EXTENT_ITEM_KEY) |
3701 | rc->search_start = key.objectid + key.offset; | ||
3702 | else | ||
3703 | rc->search_start = key.objectid + | ||
3704 | rc->extent_root->leafsize; | ||
3662 | memcpy(extent_key, &key, sizeof(key)); | 3705 | memcpy(extent_key, &key, sizeof(key)); |
3663 | return 0; | 3706 | return 0; |
3664 | } | 3707 | } |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 3d29d60bdaf8..28db5dcde0aa 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2312,8 +2312,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2312 | key_start.type = BTRFS_EXTENT_ITEM_KEY; | 2312 | key_start.type = BTRFS_EXTENT_ITEM_KEY; |
2313 | key_start.offset = (u64)0; | 2313 | key_start.offset = (u64)0; |
2314 | key_end.objectid = base + offset + nstripes * increment; | 2314 | key_end.objectid = base + offset + nstripes * increment; |
2315 | key_end.type = BTRFS_EXTENT_ITEM_KEY; | 2315 | key_end.type = BTRFS_METADATA_ITEM_KEY; |
2316 | key_end.offset = (u64)0; | 2316 | key_end.offset = (u64)-1; |
2317 | reada1 = btrfs_reada_add(root, &key_start, &key_end); | 2317 | reada1 = btrfs_reada_add(root, &key_start, &key_end); |
2318 | 2318 | ||
2319 | key_start.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | 2319 | key_start.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
@@ -2401,6 +2401,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2401 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 2401 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
2402 | if (ret < 0) | 2402 | if (ret < 0) |
2403 | goto out; | 2403 | goto out; |
2404 | |||
2404 | if (ret > 0) { | 2405 | if (ret > 0) { |
2405 | ret = btrfs_previous_item(root, path, 0, | 2406 | ret = btrfs_previous_item(root, path, 0, |
2406 | BTRFS_EXTENT_ITEM_KEY); | 2407 | BTRFS_EXTENT_ITEM_KEY); |
@@ -2418,6 +2419,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2418 | } | 2419 | } |
2419 | 2420 | ||
2420 | while (1) { | 2421 | while (1) { |
2422 | u64 bytes; | ||
2423 | |||
2421 | l = path->nodes[0]; | 2424 | l = path->nodes[0]; |
2422 | slot = path->slots[0]; | 2425 | slot = path->slots[0]; |
2423 | if (slot >= btrfs_header_nritems(l)) { | 2426 | if (slot >= btrfs_header_nritems(l)) { |
@@ -2431,14 +2434,21 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2431 | } | 2434 | } |
2432 | btrfs_item_key_to_cpu(l, &key, slot); | 2435 | btrfs_item_key_to_cpu(l, &key, slot); |
2433 | 2436 | ||
2434 | if (key.objectid + key.offset <= logical) | 2437 | if (key.type != BTRFS_EXTENT_ITEM_KEY && |
2438 | key.type != BTRFS_METADATA_ITEM_KEY) | ||
2439 | goto next; | ||
2440 | |||
2441 | if (key.type == BTRFS_METADATA_ITEM_KEY) | ||
2442 | bytes = root->leafsize; | ||
2443 | else | ||
2444 | bytes = key.offset; | ||
2445 | |||
2446 | if (key.objectid + bytes <= logical) | ||
2435 | goto next; | 2447 | goto next; |
2436 | 2448 | ||
2437 | if (key.objectid >= logical + map->stripe_len) | 2449 | if (key.objectid >= logical + map->stripe_len) |
2438 | break; | 2450 | break; |
2439 | 2451 | ||
2440 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) | ||
2441 | goto next; | ||
2442 | 2452 | ||
2443 | extent = btrfs_item_ptr(l, slot, | 2453 | extent = btrfs_item_ptr(l, slot, |
2444 | struct btrfs_extent_item); | 2454 | struct btrfs_extent_item); |
@@ -2459,18 +2469,18 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2459 | * trim extent to this stripe | 2469 | * trim extent to this stripe |
2460 | */ | 2470 | */ |
2461 | if (key.objectid < logical) { | 2471 | if (key.objectid < logical) { |
2462 | key.offset -= logical - key.objectid; | 2472 | bytes -= logical - key.objectid; |
2463 | key.objectid = logical; | 2473 | key.objectid = logical; |
2464 | } | 2474 | } |
2465 | if (key.objectid + key.offset > | 2475 | if (key.objectid + bytes > |
2466 | logical + map->stripe_len) { | 2476 | logical + map->stripe_len) { |
2467 | key.offset = logical + map->stripe_len - | 2477 | bytes = logical + map->stripe_len - |
2468 | key.objectid; | 2478 | key.objectid; |
2469 | } | 2479 | } |
2470 | 2480 | ||
2471 | extent_logical = key.objectid; | 2481 | extent_logical = key.objectid; |
2472 | extent_physical = key.objectid - logical + physical; | 2482 | extent_physical = key.objectid - logical + physical; |
2473 | extent_len = key.offset; | 2483 | extent_len = bytes; |
2474 | extent_dev = scrub_dev; | 2484 | extent_dev = scrub_dev; |
2475 | extent_mirror_num = mirror_num; | 2485 | extent_mirror_num = mirror_num; |
2476 | if (is_dev_replace) | 2486 | if (is_dev_replace) |