docs(v4.0.0): storage -- ruled: a static view over a shifting chain, the kernel's mapper, private drives
MESH.md section 8 is no longer a proposal. Ten rulings (Captain Bob, 2026-10-06), the design of step 6 as approved, what it leaves out, and one case left open. Step 6a is added for chains that change while running; its acceptance is still to be approved. V3-PARITY.md 1d stands: the mapper is the kernel's block subsystem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
348eed7fa1
commit
8cacfb663c
+151
-15
@@ -270,22 +270,144 @@ kernel-Hermes's work in v3 and is not decided for the mesh.
|
||||
|
||||
## 8. Storage
|
||||
|
||||
**Proposal.** A disk is a device on a port. Asking for a block is a
|
||||
message to it — read block *n*, or write block *n* with 1024 characters —
|
||||
and the answer is a message back; a block is exactly the most a message
|
||||
carries. Under v3's one block-number space, each device has its own range
|
||||
of numbers.
|
||||
**Ruled 2026-10-06** (Captain Bob), in the order the rulings were given.
|
||||
What is marked *step 6* is built there; what is marked *step 6a* is ruled
|
||||
and waits for that step.
|
||||
|
||||
- A node wired to a disk asks it directly.
|
||||
- A node not wired to one asks through the node that is: the message is
|
||||
forwarded like any other. So the common SSD is shared by every node that
|
||||
has a way to the node that holds it.
|
||||
- A node with its own drive has that device on one of its own ports.
|
||||
- A node with no way to any disk has no storage, and `BLOCK` says so.
|
||||
### 8.1 The rulings
|
||||
|
||||
Who may have which block is the block card's, decided where the disk is,
|
||||
under the identity in the message's ACL tag (`V3-PARITY.md` 1d). Not
|
||||
checked in this step.
|
||||
1. **A disk is a device on a port that speaks messages.** Asking for a
|
||||
block is a message — read block *n*, or write block *n* with 1024
|
||||
characters — and the answer is a message back.
|
||||
2. **A node only ever asks for a block by number, and knows nothing else.**
|
||||
It has one way to storage, as it has routes: a port, or nothing. This
|
||||
replaces the earlier proposal that a node be told ranges of block
|
||||
numbers. Nobody chooses ranges.
|
||||
3. **Two numbers.** A logical block number is what `BLOCK n` and capsules
|
||||
use. A physical block number is a place on a real device. A mapper
|
||||
stands between them.
|
||||
4. **The view is static; reality shifts to keep it so.** A logical number
|
||||
always means the same block. Devices chain one after another in physical
|
||||
space, and that chain changes as devices come and go; the mapper moves
|
||||
data and changes its map so that the logical view does not change. All
|
||||
the user sees change is how much storage there is.
|
||||
5. **One metadata format for every block device** — a cloud store, a swap
|
||||
file, an SSD, a USB drive, a thumbdrive, and any other within reason.
|
||||
It is v3's (`v3/include/block_subsystem.h`): the `STFR` version 2 header,
|
||||
the allocation map, the relocation table, and a card for every block
|
||||
(`blk_meta_t`). A disk v3 formatted reads in v4.
|
||||
6. **Plus an identity.** *(step 6a)* Two fields are added in the header's
|
||||
spare space, as v3 added its relocation and fence fields: the device's
|
||||
identity, and the identity of the chain it belongs to. A v3 disk reads
|
||||
zero there: not yet given one. With them a device is known when it
|
||||
returns, wherever it is plugged in.
|
||||
7. **The mapper is the kernel's.** `V3-PARITY.md` section 1d stands: the
|
||||
device chain, the metadata, first-touch claim, ACL, migration and the
|
||||
Stadium touch stay in the kernel's block subsystem, which is v3's C
|
||||
code. What a node finds on a storage port is that subsystem, speaking
|
||||
messages in logical block numbers. (The mapper was first ruled to be a
|
||||
capsule on the node that holds the devices; that contradicted 1d, and on
|
||||
being shown the contradiction Captain Bob ruled that 1d stands.)
|
||||
8. **A node's own drive is private.** It is a second chain in the kernel,
|
||||
wired to that node's port, and its blocks are nobody else's. A node may
|
||||
have it in addition to the common store or instead of it.
|
||||
9. **Common from the bottom up, private from the top down.** A block of the
|
||||
common store has the same logical number on every node that shares it,
|
||||
from 2048 upward. A node's private blocks are numbered from the top of
|
||||
the number space downward: private block *k* is logical number
|
||||
2^32 - 1 - *k*, v3's block numbers being 32 bits. The two meet only if
|
||||
the whole space is used up.
|
||||
10. **A device leaves by being asked for.** *(step 6a)* Asked to release a
|
||||
device, the mapper moves its blocks onto the devices that remain and
|
||||
then says it may be pulled; if there is no room, the release is refused
|
||||
with a message. A device pulled without asking leaves holes: its
|
||||
logical numbers stay claimed and answer "no storage" until it returns,
|
||||
is known by its identity, and its blocks are at the same numbers again.
|
||||
|
||||
### 8.2 What a node does *(step 6)*
|
||||
|
||||
`BLOCK`, `BUFFER`, `UPDATE` and `SAVE-BUFFERS` keep their two buffers and
|
||||
their FORTH-79 behaviour. The one word beneath them in
|
||||
`v4/capsule/blocks.v4` that read or wrote a block by storing to four
|
||||
registers sends a message and waits for the answer instead.
|
||||
|
||||
- A node wired to storage writes the message to that port.
|
||||
- A node that is not sends the same message toward the node that is, and
|
||||
it is passed on like any other (section 7).
|
||||
- A node with no way to storage has none: `BLOCK` is an error with a
|
||||
message, and the node is back at its prompt.
|
||||
|
||||
The four storage registers and `v4_node_storage_attach` go from the engine.
|
||||
|
||||
### 8.3 The messages *(step 6)*
|
||||
|
||||
Four types, beside text, output and done (section 6):
|
||||
|
||||
| Type | Payload | Answered by |
|
||||
|---|---|---|
|
||||
| Block read | the block number, one word | Block data, or Block done with an error |
|
||||
| Block write | the block number, one word; a Block data message follows it | Block done |
|
||||
| Block data | 1024 characters | |
|
||||
| Block done | one word: it worked, there is no storage, or it was refused | |
|
||||
|
||||
A write is two messages because a block is exactly the most a message
|
||||
carries, so the number cannot go with the data. Whatever answers pairs the
|
||||
two by who sent them.
|
||||
|
||||
### 8.4 What is on a storage port *(step 6)*
|
||||
|
||||
A device (4.3), in `v4/system/storage.c`, which the hosted and the
|
||||
bare-metal builds share as they share `boot.c`. It speaks the messages of
|
||||
8.3 and asks v3's block subsystem (`v3/src/block_subsystem.c`) for every
|
||||
block. The engine (`v4/src`) knows nothing of it.
|
||||
|
||||
- v3's code does what it does: header, allocation map, block cards,
|
||||
relocation, three blocks and their cards to a 4 KiB device block.
|
||||
- The devices beneath are v3's own back ends: RAM and a file when hosted,
|
||||
the virtio disk on bare metal.
|
||||
- Blocks 0 to 2047 are the chain's fast RAM, as in v3; nodes that share
|
||||
the common store share those too.
|
||||
- The device holds a **view**: the common chain, or a private chain, or
|
||||
both. A number at the top of the space (ruling 9) is the private
|
||||
chain's; any other is the common chain's; a number in a chain the view
|
||||
does not have is "no storage".
|
||||
|
||||
**A change to v3's C.** Its block subsystem is one global chain. For a
|
||||
second chain its state becomes something there can be two of. The change
|
||||
is mechanical and the one chain v3 uses behaves as it did. (Approved.)
|
||||
|
||||
Found 2026-10-06 and not yet ruled: `blk_subsys_init` must be given a v3
|
||||
`VM`, and refuses without one, though the subsystem stores it and never
|
||||
uses it (`block_subsystem.c` line 651 is its only mention). The hosted v4
|
||||
system has no v3 `VM` to give. The same change would have to take that
|
||||
argument away, which also changes the kernel's one call of it
|
||||
(`kernel/src/capsule/capsule_loader.c`).
|
||||
|
||||
**On bare metal** the lone node's storage port fronts the kernel's real
|
||||
chain — RAM, the ramdrive and the virtio disk — in place of the RAM array
|
||||
`kernel/src/v4/sk_v4.c` gives it today. (Approved.) Found 2026-10-06:
|
||||
`kernel_main.c` starts the v4 node (line 523) before it sets that chain up
|
||||
(lines 620 to 668), and the v4 node never returns, so under `STARFORTH_V4`
|
||||
the chain does not exist today. Step 6 has the kernel set it up before the
|
||||
node starts.
|
||||
|
||||
### 8.5 Not in step 6
|
||||
|
||||
- **Who may have which block is not checked.** First-touch claim, the block
|
||||
card's ACL and the Stadium touch need the node's identity, which is the
|
||||
message's ACL tag (`V3-PARITY.md` 1d). Blocks are read and written
|
||||
through v3's subsystem with nobody's claim on them. Not as intended yet.
|
||||
- **Chains of more than one device, identities, release and holes** are
|
||||
step 6a.
|
||||
- **Cloud stores and real USB drives** wait for their drivers. The format
|
||||
and the messages already fit them.
|
||||
|
||||
### 8.6 Open
|
||||
|
||||
A node that starts with only its own drive and later gains a way to the
|
||||
common store. With no common store, its blocks from 2048 upward, a
|
||||
capsule's among them, can only be on its own drive; when the common store
|
||||
appears those numbers are claimed twice. Not ruled.
|
||||
|
||||
## 9. Birth, and Hera
|
||||
|
||||
@@ -476,7 +598,21 @@ Each is tested, committed and pushed before the next.
|
||||
`BYE`, and nothing it asks is honoured, as ruled.
|
||||
- The suite now takes about four minutes, eight under the sanitizers:
|
||||
five POSTs.
|
||||
6. **Storage (section 8).**
|
||||
6. **Storage (section 8): the disk speaks messages, the kernel's mapper
|
||||
answers, private drives.** Sections 8.2 to 8.4. Tests: a node reads and
|
||||
writes blocks through a port, and a disk image v3's code formatted
|
||||
reads back; in the unit of five, one outer node writes a block and
|
||||
another reads it, one uses a drive of its own at numbers from the top
|
||||
down, and one has no way to storage and `BLOCK` on it is an error with
|
||||
a message (acceptance 3); POST 538 of 538 with `blocks.v4` changed, at
|
||||
both widths and under the sanitizers; `hosted-check`; the three
|
||||
bare-metal boots.
|
||||
|
||||
**6a. Storage that changes while running.** Rulings 6 and 10 of
|
||||
section 8.1: chains of several devices, the device and chain
|
||||
identities, a device joining at the end and known when it returns,
|
||||
release by asking, holes. Its acceptance is to be approved before it is
|
||||
built.
|
||||
7. **A second unit; scaling while running; sleep, wake and kill by
|
||||
command.**
|
||||
8. **The hosted product is the five nodes**, on three ISAs: acceptance 1
|
||||
|
||||
Reference in New Issue
Block a user