feat(vmm): v0.4 Phase 5a — memfd_create() helper for live-fork backing#186
Merged
Conversation
First piece of forkd-side wiring for the v0.4 live-fork path. The patched Firecracker fork (deeplethe/firecracker, branch forkd-v0.4-mem-backend-shared) gives FC the `MAP_SHARED` mmap option; this PR gives the forkd controller the matching helper to produce a memfd whose fd it can hand to FC. New module: `forkd_vmm::memfd` - `MemfdRegion` — owns the fd, exposes `/proc/self/fd/<N>` as the `mem_backend.backend_path` to send to FC, releases the backing pages on Drop. - `create_and_populate(source, name) -> Result<MemfdRegion>` — opens the snapshot's memory.bin, creates a memfd with MFD_CLOEXEC, ftruncates it to the source size, copies bytes in. Fails early on missing source (no partial memfd left dangling). - Linux-only via `#[cfg(target_os = "linux")]`. Non-Linux stub returns an explicit error rather than silently falling back. Three tests (Linux-only): - `create_and_populate_succeeds_for_small_file` — fd_path is `/proc/self/fd/N`-shaped, size_bytes matches. - `populated_memfd_content_matches_source` — copies 8 KiB of a byte-sequenced pattern through and reads it back via try_clone'd fd; catches off-by-one and direction bugs. - `missing_source_file_errors` — fails fast, error message includes the missing path. Not wired into Vm::boot yet. That's Phase 5b — adds a `BootConfig::with_memfd_backing(...)` option and threads `shared: true` into the JSON sent to Firecracker. Splitting it lets this PR be the zero-runtime-impact piece that lands first. Refs #101, docs/VENDORED-FIRECRACKER.md.
WaylandYang
added a commit
that referenced
this pull request
May 29, 2026
…y_with (#187) * feat(vmm): v0.4 Phase 5b — MemoryBackend::MemfdShared via restore_many_with Wires the memfd helper from #186 into the existing parallel-restore path. When ForkOpts::memory_backend == MemoryBackend::MemfdShared, each restored child gets its own memfd (created from the snapshot's memory.bin via forkd_vmm::memfd::create_and_populate) and the JSON PUT to /snapshot/load uses /proc/self/fd/<N> with mem_backend.shared: true. The patched Firecracker at deeplethe/firecracker:forkd-v0.4-mem- backend-shared honours the new shared flag and mmaps with MAP_SHARED; forkd-controller can then arm UFFDIO_WRITEPROTECT on the same backing in Phase 6 to capture dirty pages asynchronously. Changes: - MemoryBackend gains a MemfdShared variant. Docstring spells out the patched-FC dependency loudly enough that an operator running vanilla FC + setting MemfdShared knows they're on the wrong path. - Vm gains a public memfd: Option<MemfdRegion> field. Held for the VM's lifetime; Drop closes the fd and the kernel reclaims pages. - restore_many_with's pre-flight check now permits both File and MemfdShared; Userfault still bails (still v0.3 scaffolding). - After spawn, a Phase 1.5 loop creates per-child memfds when MemfdShared. Failure surfaces with the child index + the source path in the error chain — same Drop-on-error guarantee as the helper module. - The single shared JSON body is replaced with a per-child Vec<String> so each child's PUT can reference its own /proc/self/fd/<N> path without sharing state. Not in this PR: - Fresh-boot (non-snapshot) memfd backing in Vm::boot. v0.4's live- fork only needs the restore path; that's the only one wired. - `forkd doctor` check that the runtime FC binary supports the shared flag (Phase 8). Refs #101, deeplethe/firecracker#1. * fix(vmm): add memfd: None to Vm::boot constructor (missed in 5b) * style: drop redundant .into_iter() (clippy::useless_conversion)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First piece of forkd-side wiring for the v0.4 live-fork path. The vendored Firecracker fork (merged context: #185) gives FC the `MAP_SHARED` mmap option; this PR gives the forkd controller the matching helper to produce a memfd whose fd it can hand to FC.
New module: `forkd_vmm::memfd`
Linux-only via `#[cfg(target_os = "linux")]`. Non-Linux stub returns an explicit error rather than silently falling back to file-backed semantics.
Tests (Linux-only, 3 of them)
```
$ cargo test -p forkd-vmm --lib memfd
test memfd::tests::missing_source_file_errors ... ok
test memfd::tests::create_and_populate_succeeds_for_small_file ... ok
test memfd::tests::populated_memfd_content_matches_source ... ok
test result: ok. 3 passed; 0 failed
```
`cargo fmt --all -- --check` clean. `cargo check --all-targets` clean.
What's deliberately not in this PR
Not wired into `Vm::boot` yet. That's Phase 5b — adds a `BootConfig::with_memfd_backing(...)` option and threads `shared: true` into the JSON sent to Firecracker. Splitting it lets this PR be the zero-runtime-impact piece that lands first; Phase 5b builds on top.
Refs #101, `docs/VENDORED-FIRECRACKER.md`, `DESIGN-v0.4-USER-API.md` Phase 5 breakdown.