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
|
## 8. Storage
|
||||||
|
|
||||||
**Proposal.** A disk is a device on a port. Asking for a block is a
|
**Ruled 2026-10-06** (Captain Bob), in the order the rulings were given.
|
||||||
message to it — read block *n*, or write block *n* with 1024 characters —
|
What is marked *step 6* is built there; what is marked *step 6a* is ruled
|
||||||
and the answer is a message back; a block is exactly the most a message
|
and waits for that step.
|
||||||
carries. Under v3's one block-number space, each device has its own range
|
|
||||||
of numbers.
|
|
||||||
|
|
||||||
- A node wired to a disk asks it directly.
|
### 8.1 The rulings
|
||||||
- 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.
|
|
||||||
|
|
||||||
Who may have which block is the block card's, decided where the disk is,
|
1. **A disk is a device on a port that speaks messages.** Asking for a
|
||||||
under the identity in the message's ACL tag (`V3-PARITY.md` 1d). Not
|
block is a message — read block *n*, or write block *n* with 1024
|
||||||
checked in this step.
|
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
|
## 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.
|
`BYE`, and nothing it asks is honoured, as ruled.
|
||||||
- The suite now takes about four minutes, eight under the sanitizers:
|
- The suite now takes about four minutes, eight under the sanitizers:
|
||||||
five POSTs.
|
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
|
7. **A second unit; scaling while running; sleep, wake and kill by
|
||||||
command.**
|
command.**
|
||||||
8. **The hosted product is the five nodes**, on three ISAs: acceptance 1
|
8. **The hosted product is the five nodes**, on three ISAs: acceptance 1
|
||||||
|
|||||||
Reference in New Issue
Block a user