====== 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