Skip to content

File system ​

The file_system crate is the architectural contract layer for storage nodes, files, directories, and device endpoints.

Role ​

  • Defines fundamental types (Path, flags, permissions, metadata, errors, identifiers).
  • Defines operation traits consumed by VFS and implemented by concrete backends/devices.
  • Provides reusable helpers for memory devices, partitions, and MBR handling.

Boundaries ​

  • In scope: trait contracts and shared semantics for file/device operations.
  • Out of scope: global namespace mounting/orchestration (handled by Virtual file system).

Internal structure ​

  • fundamentals/: path, identifiers, permissions, statistics, flags, entry/type primitives.
  • operations/: core trait families (FileSystemOperations, BaseOperations, DirectoryOperations, ...).
  • devices/: character/block device abstractions and direct operations.
  • mbr/: partition tables and partition helpers; devices/partition_device.rs implements partition-device access.
  • devices/memory_device.rs: in-memory block device implementation.

Runtime interaction ​

  • VFS calls file-system and device traits through dynamic dispatch.
  • Device nodes expose control commands and read/write operations via the same contract surface.
  • Backends like Little FS map these traits to concrete storage engines.

Dependency model ​

Failure semantics ​

  • Uniform file_system::Error result model across traits.
  • Unsupported operations are explicit (UnsupportedOperation), allowing capability probing by callers.
  • Backend-specific failures are expected to be translated into this crate's error domain.

Extension points ​

  • Add new backend crates by implementing the operation traits.
  • Extend control-command families while preserving command identifiers for compatibility.
  • Add helper devices/partition utilities without changing core trait contracts.

Contract vs implementation ​

  • Contract: typed trait and data-model surface for file and device operations.
  • Current implementation: includes reusable helpers (MemoryDevice, MBR/partition utilities) but delegates namespace-level behavior to VFS.

Limitations and trade-offs ​

  • Intentionally broad contract surface increases flexibility, but requires careful implementer conformance.
  • Policy decisions (mount precedence, path traversal context, async scheduling) live outside this crate.

Operation contracts and wake-up semantics ​

FileSystemOperations extends FileOperations, DirectoryOperations and MountOperations; a concrete backend implements path lookup/create/remove/rename and attribute access without assuming a global namespace. The VFS owns mounts, caller identity, path routing and authorization; a standalone FileSystemOperations backend does not.

The device side supports both contextual BaseOperations (per-open Context) and direct devices, plus typed control commands. BaseOperations::read, write, flush and control return Poll<file_system::Result<T>>:

  • Poll::Pending means the backend has registered a race-free waker and will signal readiness. It must not retain pointers to the caller's buffers or task context.
  • Poll::Ready(Err(Error::RessourceBusy)) is an immediate busy failure, not a request for the caller to spin.
  • Synchronous *_sync adapters make a single attempt; if the operation would be pending they cancel the registration and return a busy error.
  • Short reads/writes are permitted. Callers must not assume a successful result consumes the entire buffer.

The ready(|| ...) helper wraps a synchronous operation into Poll::Ready exactly once, without a hidden retry loop.

Metadata capability negotiation ​

FileSystemOperations::writable_attributes() reports which AttributeFlags can be stored by the backend. get_attributes only sets requested fields it can actually supply, and must not invent data to satisfy a mask. set_attributes must reject unsupported requested attributes before modifying supported fields. A later I/O failure may still leave earlier supported attributes changed: it does not guarantee transactional rollback.

Path is a lightweight borrowed, no_std path type, while PathOwned owns its string. Permission flags, user/group identifiers, timestamp attributes and item statistics are shared across backends; they should not be reinterpreted in a driver-specific ABI.

Implementer checklist and tests ​

A new backend should validate path operations; propagate UnsupportedOperation rather than silently succeeding; maintain per-open Context state; support appropriate Poll/Waker cancellation; implement consistent attribute masks; and document geometry, concurrency and unmount constraints. The generic file-system tests in operations/file_system.rs can exercise CRUD, rename, directory iteration, positioned I/O, attributes and invalid-path handling.

rust
use file_system::{Path, PathOwned};
let root = Path::from_str("/data");
let item: PathOwned = root.join(Path::from_str("config.json")).unwrap();
assert_eq!(item.as_str(), "/data/config.json");

Source and API references ​

References ​