Files
cubelinux-2/RESUME-cubefs-daemon.md
T
CUBELinux-2 0e3f18d106 docs: mark VM durable-socket e2e done (NEXT STEP 1) in RESUME doc
VM qcow2 was pre-fix; rebuilt cubefs-mount from fixed source inside the VM,
rewired cubefs.service to --socket /run/cube/cube.sock with
Requires=cube-server.service, and proved a FUSE write survives a daemon
restart via the durable store+WAL. ./check also green inside the VM.
2026-08-13 06:25:39 -04:00

100 lines
5.6 KiB
Markdown

# RESUME POINT — cubefs FUSE <-> cube-server daemon durability wiring
Saved: 2026-08-13 (user paused session; pick up from here).
## GOAL (from task list)
Make cubefs a real FUSE view of the running `cube-server` daemon's durable
store, and prove a FUSE write lands in the daemon WAL and survives a daemon
restart. (Cube-server is a pure command server — it does NOT mount FUSE
itself; the FUSE view is a separate `cubefs-mount --socket` process, per the
PDF/spec architecture.)
## WHAT IS DONE (compiles + tests green)
1. Raw-coordinate command family added to `cubesys/src/commands.rs` dispatch:
`rawget <c> <z> <y> <x>`, `rawput <c> <z> <y> <x> <hex>`,
`rawdel <c> <z> <y> <x>`, `rawkeys`, `rawscan <c> [z] [y]`.
Helpers added: `parse_u8`, `hex_encode`, `hex_decode`.
(rawput/rawdel go through the durable `ConcurrentStore` so they hit the WAL.)
2. `cubefs/src/backend.rs` — new `DaemonBackend` implementing `CubeBackend`
over the daemon Unix socket (lazy length-prefixed framing, duplicated from
`cubesys::net` to keep cubefs free of a cubesys dep). Registered in
`cubefs/src/lib.rs` (`pub mod backend; pub use backend::DaemonBackend;`).
`DaemonBackend` is Clone (clones share socket path, reconnect lazily).
3. `cubefs/src/bin/cubefs_mount.rs` — `--socket PATH` mounts against a live
daemon; without `--socket` it falls back to an in-memory `HashBackend`.
4. `cargo build --workspace` GREEN. `cargo test --workspace` GREEN.
(Note: `DaemonBackend` is NOT yet exercised by any unit/integration test —
only manual host verification below.)
## WHAT IS PROVEN (host-level, same kernel/code path as the VM)
A. Daemon durability + WAL replay: launched daemon with `--store`, `rawput`,
killed it with `kill -9` (crash), relaunched same `--store` → `rawget`
returned the written value; recovery log showed
`wal_recovery: applied 1`. So the DAEMON half of the durability story works.
B. Direct `rawput` from a Python client checkpoints to `store.json` (4-byte
record appeared after the checkpoint interval). Confirmed daemon is alive,
reachable, and durable on the host.
## WHAT IS BROKEN (the open bug) — RESOLVED 2026-08-13 (commit 0300def)
Two separate bugs hid behind the "FUSE write didn't reach the daemon" symptom:
1. `--features mount` did not compile (E0308: `CubeFs<DaemonBackend>` vs
`CubeFs<HashBackend>` are distinct types in the `match &socket`). The build
failed silently, so the running binary was the IN-MEMORY build and
`--socket` was ignored. FIXED in 8f9e7e0 by type-erasing the backend
(`Box<dyn CubeBackend + Send + Sync>` + a forwarding impl).
2. Even after (1), `DaemonBackend` round-tripped the WRONG layer: `put` stripped
the record envelope to a bare body before `rawput`, but `get` returned that
bare body as if it were a full record — so the FUSE read-back path
(`get_record`) could not decode it, and the socket backend diverged from the
in-memory backend. FIXED in 0300def: `DaemonBackend::put`/`get` now round-trip
the FULL envelope (header+body) verbatim through rawput/rawget, matching the
in-memory `HashBackend` exactly. This is now an enforced `./check daemon`
integration test (spins up a live cube-server, runs the two `#[ignore]`d
daemon-backed tests via `--ignored`).
## GATE STATUS (2026-08-13)
- `./check` (fmt+test+clippy -D warnings) GREEN.
- `./check daemon` GREEN — proves the socket-backed record round-trip against a
real daemon.
- `./check mount` (live FUSE, root) — should be run before any future
filesystem work; it is the only stage exercising the real kernel VFS path.
## NEXT STEPS (current)
1. ~~Repeat the single-daemon + single-mount e2e INSIDE the VM...~~ DONE 2026-08-13
(this session):
- VM qcow2 was pre-fix (written 04:49, before 8f9e7e0/0300def). Rebuilt
cubefs-mount from the fixed source inside the VM (~13s, deps cached).
- Rewired /etc/systemd/system/cubefs.service from `--seed` (in-memory) to
`--socket /run/cube/cube.sock` with `Requires=cube-server.service`.
- E2E proven: wrote /cubefs/c011/z007/y003/x009 -> reached daemon store
(cube-store.json + .wal grew); record SURVIVED a `systemctl restart
cube-server` (read back through FUSE after restart). Durable-mount
contract holds inside the VM. ./check also passes there (after adding
rustfmt+clippy components to the VM stable toolchain).
2. Add a `--features mount` build to the VM image's build step / `./check` so the
durable mount can't silently regress to in-memory again. (DONE on host ./check;
VM image build step not yet updated.)
3. Optionally surface `DaemonBackend::put` failures as FUSE EIO instead of
eprintln-only (best-effort today, acceptable).
4. Confirm the desktop "CUBE Shell" launcher execs `cubec` (not `cube repl`) and
reaches the daemon (skill's #1 gotcha). Not yet visually verified.
## KEY FILES
- /home/CUBELinux/CUBELinux-2/cubesys/src/commands.rs (raw* commands + helpers)
- /home/CUBELinux/CUBELinux-2/cubefs/src/backend.rs (DaemonBackend — FIX HERE)
- /home/CUBELinux/CUBELinux-2/cubefs/src/lib.rs (module export)
- /home/CUBELinux/CUBELinux-2/cubefs/src/bin/cubefs_mount.rs (--socket wiring)
- /home/CUBELinux/CUBELinux-2/cubestore/src/lib.rs (CubeStore::put_raw L358)
- /home/CUBELinux/CUBELinux-2/cubefs/src/vfs.rs (CubeFs::write L392)
## TEST HARNESS NOTES
- Launch daemon/mount as `terminal(background=true)` so Hermes tracks them.
- A `python3` one-shot client for rawget/rawput:
socket connect, sendall(struct.pack('<I',len(payload))+payload),
read 4-byte len then body.
- Daemon flags used:
`--socket S --store STORE.json --recovery-log REC.ndjson --allow-anonymous
--checkpoint-ms 400 --wal-fsync-ms 30`