Skip to content

Releases: rustutils/btrfsutils

Release v0.13.0

14 May 18:59
ea6ff6a

Choose a tag to compare

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's FICLONERANGE
    ioctl: the destination gains extent references to the source's data,
    no bytes are copied, and subsequent modifications are copy-on-write.
    Without -r the whole source file is cloned into the (created or
    truncated) target; with one or more -r flags 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 returns EOPNOTSUPP; ours actually clones.
  • btrfs-uapi: reflink::clone_range(src, src_off, length, dst, dst_off)
    wraps BTRFS_IOC_CLONE_RANGE (same ioctl encoding as the standard
    VFS FICLONERANGE). A length of zero means "from src_off to
    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
    kernel BTRFS_IOC_SEND ioctl. Bypasses every constraint of the
    ioctl path: no CAP_SYS_ADMIN, no kernel mount, no FUSE retry
    restriction. Subvolume to send is selected with
    --offline-subvol PATH or --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 default FS_TREE. Used by btrfs send --offline
    and by btrfs-fuse's --subvol flag.
  • btrfs-fs: Filesystem::send(snapshot, output) -> Result<output>
    generates a v1 send stream describing the snapshot and writes it
    to any Write (typically a pipe to btrfs receive or 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-inode Mkfile/Mkdir/Symlink/Mknod/Mkfifo
    /Mksock, SetXattr for each xattr, Write chunks (capped at
    48 KiB to fit v1's u16 length field), Truncate, then
    Chown/Chmod/Utimes. Hardlinks beyond the first reference
    emit Link rather than re-creating the inode. Subvolume
    crossings are skipped — caller invokes send per subvolume.
    Output is decompressed (compression passthrough lands in tier 3
    alongside v2 EncodedWrite).
  • btrfs-stream: StreamWriter<W> encodes StreamCommand values
    back into the on-the-wire TLV-framed format produced by kernel
    btrfs send. Mirror of StreamReader: every command variant
    (v1+v2+v3) round-trips through write → parse cleanly. Handles the
    v2+ BTRFS_SEND_A_DATA quirk (no length field, extends to end of
    payload) so Write / EncodedWrite commands 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
    consts module shared between encoder and parser.
  • btrfs-cli: btrfs fuse <IMAGE> <MOUNTPOINT> [OPTIONS] subcommand
    behind a new opt-in fuse cargo feature. Mirrors the standalone
    btrfs-fuse binary one-for-one, sharing the same argument struct
    and mount logic via the new public btrfs_fuse::args::MountArgs
    and btrfs_fuse::run::run_mount items. Standalone binary stays
    for mount.fuse.btrfs / fstab-style integrations. Feature is
    opt-in for now since the FUSE driver is still experimental — build
    with cargo build --features fuse (or --all-features) to
    include it.
  • btrfs-fs: new crate exposing a high-level read-only filesystem
    API on top of btrfs-disk: Filesystem<R> with lookup, readdir,
    readdirplus, read, readlink, getattr, xattr_get /
    xattr_list, statfs, seek_hole_data (POSIX SEEK_HOLE /
    SEEK_DATA over the cached extent map), forget, tree_search,
    dev_info, ino_lookup, ino_paths, list_subvolumes,
    get_subvol_info, superblock, and the send / resolve_subvol_path
    helpers above. FUSE-independent — drives the btrfs-fuse mount
    and any other embedder. Inodes are modelled as (SubvolId, ino)
    so multi-subvolume traversal works. The handle is Clone (cheap
    Arc bump) and all operations are async fn, so multiple tokio
    tasks can drive the same filesystem concurrently. Sync I/O is
    wrapped in tokio::task::spawn_blocking so the runtime is never
    blocked on disk reads. R: Read + Seek + Send + 'static is the
    bound; for File and Cursor<Vec<u8>> it's free.
  • btrfs-fs: multi-subvolume traversal. Filesystem::lookup now
    detects subvolume crossings (a DirItem whose location.key_type
    is ROOT_ITEM) and returns an Inode carrying the new subvol id
    and objectid 256. Reads, readdir, readlink, and xattr ops
    follow into the new subvolume's tree automatically. .. from a
    non-default subvolume root resolves via ROOT_BACKREF in 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() -> SubvolId exposes which subvolume
    root() points at, and SubvolInfo carries dirid, otime,
    ctransid, otransid, uuid, parent_uuid, and received_uuid
    — everything BTRFS_IOC_GET_SUBVOL_INFO needs.
  • btrfs-fs: CacheConfig struct and Filesystem::open_with_caches
    / Filesystem::open_subvol_with_caches constructors 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. Existing Filesystem::open /
    Filesystem::open_subvol continue to use the defaults.
  • btrfs-disk: pluggable tree-block cache via TreeBlockCache
    trait. BlockReader::read_tree_block returns Arc<TreeBlock>,
    consults the attached cache before disk, and populates on miss.
    Trait is Send + Sync with &self methods (interior mutability)
    so the cache is shareable across threads. btrfs-disk ships the
    trait only — no LRU implementation, no extra deps; embedders
    provide their own. btrfs-fs ships LruTreeBlockCache as 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 (returns ENOPROTOOPT so
    btrfs-uapi::tree_search_auto transparently falls back to v1).
    Each FUSE_IOCTL request runs in a spawned tokio task that owns
    the ReplyIoctl, 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 return ENOTTY.
  • btrfs-fuse: lseek callback (POSIX SEEK_HOLE / SEEK_DATA),
    readdirplus (kernel-side readdir + lookup-per-entry
    coalescing — major speedup for ls -l), init (advertises
    FUSE_DO_READDIRPLUS, FUSE_AUTO_INVAL_DATA,
    FUSE_SPLICE_READ/WRITE), and forget (eager inode +
    extent-map cache eviction) callbacks. BtrfsFuse::open_with_caches
    / BtrfsFuse::open_subvol_with_caches constructors mirror the
    btrfs-fs additions.
  • btrfs-fuse CLI: --subvol PATH / --subvolid ID mount a
    specific subvolume as the FUSE root (mutually exclusive; absent
    both, the default FS_TREE is used). --cache-tree-blocks N
    (default 4096), --cache-inodes N (default 4096),
    --cache-extent-maps N (default 1024), and
    --no-default-permissions to bypass the kernel's per-file
    mode/uid/gid checks. Default behaviour now enables the kernel
    default_permissions mount option so the FUSE mount enforces
    stored ownership the way kernel btrfs does;
    --no-default-permissions opts out for image-inspection
    scenarios where stored UIDs don't match the local system.
  • btrfs-fuse integration tests: 10 unprivileged tests in
    fuse/tests/mount.rs that spawn the btrfs-fuse binary, mount
    it against a fixture image, and exercise the mounted filesystem
    through ordinary POSIX calls (std::fs, xattr crate).
    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...
Read more

v0.11.0

08 Apr 14:21
f3d226c

Choose a tag to compare

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-uapi is basically feature-complete and reliable.
  • btrfs-disk is stable, for the read part. Write-part is well tested, but still newer.
  • btrfs-stream is stable: well-tested, conceptually simple.
  • btrfs-cli has 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 --offline commands.
  • btrfs-mkfs should be stable. Missing a few edge-case tests. Might need to change the way it is implemented, it currently does not use the btrfs-transaction write paths (it was implemented before we had working transactions).
  • btrfs-transaction is 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 (through btrfs-transaction). Needs more work for sure. Initial version is published, but not ready for usage yet.