diff options
author | Josef Bacik <josef@toxicpanda.com> | 2019-08-01 18:19:37 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2019-09-09 14:59:11 +0200 |
commit | d3984c90414a36af581b3b7c0daa87f9de3c0533 (patch) | |
tree | c666e8e13aef19b143ac83cfaa96e0f49dec4d23 /fs/btrfs/space-info.c | |
parent | 9ce2f423b9463f975720782b3838640da313ecb4 (diff) | |
download | lwn-d3984c90414a36af581b3b7c0daa87f9de3c0533.tar.gz lwn-d3984c90414a36af581b3b7c0daa87f9de3c0533.zip |
btrfs: introduce an evict flushing state
We have this weird space flushing loop inside inode.c for evict where
we'll do the normal LIMIT flush, and then commit the transaction and
hope we get our space. This is super janky, and in fact there's really
nothing stopping us from using FLUSH_ALL except that we run delayed
iputs, which means we could deadlock. So introduce a new flush state
for eviction that does the normal priority flushing with all of the
states that are safe for eviction.
The nice side-effect of this is that we'll try harder for evictions.
Previously if (for example generic/269) you had a bunch of other
operations happening on the fs you could race with those reservations
when committing the transaction, and eventually miss getting a
reservation for the evict. With this code we'll have our ticket in
place through the transaction commit, so any pinned bytes will go to our
pending evictions first.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/space-info.c')
-rw-r--r-- | fs/btrfs/space-info.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 37ec31199675..5f8f65599de1 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -848,6 +848,17 @@ static const enum btrfs_flush_state priority_flush_states[] = { ALLOC_CHUNK, }; +static const enum btrfs_flush_state evict_flush_states[] = { + FLUSH_DELAYED_ITEMS_NR, + FLUSH_DELAYED_ITEMS, + FLUSH_DELAYED_REFS_NR, + FLUSH_DELAYED_REFS, + FLUSH_DELALLOC, + FLUSH_DELALLOC_WAIT, + ALLOC_CHUNK, + COMMIT_TRANS, +}; + static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, struct reserve_ticket *ticket, @@ -922,12 +933,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, u64 reclaim_bytes = 0; int ret; - if (flush == BTRFS_RESERVE_FLUSH_ALL) + switch (flush) { + case BTRFS_RESERVE_FLUSH_ALL: wait_reserve_ticket(fs_info, space_info, ticket); - else + break; + case BTRFS_RESERVE_FLUSH_LIMIT: priority_reclaim_metadata_space(fs_info, space_info, ticket, priority_flush_states, ARRAY_SIZE(priority_flush_states)); + break; + case BTRFS_RESERVE_FLUSH_EVICT: + priority_reclaim_metadata_space(fs_info, space_info, ticket, + evict_flush_states, + ARRAY_SIZE(evict_flush_states)); + break; + default: + ASSERT(0); + break; + } spin_lock(&space_info->lock); ret = ticket->error; |