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.rsimplements 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
controlcommands and read/write operations via the same contract surface. - Backends like Little FS map these traits to concrete storage engines.
Dependency model
- Depends on Task, Users, Shared, Synchronization, and Internationalization.
- Upstream consumers include virtual_file_system, executable, authentication, and drivers.
Failure semantics
- Uniform
file_system::Errorresult 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::Pendingmeans 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
*_syncadapters 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.
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
libraries/file_system/src/operations/base.rs— device polling and sync boundary.libraries/file_system/src/operations/file_system.rs— backend trait and conformance tests.libraries/file_system/src/fundamentals/path/path_reference.rs— borrowed path rules.libraries/file_system/src/devices/memory_device.rs— test block storage.file_system::FileSystemOperations— backend contract.