--- name: schfs-btree-phase1 description: "SchFS phase 1 (the CoW B-tree) is built and passing; run `make schfs-test` after touching it" metadata: node_type: memory type: project originSessionId: a665e14b-86bd-4b41-a228-51377f3e9225 modified: 2026-08-01T20:34:28.236Z --- The filesystem is called **SchFS** — not "SchFS v2". Design: `docs/architecture/schfs.md`. **Phase 1 is done** (2026-08-01): the copy-on-write B-tree exists and passes its torture harness. - `include/fs/schfs.h` — on-disk format: 4096-byte blocks, 24-byte `(objectid, type, offset)` keys, node header with a self-pointer, uberblock ring. - `kernel/fs/schfs/btree.{c,h}` — portable C against an abstract `struct schfs_bdev`, so the same code runs on a host file and in the kernel. Not yet linked into the kernel. - `tools/schfs_test.c` — the harness. **`make schfs-test`** builds and runs it. Measured geometry: max inline value 1016 bytes, fanout 84 (internal) / 127 (leaf). **Run `make schfs-test` after any change to btree.c.** It checks against a reference model, verifies structure, simulates a crash by discarding uncommitted writes, and confirms both a bit flip and a misdirected write are detected. **A test-design trap worth remembering:** the harness originally used `schfs_key_cmp` inside its own reference model. Deliberately breaking that function then broke the tree *and* the oracle identically, and every check still passed — the suite could not fail. The model now has its own `ref_key_cmp` written out longhand. Mutation-test any new oracle the same way before trusting it. Known and deliberate: delete does not merge or rebalance underfull nodes. The tree stays correct and sorted; merging is phase 3. Next: phase 2 (read-only mount of a v2 image), then writes/transaction groups, then extents. Per-pid `/proc` for ps/top should ride along with that VFS work — see [[schunix-devfs-procfs]].