Provider / volatile storage
ValidatedMemory metadata + blocks
The memory providers are the smallest complete composition: useful for tests, local tools, and a mount-free process that owns its state. They deliberately do not pretend that an acknowledged operation survives process exit. The standalone MemoryFs implementation lives in the separate mount-rs-memfs filesystem crate.
MemoryMetadataStore holds the namespace, inode records, directory entries, block references, revisions, and writer lease in process memory.
MemoryBlockStore owns immutable byte blocks separately from metadata. The two handles can be composed independently throughChunkedFs.
Storage anatomy
Follow one file through both planes.
A mount-rs namespace stores names, attributes, directory entries, layouts, and block references. The bytes stay in the independent block plane. The example below is illustrative; the provider-specific schema, keys, and prefixes are the inspectable contract.
inode 42 · size 8,192NodeMetadata → NodeData::File(FileLayout)BlockId → raw bytesNamespace {
nodes[42] = NodeMetadata {
stats: { ino: 42, size: 8192, mode: regular },
data: File(FileLayout {
chunker: { algorithm: "fixed-size", version: 1, chunk_size: 4096 },
extents: [
{ file_offset: 0, block: "b012...", block_offset: 0, length: 4096 },
{ file_offset: 4096, block: "bfed...", block_offset: 0, length: 4096 }
]
})
}
}
BlockId "b012..." -> [4 KiB raw bytes]
BlockId "bfed..." -> [4 KiB raw bytes]Volatile process storage
Process heap maps
The same logical split exists, but the records are Rust structs behind Arc<Mutex<...>> rather than persisted keys.
metadata.revisionu64 → 7integer · namespace CAS revisionmetadata.namespaceOption<Namespace>typed struct · attributes, directory entries, layouts, and block IDsmetadata.lease{ owner: "writer-a", fence: 3, expires_at_ms: ... }typed struct · single writer leasemetadata.versionsBTreeMap<VersionId, VersionInfo>map · published version graphblocks["b0123..."][raw bytes]BTreeMap<BlockId, Vec<u8>> · immutable block planeMemory provider state is reachable only through the live process handles. Export it explicitly before treating any bytes as a backup.
Core contract and local differential evidence; volatile by design. Core tests, memory provider tests, and seeded oracle traces cover the in-process contract. That evidence is intentionally narrower than crash recovery or production durability.
Layout and chunking
Files use the persisted fixed-size chunk configuration and metadata references to block IDs. In memory, both the layout and bytes disappear when the provider state is dropped; there is no on-disk object naming convention to preserve.
Durability and consistency
The store provides an in-process writer lease, monotonic fence, revision CAS, and a successful no-op flush barrier. durable() is always false, so combining memory with a durable provider remains a volatile filesystem.
Across every split-store composition, new blocks are flushed before metadata references are published. A provider acknowledgement is not automatically a power-loss or distributed-locking guarantee.
Inspect the live process state
let metadata = MemoryMetadataStore::new();
let blocks = MemoryBlockStore::new();
let loaded = metadata.load().await?;
let bytes = blocks.get(&block_id).await?;
println!("revision={} bytes={}", loaded.revision, bytes.len());Credentials, cleanup, and safe operations
No credentials or external service are involved. Drop the filesystem or await its shutdown() method; cleanup is process-local. Do not describe a memory snapshot as a backup unless the caller has explicitly exported and stored it elsewhere.
Current limits
Memory is not crash-persistent, cross-process, or a replacement for a durable database/object store. There is no raw file, SQL table, or object prefix for an operator to inspect after the process exits.