Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

rust-fs-btrfs

Pure-Rust, clean-room Btrfs driver. A reader for the Btrfs on-disk format built over the shared am-fs-core block-device trait, exposing a stable C ABI (fs_btrfs_*) for FFI from C/C++, Swift or Go.

Published on crates.io as am-fs-btrfs; the library name is fs_btrfs.

Btrfs is a copy-on-write filesystem: nothing is overwritten in place, every structure is a B-tree, and the physical location of any byte is resolved through the chunk tree rather than computed from a fixed formula. That makes it a different shape of problem from ext4 or NTFS — a reader has to bootstrap the chunk tree out of the superblock's embedded system chunk array before it can address anything else at all.

  • Clean-room — written from the published on-disk format, not translated from kernel or btrfs-progs source
  • Permissive — MIT, with a permissive dependency tree (no GPL/LGPL anywhere)
  • Cross-platform — the driver reads images on Linux, macOS and Windows; only the test oracle needs a Linux kernel

Status

Under active development. The table is the honest state of what is implemented, not a roadmap.

It was last wrong in the other direction: it described a reader with the write path "out of scope" and B-tree traversal, inodes and compression "planned", all of which had been in for some time. A status table that understates is not harmless — someone deciding whether this is usable reads it and concludes it is not.

Area Support
Superblock (primary at 64 KiB) done — 216 field comparisons against dump-super
Superblock mirrors (64 MiB, 256 GiB) parsed; mirror-selection policy pending
Checksum: crc32c done
Checksum: xxhash64, sha256, blake2b done — all four verified against real media
System chunk array → chunk tree bootstrap done
Chunk tree / logical→physical mapping done — bootstrap array, then the full tree folded in
B-tree node + leaf traversal done — walk and keyed search, on multi-level trees
Root tree, fs tree, extent tree done
Inodes, directory items, extent data done
Directory listing, lookup, path resolution done
Symlinks done
Extended attributes: read done — list_xattrs / get_xattr, checked name by name against getfattr
Extended attributes: write not yet — setting one means inserting into a tree a transaction has to commit
Profiles: single, dup, raid0, raid1, raid10 done
Profiles: raid5/6 refused explicitly, not guessed
Mixed block groups (mkfs.btrfs -M) reads; covered by the fixture matrix
Subvolumes and snapshots: listing done — id, path, parent, snapshot and read-only flags, checked against btrfs subvolume list
Subvolumes and snapshots: reading inside one done — open_subvolume gives a handle over that tree; read-only
A path that crosses into a subvolume not yet — lookup_path("/sub/x") stops at the boundary and says which subvolume to open. An inode number means nothing without its tree, so crossing has to hand back both
Compression (zlib / lzo / zstd extents) done — all three, verified against files the kernel wrote
Write path: overwrite in place done — nodatacow files only, no journal needed
Write path: anything copy-on-write planned — see docs/transaction-format.md
C ABI (fs_btrfs_*) done, including the write entry points

Test contract

Two layers, and only one of them can tell you the driver is right.

Layer 1 — unit tests. Fast, hermetic, no external tooling. They run on every cargo test and prove the parser is self-consistent: that it accepts the fixtures the crate builds for itself and reports the values those fixtures encode.

That is a weaker claim than it looks. When a fixture is hand-built from the same reading of the spec as the parser, a misread field is encoded wrong and decoded wrong in exactly the same way, and the assertion passes. Byte-order slips, transposed magic values, checksums computed over the wrong span — none of them disturb a round-trip. A green unit suite means the driver is consistent with itself, not that it reads Btrfs.

Layer 2 — the real-kernel gate. Real filesystems, built by the canonical mkfs.btrfs, described by btrfs inspect-internal dump-super, checked by btrfs check, and mounted by the in-kernel Btrfs driver. The driver then parses those same images and must agree with the reference dump field by field.

This layer is blocking in CI (.github/workflows/ci.yml, the validate against kernel btrfs driver job), not an optional confirmation. The job builds the full geometry matrix, loop-mounts every image, writes and reads a file back through the kernel, and fails if the kernel logs a single btrfs warning — a mount that succeeds while the kernel complains is not a pass.

The case for making it blocking is empirical. In the sister XFS driver the equivalent gate found three live parser bugs on its first run, with the entire unit suite green: a superblock magic with two bytes transposed, checksums stored little-endian while every other field is big-endian, and a checksum computed over the structure rather than the whole sector. Each is invisible to a round-trip test and fatal against a real filesystem. There is no reason to expect Btrfs — with more indirection, more checksum algorithms and more layout variation — to be kinder.

The geometry matrix

One list, in scripts/fixture-geometries.sh, consumed by both fixture builders so the gate a developer runs locally and the gate that guards the branch cover the same ground:

Fixture mkfs.btrfs args What it moves
default the baseline the tooling picks for itself
node4k / node16k -n 4096 / -n 16384 every b-tree item offset
csum-crc32c --csum crc32c the classic checksum, 4 bytes used of 32
csum-xxhash --csum xxhash 8-byte digest in a 32-byte field
csum-sha256 --csum sha256 full-width digest
csum-blake2 --csum blake2 full-width digest, different algorithm id
single -d single -m single explicit single profile, chunk-tree layout
dup -d dup -m dup duplicated data and metadata block groups
mixed -M data and metadata folded into one block-group type

Each fixture is a ~400 MiB image written as .vm-share/btrfs-<name>.img beside its .vm-share/btrfs-<name>.superdump. A geometry the local btrfs-progs refuses is reported loudly and counted, never silently dropped — a fixture that quietly stopped being generated is a hole in the gate that still reports green.

Running the gate

On Linux

The runner is the oracle; no VM is involved.

sudo apt-get install -y btrfs-progs
bash scripts/build-fixtures-native.sh
cargo test --test oracle_vm_fixtures -- --nocapture

On macOS

mkfs.btrfs, btrfs check and the in-kernel driver are Linux-only, so the fixtures are built inside a Debian arm64 VM (QEMU with HVF — hardware accelerated, no third-party hypervisor to install). The comparison itself still runs on the host, so the iterate-and-check loop stays fast: the VM is only needed when fixtures are regenerated, not on every cargo test.

brew install antimatter-studios/tap/qemu
brew install antimatter-studios/tap/virtiofsd
vagrant plugin install vagrant-qemu-christhomas
vagrant plugin install vagrant-notify-forwarder-christhomas
./scripts/vm.sh up # boot the oracle (first run provisions)
./scripts/vm-build-fixtures.sh # build the matrix into .vm-share
cargo test --test oracle_vm_fixtures -- --nocapture

scripts/vm.sh also takes run <cmd>, share, put <file>, down and destroy. The VM is deliberately left running between invocations — booting is the slow part, and an iterate-and-check loop should pay it once.

Fixtures are gitignored and absent on a fresh clone, so the oracle test skips rather than fails when .vm-share is empty.

Tests

cargo test # unit tests, no external tools
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --test oracle_vm_fixtures -- --nocapture # needs fixtures (see above)

Building

The crate has a path dependency on the sibling am-fs-core repository. Clone it alongside this one:

git clone https://github.com/antimatter-studios/rust-fs-core.git ../rust-fs-core
cargo build --release

License

MIT — see LICENSE.

About

Pure-Rust Btrfs filesystem driver over the am-fs-core block-device trait, exposing a stable C ABI for FFI.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /