Implements the PDF's Package 3 with new code:
- path: bijective POSIX path <-> Czyx mapping (/c001/z002/y003/x004).
Axis-letter + 3-digit zero-padded canonical names so lexical order equals
numeric order and each coordinate has exactly one spelling. Inode IS the
packed u32 coordinate — no inode side table.
- nullspace: the PDF's 'use Null cubes for ACLs, xattrs, journaling, volume
metadata', with the Z-plane allocation fixed and documented (Z=1 volume,
Z=2 ACL, Z=3 xattr, Z=4 journal ring). ACL/xattr tables are FNV
hash-bucketed with exact-match resolution inside the bucket, because 4
axes of subject cannot injectively mirror into 2 axes of Null space.
Journal is a bounded ring; wraps are detectable via a monotonic counter.
- vfs: the whole filesystem, kernel-free and unit-testable — lookup,
readdir, create/read/write/truncate/unlink, mkdir/rmdir, ACL enforcement,
xattrs, journaling, POSIX errno mapping.
- fuse (feature 'mount'): thin kernel adapter, zero TTL (the store is
writable out-of-band, so cached metadata would go stale).
- cubestore: added the PDF's 'optional scanning primitives' (keys,
scan_prefix) and the Package 2 association API (associate, linked_to)
that cubefs needs for directory listings.
Two defects were found by LIVE MOUNT testing and fixed, not by unit tests:
1. mkdir succeeded then the kernel's revalidating lookup returned ENOENT,
so 'mkdir -p' could never reach depth 4. Directories were purely
inferred from records, making an empty directory unrepresentable. Fixed
with an explicit Null-space directory marker; rmdir removes it; readdir
merges markers in. 5 regression tests added.
2. Multi-user ACL behaviour was untestable because the mount lacked
AllowOther — the kernel returned EACCES at the mountpoint before any
request reached us. Added --allow-other.
Verified: 58 unit tests pass; clippy clean; live mount exercised with cat,
echo, dd, truncate, cp, chmod, chown, getfattr/setfattr, mkdir -p, rmdir,
find, a 200-record write loop, and cross-user reads/writes as luulu.
52 lines
2.3 KiB
Rust
52 lines
2.3 KiB
Rust
//! CUBELinux-2 Package 3 — `cubefs`: a POSIX namespace over CZYX.
|
|
//!
|
|
//! Built NEW from the PDF spec (Package 3, p. "cubefs (filesystem or virtual
|
|
//! FS)"). Not recycled from the prior `/home/CUBELinux` build, which had no
|
|
//! filesystem layer at all.
|
|
//!
|
|
//! # What the PDF asks for
|
|
//!
|
|
//! > Map C/Z/Y/X ranges to top-level directories (C), subdirs (Z,Y) and files
|
|
//! > (X), or keep the 4-D API but expose FUSE hooks for POSIX compatibility.
|
|
//! > Use Null cubes/rows for: ACLs, extended attributes, journaling, volume
|
|
//! > metadata.
|
|
//!
|
|
//! # Structure of this crate
|
|
//!
|
|
//! * [`path`] — the pure, dependency-free bijection between POSIX paths and
|
|
//! [`Czyx`] coordinates. This is the part that must be provably correct, so
|
|
//! it is testable without a kernel mount.
|
|
//! * [`nullspace`] — the Null-cube control plane: ACLs, xattrs, the journal,
|
|
//! and volume metadata, each pinned to a documented `C=0` sub-cube.
|
|
//! * [`vfs`] — the backend-agnostic filesystem operations (lookup, readdir,
|
|
//! read, write, getattr, xattr, ACL check) expressed over a [`CubeStore`].
|
|
//! * `fuse` (feature `mount`) — the thin adapter that translates kernel FUSE
|
|
//! calls into [`vfs`] calls. Feature-gated so the logic above builds and
|
|
//! tests anywhere.
|
|
//!
|
|
//! # Decision: why a bijection and not an inode table
|
|
//!
|
|
//! A conventional FUSE filesystem allocates opaque inode numbers and keeps a
|
|
//! side table mapping inode -> object. CUBELinux's whole premise is that the
|
|
//! coordinate *is* the address, so allocating a second, unrelated identifier
|
|
//! space would reintroduce exactly the indirection the design removes.
|
|
//! Instead the inode number IS the packed `u32` coordinate (widened to u64),
|
|
//! so `ino <-> Czyx` is total, stateless, and needs no table. The FUSE root
|
|
//! inode is required by the kernel to be 1, and `Czyx::unpack_u32(1)` is
|
|
//! `(0,0,0,1)` — a Null cube, never a user record — so the reservation costs
|
|
//! us no addressable user space. See [`path::ino_to_czyx`].
|
|
|
|
#![forbid(unsafe_code)]
|
|
#![warn(missing_docs)]
|
|
|
|
pub mod nullspace;
|
|
pub mod path;
|
|
pub mod vfs;
|
|
|
|
#[cfg(feature = "mount")]
|
|
pub mod fuse;
|
|
|
|
pub use nullspace::{Acl, JournalEntry, JournalOp, NullSpace, VolumeMeta};
|
|
pub use path::{czyx_to_ino, ino_to_czyx, parse_path, render_path, PathError, ROOT_INO};
|
|
pub use vfs::{Attr, CubeFs, FsError, Kind};
|