volume-manager: the flip — fat is spawned, confined, and handed its channel (V3b)
The load-bearing step. The FAT service stops acquiring its own volume: the volume manager spawns it (per volume), defines its partition range on the storage driver BEFORE it runs, and answers its startup hello with the range-confined block channel over a new volume-manager protocol. fat never finds its storage by name and never sees the whole device — establishment by lineage, one layer up from the driver tree. - New library/protocol/volume-manager: one verb, hello(volume-id) -> the block channel as the reply capability (the P0 reply-cap path). - The volume manager becomes the confinement CONTROLLER: it defines the first range on usb-storage, so no other party can confine a filesystem. It supervises the filesystems it spawns and respawns one on death (the reap- and-rebuild the device manager proved, one layer up). - fat: drops acquireVolume(device-manager); hellos the volume manager for its channel; reads its volume id from argv[1]. main takes process.Init now. - init.csv no longer spawns fat (the volume manager does); protocol.csv rewires fat to be supervised by the volume manager (bind vfs, open volume-manager) and drops fat open device-manager. - The block-range fixture boots registry + device-manager only (not the full tree), so the volume manager is absent and the fixture stays the sole confinement definer — otherwise the volume manager would take the controller first and refuse it. Verified end to end (VM probes -> spawns fat -> confines it -> hands over the channel -> fat mounts) and neutral: 18/18 across the fat family, logging, shutdown, both IOMMU variants, usb restart, vfs, conformance, confinement.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
//! The volume-manager protocol (docs/file-system-development/storage-architecture.md):
|
||||
//! what a filesystem service says to the volume manager over
|
||||
//! `/protocol/volume-manager`. Defined through the envelope, so every packet
|
||||
//! begins with the folded `Header`.
|
||||
//!
|
||||
//! One verb. A filesystem the volume manager spawned announces itself with the
|
||||
//! volume id it was given as argv[1] (folded into `Header.target`); the reply
|
||||
//! carries that volume's block channel — already range-confined to the
|
||||
//! filesystem's badge — as the call's returned capability. The filesystem never
|
||||
//! finds its storage by name and never sees the whole device; establishment is
|
||||
//! by lineage, exactly as a driver reaches its controller (communication.md
|
||||
//! "Establishment: two planes"). No channel in the reply means the volume is not
|
||||
//! ready yet — retryable, never a verdict.
|
||||
|
||||
const envelope = @import("envelope");
|
||||
|
||||
pub const version: u16 = 1;
|
||||
|
||||
/// The filesystem's handshake. Carries only its protocol version; the volume it
|
||||
/// serves is `Header.target`, and the block channel it needs comes back as the
|
||||
/// reply's capability.
|
||||
pub const Hello = extern struct {
|
||||
version: u16 = version,
|
||||
_padding: u16 = 0,
|
||||
};
|
||||
|
||||
pub const Protocol = envelope.Define(.{
|
||||
.name = "volume-manager",
|
||||
.version = 1,
|
||||
.operations = &.{
|
||||
.{ .name = "hello", .request = Hello },
|
||||
},
|
||||
});
|
||||
|
||||
pub const Operation = Protocol.Operation;
|
||||
pub const message_maximum: usize = Protocol.message_maximum;
|
||||
Reference in New Issue
Block a user