diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 73 |
1 files changed, 58 insertions, 15 deletions
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 | } |