Repository navigation
State of remaining snapshot, nested-VM, and Firecracker integration work #786
Description
State of the fcvm / Firecracker work as of 2026-08-10 UTC
This issue is the handoff for everything left after the current preservation freeze. All uncommitted task work was committed with DCO and pushed before this issue was filed. No additional tests or implementation work were started during the freeze.
Published fcvm pull requests
| PR | Exact head | State | Remaining blocker |
|---|---|---|---|
| #779 — readiness interleavings and VM diagnostics | a55e2d67c98058b8a60892bd06010c856307a829 |
All required code CI jobs and Summary are green. Review-thread gate is clear. Claude failure is the known external entitlement and is intentionally ignored. | Do not merge merely from the green rerun. The distinct ARM teardown failure still needs a causal trace, deterministic RED, and production root fix. Exact-head CodeRabbit review was rate-limited rather than substantive. |
| #744 — UFFD working-set replay | 2bf96f41003afc6bd6e285e9182aeb02b61b0fa9, stacked on #779 |
All required code CI jobs and Summary are green; 7/7 review threads resolved. Local lint, 567/567 unit tests, and hostile-env real replay E2E were green; the E2E reduced demand faults from 19,091 to 2,208 (88%). | Base #779 must be resolved/merged first. Claude entitlement failure is external. |
| #751 — Linux 7.1.7 kernel rebase | f3cd13bfc75869582b2034539f300859613c6e73 |
Lint, packaging, fc-mock, both hosts, both containers, and both x64 root modes are green. Review gate is clear. | Both ARM root modes fail test_nested_run_fcvm_inside_vm after two 1,200-second attempts. SnapshotDisabled also fails, so this is not solely the timer restore bug. Exact-head CodeRabbit review was rate-limited. |
| #784 — actions/checkout 7 | 74d0a95cf3d7ae47fc01ad902a77a5db0ab556e4 |
Expected CI matrix and Summary are green. | Normal review/merge decision. |
| #785 — actions/setup-node 7 | a4824347f224fdecc3e0733c81420bedfa7eee21 |
Open. | Required CI jobs are absent; only skipped Claude jobs exist. This is fail-closed, not green. |
Published internal Firecracker stack
No pull request was opened against upstream Firecracker. These are on the ejc3/firecracker fork only.
| PR | Exact head | Purpose | State / remaining proof |
|---|---|---|---|
| #7 | 6c611684db2aa583c01768385765ef3865c3e6f4 |
Preserve the ARM counter domain across boot, pause/resume, and snapshot restore. | Clean/mergeable; local counter, seccomp, full-unit, checkstyle/checkbuild, and real restore RED/GREEN evidence completed. Final fcvm exact-pin integration remains. |
| #8 | 308032367f6009b3a1cae16f31be7ed97d17e62d |
Raise vsock muxer capacity without leaking the KILLQ_SIZE + 1 connection. |
Clean/mergeable; capacity and leak RED/GREEN evidence completed. |
| #9 | 47f85a92fee93f6ec8616da145a44b8882fda51f |
Add bounded UFFD-minor snapshot memory with robust fd handshake. | Clean/mergeable; real MINOR/CONTINUE/COW E2E, fragmented receive, partial send, checkstyle, and both-arch checkbuild are green. |
| #10 | 27305f49ab3a5d862dc56b5108713b6536d2baa7 |
Enable ARM NV2 while preserving exported API compatibility and failing closed on invalid states. | Clean/mergeable; exact-head checkstyle, both-arch checkbuild, full VMM tests, and review RED cycles are green. Still needs same-hardware flag-off/on NV2, real L2, and fcvm snapshot/restore proof. |
The intended internal stack is main -> #7 timer -> #8 vsock -> #9 UFFD -> #10 NV2. PR #5 is a frozen bundled evidence branch and must not merge. Firecracker PRs #1 and #2 are obsolete predecessor NV2 branches and should be closed as superseded only after the final stack is proven. Do not open an upstream Firecracker PR until the timer-only patch has passed the full fcvm A/B proof and explicit approval is given.
Active WIP branches preserved on GitHub
These are continuations, not merge-ready claims.
| Branch | Exact SHA | Preserved work | Validation already obtained | What remains |
|---|---|---|---|---|
agent/firecracker-commit-pin |
64dfbab316d28c41b0dacf88bb0d9855bf890026 |
Full 40-character Firecracker commit identity, exact checkout verification, arch/framed cache identity, unique concurrent paths, fail-closed launch/restore resolution. | Focused group 42/42 green with deterministic RED/revert cycles for the identified defects. | Rebase onto the intended #751 lineage if it moves; finish broad Make gates and review; open a stacked PR; then pin exact Firecracker full-top SHA 27305f49.... |
agent/pr751-nested-data |
3999e668f9e45f44116f2caeffe262069dd25312 |
Give nested L1 an isolated reflink XFS /root/fcvm-data, stage fcvm plus sibling fc-agent locally, propagate snapshot mode, and retain streamed diagnostics. |
Three invariant defects completed RED/GREEN/revert-RED/GREEN. Earlier invariant/lint gates predate the final fc-agent edit. |
Run current-tree SnapshotEnabled and SnapshotDisabled KVM cases with retries disabled, then final lint/invariant/privileged gates before restacking into #751. |
agent/wip-issue776-snapshot-network-20260810 |
c85cd6a3e4b2f1ab650100998cbaeb1fea990821 |
Cookie-bound SOCK_DIAG cleanup, NEW-flow gate/link boundary, restore readiness/ACK flow, exact vsock handling, default source-built kernel/release work, UFFD fail-closed and health-monitor ownership. | Earlier component/full gates were green before the final combined ports. | Rebase onto the final readiness/Firecracker/kernel chain; compile and run all current combined changes; validate the default two-arch kernel artifact; run the early-ingress root regression; split into reviewable stacked PRs if needed. |
fcvm-prepare-lifecycle |
79153fcddb0e29bbb4bcf4eb52a739cf606cf8b7 |
Explicit fcvm podman prepare lifecycle and publication/teardown handling. |
Focused tests/lint were green on its earlier base. | Rebase, rerun current Make gates and VM/root coverage, then open its stacked PR. |
Preservation-only branches
These refs prevent loss of investigations and prototypes. They are not merge candidates; several are deliberately superseded or contain known-invalid intermediate designs.
| Branch | Exact SHA | Note |
|---|---|---|
agent/archive-loopback-benchmark-20260810 |
504ced3fcb8e86cb12042411f9d3904f5cea98a7 |
Older loopback benchmark/quiescence and analyzer work; partially superseded. |
issue776-scale-harness |
3a198a0332383a59738fdbd97dc71c9bdcb7d66b |
Large request-scale/fault-trace harness. |
agent/archive-benchmark-state-20260810 |
b947cf71f4352d3d7f3ec874ea22fc9d2eb5fd63 |
Mixed benchmark investigation snapshot. |
agent/archive-clone-overlap-runner-20260810 |
a1311bdcee4b9a6fd1469cccffe671edb1425af0 |
Old divergent clone-overlap runner state. |
agent/archive-pr778-red-test-20260810 |
4b800f7737972b937d5c5069fe1a155566bdc1f3 |
Isolated PR #778 RED-test work. |
agent/archive-pasta-stderr-prototype-20260810 |
bfb6740af97695eeb1077ecc7bd2153eebd526ba |
Superseded pasta stderr/timeout prototype. |
agent/archive-uffd-ws-v2-20260810 |
705334a5ac043db0715bcc0595a20a98b51650f0 |
Superseded UFFD working-set prototype with known invalid ordering. |
agent/archive-uffd-ws-rework-20260810 |
920e00bdc1542ec6e3766f37f0d319fafae515c0 |
Earlier UFFD semantic-rework prototype. |
release-uffd-slot-on-peer-exit |
259b7a3308a9e03d5cabc73cf3b93f3c469214a8 |
Isolated UFFD peer-exit/slot investigation. |
agent/archive-uffd-profile-20260810 |
89a1446d67ff07ea5644207c14186a4e26e0a2a3 |
UFFD profiling instrumentation. |
Remaining engineering blockers
- ARM teardown / Cover readiness interleavings and harden VM diagnostics #779: reproduce the original class where a SIGKILLed Firecracker remains non-zombie during concurrent clone teardown. Capture the exact Firecracker D-state stack and the contemporaneous kcompactd/KVM MMU-notifier owner duration. Existing evidence shows bounded
softleaf_entry_wait_on_locked -> migration_entry_wait -> do_swap_pagewaits and nested stage-2 unmap warnings, but does not yet prove the 108-second/default-profile failure. Add a deterministic RED and fix the production root cause without retries, sleeps, serialization, skips, or weaker assertions. - Repin deployable kernels 6.18.3 -> 6.18.44 (7.x wedges nested guests) #751 nested local state: validate
3999e668...with both snapshot modes and integrate it cleanly. SnapshotDisabled currently failing in CI means timer work alone cannot close Repin deployable kernels 6.18.3 -> 6.18.44 (7.x wedges nested guests) #751. - Immutable Firecracker integration: finish and review
64dfbab3..., then create a stacked fcvm PR that pins and attests the exact full-top Firecracker commit rather than a mutable ref or 12-character identity. - Firecracker full-stack proof: on identical ARM/NV2 hardware and workload, run timer fix off/on with all other deltas fixed; run NV2 flag off/on; prove an actual L2 launch and actual snapshot load; capture monotonic/timer continuity, timer-emulation rate, vCPU/device-thread progress, and no accumulated drift. Keep any eventual upstream proposal timer-only.
- Snapshot-network correctness: finish the cookie/gate/link/ACK design in
c85cd6a3...; verify default kernels contain INET_DIAG, INET_DIAG_DESTROY, and PACKET; fail closed for unsupported/legacy snapshots; run exact early-ingress and replacement-generation tests. - Prepare lifecycle: rebase and validate
79153fcd...with real VM coverage. - Makefile FILTER defect:
_test-unitcurrently ignores$(FILTER)even thoughmake test-unit FILTER=...advertises it. Add a deterministic Makefile RED and focused fix in its own stacked PR. - Review integrity: do not count a green
CodeRabbitstatus whose description says rate-limited/skipped as a substantive review. Re-request exact-head review where noted. Continue ignoring only the explicitly authorized Claude entitlement failure.
Preservation audit
- Every source change found in the task-related dirty worktrees was committed and pushed above.
- The only remaining dirty worktree entry is an untracked generated
targetsymlink in/home/ubuntu/fcvm-btrfs-local-container; it is not source and was intentionally not committed. - No test/build/VM process was left running by the preservation pass.
Activity
Honor FILTER in _test-unit
Close the zero-check hole for ci.yml's ignored paths
ejc3 commentedon Aug 10, 2026
Session update — 2026-08-10
Seven of the PRs listed above are merged, the #751 blocker is root-caused and fixed, and the ARM teardown item has its evidence machinery landed. A new production bug was found and proven along the way. Details below; every claim here has an artifact behind it.
Merged to main
Summarycheck per PR_test-unitFILTER defect#751 was not a timer bug — the whole 7.x line wedges nested guests
A/B/A on one c7gd.metal box, holding host kernel (6.18.3-fcvm with the DSB patches), Firecracker build, rootfs and test fixed, changing only the L1 guest kernel:
test_nested_run_fcvm_inside_vmThe L2 kernel boots in about a second and keeps running for the full 600s — entropy reseeds on schedule, its vsock muxer answers every probe — while L2 userspace never reaches the container, stopping at the first burst of virtio-blk reads against the FUSE-backed root disk. L1's FUSE path is not the constraint: with no L2 running, the same file through the same mount sustains 1.6 GB in 7.2s.
Two things that had to be fixed before this was even visible, both in #751: the FUSE
remap_file_rangepatch's second hunk targeted afuse_file_operationsblock that only exists in 7.x, so it failed to apply and took the build down; andRUST_LOGdoes not cross the exec boundary, so a full 600s wedge had been capturing 262 bytes of health-monitor warnings instead of the L2 console.New: fcvm reports a VM ready when the guest is not answering
Found by running the Chromium shared-nothing benchmark. This is a production bug, not a benchmark artifact.
In
src/network/pasta.rsthe readiness loop issues an ARP-triggering ping and recordsping.status.success()— but only logs it. The branch that returns success isif neighbor_is_resolved(...), so a resolved neighbour entry alone is accepted.wait_for_port_forwarding_untilthen "verifies published ports" with aTcpStream::connectto the host-side address; pasta is a userspace stack whose listener accepts regardless of guest state, and in the captured failure that completed 95 microseconds later. fcvm then logsVM lifecycle ready.Two independent 809-request runs, one clone restored per request, strictly sequential, loadavg 0.43–0.67:
1,603 clones whose ping was answered: zero failures. The failures are
TimeoutErrorat CDP stageconnectandConnectionResetErrorat stageenable, taking 104–120s against a 0.24–0.55s norm — hard hangs to the client's own deadline. Fix in flight: require positive evidence the guest answered, keep the existing retry-until-deadline, and fail fast with a named error instead of hanging.Ruled out, each with evidence rather than argument: host load (idle); endpoint collision between concurrent clones (requests are strictly sequential — each starts the millisecond the previous ends); UFFD service starvation (the file backend, which never touches the UFFD serve, fails at a higher rate); and the 13x Firecracker log volume in failing clones (451 extra lines are vsock muxer chatter from the health monitor polling for 105s — an effect of the duration, not a cause).
Still open, and stated as open: why the ping goes unanswered for ~0.8% of clones. The guest answers ARP (the neighbour resolves) but not ICMP within 200ms, and never recovers across 100+ seconds while vsock keeps working — so it is crawling on the IP path, not dead. Because vsock exec still works during the failure, the guest is interrogable exactly when it is broken; failure-time capture of the guest's own
ip neigh/ss -ltnp/dmesgplus a healthy-clone control is in flight, since today the harness tears the clone down and the evidence dies with it.The withdrawn CDP A/B: one question closed, the gate still not met
REVIEW.md recorded the
WsClosedroot cause as undetermined and called the_recv_untilcoalesced-bytes fix "a variable removed, NOT a diagnosis." Across 104 CDP requests on the UFFD run there are zeroWsClosedrecords, against 6/60 = 10% before. That fix was the diagnosis.The availability gate (>=200 CDP requests per backend at 0 failures) is not met: 3/809 uffd, 7/809 file. But every one of those failures is now attributed to the readiness bug above rather than unexplained.
Benchmark suite defects (#790)
maketargets that do not exist —bench-quick,bench-throughput,bench-operations,bench-protocol, allNo rule to make target, exit 2.single_op/getattrandsingle_op/lookupstat one fixed path in a loop, so FUSE's 1sattr_timeoutserves them and the daemon is never contacted: 1.06µs against a 1.02µs host baseline, published as "metadata ops have ~5% overhead", while every op that reaches the server costs 40–56x.make benchroot-ownstarget/criterionvia the privileged runner, so the unprivileged protocol suite fails every write withPermission denied— it prints timings and persists nothing, so criterion can never hold a baseline for it — and the same tree trips_test-root.Not yet done and deliberately not guessed: PERFORMANCE.md's parallel-write table needs re-measuring. The host baseline alone came in at 863ms against a documented 161ms, and every reader count >=4 now sits at that same host floor.
Environment traps, now recorded in bench/chromium/AGENTS.md
Each cost a full cycle and each reports a cause that is not the cause. Rootless podman with no login session fails as
default OCI runtime "crun" not foundwhile/usr/bin/crunexists — the real error ismkdir /run/user/1000: permission denied, fixed withloginctl enable-linger. Building the image under one identity and running fcvm under another puts them in two podman stores, which the golden phase's identity guard correctly rejects in a message that reads like a corrupt cache. Andbuildsucceeding says nothing aboutfcvm setuphaving run.Corrections to this issue's earlier text
Still open
prepare+ bench/chromium:preparewrites a content-keyed system cache snapshot, but the benchmark needs a caller-named tag it cansnapshot serveper matrix arm, aUsertype thatprunewill not delete, and--force. All three in flight; the golden phase then collapses ontoprepare.Summarystill needs to be made a required check on main — the point of Give every PR exactly one Summary check #787.ejc3 commentedon Aug 10, 2026
Addendum — attribution result, a refuted fix, and WIP verdicts
The 7.x wedge is not our FUSE patch
The control named in the previous comment has now run properly: 7.1.8 built with every arm64 patch except
0001-fuse-add-remap_file_range-support.patch. Verdict RED,INNER_RC=1.Verified before believing it, because three earlier attempts each produced something that looked like a result and was not:
fuse_remap_file_range= 0,.remap_file_range= 0) while still carryingdsb(sy)innested.c;7.1.8+patches-noremap;vmlinux-nested-7.1.8-aarch64-a720f870d4d2.bin.The three false starts are worth recording because each is a reusable trap: a config silently regenerated back to the baseline (the probe script's own
fcvm setup --generate-config --forceoverwrites the pin at the top of every run);stringson a compressed vmlinux reporting 0 occurrences of the patched symbol for both kernels, an instrument that cannot distinguish them; and readingINNER_RC=0without checking which kernel produced it.So the FUSE patch is cleared. The control still carries the other arm64 patches (NV2 DSB,
mmfr4-override, psci-debug,wfx-stopped-exit), and a fully unpatched 7.1.8 cannot practically be tested — withoutmmfr4-overridethe L1 does not advertise NV2, so there is no L2 to test. Defensible statement: the wedge survives removal of the FUSE patch, reproduces on 7.0.14/7.1.7/7.1.8, and has never appeared on 6.18.x. Upstream is now the stronger candidate, not a proven one. This control is n=1; it carries weight because the wedge has appeared on every 7.x attempt and never on 6.18.x.The readiness fix was refuted by CI, and pointed at the right design
PR #792 required the readiness ping to be answered.
test_clone_port_forward_rootlessthen failed on ARM:The guest's network came up — fc-agent flushed ARP and resolved the gateway. What did not arrive was an ICMP echo reply, because in rootless mode pasta is a userspace stack that does not reliably forward ICMP to the guest. The comment that was overridden said exactly this. The 803/808 statistic behind the change came from bridged clones and was generalised to pasta rootless without checking.
The defect is still real — readiness declared from a neighbour entry with no proof the guest answered is what produces the 100 s hangs — but ICMP is the wrong instrument. The correct signal already exists and the guest already computes it: fc-agent knows when post-restore networking is up and simply does not tell fcvm. A readiness ACK over the vsock channel fcvm already holds is protocol-independent and works in every network mode. That is the "restore readiness/ACK flow" carried by
agent/wip-issue776-snapshot-network-20260810, so the requirement belongs there. #792 is a draft; itsGuestProbeseam and tests are worth keeping, since making the decision unit-testable is what let CI's failure be attributed in one read.WIP branch verdicts
Verified by content, not by branch name. Four branches fully contained in main were deleted (
vm-lifecycle-fuzz,sleep-signals,teardown-pasta-pdeathsig,uffd-minor-continue).agent/pr751-nested-datarelease-uffd-slot-on-peer-exituffd-fail-closedissue776-scale-harnessreqbench.pyis closed-loop, this drives an open-loop arrival rate and deconfounds FILE-vs-UFFD within a rate interval.agent/archive-loopback-benchmark-20260810cleanup_vmmoves the health-monitorJoinHandleinto atokio::select!, so the timeout arm drops it — which detaches rather than cancels, leaving the monitor running while cleanup destroys its netns. Same class as thewait_for_stderr_eofdefect review caught today, second location.agent/archive-benchmark-state-20260810working_set.rs:5-13asserts; nothing on main can re-derive them.agent/archive-clone-overlap-runner-20260810max-threads = 1so one process cannot produce that interleaving.agent/archive-pasta-stderr-prototype-20260810agent/archive-pr778-red-test-20260810agent/archive-uffd-ws-v2-20260810agent/archive-uffd-ws-rework-20260810SO_PEERCRED+pidfd_open(pid), which main rejects as PID-recycling-unsafe.agent/archive-uffd-profile-20260810No branch merits landing wholesale. Deletions are being held until the extractions land, so nothing is dropped before it is salvaged.
Independent finding:
FCVM_UFFD_MAX_CLONESis documented nowhere outsidesrc/while twelve otherFCVM_*vars are.Process failure worth recording
PR #790 was merged without reading its review comments, which this repo's rules make mandatory. Reading them afterwards found four P1s, all legitimate — including that
make bench-quickcannot run at all, because criterion flags land before Cargo's--separator. A broken documented target shipped inside the PR whose purpose was fixing broken documented targets, and it shipped because it was verified withmake -ninstead of being run. All five findings are being fixed with the requirement that each is proven by executing the target.ejc3 commentedon Aug 10, 2026
Final state for handoff
Summaryis now a required status check onmain(strict=false, contexts=["Summary"]), with every other protection setting preserved —enforce_adminsfalse, force-push and deletions still blocked. Enabled only after #791 landed and #785 demonstrated a green Summary on a docs-only PR, which is the class that would otherwise have been blocked outright.Note what this does and does not buy: it closes the hole where a PR could sit
CLEANwith zero executed checks. It does not stop a direct push to main by the repo owner, becauseenforce_adminsis off — so thepush.default=upstreamtrap that put one commit straight onto main today is still open. Turning on "include administrators" would close it at the cost of hand-pushing emergency fixes.Merged to main today (10)
#784, the
_test-unitFILTER fix, #779, #789, #744, #751, #788, #787, #791, #785.Open PRs (6)
fcvm podman preparewith a nameable, keepable snapshot#797 is the candidate wedge fix, and its adjudication is honest about what it does not explain
Established from artifacts, not argued: the benchmark passes no
--kernel-profile, so it ran the default profile = Kata 6.12.47, whose embedded config on both arches reads# CONFIG_INET_DIAG is not set. Soss -Kcould destroy nothing, the documentedconntrack -Ffallback needs a binary the rootfs never installs, and its error arm isErr(_) => {}. Post-restore TCP cleanup on main has been a silent no-op. Independently, the old filter spareddst 10.0.2.0/24, and under pasta a host→guest published-port connection has peer10.0.2.2— exactly the socket class a new CDP client collides with. Both premises of the stale-socket theory hold on main and this PR fixes both.But it does not explain the ping predictor: a stale TCP socket cannot stop a guest answering ICMP echo. And the PR removes
ip neigh flush all, which is a falsifiable risk — if the wedge is neighbour-state related this could make it worse. That prediction is written into the acceptance test.Acceptance test (needs Graviton3-class host with
/dev/kvm): rebuild the default kernel, confirmCONFIG_INET_DIAG=yinside a booted guest, build a golden snapshot with a non-empty non-loopback socket set, check a restored clone's manifest for non-zero cookies before cleanup, then runreqbench.sh runat 809 requests for both backends. Report the ping-predictor table, not the overall rate. Failures to zero ⇒ this was the cause. Rate drops but ping-unanswered clones still fail disproportionately ⇒ stale sockets were contributory and the ICMP fault is separate. Unchanged ⇒ the PR is right on its own merits and is not this bug. Rate goes up ⇒ theip neigh flushremoval.#795 carries a live-bug fix and a defect sweep
cleanup_vmmoved the health-monitorJoinHandleinto atokio::select!, so the timeout arm dropped it — detaching rather than cancelling, leaving the monitor running while cleanup destroyed its netns. Witnessed red. All nine detached-JoinHandlesites in the tree were then examined; one more is worth a follow-up (fc-agent/src/proxy.rs:272,275, self-limiting but real), and the rest are correct or deliberate.#794 is remediation of a process failure
#790 was merged without reading its review comments. Four P1s were waiting, including that
make bench-quickcould not run at all — criterion flags landed before Cargo's--. Running the fixes then exposed a fifth defect nobody had reported: criterion resolves a relativeCARGO_TARGET_DIRagainst the bench binary's cwd, so every suite wrote tofuse-pipe/target/criterionwhile the ownership repair scannedtarget/— the repair had never fired, andbench-protocolwas silently persisting nothing.CRITERION_HOMEnow pins one absolute path.The metadata benchmarks now force real round trips via
statx(AT_EMPTY_PATH|AT_STATX_FORCE_SYNC)and each asserts it reached the server before measuring. Measured: cache hits ~298 ns, round trips 83.1 µs and 120.3 µs — 293x and 396x, against the "~5% overhead" PERFORMANCE.md published. That conclusion is removed.Still open
mmfr4-overridethere is no L2.preparenow that Add fcvm podman prepare with a nameable, keepable snapshot #796 gives it a caller-chosen tag, aUsersnapshot type that survives prune, and--force.fc-agent/src/proxy.rsdetached handles;spawn_victim()'s orphanedsleep 600wedging the nextmakefor up to 10 minutes;tests/test_serve.rsunused import under--no-default-features.ejc3 commentedon Aug 14, 2026
Superseded by #819, the current comprehensive tracker. Everything in this 2026-08-10 snapshot has either merged (#808/#809/#792/#805/#815/#816/#817), been root-caused and published in the benchmark report, or is enumerated as an open item in #819.