Files
cubelinux-2/RESUME-cubefs-daemon.md
T

6.3 KiB

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 --storerawget 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, end of session)

  • ./check (fmt+test+clippy -D warnings) GREEN.
  • ./check daemon GREEN — proves the socket-backed record round-trip against a real daemon (3 ignored tests via --ignored all pass).
  • ./check mount (live FUSE, root) GREEN — 27/27 pass. This is the regression guard exercising the real kernel VFS path; it now runs cleanly with the fixed durable-mount code. Run before any future filesystem work.

NEXT STEPS (current)

  1. Repeat the single-daemon + single-mount e2e INSIDE the VM... DONE (see below).
  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... DONE 2026-08-13: /usr/share/applications/cube.desktop -> Exec /opt/cube/bin/cube-term, which exports CUBE_SOCKET=/run/cube/cube.sock and exec /opt/cube/bin/cubec. The skill's #1 gotcha (must use cubec, not cube repl) is satisfied at the file level (not visually launched, per user instruction to not block on viewability).

COMPLETED THIS SESSION

  • Fixed DaemonBackend envelope round-trip (commit 0300def) — was returning the bare body instead of the full record envelope; the --socket mount could not read back FUSE writes. Fixed by round-tripping the full envelope verbatim.
  • Fixed --features mount compile break (commit 8f9e7e0) — Czyx field access.
  • Enforced BOTH bugs via ./check daemon (the two #[ignore]d integration tests now run via --ignored and would fail if either regressed).
  • Host: ./check + ./check daemon + ./check mount all GREEN.
  • VM (/var/lib/cubevm/cubelinux-vm.qcow2, was pre-fix): rebuilt cubefs-mount from the fixed source, rewired cubefs.service to --socket /run/cube/cube.sock with Requires=cube-server.service, and proved a FUSE write survives a daemon restart (WAL persistence). Injected SSH key for cube+root to drive the VM. ./check also passes inside the VM (rustfmt+clippy components added).

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