From: Josef Bacik <josef@toxicpanda.com>
To: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH 16/20] btrfs: rework chunk allocate for data reservations
Date: Wed, 29 Jan 2020 18:50:20 -0500 [thread overview]
Message-ID: <20200129235024.24774-17-josef@toxicpanda.com> (raw)
In-Reply-To: <20200129235024.24774-1-josef@toxicpanda.com>
The chunk allocator only allocates chunks in min(10% ofs fs, 1gib)
chunks at a time, but if our data reservation is larger than that we
need to allocate more chunks. Historically this just magically happened
because we looped through the flushing logic a few times for data
reservations, so we were getting lucky.
Fix this by looping trying to allocate enough space to make our
reservation until it's satisfied or until we cannot allocate chunks
anymore.
Since this may result in too many chunk allocations we'll do our normal
flushing series once, and then fall back on allocate data chunks to
satisfy our reservation.
We will keep our initial one-shot chunk allocation in the normal case
for performance reasons, there's no sense in flushing all the things if
we can just allocate a single chunk and carry on.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/space-info.c | 64 ++++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 19 deletions(-)
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index 3668c2d4fadf..7a401f1c3724 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -862,17 +862,12 @@ static const enum btrfs_flush_state data_flush_states[] = {
COMMIT_TRANS,
};
-static const enum btrfs_flush_state free_space_inode_flush_states[] = {
- ALLOC_CHUNK_FORCE,
-};
-
-
-static void priority_reclaim_space(struct btrfs_fs_info *fs_info,
- struct btrfs_space_info *space_info,
- struct reserve_ticket *ticket,
- u64 to_reclaim,
- const enum btrfs_flush_state *states,
- int states_nr)
+static int priority_reclaim_space(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *space_info,
+ struct reserve_ticket *ticket,
+ u64 to_reclaim,
+ const enum btrfs_flush_state *states,
+ int states_nr)
{
int flush_state = 0;
do {
@@ -881,10 +876,11 @@ static void priority_reclaim_space(struct btrfs_fs_info *fs_info,
spin_lock(&space_info->lock);
if (ticket->bytes == 0) {
spin_unlock(&space_info->lock);
- return;
+ return 0;
}
spin_unlock(&space_info->lock);
} while (flush_state < states_nr);
+ return -ENOSPC;
}
static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
@@ -906,6 +902,41 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
states, states_nr);
}
+static void priority_reclaim_data_space(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *space_info,
+ struct reserve_ticket *ticket,
+ enum btrfs_reserve_flush_enum flush)
+{
+ int ret;
+
+ /*
+ * First see if we can reclaim pinned space before forcing a bunch of
+ * chunk allocations.
+ */
+ if (flush == BTRFS_RESERVE_FLUSH_DATA) {
+ ret = priority_reclaim_space(fs_info, space_info, ticket,
+ U64_MAX, data_flush_states,
+ ARRAY_SIZE(data_flush_states));
+ if (!ret)
+ return;
+ }
+
+ /*
+ * The chunk allocator will only allocate min(10% of the fs, 1gib) at a
+ * time, but our reservation may be much larger than that threshold, so
+ * loop allocating chunks until we're able to satisfy our allocation.
+ */
+ while (1) {
+ flush_space(fs_info, space_info, U64_MAX, ALLOC_CHUNK_FORCE);
+ spin_lock(&space_info->lock);
+ if (ticket->bytes == 0 || space_info->full) {
+ spin_unlock(&space_info->lock);
+ return;
+ }
+ spin_unlock(&space_info->lock);
+ }
+}
+
static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info,
struct reserve_ticket *ticket)
@@ -972,14 +1003,9 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
ARRAY_SIZE(evict_flush_states));
break;
case BTRFS_RESERVE_FLUSH_DATA:
- priority_reclaim_space(fs_info, space_info, ticket, U64_MAX,
- data_flush_states,
- ARRAY_SIZE(data_flush_states));
- break;
case BTRFS_RESERVE_FLUSH_FREE_SPACE_INODE:
- priority_reclaim_space(fs_info, space_info, ticket, U64_MAX,
- free_space_inode_flush_states,
- ARRAY_SIZE(free_space_inode_flush_states));
+ priority_reclaim_data_space(fs_info, space_info, ticket,
+ flush);
break;
default:
ASSERT(0);
--
2.24.1
next prev parent reply other threads:[~2020-01-29 23:50 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-29 23:50 [PATCH 00/20][RFC] Convert data reservations to the ticketing infrastructure Josef Bacik
2020-01-29 23:50 ` [PATCH 01/20] btrfs: change nr to u64 in btrfs_start_delalloc_roots Josef Bacik
2020-01-30 12:06 ` Nikolay Borisov
2020-01-31 15:07 ` Josef Bacik
2020-01-31 15:13 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 02/20] btrfs: remove orig from shrink_delalloc Josef Bacik
2020-01-30 11:44 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 03/20] btrfs: handle U64_MAX for shrink_delalloc Josef Bacik
2020-01-30 11:46 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 04/20] btrfs: make shrink_delalloc take space_info as an arg Josef Bacik
2020-01-30 12:15 ` Nikolay Borisov
2020-01-30 12:35 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 05/20] btrfs: make ALLOC_CHUNK use the space info flags Josef Bacik
2020-01-30 13:19 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 06/20] btrfs: call btrfs_try_granting_tickets when freeing reserved bytes Josef Bacik
2020-01-31 11:16 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 07/20] btrfs: call btrfs_try_granting_tickets when unpinning anything Josef Bacik
2020-01-31 11:25 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 08/20] btrfs: call btrfs_try_granting_tickets when reserving space Josef Bacik
2020-01-31 11:37 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 09/20] btrfs: use the btrfs_space_info_free_bytes_may_use helper for delalloc Josef Bacik
2020-01-31 11:56 ` Nikolay Borisov
2020-01-29 23:50 ` [PATCH 10/20] btrfs: add flushing states for handling data reservations Josef Bacik
2020-01-29 23:50 ` [PATCH 11/20] btrfs: add btrfs_reserve_data_bytes and use it Josef Bacik
2020-01-29 23:50 ` [PATCH 12/20] btrfs: use ticketing for data space reservations Josef Bacik
2020-01-29 23:50 ` [PATCH 13/20] btrfs: run delayed iputs before committing the transaction for data Josef Bacik
2020-01-29 23:50 ` [PATCH 14/20] btrfs: flush delayed refs when trying to reserve data space Josef Bacik
2020-01-29 23:50 ` [PATCH 15/20] btrfs: serialize data reservations if we are flushing Josef Bacik
2020-01-29 23:50 ` Josef Bacik [this message]
2020-01-29 23:50 ` [PATCH 17/20] btrfs: drop the commit_cycles stuff for data reservations Josef Bacik
2020-01-29 23:50 ` [PATCH 18/20] btrfs: use the same helper for data and metadata reservations Josef Bacik
2020-01-29 23:50 ` [PATCH 19/20] btrfs: do async reclaim for data reservations Josef Bacik
2020-01-29 23:50 ` [PATCH 20/20] btrfs: kill the priority_reclaim_space helper Josef Bacik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200129235024.24774-17-josef@toxicpanda.com \
--to=josef@toxicpanda.com \
--cc=kernel-team@fb.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox