diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
| -rw-r--r-- | fs/btrfs/relocation.c | 43 | 
1 files changed, 39 insertions, 4 deletions
| diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 045c9c2b2d7..31ade5802ae 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1157,6 +1157,7 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,  	new_node->bytenr = dest->node->start;  	new_node->level = node->level;  	new_node->lowest = node->lowest; +	new_node->checked = 1;  	new_node->root = dest;  	if (!node->lowest) { @@ -2028,6 +2029,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,  	while (1) {  		trans = btrfs_start_transaction(root, 0); +		BUG_ON(IS_ERR(trans));  		trans->block_rsv = rc->block_rsv;  		ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, @@ -2147,6 +2149,12 @@ again:  	}  	trans = btrfs_join_transaction(rc->extent_root, 1); +	if (IS_ERR(trans)) { +		if (!err) +			btrfs_block_rsv_release(rc->extent_root, +						rc->block_rsv, num_bytes); +		return PTR_ERR(trans); +	}  	if (!err) {  		if (num_bytes != rc->merging_rsv_size) { @@ -3222,6 +3230,7 @@ truncate:  	trans = btrfs_join_transaction(root, 0);  	if (IS_ERR(trans)) {  		btrfs_free_path(path); +		ret = PTR_ERR(trans);  		goto out;  	} @@ -3628,6 +3637,7 @@ int prepare_to_relocate(struct reloc_control *rc)  	set_reloc_control(rc);  	trans = btrfs_join_transaction(rc->extent_root, 1); +	BUG_ON(IS_ERR(trans));  	btrfs_commit_transaction(trans, rc->extent_root);  	return 0;  } @@ -3644,6 +3654,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  	u32 item_size;  	int ret;  	int err = 0; +	int progress = 0;  	path = btrfs_alloc_path();  	if (!path) @@ -3656,8 +3667,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  	}  	while (1) { +		progress++;  		trans = btrfs_start_transaction(rc->extent_root, 0); - +		BUG_ON(IS_ERR(trans)); +restart:  		if (update_backref_cache(trans, &rc->backref_cache)) {  			btrfs_end_transaction(trans, rc->extent_root);  			continue; @@ -3770,6 +3783,15 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  			}  		}  	} +	if (trans && progress && err == -ENOSPC) { +		ret = btrfs_force_chunk_alloc(trans, rc->extent_root, +					      rc->block_group->flags); +		if (ret == 0) { +			err = 0; +			progress = 0; +			goto restart; +		} +	}  	btrfs_release_path(rc->extent_root, path);  	clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, @@ -3804,7 +3826,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  	/* get rid of pinned extents */  	trans = btrfs_join_transaction(rc->extent_root, 1); -	btrfs_commit_transaction(trans, rc->extent_root); +	if (IS_ERR(trans)) +		err = PTR_ERR(trans); +	else +		btrfs_commit_transaction(trans, rc->extent_root);  out_free:  	btrfs_free_block_rsv(rc->extent_root, rc->block_rsv);  	btrfs_free_path(path); @@ -4022,6 +4047,7 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)  	int ret;  	trans = btrfs_start_transaction(root->fs_info->tree_root, 0); +	BUG_ON(IS_ERR(trans));  	memset(&root->root_item.drop_progress, 0,  		sizeof(root->root_item.drop_progress)); @@ -4125,6 +4151,11 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	set_reloc_control(rc);  	trans = btrfs_join_transaction(rc->extent_root, 1); +	if (IS_ERR(trans)) { +		unset_reloc_control(rc); +		err = PTR_ERR(trans); +		goto out_free; +	}  	rc->merge_reloc_tree = 1; @@ -4154,9 +4185,13 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	unset_reloc_control(rc);  	trans = btrfs_join_transaction(rc->extent_root, 1); -	btrfs_commit_transaction(trans, rc->extent_root); -out: +	if (IS_ERR(trans)) +		err = PTR_ERR(trans); +	else +		btrfs_commit_transaction(trans, rc->extent_root); +out_free:  	kfree(rc); +out:  	while (!list_empty(&reloc_roots)) {  		reloc_root = list_entry(reloc_roots.next,  					struct btrfs_root, root_list); | 
