Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ca17f0f authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba
Browse files

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: default avatarJosef Bacik <jbacik@fb.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ac2fabac
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 +
+20 −17
Original line number Diff line number Diff line
@@ -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;