aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c73
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
619int find_inline_backref(struct extent_buffer *leaf, int slot, 619int 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);
3259out: 3284out:
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 }