mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
Btrfs: be smarter about committing the transaction in reserve_metadata_bytes
Because of the overcommit stuff I had to make it so that we committed the transaction all the time in reserve_metadata_bytes in case we had overcommitted because of delayed items. This was because previously we had no way of knowing how much space was reserved for delayed items. Now that we have the delayed_block_rsv we can check it to see if committing the transaction would get us anywhere. This patch breaks out the committing logic into a helper function that will check to see if committing the transaction would free enough space for us to get anything done. With this patch xfstests 83 goes from taking 445 seconds to taking 28 seconds on my box. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
6d668dda0c
commit
663350ac38
1 changed files with 67 additions and 19 deletions
|
@ -3334,12 +3334,12 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|||
/*
|
||||
* shrink metadata reservation for delalloc
|
||||
*/
|
||||
static int shrink_delalloc(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 to_reclaim,
|
||||
static int shrink_delalloc(struct btrfs_root *root, u64 to_reclaim,
|
||||
bool wait_ordered)
|
||||
{
|
||||
struct btrfs_block_rsv *block_rsv;
|
||||
struct btrfs_space_info *space_info;
|
||||
struct btrfs_trans_handle *trans;
|
||||
u64 reserved;
|
||||
u64 max_reclaim;
|
||||
u64 reclaimed = 0;
|
||||
|
@ -3348,6 +3348,7 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
|
|||
int loops = 0;
|
||||
unsigned long progress;
|
||||
|
||||
trans = (struct btrfs_trans_handle *)current->journal_info;
|
||||
block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||
space_info = block_rsv->space_info;
|
||||
|
||||
|
@ -3417,6 +3418,60 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
|
|||
return reclaimed >= to_reclaim;
|
||||
}
|
||||
|
||||
/**
|
||||
* maybe_commit_transaction - possibly commit the transaction if its ok to
|
||||
* @root - the root we're allocating for
|
||||
* @bytes - the number of bytes we want to reserve
|
||||
* @force - force the commit
|
||||
*
|
||||
* This will check to make sure that committing the transaction will actually
|
||||
* get us somewhere and then commit the transaction if it does. Otherwise it
|
||||
* will return -ENOSPC.
|
||||
*/
|
||||
static int may_commit_transaction(struct btrfs_root *root,
|
||||
struct btrfs_space_info *space_info,
|
||||
u64 bytes, int force)
|
||||
{
|
||||
struct btrfs_block_rsv *delayed_rsv = &root->fs_info->delayed_block_rsv;
|
||||
struct btrfs_trans_handle *trans;
|
||||
|
||||
trans = (struct btrfs_trans_handle *)current->journal_info;
|
||||
if (trans)
|
||||
return -EAGAIN;
|
||||
|
||||
if (force)
|
||||
goto commit;
|
||||
|
||||
/* See if there is enough pinned space to make this reservation */
|
||||
spin_lock(&space_info->lock);
|
||||
if (space_info->bytes_pinned >= bytes) {
|
||||
spin_unlock(&space_info->lock);
|
||||
goto commit;
|
||||
}
|
||||
spin_unlock(&space_info->lock);
|
||||
|
||||
/*
|
||||
* See if there is some space in the delayed insertion reservation for
|
||||
* this reservation.
|
||||
*/
|
||||
if (space_info != delayed_rsv->space_info)
|
||||
return -ENOSPC;
|
||||
|
||||
spin_lock(&delayed_rsv->lock);
|
||||
if (delayed_rsv->size < bytes) {
|
||||
spin_unlock(&delayed_rsv->lock);
|
||||
return -ENOSPC;
|
||||
}
|
||||
spin_unlock(&delayed_rsv->lock);
|
||||
|
||||
commit:
|
||||
trans = btrfs_join_transaction(root);
|
||||
if (IS_ERR(trans))
|
||||
return -ENOSPC;
|
||||
|
||||
return btrfs_commit_transaction(trans, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* reserve_metadata_bytes - try to reserve bytes from the block_rsv's space
|
||||
* @root - the root we're allocating for
|
||||
|
@ -3436,7 +3491,6 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
u64 orig_bytes, int flush)
|
||||
{
|
||||
struct btrfs_space_info *space_info = block_rsv->space_info;
|
||||
struct btrfs_trans_handle *trans;
|
||||
u64 used;
|
||||
u64 num_bytes = orig_bytes;
|
||||
int retries = 0;
|
||||
|
@ -3445,7 +3499,6 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
bool flushing = false;
|
||||
bool wait_ordered = false;
|
||||
|
||||
trans = (struct btrfs_trans_handle *)current->journal_info;
|
||||
again:
|
||||
ret = 0;
|
||||
spin_lock(&space_info->lock);
|
||||
|
@ -3461,7 +3514,7 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
* deadlock since we are waiting for the flusher to finish, but
|
||||
* hold the current transaction open.
|
||||
*/
|
||||
if (trans)
|
||||
if (current->journal_info)
|
||||
return -EAGAIN;
|
||||
ret = wait_event_interruptible(space_info->wait,
|
||||
!space_info->flush);
|
||||
|
@ -3517,12 +3570,16 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
*/
|
||||
avail = (space_info->total_bytes - space_info->bytes_used) * 8;
|
||||
do_div(avail, 10);
|
||||
if (space_info->bytes_pinned >= avail && flush && !trans &&
|
||||
!committed) {
|
||||
if (space_info->bytes_pinned >= avail && flush && !committed) {
|
||||
space_info->flush = 1;
|
||||
flushing = true;
|
||||
spin_unlock(&space_info->lock);
|
||||
goto commit;
|
||||
ret = may_commit_transaction(root, space_info,
|
||||
orig_bytes, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
committed = true;
|
||||
goto again;
|
||||
}
|
||||
|
||||
spin_lock(&root->fs_info->free_chunk_lock);
|
||||
|
@ -3575,7 +3632,7 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
* We do synchronous shrinking since we don't actually unreserve
|
||||
* metadata until after the IO is completed.
|
||||
*/
|
||||
ret = shrink_delalloc(trans, root, num_bytes, wait_ordered);
|
||||
ret = shrink_delalloc(root, num_bytes, wait_ordered);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -3592,21 +3649,12 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
|
|||
goto again;
|
||||
}
|
||||
|
||||
ret = -EAGAIN;
|
||||
if (trans)
|
||||
goto out;
|
||||
|
||||
commit:
|
||||
ret = -ENOSPC;
|
||||
if (committed)
|
||||
goto out;
|
||||
|
||||
trans = btrfs_join_transaction(root);
|
||||
if (IS_ERR(trans))
|
||||
goto out;
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
ret = may_commit_transaction(root, space_info, orig_bytes, 0);
|
||||
if (!ret) {
|
||||
trans = NULL;
|
||||
committed = true;
|
||||
goto again;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue