diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 20 | 
1 files changed, 12 insertions, 8 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 59ea2e4349c..0be7a8742a4 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1862,11 +1862,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,  {  	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;  	struct btrfs_free_space *info; -	int ret = 0; +	int ret; +	bool re_search = false;  	spin_lock(&ctl->tree_lock);  again: +	ret = 0;  	if (!bytes)  		goto out_lock; @@ -1879,17 +1881,17 @@ again:  		info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),  					  1, 0);  		if (!info) { -			/* the tree logging code might be calling us before we -			 * have fully loaded the free space rbtree for this -			 * block group.  So it is possible the entry won't -			 * be in the rbtree yet at all.  The caching code -			 * will make sure not to put it in the rbtree if -			 * the logging code has pinned it. +			/* +			 * If we found a partial bit of our free space in a +			 * bitmap but then couldn't find the other part this may +			 * be a problem, so WARN about it.  			 */ +			WARN_ON(re_search);  			goto out_lock;  		}  	} +	re_search = false;  	if (!info->bitmap) {  		unlink_free_space(ctl, info);  		if (offset == info->offset) { @@ -1935,8 +1937,10 @@ again:  	}  	ret = remove_from_bitmap(ctl, info, &offset, &bytes); -	if (ret == -EAGAIN) +	if (ret == -EAGAIN) { +		re_search = true;  		goto again; +	}  	BUG_ON(ret); /* logic error */  out_lock:  	spin_unlock(&ctl->tree_lock);  |