fsys 0.6.0

Adaptive file and directory IO for Rust — fast, hardware-aware, multi-strategy.
Documentation

FSYS (fsys-rs) is a low-level file and directory IO crate for Rust. It is aimed at systems code that needs explicit control over durability, predictable cross-platform behavior, and an API surface that stays close to how storage software actually thinks about IO.

The crate sits between std::fs and a fully bespoke platform layer. It keeps the operational model explicit: you choose a durability method, build a long-lived Handle, and issue file or directory operations through that handle. On supported platforms, fsys uses the best available primitive for the selected method while keeping fallback behavior visible rather than implicit.

That makes it a good fit for storage engines, embedded databases, local-first applications, durable caches, append-heavy services, background workers, and other programs where write semantics matter as much as raw throughput. It is not trying to replace std::fs for ordinary application code.


⚠️ Status: Early development.
The crate is usable and tested, but the API is not stable yet. Expect breaking changes before 1.0.0.

 

FEATURES

  • Five real durability methodsSync, Data, Mmap, Direct, and hardware-aware Auto. Every method is platform-honest: the actual primitive in use is observable via Handle::active_method() and Handle::active_durability_primitive().
  • Cross-platform IO semantics — one API surface across Linux, macOS, and Windows, with platform-specific fallbacks documented rather than hidden.
  • NVMe passthrough flush — on Linux (NVME_IOCTL_IO_CMD) and Windows (IOCTL_STORAGE_PROTOCOL_COMMAND) when the hardware supports it and the process has the privilege. Transparent fallback to fdatasync / WRITE_THROUGH otherwise.
  • Linux io_uring pathMethod::Direct on Linux routes through io_uring when available (kernel ≥ 5.1, no SECCOMP/AppArmor block), falling back to O_DIRECT + pwrite + fdatasync cleanly.
  • Atomic replace-style writes — every public write API (write, write_copy, write_batch, Batch::commit) uses a temp-file + atomic rename pattern. The target file is either entirely the old payload or entirely the new payload — never torn.
  • Crash-safety verified — per-method crash tests with three kill points (pre-syscall, mid-syscall, post-syscall) and the 100× pre-merge stability protocol.
  • write_copy with metadata preservation — atomic-swap that preserves the target's existing mode (Unix), owner/group (Unix, when permitted), ACLs (Windows), and timestamps (all platforms).
  • Root-scoped handles — bind a Handle to a base directory and reject paths that escape it.
  • Full file and directory CRUD — write, read, append, positioned writes, range reads, truncate, rename, copy, metadata, sync, directory creation/removal, listing, recursive scan, glob find, and recursive count.
  • Batch operations — grouped writes, deletes, and copies through write_batch, delete_batch, copy_batch, and the chainable Batch builder.
  • Async layer — gated behind the async Cargo feature. Every sync method gets an _async sibling backed by tokio::task::spawn_blocking; async batch ops route through the per-handle dispatcher via tokio::sync::oneshot.
  • Configurable group lane — tune batch window, batch size, queue depth, io_uring queue depth, and aligned-buffer-pool size per handle.
  • Quick one-shot API — convenience helpers backed by a lazily initialized default handle for simple cases.
  • Structured error reporting — 18 explicit error variants with stable FS-XXXXX codes for unsupported methods, alignment failures, atomic-replace failures, NVMe passthrough denial, async-runtime requirements, glob-pattern errors, and batch failure position.

 


 

 

What fsys provides today

  • A Handle + Builder model for configuring IO once and reusing it across operations.
  • Five durability methods: Sync, Data, Mmap, Direct (with NVMe passthrough on capable hardware), and Auto.
  • Cross-platform file CRUD: atomic replace-style writes, write_copy (atomic-swap with metadata preservation), reads, appends, deletes, copies, range reads, truncate, rename, metadata, and sync operations.
  • Cross-platform directory CRUD: create, remove, recursive variants, existence checks, listing, recursive scan, glob find, and recursive count.
  • A root-scoped path model so a handle can enforce that all resolved paths stay under a chosen base directory.
  • A convenience quick module for one-shot operations when you do not want to manage a handle directly.
  • A batch API for grouped writes, deletes, and copies via Handle::write_batch, Handle::delete_batch, Handle::copy_batch, and the Batch builder.
  • A per-handle group lane with bounded queueing and configurable batch thresholds for workloads that benefit from grouped dispatch.
  • An optional async layer (feature async) covering every sync method.
  • The fsys::primitive module of canonical durability-primitive strings for runtime observation of the active code path.

Design principles

  • Explicit semantics first. The API should make durability and routing choices visible.
  • Portable without pretending platforms are identical. Linux, macOS, and Windows have different primitives; fsys exposes one model while documenting where fallbacks occur.
  • Low ceremony for the common path. A single Handle should cover most workloads; the quick module exists for one-off use.
  • Predictable failure behavior. Atomic write/replace and batch operations report where failure happened instead of silently smoothing over it.
  • Room to grow. Reserved methods and pipeline internals make it possible to expand into more advanced IO paths without replacing the public model.

When to use fsys

Use fsys when you need one or more of the following:

  • Explicit control over full sync, data-only sync, direct IO, or automatic method selection.
  • Cross-platform file IO behavior that is stricter and more deliberate than std::fs defaults.
  • Atomic replace-style writes for file updates.
  • A handle-scoped root for keeping file activity inside a known subtree.
  • Grouped write/delete/copy submission for higher-throughput batch-style work.

Non-goals

  • High-level filesystem tooling such as watchers, lock orchestration, virtual filesystems, or rich path-manipulation utilities.
  • Replacing std::fs for everyday scripting or application scaffolding.
  • Hiding platform-specific tradeoffs behind vague “fast mode” abstractions.
  • Full async-runtime integration in the core crate.

Status & roadmap

Current state: the public API is feature-complete for everything that will ship at 1.0 — with the single exception of Method::Journal, which is deliberately reserved for 0.7.x. The current release line is 0.6.x.

0.6.0 finished the public surface: the async layer, NVMe passthrough flush on Linux and Windows, completion CRUD methods (write_copy, scan, find, count), Handle::active_durability_primitive() plus the fsys::primitive constants module, and a publication-quality documentation pass across the crate. The 0.5.x line consolidated real hardware probing, the real Method::Mmap implementation, the io_uring path on Linux, and the per-method crash-test harness. Everything from earlier phases (handle/builder, full file/dir CRUD, batch + group lane) is unchanged.

What remains before 1.0:

  • Method::Journal (intent-log durability) — 0.7.x work.
  • A native io_uring async substrate (using io_uring as a true Future-driven primitive instead of spawn_blocking) — 0.7.x.
  • Deep audit, performance certification on real NVMe, full alpha → beta → RC progression.

The roadmap below shows where each phase landed.

  • 0.1.x — [DONE]: Initial setup.
  • 0.2.x — [DONE]: Scaffolding and foundation modules.
  • 0.3.x — [DONE]: Handle, CRUD, metadata, and cross-platform IO core.
  • 0.4.x — [DONE]: Group-lane batching and dispatcher pipeline.
  • 0.5.x — [DONE]: Real hardware probe, Method::Mmap, Method::Direct with io_uring on Linux, per-method crash tests.
  • 0.6.x — [CURRENT]: Async layer, NVMe passthrough, completion CRUD, publication-quality docs.
  • 0.7.x — [NEXT]: Method::Journal, native async io_uring, observability, deep audit.
  • 0.8.x — [BETA]: Public testing and compatibility validation.
  • 0.9.x — [RC]: Release candidate.
  • 1.0.0 — Stable API release.

The roadmap is aspirational, not a schedule. Versions ship when they're right, not when the calendar agrees.

Installation

[dependencies]
fsys = "0.6.0"

To opt into the async layer:

[dependencies]
fsys = { version = "0.6.0", features = ["async"] }

⚠️ The crate is published and usable, but it should still be treated as pre-stable software. Use it in production only if you are comfortable tracking breaking changes before 1.0.0.

Cargo features

Feature Default Pulls in Purpose
async off tokio (rt, rt-multi-thread, sync, macros) _async siblings for every sync method; async batch via tokio::sync::oneshot.
stress off (none) Switches the soak tests in tests/stress.rs from a 60-second validation run to the full 1-hour soak duration. CI nightly enables this; dev iteration leaves it off.
fuzz off (none) Compile-only flag for fuzz instrumentation. The actual fuzz targets live in fuzz/ (separate cargo-fuzz workspace).

Minimum supported Rust version

1.75. The MSRV may be raised in any minor version before 1.0.0. After 1.0.0, MSRV bumps require a minor version bump.

Documentation

Coming Soon

LICENSE

Licensed under the Apache License version 2.0 [ LICENSE-APACHE ], or the MIT License [ LICENSE-MIT ]; otherwise known as the ("License Agreement"); you are permitted to use this software, its source code, documentation, concepts, and any of the associated contents, within the limitations defined by the "License Agreement".