Skip to content

Open work after the restore-latency round: remaining 136ms, eth0 assumptions, cache opt-outs, 7.x wedge attribution #806

Description

@ejc3

Everything I still have open after the restore-latency work landed (#802, #803, #804 merged; #805 open). Each item below was re-verified against main at 0594e96 today rather than carried forward from notes, and items already covered by an existing issue are cross-referenced instead of restated.

Restore path: the remaining 136ms

The guest restore ACK is now 136ms p50 / 195 p95 (from ~643ms), attributed per phase by the telemetry that rides every ACK. What is left, measured on Graviton3 at concurrency 1 across 141 restores:

phase p50 p95
boundary reopen 66.1 96.1
gateway ARP 27.6 41.0
boundary verify 16.4 34.3
clock step 3.6 12.3
boundary destroy 0.9 1.4
  • Reopen (66ms) is the last spawn cluster. It is one iptables-restore per family plus one ip -batch per family. The link up/down already moved to SIOCSIFFLAGS; the same treatment for route reinstatement (rtnetlink RTM_NEWROUTE) and for the gate teardown would remove the last four spawns on the path. Each spawn on a freshly restored clone costs roughly 15-20ms because its text and libraries fault back in through the memory backend, so this is where the remaining budget is.
  • Gateway ARP (28ms) has no spawn left — it is already a native AF_PACKET frame with no reply wait. The cost is first-touch page faults in that code path, which suggests prefetching the boundary's working set into the clone rather than micro-optimising the send.
  • Verify (16ms) is two iptables -S reads and is the safety argument itself, so it should only go away if the gate state can be proven some cheaper way (reading nftables directly, or carrying a gate fingerprint in the manifest and validating that).

Interface naming: eth0 is still assumed outside the snapshot boundary

a6b6af4f (#797) taught the snapshot boundary to discover the guest's external interface, because Cloud Hypervisor's PCI virtio-net is renamed to enp0s4 by udev while Firecracker's MMIO device keeps eth0. The rest of the codebase still hardcodes the name. Verified counts of "eth0" as a literal in code (not comments, not test fixtures) on main:

  • fc-agent/src/network.rs — 8 sites: IPv6 add/del/show, the IPv6 default route, and the loopback DNAT publication

  • src/network/{veth,routed,bridged}.rs, src/commands/podman/vm_config.rs, src/storage/snapshot.rs

  • rootfs-config.toml — the 10-eth0.network systemd unit and its mmds.conf drop-in match on Name=eth0

  • Reuse the boundary's external_interface() discovery (sysfs device symlink) for these paths, or thread the discovered name through once at boot. The systemd unit is the interesting one: it runs before anything of ours and matching on Name=eth0 is what makes the kernel ip= address survive the rename.

Snapshot cache: three opt-outs remain

AGENTS.md says cache everything and take no opt-out unless behaviourally required. snapshot_cache_opt_out (src/commands/podman/mod.rs:313) still has three:

  • FCVM_BOOTPLAN=vsock — root-caused, small fix. snapshot_key() hashes the serialized FirecrackerConfig, which has no field for the boot-plan transport, so a vsock-built snapshot and an MMDS-built one collide on one key; the opt-out exists only to stop the former being restored under the latter. Adding a serialized transport field gives vsock-built entries their own namespace and lets the opt-out be deleted. Guard: that struct has #[serde(skip)] fields, so confirm the new field is not skipped, or the key will not change.
  • Cloud Hypervisor — the podman run pre-start snapshot cache is simply not wired up for CH (explicit snapshot create/run already work). Wiring it is the real fix and is larger than the above. Related: [epic] Hypervisor-agnostic abstraction: support Firecracker AND Cloud Hypervisor (the two microVMs) behind a pluggable trait #632.
  • rootfs_override — a disk-only clone cold-boots from a captured disk, so this looks behaviourally required. Re-verify against the principle rather than assuming.

Kernel: attribute the 7.x nested wedge

#751 repinned to 6.18.44 away from a wedging config; attribution between upstream 7.x and our FUSE remap patch is still undetermined. The previously banked CONTROL_VERDICT=RED is invalid and should not be reused: the 7.1.8-noremap inner run died at Reflink copy failed ... requires a kernel profile with this patch, a prerequisite failure that never reaches the virtio-blk read path under test. A positive control is banked (6.18.44 + all patches, inner run succeeded).

Stress beyond the gate

bench/restore-matrix.py (#805) covers backend × network × concurrency 1/4/16 × volumes × kill-mid-restore, and is clean at 33/33 cells. It is a closed-loop harness.

  • Drive the open-loop scale harness (reqscale, from Salvage the unlanded work from the archived WIP branches #795) at arrival rates the closed-loop bench cannot produce, deconfounding FILE vs UFFD within a rate interval, plus sustained and fan-out phases. The goal is to surface defects, not to publish numbers: every failure gets root-caused rather than retried.
  • A matrix cell that exercises the boundary repair path in vivo. Today only the unit tests cover verified_armed == false; the natural in-vivo shape is a --privileged workload mutating the gate from inside the guest while a clone restores, which is also the scenario that motivated asserting the link-down unconditionally.

CI hygiene

  • Deduplicate the btrfs bootstrap. .github/workflows/kernels.yml sets up /mnt/fcvm-btrfs inline in two places; make setup-btrfs does the same thing and is what a developer runs. One of them should call the other so they cannot drift.

Already tracked elsewhere (listed so this issue is not read as the whole picture)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions