diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 27 | 
1 files changed, 22 insertions, 5 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 153f71a5bba9..274318e9114e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1869,8 +1869,8 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,  		btrfs_pin_extent(fs_info, head->bytenr,  				 head->num_bytes, 1);  		if (head->is_data) { -			ret = btrfs_del_csums(trans, fs_info, head->bytenr, -					      head->num_bytes); +			ret = btrfs_del_csums(trans, fs_info->csum_root, +					      head->bytenr, head->num_bytes);  		}  	} @@ -3175,7 +3175,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,  		btrfs_release_path(path);  		if (is_data) { -			ret = btrfs_del_csums(trans, info, bytenr, num_bytes); +			ret = btrfs_del_csums(trans, info->csum_root, bytenr, +					      num_bytes);  			if (ret) {  				btrfs_abort_transaction(trans, ret);  				goto out; @@ -3799,6 +3800,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,  				u64 flags, int delalloc)  {  	int ret = 0; +	int cache_block_group_error = 0;  	struct btrfs_free_cluster *last_ptr = NULL;  	struct btrfs_block_group *block_group = NULL;  	struct find_free_extent_ctl ffe_ctl = {0}; @@ -3958,7 +3960,20 @@ have_block_group:  		if (unlikely(!ffe_ctl.cached)) {  			ffe_ctl.have_caching_bg = true;  			ret = btrfs_cache_block_group(block_group, 0); -			BUG_ON(ret < 0); + +			/* +			 * If we get ENOMEM here or something else we want to +			 * try other block groups, because it may not be fatal. +			 * However if we can't find anything else we need to +			 * save our return here so that we return the actual +			 * error that caused problems, not ENOSPC. +			 */ +			if (ret < 0) { +				if (!cache_block_group_error) +					cache_block_group_error = ret; +				ret = 0; +				goto loop; +			}  			ret = 0;  		} @@ -4045,7 +4060,7 @@ loop:  	if (ret > 0)  		goto search; -	if (ret == -ENOSPC) { +	if (ret == -ENOSPC && !cache_block_group_error) {  		/*  		 * Use ffe_ctl->total_free_space as fallback if we can't find  		 * any contiguous hole. @@ -4056,6 +4071,8 @@ loop:  		space_info->max_extent_size = ffe_ctl.max_extent_size;  		spin_unlock(&space_info->lock);  		ins->offset = ffe_ctl.max_extent_size; +	} else if (ret == -ENOSPC) { +		ret = cache_block_group_error;  	}  	return ret;  }  | 
