====== Lyx OS – IOFS: Island & Ocean File System ======
IOFS ist das native Dateisystem von Lyx OS. Es ersetzt FAT32 als primären Speicher und ist von Grund auf für drei Anforderungen gebaut: **Zero-Load-Ausführung** (LBF-Binaries laufen direkt aus dem Speicher, ohne Kopieren), **graphbasierte Abhängigkeitsverwaltung** (Pages sind Knoten, Abhängigkeiten sind typisierte Kanten) und **semantische Suche** (jede Page kann mit Embeddings annotiert werden).
→ [[lyxos:lbf|LBF-Binärformat]] · [[lyxos:syscalls|Syscall-ABI 0x0C00]] · [[lyxos:architektur|Architektur]] · [[lyxos:start|Übersicht]]
----
===== 1. Die Metapher: Ocean, Islands, Pages =====
┌──────────────────────────────────────────────────────────────┐
│ OCEAN (gesamtes Block-Device) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Island "system" │ │ Island "tools" │ ... │
│ │ │ │ │ │
│ │ Page 0x0001 │ │ Page 0x4A01 │ │
│ │ Page 0x0002 ────┼──┼─► Page 0x4A02 │ (Graph-Kante) │
│ │ ... │ │ ... │ │
│ └──────────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────┘
^ Begriff ^ Bedeutung ^
| **Ocean** | Das gesamte Block-Device. Enthält alle Islands als logische Namensräume. |
| **Island** | Benannter Container für zusammengehörige Pages, z.B. ''system'', ''tools'', ''ai-models''. Entspricht grob einem Dateisystem-Volume oder einer Datenbank. |
| **Page** | Kleinste Adressierungseinheit: exakt **4096 Bytes**. Jede Page trägt einen 32-Byte-Header mit Typ, CRC32C-Prüfsumme und LPID. |
| **LPID** | *Logical Page ID* — eine 64-Bit-Kennung, die eine Page eindeutig im Ocean identifiziert. Entspricht dem logischen Block-Slot (LBA-Block). |
----
===== 2. Page-Aufbau =====
Jede IOFS-Page ist exakt **4096 Bytes** groß. Der Page-Header belegt die ersten **64 Bytes** (0x00–0x3F), das Payload beginnt bei Offset **0x40**:
Offset Größe Feld Beschreibung
────── ───── ──────────────── ─────────────────────────────────────────────
0x0000 4 magic "LYX!" (0x4C 0x59 0x58 0x21)
0x0004 1 type Page-Typ (IOFS_TYPE_*)
0x0005 1 flags Page-Flags (IOFS_FLAG_*)
0x0006 2 edge_offset (LE) Byte-Offset der Kanten-Liste in der Page (0x0040 = kein Kantenblock)
0x0008 8 lpid (LE) Logical Page ID dieser Page
0x0010 2 payload_size (LE) Größe der Nutzdaten in Bytes (max. 4032)
0x0012 2 (reserviert) Muss 0 sein
0x0014 4 crc32c (LE) CRC32C-Castagnoli über die gesamte 4096-Byte-Page (Feld beim Berechnen auf 0 gesetzt)
0x0018 8 cont_lpid (LE) Continuation-LPID (0 = keine Fortsetzung; für Pages > 4032 Bytes)
0x0020 32 (reserviert) Muss 0 sein
0x0040 4032 payload Nutzdaten (ab Offset 64)
==== Page-Typen ====
^ Wert ^ Konstante ^ Beschreibung ^
| 1 | ''IOFS_TYPE_META'' | Metadaten-Page (Verzeichnis, Root-Node, Index-Segmente) |
| 2 | ''IOFS_TYPE_DATA'' | Allgemeine Nutzdaten (Datei-Inhalt, KV-Cache, Embeddings) |
| 3 | ''IOFS_TYPE_EMBED'' | Embedding-Vektor-Page (KI-Subsystem, M7+) |
| 4 | ''IOFS_TYPE_EDGE_LIST'' | Kanten-Listen-Page (WP05, Graph-Layer) |
| 5 | ''IOFS_TYPE_NAME_STORE'' | Name-Store-Page (WP07, Named Nodes, LPID=2) |
con IOFS_TYPE_META: int64 := 1;
con IOFS_TYPE_DATA: int64 := 2;
con IOFS_TYPE_EMBED: int64 := 3;
con IOFS_TYPE_EDGE_LIST: int64 := 4; // WP05
con IOFS_TYPE_NAME_STORE: int64 := 5; // WP07
==== Page-Flags ====
^ Wert ^ Konstante ^ Beschreibung ^
| 1 | ''IOFS_FLAG_IMMUTABLE'' | Page darf nach dem Schreiben nicht verändert werden (z.B. Root-Node) |
| 2 | ''IOFS_FLAG_EPHEMERAL'' | Page gilt als temporär und kann beim nächsten Kompaktierungszyklus entfernt werden |
con IOFS_FLAG_IMMUTABLE: int64 := 1;
con IOFS_FLAG_EPHEMERAL: int64 := 2;
> **Unterscheidung IOFS-Page vs. LBF-Genesis:** Beide tragen ''LYX!'' an Byte 0. Unterscheidung erfolgt über Byte ''0x0004'': LBF-Genesis hat dort die ''format_version'' (0x01 = v1.0, 0x02 = v1.1); IOFS-Pages haben dort ''IOFS_TYPE_META'' (1) bis ''IOFS_TYPE_EMBED'' (3) — semantisch gleiche Werte, aber im Context (Superblock vorhanden = IOFS-Volume) eindeutig interpretierbar.
----
===== 3. LIP-Adressierung: LPID → LBA =====
Die Kernleistung von IOFS ist die **O(1)-Übersetzung** eines LPIDs in eine physische LBA (Logical Block Address). Der Kernel hält eine kompakte In-Memory-Tabelle, die **LIP-Tabelle** (*Logical Island Page*):
lip_get(lpid) → lba O(1) — direkter Array-Zugriff
lba × 4096 → Byte-Offset auf dem Block-Device
Im Zero-Load-Modus (→ [[lyxos:lbf|LBF-Format, Abschnitt 6]]) trägt der Kernel diese LBAs direkt als physische Adressen in die CPU-Page-Tables (CR3) ein. Die CPU greift auf LBF-Code-Pages zu, als wären sie RAM — ohne eine einzige Kopie.
// Kernel-internes API (nicht als Syscall exponiert):
var lba: int64 := lip_get(block_lpid);
// pte.phys_addr = lba × 4096
// pte.flags = PROT_READ | PROT_EXEC (für .text-Pages)
----
===== 4. Graph-Kanten =====
Jede Page kann als Knoten im Kernel-Wissensgraphen (→ Syscalls 0x080F–0x0812) registriert werden. IOFS definiert zwei eingebaute Kanten-Typen für die LBF-Integration:
^ Kanten-Typ ^ Konstante ^ Bedeutung ^
| ''0xB001'' | ''IOFS_EDGE_LBF_CHAIN'' | Genesis-Block → Block 1 → Block 2 → ... (Code-Seiten-Kette) |
| ''0xD001'' | ''IOFS_EDGE_LBF_DEP'' | Genesis-Block → Dependency-Genesis (Bibliotheks-Abhängigkeit) |
con IOFS_EDGE_LBF_CHAIN : int64 := 0xB001
con IOFS_EDGE_LBF_DEP : int64 := 0xD001
Weitere Kanten-Typen werden von höheren Schichten vergeben (z.B. semantische Ähnlichkeit durch den AI-Subsystem-Layer in M7+). Die Kanten werden im Kernel-Wissensgraph (''sys_graph_*'') gespeichert — IOFS selbst speichert nur die rohen Page-Daten.
----
===== 5. Hash-Index =====
IOFS führt einen **Hash-Index** über alle Genesis-Pages (Typ ''0x04''). Schlüssel ist der SHA-256-Hash der Quelldateien (''source_sha256'' aus dem LBF-Genesis-Header), Wert ist der LPID der entsprechenden Page.
Anwendung: Der LBF-Loader löst ''DEP_HASH_GRAPH''-Einträge (TLV 0x02) ohne Verzeichnis-Traversierung auf — er berechnet den SHA-256 der Abhängigkeit und schlägt direkt im Hash-Index nach. Kein symbolisches Linking, keine Pfad-Suche.
import-Auflösung:
sha256(dep.source) → lip_index_lookup() → lpid → lba
kein ld.so, kein PATH-Scan, kein symbolisches Linking
----
===== 6. Omni-Ingest =====
Beim Import eines LBF-Binaries via ''lbf_import'' läuft der **Omni-Ingest**-Prozess:
- LBF-Blöcke werden als IOFS-Pages gespeichert (Typ ''0x04'' für Genesis, ''0x02'' für Code-/Daten-Pages)
- Der ''HUMAN_INTENT''-Text (TLV 0x01 aus dem Genesis-Block) wird durch das KI-Subsystem in einen Embedding-Vektor umgewandelt
- Der Embedding-Vektor wird an die Genesis-Page annotiert (''sys_sem_annotate'')
- Die Page wird im Kernel-Wissensgraph registriert (''sys_graph_node_create'')
- Graph-Kanten werden zwischen den LBF-Blöcken gewoben
Nach dem Ingest ist das Programm über ''sys_ai_search'' (semantische Ähnlichkeit) und ''sys_timeline_query'' (zeitbasiert) auffindbar — ohne dass der User den genauen Dateinamen kennen muss.
lbf_import main.lbf --into-island="tools"
→ IOFS-Pages anlegen
→ Omni-Ingest: Embedding + Graph-Registrierung
→ Hash-Index aktualisieren
----
===== 7. Panic-Sandbox =====
Die **Panic-Sandbox** ist ein IOFS-Modus für die Vertrauenskette des LBF-Loaders (→ [[lyxos:lbf|LBF-Format, Abschnitt 5]]).
* ''sys_iofs_sandbox_enter'' (''CAP_ADMIN'' erforderlich) aktiviert den Modus: IOFS verweigert alle Schreiboperationen außer dem Aktualisieren der Compiler-Blacklist
* In diesem Modus können kompromittierte Compiler-UUIDs sicher zur Blacklist hinzugefügt werden, ohne dass ein laufender Angriff die Liste manipulieren kann
* ''sys_iofs_sandbox_exit'' verlässt den Modus
Beim LBF-Import prüft der Kernel automatisch: Ist die ''compiler_instance_sn'' (UUID aus dem Genesis-Block) in der Blacklist? Falls ja, wird der Import abgelehnt — Schicht 3 der [[lyxos:lbf|5-Schichten-Vertrauenskette]].
----
===== 8. Kompaktierung =====
IOFS ist ein **Append-Only**-System: gelöschte oder veraltete Pages werden nicht sofort überschrieben, sondern als ''IOFS_PAGE_FREE'' markiert. Ein periodischer oder manueller Kompaktierungszyklus defragmentiert das Volume:
var mount_fd: int64 := ...;
// region_hint = 0: gesamtes Volume kompaktieren
var freed_pages: int64 := 0;
var err: int64 := 0;
// (err, freed_pages) := syscall(SYS_IOFS_COMPACT, mount_fd, 0);
''sys_iofs_compact'' (0x0C01) gibt die Anzahl der zurückgewonnenen Pages zurück. Der Kernel kann diesen Zyklus auch automatisch im Hintergrund auslösen (konfigurierbar über ''IofsOpts'' beim Mount).
----
===== 9. On-Disk-Layout (WP01+WP09, implementiert) =====
Das IOFS-Volume auf einem 64-MB-Datenträger ist in fünf feste Bereiche aufgeteilt. Alle Werte aus ''kernel/iofs_alloc.lyx'':
Page Bereich Seiten Beschreibung
──────── ─────────────── ────── ─────────────────────────────────────
0 Superblock 1 "IOFS"-Magic + Layout-Konstanten
1 Root Node 1 LPID=1, "LYX!"-Magic, Type=Meta, Flag=Immutable
2–131 Checkpoint Slot A 130 1 Header + 1 Bitmap + 128 LIP-Pages (aktiv, seq=1)
132–261 Checkpoint Slot B 130 identische Struktur, beim mkfs genullt (inaktiv)
262–325 WAL 64 Write-Ahead-Log, beim mkfs genullt
326–16383 Ocean 16058 allocierbar (≈ 62 MB)
==== Konstanten (kernel/iofs_alloc.lyx) ====
con IOFS_TOTAL_PAGES: int64 := 16384; // 64 MB / 4096 B
con IOFS_SECTORS_PER: int64 := 8; // 4096 / 512 → LBA = page_idx * 8
con IOFS_MAX_LPID: int64 := 65536;
con IOFS_BITMAP_BYTES: int64 := 2048; // ceil(16384 / 8)
con IOFS_PAGE_SUPER: int64 := 0;
con IOFS_PAGE_ROOT: int64 := 1;
con IOFS_SLOT_LIP_PAGES: int64 := 128; // MAX_LPID*8 / 4096
con IOFS_SLOT_PAGES: int64 := 130; // 1 Header + 1 Bitmap + 128 LIP
con IOFS_PAGE_SLOT_A: int64 := 2;
con IOFS_PAGE_SLOT_B: int64 := 132;
con IOFS_WAL_PAGES: int64 := 64;
con IOFS_PAGE_WAL_START: int64 := 262;
con IOFS_PAGE_WAL_END: int64 := 325;
con IOFS_PAGE_OCEAN_START: int64 := 326;
con IOFS_PAGE_OCEAN_END: int64 := 16383;
con IOFS_OCEAN_PAGES: int64 := 16058; // 16383 − 326 + 1
==== Superblock (Page 0) ====
Offset Größe Feld Wert bei mkfs
────── ───── ──────────────── ─────────────────────────────────────────
+0 4 magic "IOFS" (0x49 0x4F 0x46 0x53)
+4 1 version_major 1
+5 1 version_minor 0
+8 8 total_pages 16384
+16 8 max_lpid 65536
+24 8 ocean_start 326
+32 8 ocean_end 16383
+40 8 slot_a 2
+48 8 slot_b 132
+56 8 wal_start 262
+64 8 wal_end 325
+72 8 slot_pages 130
+80 8 wal_pages 64
+88 8 sectors_per_page 8
+96 8 ocean_pages 16058
==== Checkpoint-Slot-Header ====
Jeder Slot beginnt mit einer Header-Page (Offset 0 im Slot):
Offset Feld Beschreibung
────── ──────────── ────────────────────────────────────────────
+0 valid (1B) 1 = aktiv, 0 = inaktiv
+8 seq lo (1B) Sequenz-Nummer (32-Bit LE, über Bytes +8..+11)
+16 bitmap_pages 1 (immer 1 Bitmap-Page)
+20 lip_pages lo 128 (LE, über Bytes +20..+21)
Crash-Atomarität: der Slot-Header wird **zuletzt** geschrieben. Bitmap + LIP-Pages werden vollständig auf Disk gebracht, bevor ''valid=1'' gesetzt wird. Bei Absturz vor dem Header bleibt der Slot mit ''valid=0'' ungültig.
> **WP04:** Ab WP04 enthält der Slot-Header zusätzlich ''wal_seq_at_checkpoint'' bei Offset **+24** (uint32 LE). ''IofsCheckpoint'' schreibt dort den aktuellen ''WalSeq()''-Wert, bevor der Header auf Disk kommt. ''IofsMountDisk'' liest diesen Wert und übergibt ihn an ''WalInit()'', damit ''WalReplay'' weiß, ab welcher Sequenznummer die WAL-Einträge nach dem letzten Checkpoint relevant sind.
==== LIP-Pages (Logical Island Page Table) ====
128 LIP-Pages pro Slot bilden die LPID→page_idx-Tabelle:
lip_page[k] enthält int64-Einträge für LPID k*512 … k*512+511
Eintrag j: page_idx des physischen Blocks für LPID (k*512+j)
0 = nicht alloziert
Beim mkfs: LIP-Page 0 (Slot-Offset +2):
Byte 0..7 = 0 (LPID 0 = kein Root)
Byte 8..15 = 1 (LPID 1 = Root Node, page_idx=1)
Rest = 0
Alle weiteren LIP-Pages = 0
----
===== 10. CRC32C-Integrität (WP03, kernel/iofs_alloc.lyx) =====
WP03 ergänzt eine vollständige CRC32C-Prüfsummen-Engine für alle IOFS-Pages.
==== Algorithmus ====
Castagnoli CRC32C mit reflektiertem Polynom **0x82F63B78**. Die Lookup-Tabelle (256 × uint32 = 1024 Bytes) wird beim ersten Aufruf von ''IofsAllocInit'' einmalig per ''mmap'' alloziert und befüllt (Guard: ''crc32c_table != 0'').
CRC-Berechnung (Castagnoli):
c = 0xFFFFFFFF
for each byte b:
idx = (c XOR b) & 0xFF
c = (c >> 8) XOR table[idx]
return (c XOR 0xFFFFFFFF) & 0xFFFFFFFF
==== Funktionen (kernel/iofs_alloc.lyx) ====
^ Signatur ^ Beschreibung ^
| ''IofsCrc32c(data, len): int64'' | Öffentlicher CRC32C-Berechner für beliebige Daten. Gibt 32-Bit-CRC als int64 zurück. |
| ''IofsPageHasMagic(buf): bool'' | Prüft ob ''buf[0..3]'' == "LYX!" (0x4C 0x59 0x58 0x21). |
| ''IofsPageSetCrc(buf): void'' | Nullt Bytes 0x14–0x17 des Puffers, berechnet CRC32C über alle 4096 Bytes, schreibt Ergebnis (LE) zurück an 0x14. |
| ''IofsPageVerifyCrc(buf): bool'' | Liest gespeicherten CRC (0x14–0x17), nullt das Feld, berechnet neu, vergleicht; stellt Feld danach **immer** wieder her. Gibt ''true'' wenn gleich. |
==== Integration ====
^ Aufrufstelle ^ Verhalten ^
| ''IofsAllocInit(disk_id)'' | Ruft ''crc32c_init()'' auf (einmalig, idempotent) |
| ''IofsMkfs'' — Root-Node (p1) | ''IofsPageSetCrc(buf)'' vor dem Schreiben |
| ''IofsWriteLpid(lpid, buf)'' | Wenn ''IofsPageHasMagic(buf)'': ''IofsPageSetCrc(buf)'' automatisch — jede LYX!-Page erhält beim Schreiben eine aktuelle Prüfsumme |
| ''IofsReadLpid(lpid, buf)'' | Wenn ''IofsPageHasMagic(buf)'' und ''!IofsPageVerifyCrc(buf)'': return false — CRC-Fehler → Leseoperation schlägt fehl |
> **Hinweis:** Nur Pages mit "LYX!"-Magic werden geprüft. Superblock (Page 0) und WAL-Pages tragen kein "LYX!"-Magic und werden nicht via CRC verifiziert.
----
===== 11. Block-Allocator (WP01, kernel/iofs_alloc.lyx) =====
Der Block-Allocator verwaltet eine **In-RAM-Bitmap** (2048 Bytes) über alle 16384 Pages.
==== Initialisierung ====
''IofsAllocInit(disk_id)'' markiert die 326 reservierten Pages (p0–p325) als belegt, Ocean-Pages (p326–p16383) als frei. Legt den Hint auf ''IOFS_PAGE_OCEAN_START''.
==== Funktionen ====
^ Signatur ^ Beschreibung ^
| ''IofsAllocInit(disk_id): void'' | Bitmap allozieren + initialisieren. Muss vor ''IofsAllocPage''/''IofsFreePageIdx'' gerufen werden. |
| ''IofsAllocPage(): int64'' | Nächste freie Ocean-Page allozieren (Bitmap-Bit setzen). Zwei-Pass-Suche: Hint→End, dann Start→Hint-1. Gibt page_idx zurück; -1 wenn voll. |
| ''IofsFreePageIdx(page_idx): bool'' | Ocean-Page freigeben (Bitmap-Bit löschen). Gibt ''false'' bei ungültigem Index oder Double-Free. |
| ''IofsCountFree(): int64'' | Lineare Bitmap-Zählung aller freien Ocean-Pages (Diagnose). |
| ''IofsIsReady(): bool'' | ''true'' nach ''IofsAllocInit''. |
| ''IofsGetBitmap(): int64'' | Zeiger auf die In-RAM-Bitmap. |
| ''IofsGetDiskId(): int64'' | Disk-ID des aktuell initialisierten Volumes. |
==== Low-Level-I/O ====
^ Signatur ^ Beschreibung ^
| ''IofsWritePage(disk_id, page_idx, buf): int64'' | Schreibt 4096 Bytes (8×512-Byte-Sektoren) auf Disk. LBA = page_idx × 8. |
| ''IofsReadPage(disk_id, page_idx, buf): int64'' | Liest 4096 Bytes (8×512-Byte-Sektoren) von Disk. |
----
===== 12. IofsMkfs — Formatierungssequenz =====
''IofsMkfs(disk_id)'' (→ ''VfsMkfsIofs'' → Syscall 155 = ''sys_mkfs_iofs'') schreibt das komplette IOFS-Volume in dieser Reihenfolge:
- ''IofsAllocInit(disk_id)'' — Bitmap aufbauen
- **Superblock** (Page 0): "IOFS"-Magic + alle Layout-Konstanten
- **Root Node** (Page 1): "LYX!"-Magic, ''IOFS_TYPE_META'', ''IOFS_FLAG_IMMUTABLE'', LPID=1, payload="IOFS_ROOT_v1.1" (14 Bytes bei Offset 0x40)
- **WAL** (Pages 262–325): alle Pages genullt
- **Checkpoint Slot A** (Pages 2–131): Bitmap (p3), LIP-Page 0 mit LPID-1→p1 (p4), LIP-Pages 1–127 genullt (p5–p131), Header zuletzt (p2, valid=1, seq=1)
- **Checkpoint Slot B** (Pages 132–261): vollständig genullt (Header valid=0)
Aufruf aus Ring-3:
import bsys;
// ...
var rc: int64 := SysMkfsIofs(disk_id); // 0 = OK, -1 = Fehler
Aufruf als Shell-Tool:
> mkfs_iofs 1
mkfs_iofs: formatting disk 1 as IOFS... OK
p0 Superblock
p1 Root node (LPID=1)
p2-131 Checkpoint slot A (1 header + 1 bitmap + 128 LIP pages)
p132-261 Checkpoint slot B (inactive, zeroed)
p262-325 WAL (64 pages, zeroed)
p326-16383 Ocean (16058 free pages)
----
===== 13. WP02: Mount, Read, Write, Checkpoint (kernel/iofs_rw.lyx) =====
WP02 baut auf dem Block-Allocator (WP01) auf und liefert die vollständige LPID-basierte Lese-/Schreibschnittstelle sowie crash-atomare Checkpoints.
==== In-RAM-Strukturen ====
^ Variable ^ Typ ^ Beschreibung ^
| ''iofs_lip'' | int64 (Ptr) | LIP-Tabelle: 65536 Einträge × 2 Bytes = **128 KB**. ''LIP[lpid]'' = physischer ''page_idx'' (uint16 LE). 0 = nicht gemappt. |
| ''iofs_active_slot'' | int64 | ''IOFS_PAGE_SLOT_A'' (2) oder ''IOFS_PAGE_SLOT_B'' (132) |
| ''iofs_slot_seq'' | int64 | Sequenz-Nummer des aktiven Slots (steigt bei jedem Checkpoint) |
| ''iofs_dirty'' | bool | ''true'' wenn LIP seit letztem Checkpoint verändert wurde |
==== Kernel-API (kernel/iofs_rw.lyx) ====
^ Signatur ^ Beschreibung ^
| ''IofsMountDisk(disk_id): bool'' | Aktiven Checkpoint-Slot bestimmen (höchste ''seq'', ''valid=1''; bei Gleichstand Slot A bevorzugt). Bitmap + 128 LIP-Pages in RAM laden. |
| ''IofsReadLpid(lpid, buf): bool'' | LIP-Lookup → physische Page lesen. ''lpid'' muss ≥ 1 und gemappt sein. |
| ''IofsWriteLpid(lpid, buf): int64'' | Neue Ocean-Page allozieren, vollständig formatierten 4096-Byte-Puffer schreiben, LIP aktualisieren, alte Page freigeben. Gibt neue ''page_idx'' zurück; -1 bei Fehler. |
| ''IofsNewPage(type_, flags, payload, psize): int64'' | Freien LPID-Slot suchen (''IofsAllocLpidSlot''), Page-Header aufbauen (Magic, Type, Flags, edge_offset=0x40, LPID, payload_size), Payload ab Offset 0x40 kopieren, via ''IofsWriteLpid'' schreiben. Gibt neuen LPID zurück; 0 bei Fehler. |
| ''IofsFreeByLpid(lpid): bool'' | Physische Page freigeben + LIP-Eintrag löschen. LPID 1 (Root) ist geschützt. |
| ''IofsCheckpoint(): bool'' | Crash-atomarer Dual-Slot-Flip: (1) Bitmap → inaktiver Slot +1, (2) 128 LIP-Pages → inaktiver Slot +2–+129, (3) Slot-Header mit ''valid=1'' und ''seq+1'' **zuletzt** schreiben. Swappt ''iofs_active_slot''. |
| ''IofsUnmount(): bool'' | Falls ''iofs_dirty'': ''IofsCheckpoint()'' aufrufen. LIP-Tabelle freigeben. |
| ''IofsLipGet(lpid): int64'' | LPID → physischer ''page_idx'' (bounds-checked, 0 = nicht gemappt). |
| ''IofsAllocLpidSlot(): int64'' | Ersten freien LPID ≥ 2 suchen (LPID 0 = null, 1 = Root). |
| ''IofsCountMapped(): int64'' | Anzahl belegter LPIDs (Diagnose, lineare Suche). |
| ''IofsIsMounted(): bool'' | ''true'' wenn LIP-Tabelle geladen. |
| ''IofsActiveSlot(): int64'' | Aktueller aktiver Slot-Start-Page. |
| ''IofsSlotSeq(): int64'' | Aktuelle Sequenz-Nummer. |
| ''IofsIsDirty(): bool'' | ''true'' wenn ungespeicherte Änderungen vorhanden. |
==== Syscall-Binding (156–164) ====
^ Nr ^ Name ^ Argumente ^ Rückgabe ^ Beschreibung ^
| 156 | ''sys_iofs_mount'' | ''disk_id'' | 0 oder -1 | Checkpoint laden, LIP (128 KB) + Bitmap in RAM |
| 157 | ''sys_iofs_read_lpid'' | ''lpid, user_buf'' | 0 oder -1 | Page via LPID lesen (LIP→page_idx→DiskRead, user_buf muss 4096 Bytes groß sein) |
| 158 | ''sys_iofs_write_lpid'' | ''lpid, user_buf'' | page_idx oder -1 | Neue Ocean-Page allozieren, schreiben, LIP updaten, alte freigeben |
| 159 | ''sys_iofs_new_page'' | ''type, flags, payload_uva, psize'' | LPID oder 0 | LPID allozieren + Header bauen + schreiben (psize ≤ 4032) |
| 160 | ''sys_iofs_free_lpid'' | ''lpid'' | 0 oder -1 | Physische Page freigeben + LIP-Eintrag löschen (LPID 1 geschützt) |
| 161 | ''sys_iofs_checkpoint'' | — | 0 oder -1 | Dual-Slot-Flip: inaktiver Slot ← aktueller Stand (crash-atomar) |
| 162 | ''sys_iofs_unmount'' | — | 0 oder -1 | Checkpoint falls dirty, LIP-Tabelle freigeben |
| 163 | ''sys_iofs_lip_get'' | ''lpid'' | page_idx oder 0 | LPID→physischer page_idx (0 = nicht gemappt) |
| 164 | ''sys_iofs_info'' | ''out_buf_uva'' | 0 oder -1 | 64-Byte-Status-Buffer füllen (siehe unten) |
==== IofsInfo-Buffer (64 Bytes) ====
+0 (int64) mounted 1 = gemountet, 0 = nicht gemountet
+8 (int64) free_pages Anzahl freier Ocean-Pages
+16 (int64) mapped Anzahl belegter LPIDs
+24 (int64) active_slot IOFS_PAGE_SLOT_A (2) oder IOFS_PAGE_SLOT_B (132)
+32 (int64) seq Aktuelle Checkpoint-Sequenz-Nummer
+40 (int64) dirty 1 = ungespeicherte Änderungen vorhanden
+48 (int64) wal_head Nächster WAL-Schreib-Index (0–8191, zirkulär; WP04)
+56 (int64) wal_seq Nächste WAL-Sequenznummer (monoton ≥ 1; WP04)
==== Ring-3-Wrapper (bsys.lyx / bsys_vega.lyx) ====
SysIofsMount(disk_id): int64 // nr=156
SysIofsReadLpid(lpid, buf): int64 // nr=157; buf muss phys. Adresse sein
SysIofsWriteLpid(lpid, buf): int64 // nr=158
SysIofsNewPage(type_, flags, payload, psize): int64 // nr=159
SysIofsFreeLpid(lpid): int64 // nr=160
SysIofsCheckpoint(): int64 // nr=161
SysIofsUnmount(): int64 // nr=162
SysIofsLipGet(lpid): int64 // nr=163
SysIofsInfo(buf): int64 // nr=164; buf = 64-Byte-Puffer
> **Hinweis zu ''SysIofsReadLpid'' / ''SysIofsWriteLpid'':** Der Kernel übersetzt ''user_buf'' via ''VmmPhysFromUserVirt'' in eine physische Adresse. Der übergebene Puffer muss daher eine via ''mmap'' allozierte Page sein (kein Stack-Puffer).
==== Shell-Tool: iofs ====
^ Befehl ^ Beschreibung ^
| ''iofs mount '' | IOFS-Volume mounten (LIP + Bitmap in RAM laden) |
| ''iofs unmount'' | Checkpoint falls dirty, LIP-Tabelle freigeben |
| ''iofs info'' | Status, freie Pages, gemappte LPIDs, aktiver Slot, Seq, Dirty-Flag |
| ''iofs alloc '' | Neue Meta-Page mit Text-Payload allozieren, LPID ausgeben |
| ''iofs read '' | Page-Header + Payload (bis 256 Zeichen) anzeigen |
| ''iofs write '' | Payload überschreiben (neue physische Page, LIP aktualisiert) |
| ''iofs free '' | Physische Page freigeben + LIP-Eintrag löschen (LPID ≥ 2) |
| ''iofs checkpoint'' | LIP + Bitmap in inaktiven Slot flushen |
| ''iofs lip '' | Physischen ''page_idx'' für LPID anzeigen |
==== Beispiel ====
> mkfs_iofs 1
mkfs_iofs: formatting disk 1 as IOFS... OK
> iofs mount 1
iofs: mounting disk_id=1 ... OK
> iofs alloc "Hallo IOFS"
iofs: allocated lpid=2
> iofs read 2
magic LYX! OK
lpid 2
type 1
flags 0
psize 10 bytes
payload Hallo IOFS
> iofs checkpoint
iofs: checkpoint ... OK
> iofs info
mounted yes active slot A seq=2
free pages 16057 / 16058
mapped LPIDs 2
----
===== 14. WP04: Write-Ahead-Log (kernel/iofs_wal.lyx) =====
WP04 ergänzt einen persistenten WAL-Ring für alle Mutationen an LIP-Tabelle und Bitmap. Damit sind Änderungen nach einem Checkpoint auch bei Absturz vor dem nächsten Checkpoint wiederherstellbar — ohne den vollständigen Dual-Slot-Flip abzuwarten.
==== Konstanten ====
pub con IOFS_WAL_TYPE_LIP_UPDATE: int64 := 1; // key=lpid, value=new_page_idx
pub con IOFS_WAL_TYPE_BITMAP_SET: int64 := 2; // key=page_idx, value=0
pub con IOFS_WAL_TYPE_BITMAP_CLEAR: int64 := 3; // key=page_idx, value=0
pub con IOFS_WAL_ENTRY_SZ: int64 := 32; // Bytes je Eintrag
pub con IOFS_WAL_EPP: int64 := 128; // Einträge je 4096-Byte-Page
pub con IOFS_WAL_TOTAL: int64 := 8192; // 64 Pages × 128 Einträge (zirkulär)
==== WAL-Eintragsformat (32 Bytes) ====
Offset Größe Feld Beschreibung
────── ───── ────── ──────────────────────────────────────────────────────────
0x00 1 type 0=leer, 1=LIP_UPDATE, 2=BITMAP_SET, 3=BITMAP_CLEAR
0x01 7 (pad) Muss 0 sein
0x08 8 key LPID (LIP_UPDATE) oder page_idx (Bitmap-Ops)
0x10 8 value Neuer page_idx (LIP_UPDATE) oder 0 (Bitmap-Ops)
0x18 4 seq Monotone Sequenznummer (uint32 LE, ≥ 1)
0x1C 4 crc32c CRC32C über Bytes 0x00–0x1B (28 Bytes)
Stop-Heuristik beim Replay: ''type == 0'' oder CRC-Fehler = Ende der geschriebenen Einträge.
==== Kernel-API (kernel/iofs_wal.lyx) ====
^ Signatur ^ Beschreibung ^
| ''WalInit(initial_seq): void'' | Setzt ''g_wal_head = 0'' und ''g_wal_seq = initial_seq''. Aufgerufen von ''IofsMountDisk'' nach dem Laden des Checkpoint-Slots. |
| ''WalAppend(type_, key, value): void'' | Schreibt einen 32-Byte-Eintrag in den Ring, erhöht ''g_wal_seq'', rückt ''g_wal_head'' zirkulär vor. Aufruf-Reihenfolge: **nach** dem Page-Write, **vor** der RAM-Mutation. |
| ''WalReplay(disk_id, from_seq, lip_arr, bmp): int64'' | Scannt alle WAL-Pages linear (0 → 8191). Wendet Einträge mit ''seq ≥ from_seq'' und gültigem CRC auf ''lip_arr'' (uint16-LIP) und ''bmp'' (Bitmap-Puffer) an. Aktualisiert ''g_wal_head'' und ''g_wal_seq'' auf den Stand nach dem letzten angewendeten Eintrag. Gibt Anzahl angewendeter Einträge zurück. |
| ''WalZero(disk_id): void'' | Nullt alle 64 WAL-Pages auf Disk. Aufgerufen von ''IofsCheckpoint'' nach erfolgreichem Dual-Slot-Flip. |
| ''WalSeq(): int64'' | Nächste zu vergebende Sequenznummer (gelesen von ''IofsCheckpoint'' und in den Slot-Header geschrieben). |
| ''WalHead(): int64'' | Aktueller Schreib-Index (0–8191). |
==== Aufruf-Sequenz in IofsWriteLpid ====
1. IofsAllocPage() → new_pidx
2. IofsWritePage(disk_id, new_pidx, buf) ← physische Page auf Disk
3. WalAppend(BITMAP_SET, new_pidx, 0) ← WAL: neuen Block als belegt markieren
4. WalAppend(LIP_UPDATE, lpid, new_pidx) ← WAL: LIP-Eintrag aktualisieren
5. [falls alter Block vorhanden]
WalAppend(BITMAP_CLEAR, old_pidx, 0) ← WAL: alten Block als frei markieren
6. LIP[lpid] := new_pidx ← jetzt RAM-Mutation
7. Bitmap[new] := belegt
8. Bitmap[old] := frei
Das WAL-Eintrag kommt **vor** der RAM-Mutation: bei Absturz nach Schritt 2 aber vor Schritt 6 rekonstruiert ''WalReplay'' beim nächsten Mount den korrekten Zustand.
==== Checkpoint-Lifecycle (WP04-Erweiterung) ====
IofsCheckpoint():
1. Bitmap → inaktiver Slot +1
2. 128 LIP-Pages → inaktiver Slot +2..+129
3. wal_s := WalSeq()
4. Slot-Header mit valid=1, seq+1, wal_seq=wal_s → inaktiver Slot +0 ← zuletzt
5. WalZero(disk_id) ← WAL-Pages leeren
6. WalInit(wal_s) ← head=0, seq=wal_s
IofsMountDisk():
1. Aktiven Slot bestimmen (valid=1, höchste seq)
2. Bitmap + LIP laden
3. wal_seq_at_checkpoint := Slot-Header +24 (uint32 LE)
4. WalInit(wal_seq_at_checkpoint)
5. WalReplay(disk_id, wal_seq_at_checkpoint, lip, bmp)
> Die WAL ist ein **zirkulärer Ring** mit 8192 Slots. Bei sehr hoher Write-Last ohne zwischenzeitlichen Checkpoint kann der Ring überlaufen — älteste Einträge werden überschrieben. Deshalb sollte ''IofsCheckpoint'' regelmäßig aufgerufen werden.
----
===== 15. WP05: Graph / Edges (kernel/iofs_graph.lyx) =====
WP05 fügt eine gerichtete Kanten-Schicht auf IOFS-Pages auf. Jede Node-Page kann über ihr ''cont_lpid''-Feld (Offset 0x18) auf eine verkettete Liste von Edge-List-Pages zeigen.
==== Kanten-Struktur ====
Node-Page (beliebiger Typ mit LYX!-Magic):
+0x18 edge_list_lpid (int64) — 0 = keine Kanten; >0 = LPID der ersten Edge-List-Page
Edge-List-Page (type = IOFS_TYPE_EDGE_LIST = 4):
+0x08 lpid (int64) — LPID dieser Edge-List-Page
+0x10 payload_size (uint16) — edge_count × IOFS_EDGE_SIZE
+0x12 edge_count (uint16) — Anzahl Einträge auf dieser Page
+0x18 next_edge_page (int64) — LPID der nächsten Page (0 = letzte)
+0x40 Edge-Einträge — 12 Bytes je Eintrag:
0-7 to_lpid (int64 LE)
8-9 edge_type (uint16 LE)
10-11 padding (0x0000)
con IOFS_EDGE_SIZE: int64 := 12;
con IOFS_EDGE_MAX_PER_PAGE: int64 := 336; // (4096 - 64) / 12
Wenn eine Edge-List-Page voll ist (336 Einträge), wird transparent eine neue alloziert und via ''next_edge_page'' verkettet.
==== Kernel-API (kernel/iofs_graph.lyx) ====
^ Signatur ^ Beschreibung ^
| ''IofsEdgeAdd(from, to, edge_type): bool'' | Kante hinzufügen. Erstellt Edge-List-Page für ''from'' wenn noch keine vorhanden. Kettet neue Page an wenn aktuelle voll (> 336 Einträge). |
| ''IofsEdgeRemove(from, to): bool'' | Erste Kante ''from''→''to'' (beliebiger ''edge_type'') entfernen. Kompaktiert Einträge in-place (Left-Shift nach dem gelöschten Slot, letzter Slot wird genullt). |
| ''IofsEdgeCount(from): int64'' | Summe aller Kanten von ''from'' über die gesamte Page-Kette. |
| ''IofsEdgeGetAll(from, out_buf, max): int64'' | Bis zu ''max'' Kanten in ''out_buf'' kopieren (16 Bytes/Eintrag: [0-7]=to_lpid, [8-15]=edge_type). Gibt Anzahl geschriebener Einträge zurück. |
| ''IofsEdgeHas(from, to): bool'' | Prüft ob Kante ''from''→''to'' existiert (beliebiger ''edge_type''). |
==== Syscall-Binding (165–169) ====
^ Nr ^ Name ^ Argumente ^ Rückgabe ^ Beschreibung ^
| 165 | ''sys_iofs_edge_add'' | ''from_lpid, to_lpid, edge_type'' | 0 oder -1 | Gerichtete Kante hinzufügen (WP05) |
| 166 | ''sys_iofs_edge_rm'' | ''from_lpid, to_lpid'' | 0 oder -1 | Erste Kante ''from→to'' entfernen (WP05) |
| 167 | ''sys_iofs_edge_count'' | ''from_lpid'' | Anzahl oder 0 | Kanten von ''from_lpid'' zählen (WP05) |
| 168 | ''sys_iofs_edge_get_all'' | ''from_lpid, out_buf_uva, max_edges'' | Anzahl oder 0 | Kanten in Puffer lesen, 16 Bytes/Eintrag (WP05) |
| 169 | ''sys_iofs_edge_has'' | ''from_lpid, to_lpid'' | 1 oder 0 | Kanten-Existenz prüfen (WP05) |
==== Ring-3-Wrapper (bsys.lyx / bsys_vega.lyx) ====
SysIofsEdgeAdd(from_lpid, to_lpid, edge_type): int64 // nr=165
SysIofsEdgeRemove(from_lpid, to_lpid): int64 // nr=166
SysIofsEdgeCount(from_lpid): int64 // nr=167
SysIofsEdgeGetAll(from_lpid, out_buf, max): int64 // nr=168
SysIofsEdgeHas(from_lpid, to_lpid): int64 // nr=169
==== Shell-Befehle (iofs) ====
^ Befehl ^ Beschreibung ^
| ''iofs edge-add '' | Gerichtete Kante mit ''edge_type'' hinzufügen |
| ''iofs edge-rm '' | Erste Kante ''from→to'' entfernen |
| ''iofs edge-count '' | Anzahl ausgehender Kanten ausgeben |
| ''iofs edge-list '' | Alle ausgehenden Kanten mit ''to_lpid'' und ''edge_type'' auflisten |
| ''iofs edge-has '' | Kanten-Existenz prüfen (1/0) |
==== Beispiel ====
> iofs mount 1
iofs: mounting disk_id=1 ... OK
> iofs alloc "NodeA"
iofs: allocated lpid=2
> iofs alloc "NodeB"
iofs: allocated lpid=3
> iofs alloc "NodeC"
iofs: allocated lpid=4
> iofs edge-add 2 3 1
iofs: edge 2 -> 3 type=1 added
> iofs edge-add 2 4 2
iofs: edge 2 -> 4 type=2 added
> iofs edge-add 2 3 3
iofs: edge 2 -> 3 type=3 added
> iofs edge-count 2
iofs: lpid=2 edges=3
> iofs edge-has 2 3
iofs: edge 2 -> 3 exists=1
> iofs edge-rm 2 3
iofs: edge 2 -> 3 removed
> iofs edge-list 2
[0] 2 -> 4 type=2
[1] 2 -> 3 type=3
----
===== 16. WP06: Graph-Traversal (kernel/iofs_traverse.lyx) =====
WP06 implementiert vier Graph-Traversal-Algorithmen auf den IOFS-Kanten (WP05). Alle Funktionen sind **iterativ** (keine Rekursion) und arbeiten mit pre-allozieren Puffern fixer Größe.
==== Interne Konstanten ====
con IOFS_VISITED_BYTES: int64 := 8192; // ceil(65536 / 8) — 1 Bit pro LPID
con TRAV_QUEUE_MAX: int64 := 4096; // max. Einträge im BFS-Queue / DFS-Stack
con SP_PARENT_BYTES: int64 := 131072; // 65536 × 2 Bytes — uint16-Parent-Array (ShortestPath)
con SP_SENTINEL: int64 := 65535; // Markiert den BFS-Startknoten im Parent-Array
==== Kernel-API (kernel/iofs_traverse.lyx) ====
^ Signatur ^ Beschreibung ^
| ''IofsBfs(start_lpid, out_buf, max_nodes): int64'' | BFS-Traversal ab ''start_lpid''. Schreibt besuchte LPIDs in BFS-Reihenfolge als int64-Array in ''out_buf''. Gibt Anzahl zurück; capped auf ''min(max_nodes, TRAV_QUEUE_MAX)''. |
| ''IofsDfs(start_lpid, out_buf, max_nodes): int64'' | DFS-Traversal (iterativer Stack). Nachbarn werden in umgekehrter Kanten-Reihenfolge gepusht, damit die erste Kante zuerst traversiert wird (LIFO-Verhalten). |
| ''IofsReachable(from_lpid, to_lpid): bool'' | BFS mit Early-Exit: ''true'' sobald ''to_lpid'' im Queue gefunden wird. Gibt sofort ''true'' zurück wenn ''from_lpid == to_lpid''. |
| ''IofsShortestPath(from_lpid, to_lpid, path_buf, max_len): int64'' | Kürzester Pfad via BFS + Parent-Array (131 072 Bytes, uint16 LE). Rekonstruiert Pfad rückwärts und dreht ihn um. Gibt Pfadlänge zurück; 0 = nicht erreichbar oder Pfad > ''max_len''. |
==== Speichermodell ====
Jede Traversal-Funktion alloziert ihre Arbeitspuffer per ''mmap'' und gibt sie nach Abschluss frei:
BFS / DFS:
visited — 8 192 Bytes (1 Bit / LPID, 65 536 LPIDs)
queue / stack — max. TRAV_QUEUE_MAX × 8 Bytes = 32 KB
ShortestPath:
parent — 131 072 Bytes (65 536 × uint16, 0=unbesucht, 65535=Startknoten)
queue — 32 KB
Kein globaler Traversal-Zustand — jeder Aufruf ist vollständig re-entrant.
==== Syscall-Binding (170–173) ====
^ Nr ^ Name ^ Argumente ^ Rückgabe ^ Beschreibung ^
| 170 | ''sys_iofs_bfs'' | ''start_lpid, out_buf_uva, max_nodes'' | Anzahl oder 0 | BFS-Traversal; ''out_buf'' = int64-Array (WP06) |
| 171 | ''sys_iofs_dfs'' | ''start_lpid, out_buf_uva, max_nodes'' | Anzahl oder 0 | DFS-Traversal (iterativer Stack, WP06) |
| 172 | ''sys_iofs_reachable'' | ''from_lpid, to_lpid'' | 1 oder 0 | Erreichbarkeit prüfen (WP06) |
| 173 | ''sys_iofs_shortest_path'' | ''from_lpid, to_lpid, path_buf_uva, max_len'' | Pfadlänge oder 0 | Kürzester Pfad (WP06) |
==== Ring-3-Wrapper (bsys.lyx) ====
SysIofsBfs(start_lpid, out_buf, max_nodes): int64 // nr=170
SysIofsDfs(start_lpid, out_buf, max_nodes): int64 // nr=171
SysIofsReachable(from_lpid, to_lpid): int64 // nr=172
SysIofsShortestPath(from_lpid, to_lpid, path_buf, max_len): int64 // nr=173
==== Shell-Befehle (iofs) ====
^ Befehl ^ Beschreibung ^
| ''iofs bfs [max]'' | BFS-Traversal ab ''lpid''; Standard-max=64 |
| ''iofs dfs [max]'' | DFS-Traversal ab ''lpid'' |
| ''iofs reachable '' | Erreichbarkeit prüfen (YES/NO) |
| ''iofs path [max]'' | Kürzesten Pfad ausgeben |
==== Beispiel ====
> iofs mount 1
iofs: mounting disk_id=1 ... OK
> iofs bfs 1
iofs bfs lpid=1 visited=4:
1
3
4
5
> iofs reachable 1 5
iofs: 1 -> 5 reachable=YES
> iofs path 1 5
iofs path (3 hops):
1 -> 3 -> 5
----
===== 17. WP07: Named Nodes (kernel/iofs_names.lyx) =====
WP07 ergänzt einen String-zu-LPID-Namensraum auf der reservierten LPID=2. Namen sind bis zu 55 Bytes lang; pro Name-Store-Page passen 63 Einträge.
==== Konstanten ====
pub con IOFS_NS_LPID: int64 := 2; // well-known LPID für den Name Store
pub con IOFS_NS_ENTRY_SIZE: int64 := 64;
pub con IOFS_NS_MAX_NAME: int64 := 55;
pub con IOFS_NS_ENTRIES_PER_PAGE: int64 := 63; // (4096 − 64) / 64
pub con IOFS_NS_OUT_ENTRY: int64 := 80;
> **LPID-Reservierung:** Nach ''IofsNameInit()'' sind LPID 1 (Root) und LPID 2 (Name Store) belegt. Neue Allokationen via ''IofsAllocLpidSlot()'' starten ab LPID 3.
==== Name-Store-Page-Layout ====
Name-Store-Pages haben ''type = IOFS_TYPE_NAME_STORE (5)''. Das ''cont_lpid''-Feld (Offset 0x18) zeigt auf die nächste Name-Store-Page in der Kette (0 = letzte Page).
Standard LYX!-Header (0x00–0x3F):
0x04 IOFS_TYPE_NAME_STORE (5)
0x08 LPID dieser Page
0x12–0x13 entry_count (uint16 LE)
0x18 next_name_page_lpid (int64, 0 = letzte Page)
Payload ab 0x40: entry_count × 64 Bytes je Eintrag:
+0 lpid (int64 LE) — gebundener LPID
+8 name_len (uint8) — Namenslänge in Bytes (1–55)
+9 name (bis 55 Bytes, kein Null-Terminator gespeichert)
==== Kernel-API (kernel/iofs_names.lyx) ====
^ Signatur ^ Beschreibung ^
| ''IofsNameInit(): bool'' | Stellt sicher dass LPID=2 als Name-Store-Root existiert. **Idempotent** — sicher nach jedem Mount aufzurufen; prüft via ''IofsLipGet(2) != 0''. |
| ''IofsNameBind(name, name_len, lpid): bool'' | Bindet Name an LPID. Existiert der Name bereits, wird nur der LPID aktualisiert (2-Pass: Pass 1 sucht zum Updaten, Pass 2 findet freien Slot oder kettet neue Page an). |
| ''IofsNameLookup(name, name_len): int64'' | Sucht Name linear in der Page-Kette. Gibt gebundenen LPID zurück; 0 = nicht gefunden. |
| ''IofsNameUnbind(name, name_len): bool'' | Entfernt Eintrag. Kompaktiert verbleibende Einträge der Page in-place (Left-Shift, letzter Slot wird genullt). Gibt ''false'' wenn Name nicht gefunden. |
| ''IofsNameList(out_buf, max_entries): int64'' | Kopiert bis zu ''max_entries'' Einträge in ''out_buf'' (80 Bytes/Eintrag, siehe unten). Gibt Anzahl kopierter Einträge zurück. |
==== IofsNameList-Ausgabepuffer (80 Bytes/Eintrag) ====
+0 lpid (int64) — gebundener LPID
+8 name_len (int64) — Namenslänge (uint8, zero-extended)
+16 name (bis 56 Bytes inkl. Null-Terminator)
==== Syscall-Binding (174–178) ====
^ Nr ^ Name ^ Argumente ^ Rückgabe ^ Beschreibung ^
| 174 | ''sys_iofs_name_init'' | — | 0 oder -1 | Name-Store initialisieren (idempotent, WP07) |
| 175 | ''sys_iofs_name_lookup'' | ''name_uva, name_len'' | LPID oder 0 | Name → LPID (0 = nicht gefunden, WP07) |
| 176 | ''sys_iofs_name_bind'' | ''name_uva, name_len, lpid'' | 0 oder -1 | Name an LPID binden / aktualisieren (WP07) |
| 177 | ''sys_iofs_name_unbind'' | ''name_uva, name_len'' | 0 oder -1 | Bindung entfernen (WP07) |
| 178 | ''sys_iofs_name_list'' | ''out_buf_uva, max_entries'' | Anzahl oder 0 | Alle Bindungen auflisten, 80 Bytes/Eintrag (WP07) |
==== Ring-3-Wrapper (bsys.lyx) ====
SysIofsNameInit(): int64 // nr=174
SysIofsNameLookup(name: pchar, name_len): int64 // nr=175; Rückgabe = LPID oder 0
SysIofsNameBind(name: pchar, name_len, lpid): int64 // nr=176
SysIofsNameUnbind(name: pchar, name_len): int64 // nr=177
SysIofsNameList(out_buf, max_entries): int64 // nr=178
==== Shell-Befehle (iofs) ====
^ Befehl ^ Beschreibung ^
| ''iofs name-init'' | Name-Store auf LPID=2 initialisieren (idempotent) |
| ''iofs name-bind '' | Name an LPID binden (Update wenn Name schon existiert) |
| ''iofs name-lookup '' | Gebundenen LPID ausgeben (0 = nicht gefunden) |
| ''iofs name-unbind '' | Bindung entfernen |
| ''iofs name-list'' | Alle Bindungen ausgeben (max. 64 Einträge) |
==== Beispiel ====
> iofs mount 1
iofs: mounting disk_id=1 ... OK
> iofs name-init
iofs name-init: OK
> iofs name-bind system 1
iofs: 'system' -> lpid=1 bound
> iofs name-bind config 3
iofs: 'config' -> lpid=3 bound
> iofs name-lookup config
iofs: name='config' lpid=3
> iofs name-list
lpid=1 'system'
lpid=3 'config'
> iofs name-unbind config
iofs: 'config' unbound
----
===== 18. Implementierungsstand =====
^ Komponente ^ Status ^ Quelldatei ^
| Superblock, Root-Node, Checkpoint-Slots, WAL, Bitmap | **Implementiert** (WP01+WP09) | ''kernel/iofs_alloc.lyx'' |
| Block-Allocator (Alloc/Free/Count) | **Implementiert** (WP01) | ''kernel/iofs_alloc.lyx'' |
| Page-I/O (IofsReadPage / IofsWritePage) | **Implementiert** | ''kernel/iofs_alloc.lyx'' |
| ''sys_mkfs_iofs'' (Syscall 155) | **Implementiert** | ''kernel/ring3.lyx'', ''kernel/vfs.lyx'' |
| Shell-Tool ''mkfs_iofs'' | **Implementiert** | ''bin/mkfs_iofs.lyx'' |
| Mount / LIP-Tabelle (128 KB) | **Implementiert** (WP02) | ''kernel/iofs_rw.lyx'' |
| LPID-Lesen/Schreiben (sys 156–158) | **Implementiert** (WP02) | ''kernel/iofs_rw.lyx'' |
| NewPage / FreeLpid (sys 159–160) | **Implementiert** (WP02) | ''kernel/iofs_rw.lyx'' |
| Checkpoint / Unmount (sys 161–162) | **Implementiert** (WP02) | ''kernel/iofs_rw.lyx'' |
| LipGet / Info (sys 163–164) | **Implementiert** (WP02) | ''kernel/iofs_rw.lyx'' |
| Shell-Tool ''iofs'' | **Implementiert** (WP02+WP05) | ''bin/iofs.lyx'' |
| Graph-Kanten (IofsEdgeAdd/Remove/Count/GetAll/Has) | **Implementiert** (WP05) | ''kernel/iofs_graph.lyx'' |
| Syscalls 165–169 (edge_add/rm/count/get_all/has) | **Implementiert** (WP05) | ''kernel/ring3.lyx'' |
| VFS-Mount (IOFS als aktives sys_open-Backend) | Geplant (M5) | — |
| LBF-Zero-Load-Ausführung | Geplant (M5) | — |
| Panic-Sandbox, Kompaktierung | Geplant (M6+) | — |
| CRC32C-Engine (IofsCrc32c, IofsPageSetCrc, IofsPageVerifyCrc) | **Implementiert** (WP03) | ''kernel/iofs_alloc.lyx'' |
| WAL-Ring (WalInit/WalAppend/WalReplay/WalZero, 8192 Einträge) | **Implementiert** (WP04) | ''kernel/iofs_wal.lyx'' |
| Graph-Traversal (IofsBfs/IofsDfs/IofsReachable/IofsShortestPath) | **Implementiert** (WP06) | ''kernel/iofs_traverse.lyx'' |
| Syscalls 170–173 (bfs/dfs/reachable/shortest_path) | **Implementiert** (WP06) | ''kernel/ring3.lyx'' |
| Named Nodes (IofsNameInit/Bind/Lookup/Unbind/List) | **Implementiert** (WP07) | ''kernel/iofs_names.lyx'' |
| Syscalls 174–178 (name_init/lookup/bind/unbind/list) | **Implementiert** (WP07) | ''kernel/ring3.lyx'' |
FAT32 bleibt das aktive ''sys_open''/''sys_read''/''sys_write''-Backend. IOFS ist direkt über die Syscalls 155–164 erreichbar — als eigenständige Page-Store-Engine, noch nicht als VFS-Dateisystem.
----
===== 19. Verhältnis zu VFS und FAT32 =====
Ring-3-Anwendungen
│
├─ sys_open / sys_read / sys_write → VFS → FAT32 (aktives VFS-Backend)
│
└─ Syscalls 155–178 direkt → IOFS (Page-Store-Engine, kein VFS-Layer)
mkfs_iofs / iofs mount / iofs alloc / iofs read / iofs write / iofs checkpoint
iofs edge-* / iofs bfs / iofs dfs / iofs path / iofs name-*
IOFS ist ab WP02 als eigenständige Page-Store-Engine nutzbar. Der VFS-Mount-Layer (''sys_open'' auf IOFS-Volumes) folgt in M5.
----
===== 20. Quelldateien =====
^ Modul ^ Datei ^
| Block-Allocator, mkfs, Page-I/O | ''kernel/iofs_alloc.lyx'' |
| Mount, Read, Write, Checkpoint (WP02) | ''kernel/iofs_rw.lyx'' |
| Write-Ahead-Log / WAL-Ring (WP04) | ''kernel/iofs_wal.lyx'' |
| Graph-Kanten (WP05) | ''kernel/iofs_graph.lyx'' |
| Graph-Traversal, Kürzeste Pfade (WP06) | ''kernel/iofs_traverse.lyx'' |
| Named Nodes, Name-Store (WP07) | ''kernel/iofs_names.lyx'' |
| VFS-Wrapper (VfsMkfsIofs, VfsIofsMountDisk …) | ''kernel/vfs.lyx'' |
| Syscall-Handler (nr=155–178) | ''kernel/ring3.lyx'' |
| Ring-3-Wrapper | ''bin/bsys.lyx'', ''vega/bsys_vega.lyx'' |
| Shell-Tool mkfs_iofs | ''bin/mkfs_iofs.lyx'' |
| Shell-Tool iofs | ''bin/iofs.lyx'' |
Letzte Aktualisierung: 2026-06-20