Releases: rustutils/btrfsutils
Release v0.13.0
btrfsutils 0.13 is the read-side feature-completeness release: a new
btrfs-fs crate extracts the read-only filesystem API from btrfs-fuse
(multi-subvolume traversal, async, three-layer caching) and drives both
the matured FUSE driver and a new btrfs send --offline IMAGE that streams
snapshots from unmounted images with no privileges. btrfs-fuse rounds
out POSIX coverage with lseek SEEK_HOLE/SEEK_DATA, readdirplus,
eager forget, and eight btrfs ioctls (with a tree_search_auto v2 to v1
fallback so the kernel's FUSE_IOCTL_RETRY restriction doesn't bite),
and now ships as both standalone btrfs-fuse and an opt-in btrfs fuse
subcommand. btrfs reflink clone lands as a small bonus (the C reference
is a stub that returns EOPNOTSUPP). And finally there's a real release
pipeline: cross-compiled static musl .deb, .rpm, .tar.zst, bare-zstd
artifacts for x86_64, aarch64, and riscv64gc, published to GitLab
and mirrored to GitHub on every vX.Y.Z tag.
Added
btrfs-cli:btrfs reflink clone [-r SRCOFF:LENGTH:DESTOFF]... SRC DST
performs lightweight file copies via the kernel'sFICLONERANGE
ioctl: the destination gains extent references to the source's data,
no bytes are copied, and subsequent modifications are copy-on-write.
Without-rthe whole source file is cloned into the (created or
truncated) target; with one or more-rflags only the specified
ranges are cloned and the surrounding target bytes are preserved.
Each range component (SRCOFF, LENGTH, DESTOFF) accepts the
k/m/g/t/p/e size suffix. The C reference in btrfs-progs ships a
stub that always returnsEOPNOTSUPP; ours actually clones.btrfs-uapi:reflink::clone_range(src, src_off, length, dst, dst_off)
wrapsBTRFS_IOC_CLONE_RANGE(same ioctl encoding as the standard
VFSFICLONERANGE). Alengthof zero means "fromsrc_offto
end-of-source", per the kernel ABI.btrfs-cli:btrfs send --offline IMAGE [-f OUT]generates a v1
send stream from an unmounted btrfs image without touching the
kernelBTRFS_IOC_SENDioctl. Bypasses every constraint of the
ioctl path: noCAP_SYS_ADMIN, no kernel mount, no FUSE retry
restriction. Subvolume to send is selected with
--offline-subvol PATHor--offline-subvolid ID(defaults to
the default subvolume). Tier 1: incremental, clone sources,
--no-data, alternate protocol versions, and compressed-data
passthrough are not yet supported in offline mode and clap
rejects them.btrfs-fs:Filesystem::resolve_subvol_path(path) -> Option<SubvolId>
walks the subvolume graph and resolves a slash-separated path
(relative to the FS root) to its tree id. Empty path /"/"
resolves to the defaultFS_TREE. Used bybtrfs send --offline
and bybtrfs-fuse's--subvolflag.btrfs-fs:Filesystem::send(snapshot, output) -> Result<output>
generates a v1 send stream describing the snapshot and writes it
to anyWrite(typically a pipe tobtrfs receiveor a backup
file). Tier 1 of the send roadmap: full sends only (no parent
comparison), no clone sources, no encoded-write passthrough. The
walker emits per-inodeMkfile/Mkdir/Symlink/Mknod/Mkfifo
/Mksock,SetXattrfor each xattr,Writechunks (capped at
48 KiB to fit v1's u16 length field),Truncate, then
Chown/Chmod/Utimes. Hardlinks beyond the first reference
emitLinkrather than re-creating the inode. Subvolume
crossings are skipped — caller invokessendper subvolume.
Output is decompressed (compression passthrough lands in tier 3
alongside v2EncodedWrite).btrfs-stream:StreamWriter<W>encodesStreamCommandvalues
back into the on-the-wire TLV-framed format produced by kernel
btrfs send. Mirror ofStreamReader: every command variant
(v1+v2+v3) round-trips through write → parse cleanly. Handles the
v2+BTRFS_SEND_A_DATAquirk (no length field, extends to end of
payload) soWrite/EncodedWritecommands can carry payloads
beyond the v1 64 KiB cap. CRC32C uses the same raw (init=0)
variant the parser checks. Wire-format constants moved to a new
constsmodule shared between encoder and parser.btrfs-cli:btrfs fuse <IMAGE> <MOUNTPOINT> [OPTIONS]subcommand
behind a new opt-infusecargo feature. Mirrors the standalone
btrfs-fusebinary one-for-one, sharing the same argument struct
and mount logic via the new publicbtrfs_fuse::args::MountArgs
andbtrfs_fuse::run::run_mountitems. Standalone binary stays
formount.fuse.btrfs/ fstab-style integrations. Feature is
opt-in for now since the FUSE driver is still experimental — build
withcargo build --features fuse(or--all-features) to
include it.btrfs-fs: new crate exposing a high-level read-only filesystem
API on top ofbtrfs-disk:Filesystem<R>withlookup,readdir,
readdirplus,read,readlink,getattr,xattr_get/
xattr_list,statfs,seek_hole_data(POSIXSEEK_HOLE/
SEEK_DATAover the cached extent map),forget,tree_search,
dev_info,ino_lookup,ino_paths,list_subvolumes,
get_subvol_info,superblock, and thesend/resolve_subvol_path
helpers above. FUSE-independent — drives thebtrfs-fusemount
and any other embedder. Inodes are modelled as(SubvolId, ino)
so multi-subvolume traversal works. The handle isClone(cheap
Arcbump) and all operations areasync fn, so multiple tokio
tasks can drive the same filesystem concurrently. Sync I/O is
wrapped intokio::task::spawn_blockingso the runtime is never
blocked on disk reads.R: Read + Seek + Send + 'staticis the
bound; forFileandCursor<Vec<u8>>it's free.btrfs-fs: multi-subvolume traversal.Filesystem::lookupnow
detects subvolume crossings (aDirItemwhoselocation.key_type
isROOT_ITEM) and returns anInodecarrying the new subvol id
andobjectid 256. Reads,readdir,readlink, and xattr ops
follow into the new subvolume's tree automatically...from a
non-default subvolume root resolves viaROOT_BACKREFin the
root tree, returning the directory in the parent subvolume that
contains the current one.Filesystem::open_subvol(reader, SubvolId)
opens the filesystem with a non-default subvolume as the root,
Filesystem::default_subvol() -> SubvolIdexposes which subvolume
root()points at, andSubvolInfocarriesdirid,otime,
ctransid,otransid,uuid,parent_uuid, andreceived_uuid
— everythingBTRFS_IOC_GET_SUBVOL_INFOneeds.btrfs-fs:CacheConfigstruct andFilesystem::open_with_caches
/Filesystem::open_subvol_with_cachesconstructors that let
embedders override the default cache sizes (4096 tree blocks, 4096
inodes, 1024 extent maps).CacheConfig::no_cache()provides the
minimum-viable single-entry caches for benchmarking the cold path
or memory-constrained embedders. ExistingFilesystem::open/
Filesystem::open_subvolcontinue to use the defaults.btrfs-disk: pluggable tree-block cache viaTreeBlockCache
trait.BlockReader::read_tree_blockreturnsArc<TreeBlock>,
consults the attached cache before disk, and populates on miss.
Trait isSend + Syncwith&selfmethods (interior mutability)
so the cache is shareable across threads.btrfs-diskships the
trait only — no LRU implementation, no extra deps; embedders
provide their own.btrfs-fsshipsLruTreeBlockCacheas the
default impl and exposes
Filesystem::tree_block_cache_stats() -> CacheStats(lock-free
hit/miss/insertion counters) for tests and benchmarks.btrfs-fuse: btrfs ioctl support over the FUSE mount.
BTRFS_IOC_FS_INFO,BTRFS_IOC_GET_FEATURES,
BTRFS_IOC_GET_SUBVOL_INFO,BTRFS_IOC_DEV_INFO,
BTRFS_IOC_INO_LOOKUP,BTRFS_IOC_TREE_SEARCH(v1, fixed
4 KiB struct),BTRFS_IOC_GET_SUBVOL_ROOTREF, and
BTRFS_IOC_TREE_SEARCH_V2(returnsENOPROTOOPTso
btrfs-uapi::tree_search_autotransparently falls back to v1).
Each FUSE_IOCTL request runs in a spawned tokio task that owns
theReplyIoctl, awaits the filesystem call, and serialises the
response into the kernel's C struct layout (no bindgen types
leak into the public API). Unknown ioctls returnENOTTY.btrfs-fuse:lseekcallback (POSIXSEEK_HOLE/SEEK_DATA),
readdirplus(kernel-sidereaddir + lookup-per-entry
coalescing — major speedup forls -l),init(advertises
FUSE_DO_READDIRPLUS,FUSE_AUTO_INVAL_DATA,
FUSE_SPLICE_READ/WRITE), andforget(eager inode +
extent-map cache eviction) callbacks.BtrfsFuse::open_with_caches
/BtrfsFuse::open_subvol_with_cachesconstructors mirror the
btrfs-fsadditions.btrfs-fuseCLI:--subvol PATH/--subvolid IDmount a
specific subvolume as the FUSE root (mutually exclusive; absent
both, the defaultFS_TREEis used).--cache-tree-blocks N
(default 4096),--cache-inodes N(default 4096),
--cache-extent-maps N(default 1024), and
--no-default-permissionsto bypass the kernel's per-file
mode/uid/gid checks. Default behaviour now enables the kernel
default_permissionsmount option so the FUSE mount enforces
stored ownership the way kernel btrfs does;
--no-default-permissionsopts out for image-inspection
scenarios where stored UIDs don't match the local system.btrfs-fuseintegration tests: 10 unprivileged tests in
fuse/tests/mount.rsthat spawn thebtrfs-fusebinary, mount
it against a fixture image, and exercise the mounted filesystem
through ordinary POSIX calls (std::fs,xattrcrate).
Coverage: mount/unmount lifecycle, root listing, file reads
(small, large, nested),stat(verifies the 1↔256 inode swap),
readlink, xattr get/list, and a 16-thread × 50-iteration
concurrent-read stress test that catches double-reply,
dropped-reply, and deadlock bugs in the spawn-task dispatch path.
`MountedF...
v0.11.0
Releases v0.11.0.
This is still a pre-1.0 release, so don't use this in production. What this release adds is some missing transaction functionality that was needed for wiring up some missing btrfs-tune flags.
Current status:
btrfs-uapiis basically feature-complete and reliable.btrfs-diskis stable, for the read part. Write-part is well tested, but still newer.btrfs-streamis stable: well-tested, conceptually simple.btrfs-clihas most subcommands implemented and tested. Some subcommands (btrfs rescue) have gaps and are in need of thorough testing. Commands that make use of transactions are considered experimental, README.md and crate-level docs make a note of this. This includes any of the--offlinecommands.btrfs-mkfsshould be stable. Missing a few edge-case tests. Might need to change the way it is implemented, it currently does not use thebtrfs-transactionwrite paths (it was implemented before we had working transactions).btrfs-transactionis new, implemented from scratch. Have had a number of bugs in there, so definitely considered experimental. Still has some gaps that need to be addressed. In need of a thorough testing effort.btrfs-fuse: scaffolding exists, currently broken. Goal is to make a proper FUSE implementation, initially read-only, but later adding write support (throughbtrfs-transaction). Needs more work for sure. Initial version is published, but not ready for usage yet.