diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 12096496cc99..aacc2121e87c 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -335,7 +335,7 @@ static void backref_tree_panic(struct rb_node *rb_node, int errno, u64 bytenr) | |||
335 | if (bnode->root) | 335 | if (bnode->root) |
336 | fs_info = bnode->root->fs_info; | 336 | fs_info = bnode->root->fs_info; |
337 | btrfs_panic(fs_info, errno, "Inconsistency in backref cache " | 337 | btrfs_panic(fs_info, errno, "Inconsistency in backref cache " |
338 | "found at offset %llu\n", (unsigned long long)bytenr); | 338 | "found at offset %llu\n", bytenr); |
339 | } | 339 | } |
340 | 340 | ||
341 | /* | 341 | /* |
@@ -641,6 +641,11 @@ int find_inline_backref(struct extent_buffer *leaf, int slot, | |||
641 | WARN_ON(item_size < sizeof(*ei) + sizeof(*bi)); | 641 | WARN_ON(item_size < sizeof(*ei) + sizeof(*bi)); |
642 | return 1; | 642 | return 1; |
643 | } | 643 | } |
644 | if (key.type == BTRFS_METADATA_ITEM_KEY && | ||
645 | item_size <= sizeof(*ei)) { | ||
646 | WARN_ON(item_size < sizeof(*ei)); | ||
647 | return 1; | ||
648 | } | ||
644 | 649 | ||
645 | if (key.type == BTRFS_EXTENT_ITEM_KEY) { | 650 | if (key.type == BTRFS_EXTENT_ITEM_KEY) { |
646 | bi = (struct btrfs_tree_block_info *)(ei + 1); | 651 | bi = (struct btrfs_tree_block_info *)(ei + 1); |
@@ -691,6 +696,7 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, | |||
691 | int cowonly; | 696 | int cowonly; |
692 | int ret; | 697 | int ret; |
693 | int err = 0; | 698 | int err = 0; |
699 | bool need_check = true; | ||
694 | 700 | ||
695 | path1 = btrfs_alloc_path(); | 701 | path1 = btrfs_alloc_path(); |
696 | path2 = btrfs_alloc_path(); | 702 | path2 = btrfs_alloc_path(); |
@@ -914,6 +920,7 @@ again: | |||
914 | cur->bytenr); | 920 | cur->bytenr); |
915 | 921 | ||
916 | lower = cur; | 922 | lower = cur; |
923 | need_check = true; | ||
917 | for (; level < BTRFS_MAX_LEVEL; level++) { | 924 | for (; level < BTRFS_MAX_LEVEL; level++) { |
918 | if (!path2->nodes[level]) { | 925 | if (!path2->nodes[level]) { |
919 | BUG_ON(btrfs_root_bytenr(&root->root_item) != | 926 | BUG_ON(btrfs_root_bytenr(&root->root_item) != |
@@ -957,14 +964,12 @@ again: | |||
957 | 964 | ||
958 | /* | 965 | /* |
959 | * add the block to pending list if we | 966 | * add the block to pending list if we |
960 | * need check its backrefs. only block | 967 | * need check its backrefs, we only do this once |
961 | * at 'cur->level + 1' is added to the | 968 | * while walking up a tree as we will catch |
962 | * tail of pending list. this guarantees | 969 | * anything else later on. |
963 | * we check backrefs from lower level | ||
964 | * blocks to upper level blocks. | ||
965 | */ | 970 | */ |
966 | if (!upper->checked && | 971 | if (!upper->checked && need_check) { |
967 | level == cur->level + 1) { | 972 | need_check = false; |
968 | list_add_tail(&edge->list[UPPER], | 973 | list_add_tail(&edge->list[UPPER], |
969 | &list); | 974 | &list); |
970 | } else | 975 | } else |
@@ -2314,8 +2319,13 @@ again: | |||
2314 | BUG_ON(root->reloc_root != reloc_root); | 2319 | BUG_ON(root->reloc_root != reloc_root); |
2315 | 2320 | ||
2316 | ret = merge_reloc_root(rc, root); | 2321 | ret = merge_reloc_root(rc, root); |
2317 | if (ret) | 2322 | if (ret) { |
2323 | __update_reloc_root(reloc_root, 1); | ||
2324 | free_extent_buffer(reloc_root->node); | ||
2325 | free_extent_buffer(reloc_root->commit_root); | ||
2326 | kfree(reloc_root); | ||
2318 | goto out; | 2327 | goto out; |
2328 | } | ||
2319 | } else { | 2329 | } else { |
2320 | list_del_init(&reloc_root->root_list); | 2330 | list_del_init(&reloc_root->root_list); |
2321 | } | 2331 | } |
@@ -2344,9 +2354,6 @@ again: | |||
2344 | if (IS_ERR(root)) | 2354 | if (IS_ERR(root)) |
2345 | continue; | 2355 | continue; |
2346 | 2356 | ||
2347 | if (btrfs_root_refs(&root->root_item) == 0) | ||
2348 | continue; | ||
2349 | |||
2350 | trans = btrfs_join_transaction(root); | 2357 | trans = btrfs_join_transaction(root); |
2351 | BUG_ON(IS_ERR(trans)); | 2358 | BUG_ON(IS_ERR(trans)); |
2352 | 2359 | ||
@@ -3628,7 +3635,7 @@ int add_data_references(struct reloc_control *rc, | |||
3628 | unsigned long ptr; | 3635 | unsigned long ptr; |
3629 | unsigned long end; | 3636 | unsigned long end; |
3630 | u32 blocksize = btrfs_level_size(rc->extent_root, 0); | 3637 | u32 blocksize = btrfs_level_size(rc->extent_root, 0); |
3631 | int ret; | 3638 | int ret = 0; |
3632 | int err = 0; | 3639 | int err = 0; |
3633 | 3640 | ||
3634 | eb = path->nodes[0]; | 3641 | eb = path->nodes[0]; |
@@ -3655,6 +3662,10 @@ int add_data_references(struct reloc_control *rc, | |||
3655 | } else { | 3662 | } else { |
3656 | BUG(); | 3663 | BUG(); |
3657 | } | 3664 | } |
3665 | if (ret) { | ||
3666 | err = ret; | ||
3667 | goto out; | ||
3668 | } | ||
3658 | ptr += btrfs_extent_inline_ref_size(key.type); | 3669 | ptr += btrfs_extent_inline_ref_size(key.type); |
3659 | } | 3670 | } |
3660 | WARN_ON(ptr > end); | 3671 | WARN_ON(ptr > end); |
@@ -3700,6 +3711,7 @@ int add_data_references(struct reloc_control *rc, | |||
3700 | } | 3711 | } |
3701 | path->slots[0]++; | 3712 | path->slots[0]++; |
3702 | } | 3713 | } |
3714 | out: | ||
3703 | btrfs_release_path(path); | 3715 | btrfs_release_path(path); |
3704 | if (err) | 3716 | if (err) |
3705 | free_block_list(blocks); | 3717 | free_block_list(blocks); |
@@ -4219,8 +4231,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
4219 | } | 4231 | } |
4220 | 4232 | ||
4221 | printk(KERN_INFO "btrfs: relocating block group %llu flags %llu\n", | 4233 | printk(KERN_INFO "btrfs: relocating block group %llu flags %llu\n", |
4222 | (unsigned long long)rc->block_group->key.objectid, | 4234 | rc->block_group->key.objectid, rc->block_group->flags); |
4223 | (unsigned long long)rc->block_group->flags); | ||
4224 | 4235 | ||
4225 | ret = btrfs_start_all_delalloc_inodes(fs_info, 0); | 4236 | ret = btrfs_start_all_delalloc_inodes(fs_info, 0); |
4226 | if (ret < 0) { | 4237 | if (ret < 0) { |
@@ -4242,7 +4253,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
4242 | break; | 4253 | break; |
4243 | 4254 | ||
4244 | printk(KERN_INFO "btrfs: found %llu extents\n", | 4255 | printk(KERN_INFO "btrfs: found %llu extents\n", |
4245 | (unsigned long long)rc->extents_found); | 4256 | rc->extents_found); |
4246 | 4257 | ||
4247 | if (rc->stage == MOVE_DATA_EXTENTS && rc->found_file_extent) { | 4258 | if (rc->stage == MOVE_DATA_EXTENTS && rc->found_file_extent) { |
4248 | btrfs_wait_ordered_range(rc->data_inode, 0, (u64)-1); | 4259 | btrfs_wait_ordered_range(rc->data_inode, 0, (u64)-1); |