Skip to content

feat(snapshot): support full dumps to non-seekable files - #6232

Open
coffeeinit wants to merge 5 commits into
firecracker-microvm:mainfrom
coffeeinit:feat/snapshot-fifo-pr
Open

coffeeinit wants to merge 5 commits into
firecracker-microvm:mainfrom
coffeeinit:feat/snapshot-fifo-pr

Conversation

@coffeeinit

Copy link
Copy Markdown

Changes

Full snapshots (SnapshotType::Full) can now write guest memory to
non-seekable files such as FIFOs, so memory can be streamed to another
process (compression, encryption, upload) without landing on local disk.

  • snapshot_memory_to_file() detects non-regular files via
    metadata().file_type().is_file() and skips set_len()/truncate-size
    handling/sync_all() for them (previously failed with EINVAL).
  • New GuestMemoryExtension::dump_non_seekable(): writes unplugged slots
    as zeroes in 4K chunks instead of seek()ing over them (previously
    panicked with ESPIPE via .unwrap()).
  • dump_dirty() (diff path) intentionally untouched: seeked-means-clean
    is load-bearing there.
  • Tests: test_full_snapshot_to_fifo (integration, FIFO drained on a
    reader thread, bytes equal to a regular snapshot) and
    test_dump_non_seekable_matches_dump (unit, Vec<u8> as the
    non-seekable writer). Implements PR-1 of [Feature Request] Support non-seekable file descriptors (e.g. FIFOs) for snapshot memory output #6030 as agreed with
    marco-marangoni.

Reason

Support pointing mem_file_path at a FIFO to stream snapshot memory
(#6030). Follow-up efficient sparse wire format intentionally left for
PR-2 per maintainer direction.

License Acceptance

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license. For more information on
following Developer Certificate of Origin and signing off your commits,
please check CONTRIBUTING.md.

PR Checklist

  • I have read and understand CONTRIBUTING.md.
  • I have run tools/devtool checkbuild --all to verify that the PR passes
    build checks on all supported architectures. (runs in Buildkite)
  • I have run tools/devtool checkstyle --no-clippy to verify that the PR
    passes the automated style checks. (added lines verified nightly-fmt
    clean; full checkstyle runs in Buildkite)
  • I have described what is done in these changes, why they are needed, and
    how they are solving the problem in a clear and encompassing way.
  • I have updated any relevant documentation (both in code and in the docs)
    in the PR.
  • I have mentioned all user-facing changes in CHANGELOG.md.
  • If a specific issue led to this PR, this PR closes the issue. (implements
    PR-1 of [Feature Request] Support non-seekable file descriptors (e.g. FIFOs) for snapshot memory output #6030; wire-format follow-up remains)
  • When making API changes, I have followed the
    Runbook for Firecracker API changes. (no API surface change)
  • I have tested all new and changed functionalities in unit tests and/or
    integration tests.
  • I have linked an issue to every new TODO. (no new TODOs)

  • This functionality cannot be added in rust-vmm. (Firecracker
    snapshot-path specific: plugged-slot handling and KvmVm backing-file
    logic)

@marco-marangoni
marco-marangoni self-requested a review September 18, 2026 15:23
@marco-marangoni marco-marangoni self-assigned this Sep 18, 2026
Comment thread src/vmm/src/vstate/memory.rs Resolved
Comment thread src/vmm/src/vstate/memory.rs Outdated
}

fn dump_non_seekable<T: WriteVolatile>(&self, writer: &mut T) -> Result<(), MemoryError> {
let zeroes = &mut [0u8; 4096];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing each 4KiB separately might be terribly inefficient since each write to the FIFO results in a syscall.

I'd argue that using a bigger buffer would yield more performance. E.g. using a vec![0u8; chunk], where chunk is the length to "seek" limited to let's say 2MiB.

Could you also check whether a vec![0u8; 2MiB] call on a normal system without hugepages/THP actually consumes RSS from Firecracker, or is Rust allocator+kernel able to optimize this to use the shared zero page as long as we don't write to it? I think both glibc and musl should do it, but please double check me.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this dump_non_seekable + 4K stack. Now reused dump(writer, HoleStrategy) with shared write_zeros() using [0u8; 64K] stack, chunked by min(remaining,64K).

On RSS: confirmed your guess — vec![0u8;2M] read-only would stay on shared zero-page COW on both glibc and musl without THP/hugetlb, only page-tables. Used 64K stack instead to get same benefit with no heap and pipe-aligned writes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optimization I was mentioning only happens: on the heap, and (2) if the allocation is at least 128KiB (on glibc at least)

@coffeeinit coffeeinit closed this Sep 22, 2026
@coffeeinit
coffeeinit deleted the feat/snapshot-fifo-pr branch September 22, 2026 05:21
@coffeeinit
coffeeinit restored the feat/snapshot-fifo-pr branch September 22, 2026 05:22
@coffeeinit coffeeinit reopened this Sep 22, 2026
@coffeeinit
coffeeinit force-pushed the feat/snapshot-fifo-pr branch from a397c0c to 1029943 Compare September 22, 2026 05:39
Comment thread src/vmm/src/vstate/memory.rs Outdated
if len == 0 {
return Ok(());
}
let mut zeroes = [0u8; ZERO_FILL_CHUNK_SIZE];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to be mutable?

Also, like I mentioned in the other comment, this won't optimize down to re-use the shared zero page from the kernel. In this form, it will actually memset.

@not4s not4s added the Status: Awaiting author Indicates that an issue or pull request requires author action label Sep 30, 2026
@coffeeinit coffeeinit closed this Nov 4, 2026
@coffeeinit
coffeeinit force-pushed the feat/snapshot-fifo-pr branch from 1029943 to 220c76e Compare November 4, 2026 12:08
@coffeeinit
coffeeinit deleted the feat/snapshot-fifo-pr branch November 4, 2026 13:10
Signed-off-by: Janarthanan <janasuba2307@gmail.com>
@coffeeinit coffeeinit reopened this Nov 4, 2026
Signed-off-by: Janarthanan <janasuba2307@gmail.com>
@coffeeinit
coffeeinit force-pushed the feat/snapshot-fifo-pr branch from f9322ea to 4a73034 Compare November 5, 2026 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Awaiting author Indicates that an issue or pull request requires author action

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants