Btrfs: use FLUSH_LIMIT for relocation in reserve_metadata_bytes
We used to allow you to set FLUSH_ALL and then just wouldn't do things like commit transactions or wait on ordered extents if we noticed you were in a transaction. However now that all the flushing for FLUSH_ALL is asynchronous we've lost the ability to tell, and we could end up deadlocking. So instead use FLUSH_LIMIT in reserve_metadata_bytes in relocation and then return -EAGAIN if we error out to preserve the previous behavior. I've also added an ASSERT() to catch anybody else who tries to do this. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
ac2fabac42
commit
8ca17f0f59
|
@ -5135,6 +5135,8 @@ static int __reserve_metadata_bytes(struct btrfs_root *root,
|
|||
int ret = 0;
|
||||
|
||||
ASSERT(orig_bytes);
|
||||
ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_ALL);
|
||||
|
||||
spin_lock(&space_info->lock);
|
||||
ret = -ENOSPC;
|
||||
used = space_info->bytes_used + space_info->bytes_reserved +
|
||||
|
|
|
@ -2604,25 +2604,28 @@ static int reserve_metadata_space(struct btrfs_trans_handle *trans,
|
|||
|
||||
trans->block_rsv = rc->block_rsv;
|
||||
rc->reserved_bytes += num_bytes;
|
||||
|
||||
/*
|
||||
* We are under a transaction here so we can only do limited flushing.
|
||||
* If we get an enospc just kick back -EAGAIN so we know to drop the
|
||||
* transaction and try to refill when we can flush all the things.
|
||||
*/
|
||||
ret = btrfs_block_rsv_refill(root, rc->block_rsv, num_bytes,
|
||||
BTRFS_RESERVE_FLUSH_ALL);
|
||||
BTRFS_RESERVE_FLUSH_LIMIT);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN) {
|
||||
tmp = rc->extent_root->nodesize *
|
||||
RELOCATION_RESERVED_NODES;
|
||||
tmp = rc->extent_root->nodesize * RELOCATION_RESERVED_NODES;
|
||||
while (tmp <= rc->reserved_bytes)
|
||||
tmp <<= 1;
|
||||
/*
|
||||
* only one thread can access block_rsv at this point,
|
||||
* so we don't need hold lock to protect block_rsv.
|
||||
* we expand more reservation size here to allow enough
|
||||
* space for relocation and we will return earlier in
|
||||
* space for relocation and we will return eailer in
|
||||
* enospc case.
|
||||
*/
|
||||
rc->block_rsv->size = tmp + rc->extent_root->nodesize *
|
||||
RELOCATION_RESERVED_NODES;
|
||||
}
|
||||
return ret;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue