From: David Sterba <dsterba@suse.cz>
To: Josef Bacik <josef@toxicpanda.com>
Cc: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: Re: [PATCH] btrfs: introduce BTRFS_RESERVE_FLUSH_EMERGENCY
Date: Mon, 10 Oct 2022 18:59:10 +0200 [thread overview]
Message-ID: <20221010165910.GF13389@twin.jikos.cz> (raw)
In-Reply-To: <d1da73f6ed291d53d4cc7dcab142ebfb0541f06e.1662730491.git.josef@toxicpanda.com>
On Fri, Sep 09, 2022 at 09:35:01AM -0400, Josef Bacik wrote:
> Inside of FB, as well as some user reports, we've had a consistent
> problem of occasional ENOSPC transaction aborts. Inside FB we were
> seeing ~100-200 ENOSPC aborts per day in the fleet, which is a really
> low occurrence rate given the size of our fleet, but it's not nothing.
>
> There are two causes of this particular problem.
>
> First is delayed allocation. The reservation system for delalloc
> assumes that contiguous dirty ranges will result in 1 file extent item.
> However if there is memory pressure that results in fragmented writeout,
> or there is fragmentation in the block groups, this won't necessarily be
> true. Consider the case where we do a single 256MiB write to a file and
> then close it. We will have 1 reservation for the inode update, the
> reservations for the checksum updates, and 1 reservation for the file
> extent item. At some point later we decide to write this entire range
> out, but we're so fragmented that we break this into 100 different file
> extents. Since we've already closed the file and are no longer writing
> to it there's nothing to trigger a refill of the delalloc block rsv to
> satisfy the 99 new file extent reservations we need. At this point we
> exhaust our delalloc reservation, and we begin to steal from the global
> reserve. If you have enough of these cases going in parallel you can
> easily exhaust the global reserve, get an ENOSPC at
> btrfs_alloc_tree_block() time, and then abort the transaction.
>
> The other case is the delayed refs reserve. The delayed refs reserve
> updates its size based on outstanding delayed refs and dirty block
> groups. However we only refill this block reserve when returning
> excess reservations and when we call btrfs_start_transaction(root, X).
> We will reserve 2*X credits at transaction start time, and fill in X
> into the delayed refs reserve to make sure it stays topped off.
> Generally this works well, but clearly has downsides. If we do a
> particularly delayed ref heavy operation we may never catch up in our
> reservations. Additionally running delayed refs generates more delayed
> refs, and at that point we may be committing the transaction and have no
> way to trigger a refill of our delayed refs rsv. Then a similar thing
> occurs with the delalloc reserve.
>
> Generally speaking we well over-reserve in all of our block rsvs. If we
> reserve 1 credit we're usually reserving around 264k of space, but we'll
> often not use any of that reservation, or use a few blocks of that
> reservation. We can be reasonably sure that as long as you were able to
> reserve space up front for your operation you'll be able to find space
> on disk for that reservation.
>
> So introduce a new flushing state, BTRFS_RESERVE_FLUSH_EMERGENCY. This
> gets used in the case that we've exhausted our reserve and the global
> reserve. It simply forces a reservation if we have enough actual space
> on disk to make the reservation, which is almost always the case. This
> keeps us from hitting ENOSPC aborts in these odd occurrences where we've
> not kept up with the delayed work.
>
> Fixing this in a complete way is going to be relatively complicated and
> time consuming. This patch is what I discussed with Filipe earlier this
> year, and what I put into our kernels inside FB. With this patch we're
> down to 1-2 ENOSPC aborts per week, which is a significant reduction.
> This is a decent stop gap until we can work out a more wholistic
> solution to these two corner cases.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
I'll add this to misc-next, we now have a full development cycle to find
problems and could remove it eventually.
prev parent reply other threads:[~2022-10-10 16:59 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-09 13:35 [PATCH] btrfs: introduce BTRFS_RESERVE_FLUSH_EMERGENCY Josef Bacik
2022-09-12 9:59 ` Filipe Manana
2022-09-12 10:26 ` Qu Wenruo
2022-09-12 10:42 ` Filipe Manana
2022-09-12 11:02 ` Qu Wenruo
2022-09-12 11:21 ` Filipe Manana
2022-09-12 11:31 ` Qu Wenruo
2022-09-12 11:52 ` Qu Wenruo
2022-09-12 18:18 ` Josef Bacik
2022-09-12 10:40 ` Neal Gompa
2022-10-10 16:59 ` David Sterba [this message]
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=20221010165910.GF13389@twin.jikos.cz \
--to=dsterba@suse.cz \
--cc=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