]> git.hungrycats.org Git - bees/log
bees
20 months agoRevert "roots: use a non-idle task for next_transid"
Zygo Blaxell [Sun, 12 Jan 2025 23:23:44 +0000 (18:23 -0500)]
Revert "roots: use a non-idle task for next_transid"

next_transid tasks don't respect queue selection very well, because
they effectively end up spinning in a loop until all other worker
threads become busy.

Back this out, and fix the priority handling in the Task library.

This reverts commit 58db4071de5f524c35b1362bfb5b1fceedea503f.

20 months agotask: do not allow queue loops in priority queueing mode
Zygo Blaxell [Sun, 12 Jan 2025 20:17:21 +0000 (15:17 -0500)]
task: do not allow queue loops in priority queueing mode

Tasks using non-priority FIFO dependency tracking can insert themselves
into their own queue, to run the Task again immediately after it exits.

For priority queues, this attempts to splice the post-exec queue into
itself, which doesn't seem like a good idea.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agotask: flatten queues of dependent Tasks
Zygo Blaxell [Sun, 12 Jan 2025 18:54:54 +0000 (13:54 -0500)]
task: flatten queues of dependent Tasks

Suppose Task A, B, and C are created in that order, and currently running.
Task T acquires Exclusion E.  Task B, A, and C attempt to acquire the
same Exclusion, in that order, but fail because Task T holds it.

The result is Task T with a post-exec queue:

        T, [ B, A, C ]  sort_requested

Now suppose Task U acquires Exclusion F, then Task T attempts to acquire
Exclusion F.  Task T fails to acquire F, so T is inserted into U's
post-exec queue.  The result at the end of the execution of T is a tree:

        U, [ T ]  sort_requested
             \-> [ B, A, C ] sort_requested

Task T exits after failing to acquire a lock.  When T exits, T will
sort its post-exec queue and submit the post-exec queue for execution
immediately:

        Worker 1: U, [ T ]  sort_requested
        Worker 2: A, B, C

This isn't ideal because T, A, B, and C all depend on at least one
common Exclusion, so they are likely to immediately conflict with T
when U exits and T runs again.

Ideally, A, B, and C would at least remain in a common queue with T,
and ideally that queue is sorted.

Instead of inserting T into U's post-exec queue, insert T and all
of T's post-exec queue, which creates a single flattened Task list:

        U, [ T, B, A, C ]   sort_requested

Then when U exits, it will sort [ T, B, A, C ] into [ A, B, C, T ],
and run all of the queued Tasks in age priority order:

        U exited, [ T, B, A, C ]   sort_requested

        U exited, [ A, B, C, T ]

        [ A, B, C, T ] on TaskConsumer queue

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agotask: add an `insert` method for priority-queueing Tasks by age
Zygo Blaxell [Sun, 12 Jan 2025 04:21:31 +0000 (23:21 -0500)]
task: add an `insert` method for priority-queueing Tasks by age

Task started out as a self-organizing parallel-make algorithm, but ended
up becoming a half-broken wait-die algorithm.  When a contended object
is already locked, Tasks enter a FIFO queue to restart and acquire the
lock.  This is the "die" part of wait-die (all locks on an Exclusion are
non-blocking, so no Task ever does "wait").  The lock queue is FIFO wrt
_lock acquisition order_, not _Task age_ as required by the wait-die
algorithm.

Make it a 25%-broken wait-die algorithm by sorting the Tasks on lock
queues in order of Task ID, i.e. oldest-first, or FIFO wrt Task age.
This ensures the oldest Task waiting for an object is the one to get
it when it becomes available, as expected from the wait-die algorithm.

This should reduce the amount of time Tasks spend on the execution queue,
and reduce memory usage by avoiding the accumulation of Tasks that cannot
make forward progress.

Note that turning `TaskQueue` into an ordered container would have
undesirable side-effects:

 * `std::list` has some useful properties wrt stability of object
 location and cost of splicing.  Other containers may not have these,
 and `std::list` does have a `sort` method.

 * Some Task objects are created at the beginning and reused continually,
 but we really do want those Tasks to be executed in FIFO order wrt
 submission, not Task ID.  We can exclude these tasks by only doing the
 sorting when a Task is queued for an Exclusin object.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: deprecate the `--workaround-btrfs-send` option
Zygo Blaxell [Sat, 11 Jan 2025 07:12:28 +0000 (02:12 -0500)]
docs: deprecate the `--workaround-btrfs-send` option

Emphasize that the option is relevant to old kernels, older than the
minimum supportable version threshold.

De-emphasize the use case of "send-workaround" as a synonym for "exclude
read-only".

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: expand "Threads and load management" to suggest not running bees so much
Zygo Blaxell [Sat, 11 Jan 2025 07:09:30 +0000 (02:09 -0500)]
docs: expand "Threads and load management" to suggest not running bees so much

One of the more obvious ways to reduce bees load is to simply not run
it all the time.  Explicitly state using maintenance windows as a load
management option.

SIGUSR1 and SIGUSR2 should have been documented somewhere else before now.
Better late than never.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: config.md updates
Zygo Blaxell [Sat, 11 Jan 2025 06:29:16 +0000 (01:29 -0500)]
docs: config.md updates

The theories behind bees slowing down when presented with a larger has
table turned out to be wrong.  The real cause was a very old bug which
submitted thousands of `LOGICAL_INO` requests when only a handful of
requests were needed.

"Compression on the filesystem" -> "Compression in files"

Don't be so "dramatic".  Be "rapid" instead.

Remove "cannot avoid modifying read-only snapshots" as a distinction
between subvol and extent scans.  Both modes support send workaround
and send waiting with no significant distinction.

Emphasize extent scan's better handling of many snapshots.  Also reflinks.

Add some discussion of `--throttle-factor`.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: update the bug reporting and status instructions
Zygo Blaxell [Sat, 11 Jan 2025 06:01:40 +0000 (01:01 -0500)]
docs: update the bug reporting and status instructions

Thread names have changed.  Document some of the newer ones.

Don't jump immediately to blaming poor performance on qgroups or
autodefrag.  These do sometimes have kernel regressions but not all
the time.

Emphasize advantage of controlling bees deferred work requests at the
source, before btrfs gets stuck committing them.

Avoid asserting that it's OK for gdb to crash.

Remove mention of lower-layer block device issues wrt corruption.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: update kernel bugs page for January 2025
Zygo Blaxell [Sat, 11 Jan 2025 05:41:32 +0000 (00:41 -0500)]
docs: update kernel bugs page for January 2025

"Kernel" -> "Linux kernel".  If you can run bees on a kernel that isn't
Linux, congratulations!

Emphasize the age of the data corruption warnings.  Once 5.4 reaches
EOL we can remove those.

Simplify the discussion of old kernels and API levels.  There's a
new optional kernel API for `openat2` support at 5.6.  The absolute
minimum kernel version is still 4.2, and will not increase to 4.15
until the subvol scanners are removed.

Remove discussion of bees support for kernels 4.19 (which recently
reached EOL) and earlier.

The `LOGICAL_INO` vs dedupe bug is actually a `LOGICAL_INO` vs clone bug.
Dedupe isn't necessary to reproduce it.

Remove a stray ')'.

Strip out most of the discussion of slow backrefs, as they are no longer a
concern on the range of supported kernel versions.  Leave some description
there because bees still has some vestigial workarounds.

Remove `btrfs send` from the "Unfixed kernel bugs" section, which makes
the section empty, so remove the section too.  bees now handles send on
a subvol reasonably well.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: update README.md
Zygo Blaxell [Sat, 11 Jan 2025 04:37:04 +0000 (23:37 -0500)]
docs: update README.md

Emphasize "large" is an upper bound on the size of filesystem bees
can handle.

New strengths:  largest extent first for fixed maintenance windows,
scans data only once (ish), recovers more space

Removed weaknesses:  less temporary space

Need more caps than `CAP_SYS_ADMIN`.

Emphasize DATA CORRUPTION WARNING is an old-kernel thing.

Update copyright year.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: update feature interaction lists
Zygo Blaxell [Sat, 11 Jan 2025 03:21:10 +0000 (22:21 -0500)]
docs: update feature interaction lists

Tested on larger filesystems than 100T too, but let's use Fermi
approximation.  Next size is 1P.

Removed interaction with block-level SSD caching subsystems.  These are
really btrfs metadata vs. a lower block layer, and have nothing to do
with bees.

Added mixed block groups to the tested list, as mixed block groups
required explicit support in the extent scanner.

Added btrfs-convert to the tested list.  btrfs-convert has various
problems with space allocation in general, but these can be solved by
carefully ordered balances after conversion, and they have nothing to
do with bees.

In-kernel dedupe is dead and the stubs were removed years ago.  Remove it
from the list.

btrfs send now plays nicely with bees on all supportable kernels, now
that stable/linux-4.19.y is dead.  Send workaround is only needed for
kernels before v5.4 (technically v5.2, but nobody should ever mount a
btrfs with kernel v5.1 to v5.3).  bees will pause automatically when
deduping a subvol that is currently running a send.

bees will no longer gratuitously refragment data that was defragmented
by autodefrag.

Explicitly list all the RAID profiles tested so far, as there have been
some new ones.

Explicitly list other deduplicators tested.

Sort the list of btrfs features alphabetically.

Add scrub and balance, which have been tested with bees since the
beginning.

New tested btrfs features:  block-group-tree, raid1c3, raid1c4.

New untested btrfs features:  squotas, raid-stripe-tree.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoprogress: put a timestamp in the bottom row
Zygo Blaxell [Fri, 10 Jan 2025 14:12:35 +0000 (09:12 -0500)]
progress: put a timestamp in the bottom row

This records the time when the progress data was calculated, to help
indicate when the data might be very old.

While we're here, move "now" out of the loop so there's only one value.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agotask: get rid of the `insert_task` method
Zygo Blaxell [Sun, 12 Jan 2025 03:49:21 +0000 (22:49 -0500)]
task: get rid of the `insert_task` method

Nothing calls it (not even tests), and there's significant functional
overlap with `try_lock`.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoroots: use openat2 instead of openat when available
Zygo Blaxell [Thu, 9 Jan 2025 07:20:11 +0000 (02:20 -0500)]
roots: use openat2 instead of openat when available

This increases resistance to symlink and mount attacks.

Previously, bees could follow a symlink or a mount point in a directory
component of a subvol or file name.  Once the file is opened, the open
file descriptor would be checked to see if its subvol and inode matches
the expected file in the target filesystem.  Files that fail to match
would be immediately closed.

With openat2 resolve flags, symlinks and mount points terminate path
resolution in the kernel.  Paths that lead through symlinks or onto
mount points cannot be opened at all.

Fall back to openat() if openat2() returns ENOSYS, so bees will still
run on kernels before v5.6.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoprocess: replace crucible::gettid() with a weak symbol
Zygo Blaxell [Thu, 9 Jan 2025 06:22:49 +0000 (01:22 -0500)]
process: replace crucible::gettid() with a weak symbol

Since we're now using weak symbols for dodgy libc functions, we might
as well do it for gettid() too.

Use the ::gettid() global namespace and let libc override it.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoopenat2: create a weak syscall wrapper for it
Zygo Blaxell [Thu, 9 Jan 2025 06:16:02 +0000 (01:16 -0500)]
openat2: create a weak syscall wrapper for it

openat2 allows closing more TOCTOU holes, but we can only use it when
the kernel supports it.

This should disappear seamlessly when libc implements the function.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoprogress: rename "ctime" -> "tm_left"
Zygo Blaxell [Mon, 6 Jan 2025 17:18:33 +0000 (12:18 -0500)]
progress: rename "ctime" -> "tm_left"

"ctime", an abbreviation of "cycle time", collides with "ctime", an
abbreviation of "st_ctime", a well-known filesystem term.

"tm_left" fits in the column, so use that.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoprogress: rework the progress table after github discussion
Zygo Blaxell [Sat, 4 Jan 2025 01:05:21 +0000 (20:05 -0500)]
progress: rework the progress table after github discussion

* Report position within cycle in units that cannot be mistaken for size or percentage
* Put the total/maximum values in their own row
* Add a start time column
* Change column titles to reference "cycles"
* Use "idle" instead of "finished" when a crawler is not running
* Replace "transid" with "gen" because it's shorter

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoroots: use a non-idle task for next_transid
Zygo Blaxell [Fri, 3 Jan 2025 06:25:21 +0000 (01:25 -0500)]
roots: use a non-idle task for next_transid

The scanners which finish early can become stuck behind scanners that are
able to keep the queue full.  Switch the next_transid task to the normal
Task queues so that we force scanners to restart on every new transaction,
possibly deferring already queued work to do so.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agocontext: report time in scan_one_extent
Zygo Blaxell [Mon, 30 Dec 2024 20:07:57 +0000 (15:07 -0500)]
context: report time in scan_one_extent

Add yet another field to the scan/skip report line:  the wallclock
time used to process the extent ref.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoroots: don't access a shared variable after releasing a lock
Zygo Blaxell [Sat, 4 Jan 2025 00:56:37 +0000 (19:56 -0500)]
roots: don't access a shared variable after releasing a lock

Access the local copy of `m_root_crawl_map` instead.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoextent scan: don't put non-data block groups in the data extent map
Zygo Blaxell [Sat, 4 Jan 2025 00:55:44 +0000 (19:55 -0500)]
extent scan: don't put non-data block groups in the data extent map

The total data size should not include metadata or system block groups,
and already does not; however, we still have these block groups in the map
for mapping the crawl pointer to a logical offset within the filesystem.

Rearrange a few lines around the `if` statement so that the map doesn't
contain anything it should not.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agoextent scan: pick the right block groups for mixed-bg filesystems
Zygo Blaxell [Thu, 19 Dec 2024 04:32:09 +0000 (23:32 -0500)]
extent scan: pick the right block groups for mixed-bg filesystems

The progress indicator was failing on a mixed-bg filesystem because those
filesystems have block groups which have both _DATA and _METADATA bits,
and the filesystem size calculation was excluding block groups that have
_METADATA set.  It should exclude block groups that have _DATA not set.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agooptions: improve message when too many--or too few--path arguments given
Zygo Blaxell [Tue, 17 Dec 2024 03:30:34 +0000 (22:30 -0500)]
options: improve message when too many--or too few--path arguments given

Running bees with no arguments complains about "Only one" path argument.
Replace this with "Exactly one" which uses similar terminology to other
btrfs tools.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agooptions: return EXIT_SUCCESS after displaying help message
Zygo Blaxell [Tue, 17 Dec 2024 03:25:02 +0000 (22:25 -0500)]
options: return EXIT_SUCCESS after displaying help message

`getopt_long` already supplies a message when an option cannot be parsed,
so there isn't a need to distinguish option parse failures from help
requests.

Fixes: https://github.com/Zygo/bees/pull/277
Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agothrottle: don't hold the multilock during throttle
Zygo Blaxell [Mon, 23 Dec 2024 02:50:34 +0000 (21:50 -0500)]
throttle: don't hold the multilock during throttle

Release the lock before entering the throttle sleep, so that other
threads can still run.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: default throttle is zero
Zygo Blaxell [Fri, 27 Dec 2024 18:02:43 +0000 (13:02 -0500)]
docs: default throttle is zero

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agothrottle: set default to 0.0
Zygo Blaxell [Fri, 27 Dec 2024 18:01:28 +0000 (13:01 -0500)]
throttle: set default to 0.0

Longer latency testing runs are not showing a consistent gain from a
throttle factor of 1.0.  Make the default more conservative.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agodocs: add `--throttle-factor` option
Zygo Blaxell [Tue, 17 Dec 2024 04:24:39 +0000 (23:24 -0500)]
docs: add `--throttle-factor` option

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agothrottle: track time values more closely
Zygo Blaxell [Sat, 21 Dec 2024 16:25:20 +0000 (11:25 -0500)]
throttle: track time values more closely

Decaying averages by 10% every 5 minutes gives roughly a half-hour
half-life to the rolling average.  Speed that up to once per minute.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
20 months agothrottle: add --throttle-factor option to control throttling factor
Zygo Blaxell [Tue, 17 Dec 2024 03:23:56 +0000 (22:23 -0500)]
throttle: add --throttle-factor option to control throttling factor

Also change the initializer syntax for the option list to use C99
compound literals.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agooptions: clean up the parser, prepare for new options with no short form
Zygo Blaxell [Tue, 17 Dec 2024 03:22:31 +0000 (22:22 -0500)]
options: clean up the parser, prepare for new options with no short form

We're not adding any more short options, but the debugging code doesn't
work with optvals above 255.  Also clean up constness and variable
lifetimes.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agothrottle: add delays to match deferred request rate to btrfs completion rate
Zygo Blaxell [Tue, 10 Dec 2024 05:36:28 +0000 (00:36 -0500)]
throttle: add delays to match deferred request rate to btrfs completion rate

Measure the time spent running various operations that extend btrfs
transaction completion times (`LOGICAL_INO`, tmpfiles, and dedupe)
and arrange for each operation to run for not less than the average
amount of time by adding a sleep after each operation that takes less
than the average.

The delay after each operation is intended to slow down the rate of
deferred and long-running requests from bees to match the rate at which
btrfs is actually completing them.  This may help avoid big spikes in
latency if btrfs has so many requests queued that it has to force a
commit to release memory.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobees: bump the file limits again, 512k files and 64k dirs
Zygo Blaxell [Tue, 17 Dec 2024 03:15:55 +0000 (22:15 -0500)]
bees: bump the file limits again, 512k files and 64k dirs

Test machines keep blowing past the 32k file limit.  16 worker
threads at 10,000 files each is much larger than 32k.

Other high-FD-count services like DNS servers ask for million-file
rlimits.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: no need for "No ref for extent" debug message
Zygo Blaxell [Sat, 14 Dec 2024 03:44:38 +0000 (22:44 -0500)]
extent scan: no need for "No ref for extent" debug message

While a snapshot is being deleted, there will be a continuous stream of
"No ref for extent" messages.  This is a common event that does not need
to be reported.

There is an analogous situation when a call to open() fails with ENOENT.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocontext: wait for btrfs send to finish, then try dedupe again
Zygo Blaxell [Sat, 14 Dec 2024 04:07:21 +0000 (23:07 -0500)]
context: wait for btrfs send to finish, then try dedupe again

Dedupe is not possible on a subvol where a btrfs send is running:

    BTRFS warning (device dm-22): cannot deduplicate to root 259417 while send operations are using it (1 in progress)

btrfs informs a process with EAGAIN that a dedupe could not be performed
due to a running send operation.

It would be possible to save the crawler state at the affected point,
fork a new crawler that avoids the subvol under send, and resume the
crawler state after a successful dedupe is detected; however, this only
helps the intersection of the set of users who have unrelated subvols
that don't share extents, and the set of users who cannot simply delay
dedupe until send is finished.  The simplest approach is to simply stop
and wait until the send goes away.

The simplest approach is taken here.  When a dedupe fails with EAGAIN,
affected Tasks will poll, approximately once per transaction, until the
dedupe succeeds or fails with a different error.

bees dedupe performance corresponds with the availability of subvols that
can accept dedupe requests.  While the dedupe is paused, no new Tasks can
be performed by the worker thread.  If subvols are small and isolated
from the bulk of the filesystem data, the result will be a small but
partial loss of dedupe performance during the send as some worker threads
get stuck on the sending subvol.  If subvols heavily share extents with
duplicate data in other subvols, worker threads will all become blocked,
and the entire bees process will pause until at least some of the running
sends terminate.

During the polling for btrfs send, the dedupe Task will hold its dst
file open.  This open FD won't interfere with snapshot or file delete
because send subvols are always read-only (it is not possible to delete
a file on a RO subvol, open or otherwise) and send itself holds the
affected subvol open, preventing its deletion.  Once the send terminates,
the dedupe will terminate soon after, and the normal FD release can occur.

This pausing during btrfs send is unrelated to the
`--workaround-btrfs-send` option, although `--workaround-btrfs-send` will
cause the pausing to trigger less often.  It applies to all scan modes.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoroots: drop method `transid_re`
Zygo Blaxell [Sat, 14 Dec 2024 04:05:47 +0000 (23:05 -0500)]
roots: drop method `transid_re`

There are no callers of this method any more, and it exposes more
of BeesRoots than we really want things to have access to.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoroots: move the transid cache update into transid_max_nocache()
Zygo Blaxell [Sat, 14 Dec 2024 04:04:28 +0000 (23:04 -0500)]
roots: move the transid cache update into transid_max_nocache()

All callers of the `transid_max_nocache` method update `m_transid_re`
with the return value, so do that in `transid_max_nocache` itself.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotime: add more methods to support dynamic rate throttling
Zygo Blaxell [Tue, 10 Dec 2024 05:33:22 +0000 (00:33 -0500)]
time: add more methods to support dynamic rate throttling

 * Allow RateLimiter to change rate after construction.
 * Check range of rate argument in constructor.
 * Atomic increment for RateEstimator.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobytevector: rename the argument to operator[] to be more descriptive
Zygo Blaxell [Wed, 4 Dec 2024 03:58:15 +0000 (22:58 -0500)]
bytevector: rename the argument to operator[] to be more descriptive

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoprogress: move the "finished" tag to a column where it won't obscure data
Zygo Blaxell [Mon, 9 Dec 2024 02:47:43 +0000 (21:47 -0500)]
progress: move the "finished" tag to a column where it won't obscure data

The "done" pointer and the "%done" fields are still useful because they
indicate _actual_ progress, not the work that has been _promised_.
So it is possible for a crawl to be "finished" (all extents queued)
but not "100.0000%" (some of those extents still active or in the queue).

"deferred" state isn't particularly useful, so drop it.

"finished" state implies no ETA, so that column is unused.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoprogress: relabel the inaccurate ETA column
Zygo Blaxell [Fri, 13 Dec 2024 03:56:48 +0000 (22:56 -0500)]
progress: relabel the inaccurate ETA column

ETA is calculated using a sample obtained by snooping on bees's normal
crawling operations.

This sample is heavily biased and not representative of the entire
filesystem.  If the distribution of extent sizes in the filesystem is
not uniform, the ETA can be wildly wrong.

Collecting an accurate sample set would require extra IO and CPU time
which should be spent doing dedupes instead.

Explicitly label the ETA as inaccurate to avoid having too many users
report the same bug.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotask: ignore paused status while calculating dynamic thread count
Zygo Blaxell [Fri, 13 Dec 2024 03:55:57 +0000 (22:55 -0500)]
task: ignore paused status while calculating dynamic thread count

bees might be unpaused at any time, so make sure that the dynamic load
calculation is ready with a non-zero thread count.

This avoids a delay of up to 5 seconds when responding to SIGUSR2
when loadavg tracking is enabled.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agomain: add support for pause (SIGUSR1) and resume (SIGUSR2)
Zygo Blaxell [Fri, 13 Dec 2024 03:53:56 +0000 (22:53 -0500)]
main: add support for pause (SIGUSR1) and resume (SIGUSR2)

These are simple on/off switches for the task queue.  They are lightweight
requests for bees to be paused temporarily, but allow bees to release
open files and save progress while paused.

These signals are an alternative to SIGSTOP and SIGCONT, or using the
cgroup freezer's FROZEN and THAWED states, which pause and resume the
bees process, but do not allow the bees process to release open files
or save progress.  Snapshot and file deletes can occur on the filesystem
while bees is paused by SIGUSR1 but not by SIGSTOP.

These signals are also an alternative to SIGTERM and restart, which
flush out the whole hash table and progress state on exit, and read
the whole table back into memory on restart.

This feature is experimental and may be replaced by a more general
configuration or runtime control mechanism in the future.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotask: start up more worker threads when unpausing
Zygo Blaxell [Fri, 13 Dec 2024 03:53:00 +0000 (22:53 -0500)]
task: start up more worker threads when unpausing

When paused, TaskConsumer threads will eventually notice the paused
condition and exit; however, there's nothing to restart threads when
exiting the paused state.

When unpausing, and while the lock is already held, create TaskConsumer
threads as needed to reach the target thread count.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agofs: set the correct nr_items to 0 in the ENOENT search case
Zygo Blaxell [Fri, 13 Dec 2024 03:48:15 +0000 (22:48 -0500)]
fs: set the correct nr_items to 0 in the ENOENT search case

Commit 72c3bf8438830b65cae7bdaff126053e562280e5 ("fs: handle ENOENT
within lib") was meant to prevent exceptions when a subvol is deleted.

If the search ioctl fails, the kernel won't set nr_items in the
ioctl output, which means `nr_items` still has the input value.  When
ENOENT is detected, `this->nr_items` is set to 0, then later `*this =
ioctl_ptr->key` overwrites `this->nr_items` with the original requested
number of items.

This replaced the ENOENT exception with an exception triggered by
interpreting garbage in the memory buffer.  The number of exceptions
was reduced because the memory buffers are frequently reused, but upper
layers would then reject the data or ignore it because it didn't match
the key range.

Fix by setting `ioctl_ptr->key.nr_items`, which then overwrites
`this->nr_items`, so the loop that extracts items from the ioctl data
gets the right number of items (i.e. zero).

Fixes: 72c3bf8438830b65cae7bdaff126053e562280e5 ("fs: handle ENOENT within lib")
Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoreadahead: use the right parameter order when checking the range
Zygo Blaxell [Wed, 4 Dec 2024 16:11:13 +0000 (11:11 -0500)]
readahead: use the right parameter order when checking the range

In some cases the offset and size arguments were flipped when checking to
see if a range had already been read.  This would have been OK as long as
the same mistake had been made consistently, since `bees_readahead_check`
only does a cache lookup on the parameters, it doesn't try to use them to
read a file.  Alas, there was one case where the correct order was used,
albeit a relatively rare one.

Fix all the calls to use the correct order.

Also fix a comment:  the recent request cache is global to all threads.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agofs: drop extra declaration of hexdump
Zygo Blaxell [Wed, 4 Dec 2024 04:40:18 +0000 (23:40 -0500)]
fs: drop extra declaration of hexdump

hexdump was moved into a template in its own header years ago, but
the declaration of the implementation that used to be in fs.cc remains.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agohexdump: be a little more lock-friendly
Zygo Blaxell [Wed, 4 Dec 2024 04:37:48 +0000 (23:37 -0500)]
hexdump: be a little more lock-friendly

hexdump processes a vector as a contiguous sequence of bytes, regardless
of V's value type, so hexdump should get a pointer and use uint8_t to
read the data.

Some vector types have a lock and some atomics in their operator[], so
let's avoid hammering those.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobytevector: don't deadlock on operator<<
Zygo Blaxell [Wed, 4 Dec 2024 04:34:09 +0000 (23:34 -0500)]
bytevector: don't deadlock on operator<<

operator<< was a friend class that locked the ByteVector, then invoked
hexdump on the bytevector, which used ByteVector::operator[]...which
locked the ByteVector, resulting in a deadlock.

operator<< shouldn't be a friend class anyway.  Make hexdump use the
normal public access methods for ByteVector.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoroots: avoid copying a BtrfsIoctlSearchKey
Zygo Blaxell [Tue, 3 Dec 2024 21:51:24 +0000 (16:51 -0500)]
roots: avoid copying a BtrfsIoctlSearchKey

Although all the members of BtrfsExtentDataFetcher are theoretically
copiable, there's no need to actually make any such copy.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocontext: spell "progress" correctly
Zygo Blaxell [Mon, 2 Dec 2024 14:49:58 +0000 (09:49 -0500)]
context: spell "progress" correctly

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocontext: add a PROGRESS: header in $BEESSTATUS
Zygo Blaxell [Sun, 1 Dec 2024 16:32:36 +0000 (11:32 -0500)]
context: add a PROGRESS: header in $BEESSTATUS

Make it clearer where the progress information goes.

Also add placeholder text so the progress section isn't empty at startup,
when the progress hasn't been calculated yet.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: post-5.7 toxic extent handling
Zygo Blaxell [Wed, 27 Nov 2024 01:29:54 +0000 (20:29 -0500)]
docs: post-5.7 toxic extent handling

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobees: post-kernel-5.7 toxic extent handling
Zygo Blaxell [Fri, 28 May 2021 06:13:33 +0000 (02:13 -0400)]
bees: post-kernel-5.7 toxic extent handling

Toxic extents are mostly gone in kernel 5.7 and later.  Increase the
timeout for toxic extent handling to reduce false positives, and remove
persistenly stored toxic hashes from the hash table.

Toxic hashes are still stored nonpersistently to help mitigate problems
due to any remaining kernel bugs.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: don't serialize dedupe and LOGICAL_INO when using extent scan mode
Zygo Blaxell [Sat, 23 Nov 2024 04:26:37 +0000 (23:26 -0500)]
extent scan: don't serialize dedupe and LOGICAL_INO when using extent scan mode

The serialization doesn't seem to be necessary for the extent scan mode.
No infinite loops in the kernel have been observed in the past two years,
despite never having used MultiLock for the extent scanner.

Leave the serialization for now on the subvol scanners.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: default scan mode is 4, "extent"
Zygo Blaxell [Wed, 27 Nov 2024 02:59:20 +0000 (21:59 -0500)]
docs: default scan mode is 4, "extent"

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agomain: set default scan mode to mode 4 (EXTENT)
Zygo Blaxell [Mon, 16 Jan 2023 04:11:09 +0000 (23:11 -0500)]
main: set default scan mode to mode 4 (EXTENT)

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: old missing features are not missing any more
Zygo Blaxell [Sat, 25 Feb 2023 08:13:23 +0000 (03:13 -0500)]
docs: old missing features are not missing any more

The extent scan mode has been implemented (partially, but close enough
to win benchmarks).

New features include several nuisance dedupe countermeasures.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: add scan mode 4, "extent"
Zygo Blaxell [Thu, 5 Jan 2023 06:06:06 +0000 (01:06 -0500)]
docs: add scan mode 4, "extent"

Extent is a different kind of scan mode, so introduce the concept of
the two kinds of scan mode, and rearrange the description of scan modes
along the new boundaries.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoprogress: squeeze the progress table into 80 columns or less
Zygo Blaxell [Fri, 29 Nov 2024 06:51:33 +0000 (01:51 -0500)]
progress: squeeze the progress table into 80 columns or less

We don't need the subvol numbers since they're only interesting to
developers.

We don't need both max and min sizes, pick one and drop the other.

Replace "16E" with "max"--it is the same number of characters, but
doesn't require the user to know what 1<<64 is off the top of their head.

Shorten "remain" to "todo" because sometimes those extra two columns
matter.

Drop the seconds field in ETA timestamps.  Long scan arrival times are
years away, and short scan arrival times are only updated once every
5 minutes, so the extra precision isn't useful.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoprogress: put the progress table in the stats and status files
Zygo Blaxell [Wed, 27 Nov 2024 20:58:06 +0000 (15:58 -0500)]
progress: put the progress table in the stats and status files

Make the progress information more accessible, without having to
enable full debug log and fish it out of the stream with grep.

Also increase the progress log level to INFO.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: fix crawl_map creation
Zygo Blaxell [Sat, 30 Nov 2024 17:45:58 +0000 (12:45 -0500)]
extent scan: fix crawl_map creation

There are two crawl_maps in extent scan's next_transid:  one gets
initialized, the other gets used.  This works OK as long as bees is
resuming an existing scan, because the two maps are identical; however,
but it fails if bees is starting without an existing set of crawl data,
and one of the two maps is empty or partially filled.

The failure is intermittent, as the crawl map is being populated at
the same time next_transid runs.  It will eventually be completed after
several transaction cycles, at which point bees runs normally.
It does add significant delays during startup for benchmarks.

There's only one crawl_map in extent scan, it always has the same
crawlers, and extent scan's `next_transid` creates it by itself.
Ignore the map from BeesRoots/BeesCrawl.

Also throw in some missing but helpful trace statements.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoprogress: estimate actual data sizes for progress report
Zygo Blaxell [Tue, 26 Nov 2024 22:47:33 +0000 (17:47 -0500)]
progress: estimate actual data sizes for progress report

Replace pointers in the "done" and "total" columns with estimated data
sizes for each size tier.  The estimation is based on statistics
collected from extents scanned during the current bees run.

Move the total size for the entire filesystem up to the heading.

Report the _completed_ position (i.e. the one that would be saved in
`beescrawl.dat`), not the _queued_ position (i.e. the one where the
next Task would be created in memory).

At the end of the data, the crawl pointer ends up at some random point
in the filesystem just after the newest extent, so the progress gets to
99.7% and then goes to some random value like 47% or 3%, not to 100%.
Report "deferred" in the "done" column when the crawler is waiting for
the next transid, and "finished" in the "%done" column when the crawler
has reached the end of the data.  Suppress the ETA when finished.  This
makes it clear that there's no further work to do for these crawlers.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: add event counters for extent scan
Zygo Blaxell [Thu, 6 Jul 2023 17:13:42 +0000 (13:13 -0400)]
docs: add event counters for extent scan

Add a section for all the new extent scan event counters.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: refactor BeesScanMode so derived classes decide their own scan scheduling
Zygo Blaxell [Sat, 30 Nov 2024 04:57:15 +0000 (23:57 -0500)]
extent scan: refactor BeesScanMode so derived classes decide their own scan scheduling

BeesScanModeExtent uses six scan Tasks instead of one, which leads
to awkwardness like the do_scan method to tell crawl_roots how to do
what it shouldn't need to know how to do anyway.

Move the crawl_roots logic into the ::scan methods themselves.

This also deletes the very popular "crawl_more ran out of data" message.
Extent scan explicitly indicates when a scan is complete, so there's
no longer a need to fish this message out of the log.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: put all the refs in a single Task, sort them, use idle task
Zygo Blaxell [Wed, 27 Nov 2024 20:46:29 +0000 (15:46 -0500)]
extent scan: put all the refs in a single Task, sort them, use idle task

The sorting avoids problematic read orders, like extent refs in the same
inode with descending offsets, that btrfs is not optimized for.

Putting everything in one Task keeps the queue sizes small, and
manages the lock contention much more calmly.

We only want to be mapping extent refs if there's not enough extents
already in the queue to keep worker threads busy, so use the `idle()`
method instead of `run()`.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoextent scan: introduce SCAN_MODE_EXTENT
Zygo Blaxell [Thu, 22 Dec 2022 03:42:39 +0000 (22:42 -0500)]
extent scan: introduce SCAN_MODE_EXTENT

The EXTENT scan mode reads the extent tree, splits it into tiers by
extent size, converts each tiers's extents into subvol/inode/offset refs,
then runs the legacy bees dedupe engine on the refs.

The extent scan mode can cheaply compute completion percentage and ETA,
so do that every time a new transid is observed.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotask: add an idle queue
Zygo Blaxell [Thu, 28 Nov 2024 05:01:37 +0000 (00:01 -0500)]
task: add an idle queue

Add a second level queue which is only serviced when the local and global
queues are empty.

At some point there might be a need to implement a full priority queue,
but for now two classes are sufficient.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agofs: add some performance metrics for TREE_SEARCH_V2 calls
Zygo Blaxell [Sun, 24 Oct 2021 19:17:43 +0000 (15:17 -0400)]
fs: add some performance metrics for TREE_SEARCH_V2 calls

These give some visibility into how efficiently bees is using the
TREE_SEARCH_V2 ioctl.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotable: add a simple text table renderer
Zygo Blaxell [Sun, 29 Jan 2023 02:26:51 +0000 (21:26 -0500)]
table: add a simple text table renderer

This should help clean up some of the uglier status outputs.

Supports:

 * multi-line table cells
 * character fills
 * sparse tables
 * insert, delete by row and column
 * vertical separators

and not much else.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: remove "matched_" prefix event counters
Zygo Blaxell [Thu, 28 Nov 2024 01:39:09 +0000 (20:39 -0500)]
docs: remove "matched_" prefix event counters

We can no longer reliably determine the number of hash table matches,
since we'll stop counting after the first one.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoscan_one_extent: remove the unreadahead after benchmark results
Zygo Blaxell [Sat, 30 Nov 2024 00:22:53 +0000 (19:22 -0500)]
scan_one_extent: remove the unreadahead after benchmark results

That unreadahead used to result in a 10% hit on benchmarks.  Now it's
closer to 75%.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoBeesRangePair: drop the _really_ expensive toxic extent workaround
Zygo Blaxell [Fri, 29 Nov 2024 06:42:28 +0000 (01:42 -0500)]
BeesRangePair: drop the _really_ expensive toxic extent workaround

We were doing a `LOGICAL_INO` ioctl on every _block_ of a matching extent,
just to see how long it takes.  It takes a while!

This could be modified to do an ioctl with the `IGNORE_OFFSET` flag,
once per new extent, but the kernel bug was fixed a long time ago, so
we can start removing all the toxic extent code.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoscan_one_extent: in skip/scan lines, log whether extent is compressed
Zygo Blaxell [Thu, 28 Nov 2024 19:02:57 +0000 (14:02 -0500)]
scan_one_extent: in skip/scan lines, log whether extent is compressed

Useful for debugging the compressed-zero-block cases.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoscan_one_extent: reduce the number of LOGICAL_INO calls before finding a duplicate...
Zygo Blaxell [Thu, 28 Nov 2024 01:29:09 +0000 (20:29 -0500)]
scan_one_extent: reduce the number of LOGICAL_INO calls before finding a duplicate block range

When we have multiple possible matches for a block, we proceed in three
phases:

1.  retrieve each match's extent refs and put them in a list,
2.  iterate over the list converting viable block matches into range matches,
3.  sort and flatten the list of range matches into a non-overlapping
list of ranges that cover all duplicate blocks exactly once.

The separation of phase 1 and 2 creates a performance issue when there
are many block matches in phase 1, and all the range matches in phase
2 are the same length.  Even though we might quickly find the longest
possible matching range early in phase 2, we first extract all of the
extent refs from every possible matching block in phase 1, even though
most of those refs will never be used.

Fix this by moving the extent ref retrieval in phase 1 into a single
loop in phase 2, and stop looping over matching blocks as soon as any
dedupe range is created.  This avoids iterating over a large list of
blocks with expensive `LOGICAL_INO` ioctls in an attempt to improve the
match when there is no hope of improvement, e.g. when all match ranges
are 4K and the content is extremely prevalent in the data.

If we find a matched block that is part of a short matching range,
we can replace it with a block that is part of a long matching range,
because there is a good chance we will find a matching hash block in
the long range by looking up hashes after the end of the short range.
In that case, overlapping dedupe ranges covering both blocks in the
target extent will be inserted into the dedupe list, and the longest
matches will be selected at phase 3.  This usually provides a similar
result to that of the loop in phase 1, but _much_ more efficiently.

Some operations are left in phase 1, but they are all using internal
functions, not ioctls.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: event counter updates after fixing counter names and scan_one_extent improvements
Zygo Blaxell [Wed, 27 Nov 2024 03:27:07 +0000 (22:27 -0500)]
docs: event counter updates after fixing counter names and scan_one_extent improvements

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoscan_one_extent: eliminate nuisance dedupes, drop caches after reading data
Zygo Blaxell [Sat, 23 Nov 2024 16:14:37 +0000 (11:14 -0500)]
scan_one_extent: eliminate nuisance dedupes, drop caches after reading data

A laundry list of problems fixed:

 * Track which physical blocks have been read recently without making
 any changes, and don't read them again.

 * Separate dedupe, split, and hole-punching operations into distinct
 planning and execution phases.

 * Keep the longest dedupe from overlapping dedupe matches, and flatten
 them into non-overlapping operations.

 * Don't scan extents that have blocks already in the hash table.
 We can't (yet) touch such an extent without making unreachable space.
 Let them go.

 * Give better information in the scan summary visualization:  show dedupe
 range start and end points (<ddd>), matching blocks (=), copy blocks
 (+), zero blocks (0), inserted blocks (.), unresolved match blocks
 (M), should-have-been-inserted-but-for-some-reason-wasn't blocks (i),
 and there's-a-bug-we-didn't-do-this-one blocks (#).

 * Drop cached data from extents that have been inserted into the hash
 table without modification.

 * Rewrite the hole punching for uncompressed extents, which apparently
 hasn't worked properly since the beginning.

Nuisance dedupe elimination:

 * Don't do more than 100 dedupe, copy, or hole-punch operations per
 extent ref.

 * Don't split an extent or punch a hole unless dedupe would save at
 least half of the extent ref's size.

 * Write a "skip:" summary showing the planned work when nuisance
 dedupe elimination decides to skip an extent.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotypes: add shrink_begin and shrink_end methods for BeesFileRange and BeesRangePair
Zygo Blaxell [Tue, 19 Nov 2024 04:57:29 +0000 (23:57 -0500)]
types: add shrink_begin and shrink_end methods for BeesFileRange and BeesRangePair

These allow trimming of overlapping dedupes.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocounters: fix counter names for scan_eof, scan_no_fd, scanf_deferred_inode
Zygo Blaxell [Tue, 19 Nov 2024 22:39:45 +0000 (17:39 -0500)]
counters: fix counter names for scan_eof, scan_no_fd, scanf_deferred_inode

This code gets moved around from time to time and ends up with the
wrong prefix.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agomultilock: allow turning it off
Zygo Blaxell [Thu, 21 Nov 2024 21:26:05 +0000 (16:26 -0500)]
multilock: allow turning it off

Add a master switch to turn off the entire MultiLock infrastructure for
testing, without having to remove and add all the individual entry points.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agofs: handle ENOENT within lib
Zygo Blaxell [Fri, 29 Nov 2024 06:07:55 +0000 (01:07 -0500)]
fs: handle ENOENT within lib

This prevents the storms of exceptions that occur when a subvol is
deleted.  We simply treat the entire tree as if it was empty.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobtrfs-tree: accessors for TreeFetcher classes' type and tree values
Zygo Blaxell [Wed, 20 Nov 2024 16:30:28 +0000 (11:30 -0500)]
btrfs-tree: accessors for TreeFetcher classes' type and tree values

Sometimes we have a generic TreeFetcher and we need to know which tree
it came from.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobtrfs-tree: add root refs and extent flags fields
Zygo Blaxell [Wed, 20 Nov 2024 15:15:53 +0000 (10:15 -0500)]
btrfs-tree: add root refs and extent flags fields

Lazily filling in accessor methods for btrfs objects as needed by bees.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotask: fix try_lock argument description
Zygo Blaxell [Tue, 19 Nov 2024 20:29:41 +0000 (15:29 -0500)]
task: fix try_lock argument description

try_lock allows specification of a different Task to be run instead of
the current Task when the lock is busy.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobees: increase file cache size limits
Zygo Blaxell [Thu, 15 Jul 2021 01:37:40 +0000 (21:37 -0400)]
bees: increase file cache size limits

With some extents having 9999 refs, we can use much larger caches for
file descriptors.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: resolve_overflow limit is only 655050 when BTRFS_MAX_EXTENT_REF_COUNT is
Zygo Blaxell [Thu, 28 Nov 2024 19:37:06 +0000 (14:37 -0500)]
docs: resolve_overflow limit is only 655050 when BTRFS_MAX_EXTENT_REF_COUNT is

Use the current header value in the doc.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agobees: reduce extent ref limit to 9999
Zygo Blaxell [Mon, 14 Jun 2021 15:50:18 +0000 (11:50 -0400)]
bees: reduce extent ref limit to 9999

Originally the limit was 2730 (64KiB worth of ref pointers).  This limit
was a little too low for some common workloads, so it was then raised by
a factor of 256 to 699050, but there are a lot of problems with extent
counts that large.  Most of those problems are memory usage and speed
problems, but some of them trigger subtle kernel MM issues.

699050 references is too many to be practical.  Set the limit to 9999,
only 3-4x larger than the original 2730, to give up on deduplication
when each deduped ref reduces the amount of space by no more than 0.01%.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: event counter updates after readahead sanity improvements
Zygo Blaxell [Wed, 27 Nov 2024 03:23:55 +0000 (22:23 -0500)]
docs: event counter updates after readahead sanity improvements

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoreadahead: inject more sanity at the foundation of an insane architecture
Zygo Blaxell [Mon, 18 Nov 2024 19:22:26 +0000 (14:22 -0500)]
readahead: inject more sanity at the foundation of an insane architecture

This solves a third bad problem with bees reads:

3.  The architecture above the read operations will issue read requests
for the same physical blocks over and over in a short period of time.

Fixing that properly requires rewriting the upper-level code, but a
simple small table of recent read requests can reduce the effect of the
problem by orders of magnitude.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoreadahead: inject some sanity at the foundation of an insane architecture
Zygo Blaxell [Fri, 15 Nov 2024 19:35:01 +0000 (14:35 -0500)]
readahead: inject some sanity at the foundation of an insane architecture

This solves some of the worst problems with bees reads:

1.  The kernel readahead doesn't work.  More precisely, it's much better
adapted for a very different use case:  a single thread alternating
between reading a file sequentially and processing the data that was read.
bees has multiple threads which compete for access to IO and then issue
reads in random order immediately after the call to readahead.  The kernel
uses idle ioprio scheduling for the readaheads, so the readaheads get
preempted by the random reads, or cancels the readaheads because the
data access pattern isn't sequential after the readahead was issued.

2.  Seeking drives perform terribly with multiple competing readers,
especially with btrfs striped profiles where the iops are broken into
tiny stripe-sized pieces.  At one point I intended to read the btrfs
device map and figure out which devices can be read in parallel, but to
make that useful, the user needs to have an array with multiple drives
in single profile, or 4+ drives in raid1 profile.  In all other cases,
the elaborate calculations always return the same result:  there can be
only one reader at a time.

This commit fixes both problems:

1.  Don't use the kernel readahead.  Use normal reads into a dummy
buffer instead.

2.  Allow only one thread to readahead at any time.  Once the read is
completed, the data is in the page cache, and all the random-order small
reads that bees does will hit the page cache, not a spinning disk.
In some cases we need to read two things close together, so add a
`bees_readahead_pair` which holds one lock across both reads.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agohash: use kernel readahead instead of bees_readahead to prefetch hash table
Zygo Blaxell [Mon, 25 Nov 2024 03:11:42 +0000 (22:11 -0500)]
hash: use kernel readahead instead of bees_readahead to prefetch hash table

The hash table is read sequentially and from a single thread, so
the kernel's implementation of readahead is appropriate here.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: add allocator regression in 6.0+ kernels
Zygo Blaxell [Sat, 7 Oct 2023 05:35:07 +0000 (01:35 -0400)]
docs: add allocator regression in 6.0+ kernels

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocontext: when a task fails to acquire an extent lock, don't go ahead and scan the...
Zygo Blaxell [Tue, 19 Nov 2024 20:17:41 +0000 (15:17 -0500)]
context: when a task fails to acquire an extent lock, don't go ahead and scan the extent anyway

Commit c3b664fea54cfd8ac25411cbdb9536e4f24b008e ("context: don't forget
to retry locked extents") removed the critical return that prevents a
Task from processing an extent that is locked.

Put the return back.

Fixes: c3b664fea54cfd8ac25411cbdb9536e4f24b008e ("context: don't forget to retry locked extents")
Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agofs: get rid of 16 MiB limit on dedupe requests
Zygo Blaxell [Tue, 12 Nov 2024 01:47:36 +0000 (20:47 -0500)]
fs: get rid of 16 MiB limit on dedupe requests

The kernel has not required a 16 MiB limit on dedupe requests since
v4.18-rc1 b67287682688 ("Btrfs: dedupe_file_range ioctl: remove 16MiB
restriction").

Kernels before v4.18 would truncate the request and return the size
actually deduped in `bytes_deduped`.  Kernel v4.18 and later will loop
in the kernel until the entire request is satisfied (although still
in 16 MiB chunks, so larger extents will be split).

Modify the loop in userspace to measure the size the kernel actually
deduped, instead of assuming the kernel will only accept 16 MiB.
On current kernels this will always loop exactly once.

Since we now rely on `bytes_deduped`, make sure it has a sane value.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agoRevert "context: add experimental code for avoiding tiny extents"
Zygo Blaxell [Mon, 25 Nov 2024 01:16:46 +0000 (20:16 -0500)]
Revert "context: add experimental code for avoiding tiny extents"
because this problem is better solved elsewhere.

This reverts commit 11fabd66a84b6631fb39bb6b2c066c689351fc26.

21 months agousage: the default scan mode is 3 (recent)
Zygo Blaxell [Sat, 2 Sep 2023 16:19:43 +0000 (12:19 -0400)]
usage: the default scan mode is 3 (recent)

The code and docs were changed some time ago, but not the usage message.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agodocs: add the 6.10..6.12 delayed refs bug
Zygo Blaxell [Sat, 30 Nov 2024 00:30:42 +0000 (19:30 -0500)]
docs: add the 6.10..6.12 delayed refs bug

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agocrawl: rename next_transid() to avoid confusion with BeesScanMode::next_transid()
Zygo Blaxell [Sat, 30 Nov 2024 17:49:22 +0000 (12:49 -0500)]
crawl: rename next_transid() to avoid confusion with BeesScanMode::next_transid()

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
21 months agotrace: add file and line numbers all the way up the stack
Zygo Blaxell [Sat, 30 Nov 2024 15:18:58 +0000 (10:18 -0500)]
trace: add file and line numbers all the way up the stack

These were added to crucible all the way back in 2018 (1beb61fb78ba
"crucible: error: record location of exception in what() message")
but it's even more useful in the stack tracer in bees.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>