Commit a1ed0a82 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: add the data transaction commit logic into may_commit_transaction

Data space flushing currently unconditionally commits the transaction
twice in a row, and the last time it checks if there's enough pinned
extents to satisfy its reservation before deciding to commit the
transaction for the 3rd and final time.

Encode this logic into may_commit_transaction().  In the next patch we
will pass in U64_MAX for bytes_needed the first two times, and the final
time we will pass in the actual bytes we need so the normal logic will
apply.

This patch exists solely to make the logical changes I will make to the
flushing state machine separate to make it easier to bisect any
performance related regressions.
Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
Tested-by: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 058e6d1d
...@@ -579,21 +579,33 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info, ...@@ -579,21 +579,33 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info,
* will return -ENOSPC. * will return -ENOSPC.
*/ */
static int may_commit_transaction(struct btrfs_fs_info *fs_info, static int may_commit_transaction(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info) struct btrfs_space_info *space_info,
u64 bytes_needed)
{ {
struct reserve_ticket *ticket = NULL; struct reserve_ticket *ticket = NULL;
struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv;
struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
struct btrfs_block_rsv *trans_rsv = &fs_info->trans_block_rsv; struct btrfs_block_rsv *trans_rsv = &fs_info->trans_block_rsv;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
u64 bytes_needed;
u64 reclaim_bytes = 0; u64 reclaim_bytes = 0;
u64 cur_free_bytes = 0; u64 cur_free_bytes = 0;
bool do_commit = false;
trans = (struct btrfs_trans_handle *)current->journal_info; trans = (struct btrfs_trans_handle *)current->journal_info;
if (trans) if (trans)
return -EAGAIN; return -EAGAIN;
/*
* If we are data and have passed in U64_MAX we just want to
* unconditionally commit the transaction to match the previous data
* flushing behavior.
*/
if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) &&
bytes_needed == U64_MAX) {
do_commit = true;
goto check_pinned;
}
spin_lock(&space_info->lock); spin_lock(&space_info->lock);
cur_free_bytes = btrfs_space_info_used(space_info, true); cur_free_bytes = btrfs_space_info_used(space_info, true);
if (cur_free_bytes < space_info->total_bytes) if (cur_free_bytes < space_info->total_bytes)
...@@ -607,7 +619,8 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, ...@@ -607,7 +619,8 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
else if (!list_empty(&space_info->tickets)) else if (!list_empty(&space_info->tickets))
ticket = list_first_entry(&space_info->tickets, ticket = list_first_entry(&space_info->tickets,
struct reserve_ticket, list); struct reserve_ticket, list);
bytes_needed = (ticket) ? ticket->bytes : 0; if (ticket)
bytes_needed = ticket->bytes;
if (bytes_needed > cur_free_bytes) if (bytes_needed > cur_free_bytes)
bytes_needed -= cur_free_bytes; bytes_needed -= cur_free_bytes;
...@@ -618,6 +631,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, ...@@ -618,6 +631,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
if (!bytes_needed) if (!bytes_needed)
return 0; return 0;
check_pinned:
trans = btrfs_join_transaction(fs_info->extent_root); trans = btrfs_join_transaction(fs_info->extent_root);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
...@@ -627,15 +641,18 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, ...@@ -627,15 +641,18 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
* we have block groups that are going to be freed, allowing us to * we have block groups that are going to be freed, allowing us to
* possibly do a chunk allocation the next loop through. * possibly do a chunk allocation the next loop through.
*/ */
if (test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || if (do_commit ||
test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) ||
__percpu_counter_compare(&space_info->total_bytes_pinned, __percpu_counter_compare(&space_info->total_bytes_pinned,
bytes_needed, bytes_needed,
BTRFS_TOTAL_BYTES_PINNED_BATCH) >= 0) BTRFS_TOTAL_BYTES_PINNED_BATCH) >= 0)
goto commit; goto commit;
/* /*
* See if there is some space in the delayed insertion reservation for * See if there is some space in the delayed insertion reserve for this
* this reservation. * reservation. If the space_info's don't match (like for DATA or
* SYSTEM) then just go enospc, reclaiming this space won't recover any
* space to satisfy those reservations.
*/ */
if (space_info != delayed_rsv->space_info) if (space_info != delayed_rsv->space_info)
goto enospc; goto enospc;
...@@ -742,7 +759,7 @@ static void flush_space(struct btrfs_fs_info *fs_info, ...@@ -742,7 +759,7 @@ static void flush_space(struct btrfs_fs_info *fs_info,
btrfs_wait_on_delayed_iputs(fs_info); btrfs_wait_on_delayed_iputs(fs_info);
break; break;
case COMMIT_TRANS: case COMMIT_TRANS:
ret = may_commit_transaction(fs_info, space_info); ret = may_commit_transaction(fs_info, space_info, num_bytes);
break; break;
default: default:
ret = -ENOSPC; ret = -ENOSPC;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment