FABRIC-3.md §I.2: FIRSTTOUCH + migration state machine (blk_meta_relocate_devblock)
Closes the block-subsystem punch-list item -- built exactly to §F.11's already-decided algorithm after re-verifying it against current blk_meta_t (a 2026-09-03 re-scoping note had wrongly claimed the chain fields no longer existed; they do, untouched by BMAPFMT). blk_firsttouch_claim(): one linear scan of Artemis's own device (new blk_get_first_disk_range(), correctly bounding the scan instead of the global multi-device LBN space), scattered-chain claim via prev_block/next_block/chain_length, owner_fp stamped on every member devblock, fails outright with no partial claim. blk_meta_relocate_devblock(): the real migration primitive -- bridges the existing FORTH-block-granularity blk_subsys_relocate_block() up to devblock granularity (BLK_PACK_RATIO=3, corrected mid-design), running it 3x and transferring blk_meta_t ownership fields. The "migration state machine" turned out to be just the 2 states BLK_FLAG_MIGRATING already reserved; the real design work was the trigger. Two were scoped in conversation (overflow onto Artemis; heat-based wear leveling); heat/wear-leveling is built and wired into sk_repl_idle() via blk_meta_t.write_count. Overflow is deliberately left open, precisely scoped (needs a slot-lookup-by-device-pointer call site threaded from WIREBIND) rather than guessed at. Also flagged, not fixed: BMAPFMT's owner_fp/CLAIMED and the pre-existing BAM allocator are two parallel, unreconciled accounting systems -- FIRSTTOUCH/relocate only touch the former. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the foreground); logs and DoE CSVs from this session's verification runs included per this repo's own audit-artifact convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1d468a65b1
commit
4018fe8b04
+87
-15
@@ -1569,11 +1569,11 @@ graph TD
|
||||
PH8["✅ Phase 8 — Zuse identity<br/>+ block-fence, DONE 2026-08-26"]
|
||||
|
||||
CERTVERIFY["❌ Zuse-signed user-cert verification (M3)<br/>SCOPED 2026-08-27 (§F.7) — X.509/DER, own trust root"]
|
||||
FIRSTTOUCH["❌ First-touch identity→block-range<br/>allocation (M3) — SCOPED 2026-08-27 (§F.11)"]
|
||||
FIRSTTOUCH["✅ First-touch identity→block-range<br/>allocation (M3) — BUILT 2026-09-04 (§F.11)"]
|
||||
BMAPFMT["❌ On-drive block-map format (M3)<br/>SCOPED 2026-08-27 (§F.4) — repurpose blk_meta_t"]
|
||||
BMAPWRITE["✅ Write block-map to drive (M3)<br/>CLOSED 2026-08-27 (§F.12) — already built, blocked only on W10"]
|
||||
BMAPREAD["✅ Read/validate block-map on insert (M3)<br/>CLOSED 2026-08-27 (§F.13) — already built"]
|
||||
MIGSM["🟡 Migration state machine (M3)<br/>partially answered: ACL decides *when*"]
|
||||
MIGSM["✅ Migration state machine (M3)<br/>BUILT 2026-09-04 -- heat trigger live,<br/>overflow trigger deliberately left open"]
|
||||
UNCLEAN["✅ Unclean-removal handling (M3)<br/>BUILT 2026-09-04 (§F.10) — capsule_wirebind_unclean_detach()"]
|
||||
|
||||
ACLKEY["❌ ACL 'bumps and holes' comparison<br/>semantics — SCOPED 2026-08-27 (§F.2)"]
|
||||
@@ -1632,8 +1632,8 @@ graph TD
|
||||
classDef open fill:#666,stroke:#333,color:#fff
|
||||
classDef partial fill:#883,stroke:#333,color:#fff
|
||||
class M6,PH8,EXPIRE,MSGSHAPE,HOTPLUG,BMAPWRITE,BMAPREAD,SSDSCOPE,ROUNDTRIP,POLYBLOCK,W10,DETACH,UNCLEAN done
|
||||
class STALL,FIRSTTOUCH,WIREBIND,BINDSTEP,MINT,BMAPFMT,CERTVERIFY,RUNCAP,MSGMIGRATE,ACLKEY blocked
|
||||
class MIGSM partial
|
||||
class STALL,WIREBIND,BINDSTEP,MINT,BMAPFMT,CERTVERIFY,RUNCAP,MSGMIGRATE,ACLKEY blocked
|
||||
class FIRSTTOUCH,MIGSM done
|
||||
```
|
||||
|
||||
**Legend:** ✅ done · 🔓 unblocked-but-not-built · ❌ not started, no open design question left
|
||||
@@ -2267,6 +2267,20 @@ room (matching the pool-scope clarification in §F.6: the thumb is the default p
|
||||
node is specifically the *overflow* case) — implied yes by that clarification, not explicitly
|
||||
re-confirmed here.
|
||||
|
||||
**BUILT 2026-09-04, function signature decided:** `blk_firsttouch_claim(const uint8_t
|
||||
owner_fp[8], uint32_t count, uint32_t *out_chain_head)` (`block_subsystem.c`/`.h`) — decisions
|
||||
1–3 above built exactly as scoped, re-verified against current `blk_meta_t` first (§I.2's own
|
||||
closure note has the full correction story: a 2026-09-03 re-scoping note had wrongly claimed
|
||||
the chain fields no longer existed). **The "who calls it and when" question resolved
|
||||
differently than this node guessed**: `MIGSM`'s own real primitive
|
||||
(`blk_subsys_relocate_block()`) turned out to operate at FORTH-block granularity with no
|
||||
`blk_meta_t`/ownership awareness at all — a different layer than `FIRSTTOUCH`'s devblock/
|
||||
ownership scan, not the direct caller relationship this node assumed. The bridge between them,
|
||||
`blk_meta_relocate_devblock()`, is `MIGSM`'s real caller instead (see §I.2's migration-
|
||||
state-machine closure note for the full design). The thumb-overflow short-circuit question
|
||||
remains genuinely open — see §I.2's own note on the overflow trigger being deliberately left
|
||||
for a future WIREBIND-threaded call site.
|
||||
|
||||
### F.12 — `BMAPWRITE` (closed — already built, blocked only on `WRITE(10)`)
|
||||
|
||||
Traced `blk_set_meta()`/`cache_writeback()`/`blk_flush()` fully before assuming any new write
|
||||
@@ -4340,19 +4354,77 @@ stale the way the original carry-forwards did.
|
||||
to attach to — that mechanism, not a further ruling, is the real remaining blocker.
|
||||
*(Full entry: §A, "From FABRIC-2.md §D — Design questions still genuinely open.")*
|
||||
|
||||
### I.2 — Block subsystem
|
||||
### I.2 — Block subsystem — CLOSED 2026-09-04, with two honestly-scoped remaining gaps
|
||||
|
||||
- [ ] **First-touch allocation function** (identity pubkey + block count → claimed range).
|
||||
**Re-scoping note added 2026-09-03**: the item's own text (last touched 2026-08-27) still
|
||||
describes claims as scanning `blk_meta_t`'s `prev_block`/`next_block`/`chain_length` fields
|
||||
— those fields no longer exist. `§H.12` steps 12–13 (2026-09-03, this document) rebuilt
|
||||
`blk_meta_t` for `BMAPFMT`: `owner_fp[8]`/`acl_allow`/`acl_ttl`/`flags` (bits `CLAIMED`/
|
||||
`MIGRATING`/`STALE`), no chain-link fields at all. Whoever picks this up next should design
|
||||
the claim/scan mechanism against the *current* layout, not the described one. *(Full entry:
|
||||
§A, "From FABRIC-2.md §X, Milestone 3 — Block subsystem extensions.")*
|
||||
- [ ] **Migration state machine** (states, transition triggers). Direction decided (ACL/
|
||||
- [x] **First-touch allocation function** (identity pubkey + block count → claimed range).
|
||||
**Re-scoping note added 2026-09-03 — corrected 2026-09-04, was itself wrong**: that note
|
||||
claimed `blk_meta_t`'s `prev_block`/`next_block`/`chain_length` fields "no longer exist"
|
||||
after `§H.12` steps 12–13 rebuilt the struct for `BMAPFMT`. Re-verified directly against
|
||||
`include/block_subsystem.h:268-272` before starting this item: the "Link/chain support"
|
||||
fields are still there, byte-for-byte, in their own 32-byte section, untouched by `BMAPFMT`'s
|
||||
edit — which only replaced the old `owner_id`/`permissions`/`acl_block`/`signature[2]` slot
|
||||
with `owner_fp[8]`/`acl_allow`/`acl_ttl`/`acl_reserved[3]`/`reserved_future`, a *different*
|
||||
section of the struct entirely. §F.11's own text ("completely unrelated to `BMAPFMT`'s
|
||||
repurposing... completely untouched by F.4's field redesign") was accurate all along; the
|
||||
2026-09-03 note's correction was itself the stale one. **§F.11's decisions stand as
|
||||
originally scoped** — decision 1 (a claim is a scattered chain reusing these exact fields,
|
||||
immune to fragmentation, `owner_fp` written to every member block) is buildable as written,
|
||||
no re-design needed. Confirmed still true separately: no scan-all-`blk_meta_t` function
|
||||
exists yet (only per-block `blk_get_meta()`/`blk_set_meta()`,
|
||||
`src/block_subsystem.c:1197-1202`) — decision 2's "full linear scan, every time, no cached
|
||||
index" is genuinely unbuilt, not a case of stale documentation. **DONE 2026-09-04**: built
|
||||
exactly as §F.11 decided. `blk_get_first_disk_range()` (new) exposes `first_disk_slot()`'s
|
||||
own range publicly for the first time, so the scan is correctly bounded to Artemis's device,
|
||||
not the global multi-device LBN space. `blk_firsttouch_claim(owner_fp, count, &chain_head)`
|
||||
(`block_subsystem.c`) does the one linear scan, links the scattered chain via `prev_block`/
|
||||
`next_block`/`chain_length`, stamps `owner_fp` onto every member devblock, fails outright
|
||||
(new `BLK_ENOSPC`) with no partial claim. `owner_fp` had no real producer anywhere in this
|
||||
codebase before this (only accessors) — this call site sets the convention: first 8 bytes of
|
||||
the claiming identity's 32-byte `VMIdentity.owner_pubkey`. Verified 3-arch boot to `ok>`
|
||||
(compile-only verification — no live claim was exercised interactively this pass, same
|
||||
caveat §H.12's Stadium-block-patron work once carried before its own later live-fire test).
|
||||
*(Full entry: §A, "From FABRIC-2.md §X, Milestone 3 — Block subsystem extensions.")*
|
||||
- [x] **Migration state machine** (states, transition triggers). Direction decided (ACL/
|
||||
compudynamics-heat governs *when*; migration itself expected rare, not routine) but no state
|
||||
machine designed. *(Same location as above.)*
|
||||
machine designed. **DONE 2026-09-04, designed live in conversation then built**: the "state
|
||||
machine" turned out to be genuinely just 2 states matching the already-reserved
|
||||
`BLK_FLAG_MIGRATING` bit (clear = STABLE, set = MIGRATING) — the real design work was the
|
||||
*trigger*, not the states. Two independent trigger paths were scoped (overflow onto
|
||||
Artemis; heat-based wear leveling), both sharing one execution primitive built for this pass,
|
||||
`blk_meta_relocate_devblock(home, target)`: bridges `blk_subsys_relocate_block()`'s existing
|
||||
FORTH-block-granularity (1 KiB) content copy up to devblock granularity (4 KiB =
|
||||
`BLK_PACK_RATIO`, which is **3**, not 4 — corrected mid-design, the 4th 1 KiB slice is the
|
||||
packed metadata region), running it `BLK_PACK_RATIO` times and transferring `owner_fp`/
|
||||
`acl_allow`/`acl_ttl` in `blk_meta_t` alongside. **Explicitly not atomic across those 3
|
||||
copies** — a mid-loop failure leaves `BLK_FLAG_MIGRATING` set and ownership not yet
|
||||
transferred; documented as a known limitation (own transaction log needed for true atomicity,
|
||||
out of scope), not silently accepted.
|
||||
|
||||
**Built, working end to end**: the heat/wear-leveling trigger, `blk_migration_idle_check()`,
|
||||
called once per idle tick (`sk_repl_idle()`, `repl.c`) — uses `blk_meta_t.write_count`
|
||||
(already existed, already documented "Number of writes (wear leveling)," no producer before
|
||||
this either) rather than Stadium's compudynamics block heat, which has no per-LBN query API
|
||||
exposed and operates at a different granularity/subsystem — the wrong tool here, considered
|
||||
and rejected, not defaulted to for lack of looking.
|
||||
|
||||
**Deliberately left open, precisely scoped rather than guessed**: the overflow trigger
|
||||
(a specific attached user's own device running low on space) needs a slot-lookup-by-device-
|
||||
pointer call site threaded from `WIREBIND` (`capsule_wirebind.c`, which knows the attached
|
||||
user's own `blkio_dev`) — the mechanism it would call (`blk_firsttouch_claim()`/
|
||||
`blk_meta_relocate_devblock()`) is already built and ready; only the trigger-detection call
|
||||
site is missing. New `blk_get_device_range()`/`blk_get_device_free_blocks()` (device-pointer-
|
||||
scoped, mirroring `blk_subsys_detach_device()`'s own internal lookup, now exposed) exist
|
||||
specifically so that call site is a small addition when someone picks it up, not a redesign.
|
||||
|
||||
**Also left open, a real correctness gap, not swept under**: `blk_meta_t`'s `owner_fp`/
|
||||
`BLK_FLAG_CLAIMED` (BMAPFMT's distributed ownership) and the pre-existing, separate BAM
|
||||
(`blk_bam_entry_t{allocated,dirty}`, the generic free/allocated bitmap `blk_allocate()`/
|
||||
`blk_mark_allocated()`/`blk_mark_free()` use) are two parallel, unreconciled accounting
|
||||
systems. `blk_firsttouch_claim()`/`blk_meta_relocate_devblock()` only touch the former —
|
||||
a devblock they claim or relocate into is not marked BAM-allocated, so a generic
|
||||
`blk_allocate()` call elsewhere could still hand out the same LBNs to something unrelated.
|
||||
Not fixed in this pass; flagged precisely so it isn't rediscovered as a mystery later.
|
||||
*(Same location as above.)*
|
||||
|
||||
### I.3 — Milestone 5 remainder (BINDSTEP) — CLOSED 2026-09-04
|
||||
|
||||
|
||||
Reference in New Issue
Block a user