public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
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.

      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