[6.12] Track btrfs patches#36
Closed
kakra wants to merge 36 commits into
Closed
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Export patch series: https://github.com/kakra/linux/pull/36.patch
Here's a good guide by @Forza-tng: https://wiki.tnonline.net/w/Btrfs/Allocator_Hints. Please leave them a nice comment. Thanks. :-)
Allocator hints
To make use of the allocator hints, add these to your kernel. Then run
btrfs device usage /path/to/btrfsand take note of which device IDs are SSDs and which are HDDs.Go to
/sys/fs/btrfs/BTRFS-UUID/devinfoand run:echo 0 | sudo tee HDD-ID/typeto prefer writing data to this device (btrfs will then prefer allocating data chunks from this device before considering other devices) - recommended for HDDs, set by defaultecho 1 | sudo tee SSD-ID/typeto prefer writing meta-data to this device (btrfs will then prefer allocating meta-data chunks from this device before considering other devices) - recommended for SSDsecho 4 | sudo tee LEGACY-ID/typeecho 5 | sudo tee LEGACY-ID/typeImportant note: This recommends to use at least two independent SSDs so btrfs meta-data raid1 requirement is still satisfied. You can, however, create two partitions on the same SSD but then it's no longer protected against hardware faults, it's essentially dup-quality meta-data then, not raid1. Before sizing the partitions, look at
btrfs device usageto find the amount of meta-data, at least double that size to size your meta-data partitions.This can be combined with bcache by directly using meta-data partitions as a native SSD partition for btrfs, and only using data partitions routed through bcache. This also takes a lot of meta-data pressure from bcache, making it more efficient and less write-wearing as a result.
Real-world example
In this example,
sdeis a 1 TB SSD having two meta-data partitions (2x 128 GB) with the remaining space dedicated to a single bcache partition attached to my btrfs pool devices:A curious reader may find that
sde1andsde3are missing, which is my EFI boot partition (sde1) and swap space (sde3).Read Policies aka "RAID1 read balancer"
To use the balancer,
CONFIG_BTRFS_EXPERIMENTAL=yis needed while building the kernel. The balancer offers six modes:Combined with bcache, performance is unstable with both
round-robinandlatencybecause latency and throughput depend on whether data is cached or not - but still it is overall better than the old PID balancer.Unexpectedly,
queueperforms exceptionally well on my mixed device setup. YMMV with identical member devices. It outperforms all other policies in each discipline and benchmark.To use the balancer, use
btrfs.read_policy=<pid,round-robin,latency,latency-rr,queue,devid:#>on the kernel cmdline. There's also a sysfs interface at/sys/fs/btrfs/<UUID>/read_policyto switch balancers on demand (e.g., for benchmarks). Seemodinfo btrfsfor more information.Benchmark results: https://gist.github.com/kakra/ce99896e5915f9b26d13c5637f56ff37
Note 1: The latency calculation currently uses an average of the full history of requests only - which is bad because it will cancel out changing variations over time. A better approach would be to use an EMA (exponential moving average) with an alpha of 1/8 or 1/16. This requires to sample individual bio latency and thus requires to change structs and code in other parts of btrfs. I'm not very familiar with all the internal structures yet, and the feature is still guarded by
CONFIG_BTRFS_EXPERIMENTAL, making that approach more complex. OTOH, having a permanent EMA right in the bio structures of btrfs could prove useful in other areas of btrfs.Note 2: In theory, both latency modes should automatically prefer faster zones of HDDs and properly switch stripes automatically. In practice, this is probably overruled by note 1 except most of your data is in specific zones by coincidence, in which case the average would properly hold some sort of "zone performance".
Note 3: With high CPU core counts,
queuemight have a measurable CPU overhead due to queue length calculation (per-core counters have to be summed per each request).Real-world example
Some simple tests have shown that both the round-robin and latency balancers can increase throughput while loading games from 200-300 MB/s to 500-700 MB/s when combined with bcache.
Important note: This will be officially available with kernel 6.15 or later, excluding the latency balancer. I've included it because I think it can provide better performance in edge cases, e.g. asymmetric RAID or bcache. It may also provide better performance on the desktop because on the desktop, latency is more important than throughput. The latency balancer is thus an experiment and may go away. But I will keep it until at least the next LTS kernel.
Description / instructions for balancing
(AI generated after training with some stats, observations and incremental development steps)
Interpreting the Btrfs
read_statsSysfs OutputThe
/sys/fs/btrfs/<UUID>/devinfo/<DEVID>/read_statsfile, enhanced by these patches, offers valuable insights into the dynamic read balancing behavior and performance of individual devices within a Btrfs RAID1/10/1C3/4 setup. Here's a breakdown of the fields:cumulative ios %lu: The total count of read I/O operations completed on this specific device since the filesystem was mounted.cumulative wait %llu: The total time (in nanoseconds) accumulated waiting for all cumulative read IOs on this device.cumulative avg %llu: The long-term average read latency (cumulative wait / cumulative ios) in nanoseconds. This represents the device's average performance over its entire operational history within the current mount. It changes very slowly and can be heavily influenced by caching layers (like bcache or the page cache) if present.checkpoint ios %ld: The number of read IOs completed since the last checkpoint. A checkpoint is established when a device undergoes "rehabilitation" – meaning itsagecounter reached theBTRFS_DEVICE_LATENCY_CHECKPOINT_AGEthreshold, triggering a read probe and a reset of these checkpoint statistics. For devices that have never been rehabilitated, this value will equalcumulative ios.checkpoint wait %lld: The total time (in nanoseconds) accumulated waiting for reads since the last checkpoint.checkpoint avg %llu: The average read latency (checkpoint wait / checkpoint ios) calculated only using the IOs since the last checkpoint. This is a key metric reflecting recent performance. It's much more responsive to current conditions than the cumulative average, especially after a period of being ignored.age %lld: This counter tracks how "stale" the device is in terms of read selection. It increments each time a read balancing decision is made for a stripe group containing this device, but another device from that group is chosen.0: The device was selected for a read very recently (in the last relevant balancing decision).> 0: The device has been ignored for this many consecutive selection events where it was a candidate. A high value indicates it's consistently considered slower or less preferred than its peers.< 0: The device has just been rehabilitated (hit theagethreshold). It is now in a "burst IO" probation period (e.g., starting at -100 and incrementing towards 0). During this negative age phase, its reported latency is forced to 0 to guarantee it receives reads.count %llu: The number of times this device has triggered the rehabilitation mechanism by reaching theagethreshold. A high count suggests the device is frequently deemed too slow by the latency policy or is subject to other selection biases (like non-balancing metadata reads).ignored %lld: A counter incremented every time this device was a candidate for a read, but the balancing policy ultimately selected a different device from the same stripe group. This provides insight into how often the policy actively chooses a peer over this device, indicating relative preference or "fairness" of the algorithm.How to Use These Stats:
checkpoint avg(compared to peers) and a high, frequently resetageare likely performance bottlenecks under the current load.cumulative avgandcheckpoint avg. A large difference after rehabilitation (count > 0) shows the policy is adapting to performance changes more quickly than the cumulative average would suggest.checkpoint avgbut a persistently highageandignoredcount (like NVMe metadata mirrors sometimes exhibit) points towards a selection bias not based purely on latency.ageandcountvalues help evaluate theAGE_THRESHOLDandIO_BURSTparameters. Ifagehits the threshold very frequently, it might be too low. Ifcheckpoint iosbarely increases after a reset, theIO_BURSTmight be too short (or the device becomes slow again immediately).These enhanced statistics provide a powerful diagnostic tool for understanding and fine-tuning Btrfs's read balancing behavior in complex, real-world storage environments.