Repository navigation
Would you accept a read-only btrfs driver? (adds one dependency: aircompressor, for zstd/lzo) #33
Description
Would you accept a read-only btrfs driver? (adds one dependency: aircompressor, for zstd/lzo)
Body:
Hi - I've built a read-only btrfs driver for jnode-fs and I'd like to contribute it, but before I
prepare a PR I want to check two things: whether btrfs support is in scope for the project, and
whether the one new dependency it needs is acceptable. Also, in the spirit of full disclosure, this
was largely written by Claude (Fable 5), and if you'd prefer not to have AI submissions, I totally
understand.
What it is
A new org.jnode.fs.btrfs package (~16 classes, no changes to existing code beyond the pom):
- Superblock →
sys_chunk_arraybootstrap → chunk tree → logical→physical mapping (single and
DUP profiles; multi-device/RAID is rejected cleanly with a clear message). - Root tree → FS trees; subvolume descent. Snapshots (
parent_uuidset) are skipped by default —
a snapper/openSUSE root has dozens of near-identical snapshots — with a toggle to include them. - Directory tree, sizes, mode, and timestamps (
FSEntryCreated/FSEntryLastAccessed/
FSEntryLastChanged, matchingXfsEntry); volume-unique entry ids (subvolId-objectId);
volume label; symlinks (flagged + target readable); extended attributes
(getAttributes() → List<FSAttribute>, again matching the XFS surface). - File content: inline, regular and prealloc extents (prealloc reads as zeros), with all four
compression types — none, zlib (JDK Inflater), zstd and lzo (aircompressor). Keyed B-tree
search for extent/xattr lookup (O(depth), no full-tree scan per open); uncompressed extents are
read by range; optional crc32c metadata verification (off by default).
How it's tested
JUnit 4, same idioms as the existing drivers, including DataStructureAsserts.assertStructure
per fixture. Six gzipped image fixtures (~1.9 MB total): four built unprivileged with
mkfs.btrfs -r (incl. a multi-level tree that forces real B-tree descent, a symlink image, and an
xattr image), and two built from privileged mount -o compress-force={zstd,lzo} so the compressed
content is kernel-written — decompressed bytes are asserted against exactly what was written.
That end-to-end gate caught a real bug the synthetic tests missed (kernel inline zstd frames
declare a whole-page content size), so I'd call it load-bearing. There's also a differential test
locking the keyed B-tree cursor against the full-scan walk (order + bytes, thousands of items).
109 tests run green in the fork.
The question: one new dependency
zstd is the default compression on the distros that default to btrfs (Fedora, openSUSE), so a
btrfs reader without it can browse the tree but not read most compressed content. I used
io.airlift:aircompressor 0.27 for zstd and lzo:
- pure Java (no native libraries — same portability story as the rest of jnode-fs),
- Apache-2.0, on Maven Central, ~600 KB,
- Java 8 bytecode (0.27 is the last Java-8 line; the 2.x line requires Java 22),
- actively maintained (Trino/Airlift).
zlib needs nothing (JDK). If you'd rather not take the dependency I could make zstd/lzo degrade to
a clear "compression not supported" error when aircompressor isn't on the classpath, but a hard
dependency is simpler and I'd prefer it — your call.
Known limitations (documented in the package README)
Read-only; single-device only (multi-device/RAID rejected, not mis-read); primary superblock only
(backup mirrors at 64 MiB/256 GiB not consulted); crc32c is the only checksum type verified.
The work is on my fork if you want to look before I prepare anything:
https://github.com/davidbairdala/jnode-fs — the org.jnode.fs.btrfs package (the fork's version
suffix and tags are local; a PR would come as a clean branch off your master without them).
If this is in scope I'm happy to adjust conventions, split the change, or trim fixtures to
whatever you prefer.
Activity
CoffeeForOven commentedon Sep 22, 2026
Please feel free to raise a PR. We're currently reviewing changes to the library with the goal of a release soon.