Skip to content

criu: add an external-memory provider for restore - #3119

Open
dfeigin-nv wants to merge 6 commits into
checkpoint-restore:criu-devfrom
dfeigin-nv:extmem-provider-upstream
Open

criu: add an external-memory provider for restore#3119
dfeigin-nv wants to merge 6 commits into
checkpoint-restore:criu-devfrom
dfeigin-nv:extmem-provider-upstream

Conversation

@dfeigin-nv

@dfeigin-nv dfeigin-nv commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

This adds a generic external-memory provider interface for restore.

CRIU can use an inherited extmem-provider Unix SOCK_SEQPACKET FD to obtain:

  • image FDs for selected image files;
  • ready memfds for private anonymous VMAs;
  • ready memfds for shared-memory and memfd objects.

The provider receives relative image names and object identities. It can decline unsupported image files with -ENOTSUP; CRIU then uses its normal local image path. Private and shared-memory requests must succeed.

The protocol uses protobuf request/response envelopes and SCM_RIGHTS for one-FD replies. CRIU validates received FDs, prepares provider-backed VMAs early, waits for provider readiness before pre-resume, and closes the provider session with
COMMIT or ABORT.

This is restore-only. Checkpoint output remains unchanged (upcoming commit/PR)

Tests cover the request operations, VMA ID zero, scoped provider FDs, FD validation, image fallback, provider failures, readiness, commit/abort, and a focused static restore with a mock provider.

120B restore measurements

Workload: GPT-OSS-120B
Checkpoint data: ~140 GB

“Provider I/O” is the time spent reading checkpoint data and preparing memfds before CRIU starts.
Will add a few more benchmarks in place.

Restore source / mode Provider I/O CRIU core CUDA Detection → complete
CRIU-dev, tmpfs 11.468 s 11.779 s 23.247 s
CRIU-dev, one local NVMe 21.802 s 12.414 s 34.332 s
Provider, prefetched memfds, one NVMe 19.941 s 1.466 s 11.149 s 33.480 s
Provider, prefetched memfds, four NVMe 6.694 s 1.312 s 10.744 s 19.757 s

S3 restore measurements

Workload: Qwen3-14B
Checkpoint data: 45.7 GiB

Restore path Downloader Download CRIU Download + CRIU
S3 directly into provider memfds Run:ai Model Streamer 5.478 s 0.566 s 6.056 s
S3 to tmpfs, then normal CRIU s5cmd 6.300 s 7.130 s 13.430 s

Each row is the median of five successful restores.

More information can be found in:
https://docs.google.com/document/d/1i6xlonOpnY-HkUPmsLnuXzB0RqsiM9_YjwFVS-mVQ1M/edit?tab=t.0#heading=h.qkpu5w2ghwv9

Comment thread test/zdtm/extmem_provider.py Fixed
Comment thread criu/extmem.c Fixed
Comment thread test/zdtm/static/extmem_recheckpoint.c
Comment thread Documentation/under-the-hood/index.md
@dfeigin-nv
dfeigin-nv force-pushed the extmem-provider-upstream branch 2 times, most recently from 99e03f3 to 28819da Compare August 23, 2026 06:29
@codecov-commenter

codecov-commenter commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 29.12913% with 472 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.36%. Comparing base (71285b3) to head (78ef07f).
⚠️ Report is 9 commits behind head on criu-dev.

Files with missing lines Patch % Lines
criu/unittest/extmem-test.c 5.22% 272 Missing ⚠️
criu/mem.c 12.50% 84 Missing ⚠️
criu/extmem.c 65.89% 74 Missing ⚠️
criu/shmem.c 0.00% 19 Missing ⚠️
criu/cr-restore.c 53.84% 12 Missing ⚠️
criu/memfd.c 0.00% 11 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           criu-dev    #3119      +/-   ##
============================================
- Coverage     57.77%   57.36%   -0.42%     
============================================
  Files           161      163       +2     
  Lines         43886    44567     +681     
  Branches       9626     9720      +94     
============================================
+ Hits          25357    25566     +209     
- Misses        18290    18762     +472     
  Partials        239      239              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dfeigin-nv
dfeigin-nv force-pushed the extmem-provider-upstream branch 2 times, most recently from c3f5114 to 3ebcde6 Compare August 24, 2026 06:59
@dfeigin-nv
dfeigin-nv marked this pull request as ready for review August 24, 2026 08:40
@avagin

avagin commented Aug 25, 2026

Copy link
Copy Markdown
Member

please format commits properly.

Comment thread criu/mem.c
(vma->e->madv & (1ul << MADV_WIPEONFORK)))
continue;

vma->e->flags &= ~MAP_ANONYMOUS;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need to do that here? What if a memory provider restores only a few specified VMAs or only shared VMAs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that’s fair. A provider may only support some VMAs, or only shared memory. We’ll treat -ENOTSUP from GET_VMA as “this VMA isn’t handled” and let CRIU restore it normally. Other errors will still fail the restore.

Comment thread criu/shmem.c Outdated
if (kdat.has_memfd && (!is_hugetlb || kdat.has_memfd_hugetlb)) {
provider_ret = extmem_init();
if (provider_ret == 0) {
provider_ret = extmem_get_shared(si->shmid, si->size, &f);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why extmem_get_shared can't call extmem_init and extmem_validate_memfd_mapping_fd?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I’ll make extmem_get_shared() handle all that.

Comment thread criu/extmem.c Outdated
return provider_request(&req, fd);
}

int extmem_validate_mapping_fd(int fd, unsigned long length)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why do we need validating fd? In real life, a mapping can be wider than its backing store.

@dfeigin-nv dfeigin-nv Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think you're right. I was trying to be defensive but that's shouldn't be the case here. A mapping can be wider than its backing file, so I'll remove the FD validation from the provider paths.

@avagin

avagin commented Aug 25, 2026

Copy link
Copy Markdown
Member

I think the first patch should be split into three patches: handling images, handling memfd/shmem files, and handling anon VMAs.

@rst0git

rst0git commented Aug 26, 2026

Copy link
Copy Markdown
Member

@dfeigin-nv Adding a few notes from the meeting earlier today: it would be good to have a reference implementation of an external-memory provider. For example, this could follow the precedent of criu-image-streamer - a separate repository with a more permissive license, independent code reviews, and its own release cycle; or use tighter integration, similar to the page-server command, allowing us to test and extend the functionality directly in CRIU.

@avagin
avagin marked this pull request as draft August 26, 2026 19:57
@dfeigin-nv

Copy link
Copy Markdown
Contributor Author

I think the first patch should be split into three patches: handling images, handling memfd/shmem files, and handling anon VMAs.
@avagin - Makes sense. I’ll split it.

@dfeigin-nv

Copy link
Copy Markdown
Contributor Author

@dfeigin-nv Adding a few notes from the meeting earlier today: it would be good to have a reference implementation of an external-memory provider. For example, this could follow the precedent of criu-image-streamer - a separate repository with a more permissive license, independent code reviews, and its own release cycle; or use tighter integration, similar to the page-server command, allowing us to test and extend the functionality directly in CRIU.

@rst0git as discussed I'll open it in https://github.com/ai-dynamo/snapshot in a subdirectory so that I can start using it and you can take a look at it and see how it can look like. If you will deem it appropriate we can move it to its own repo under checkpoint-restore.
I'll post a comment here with a link to the directory when it is ready.

@dfeigin-nv

Copy link
Copy Markdown
Contributor Author

I think the first patch should be split into three patches: handling images, handling memfd/shmem files, and handling anon VMAs.

You're right. I think a fourth patch for the protocol itself is also good to make it more readable. I'll restructure it.

Add the CRIU-side protocol for external memory providers.

Connect through the inherited provider socket and request image,
shared-memory, and anonymous-VMA objects through one restore-side
interface. Initialize the provider early enough to serve restore
metadata and wait for it to be ready before applying memfd seals.

Keep restore setup compatible with CG_MODE_IGNORE.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Use provider-supplied FDs for restore images while keeping dump-time
and locally required inventory images on CRIU's existing path.
Treat -ENOTSUP as a per-image fallback so providers can add image
types incrementally.

Keep returned image FDs in CRIU's existing buffered reader. Non-page
images are small compared with the memory payload, so a mmap-based
reader can be considered separately if it proves worthwhile.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Restore checkpointed memfd and shmem mappings from provider-supplied
file descriptors. Fall back to CRIU's normal path only when the
provider returns ENOTSUP; propagate other provider errors.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Restore provider-backed anonymous mappings from provider-supplied file
descriptors. Fall back per VMA on ENOTSUP, preserving normal CRIU
handling for unsupported regions.

Tolerate ESRCH when detaching a thread that has already exited.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Add unit tests for the provider protocol and a ZDTM mock that restores
private and shared memory through the provider. Exercise a regular
checkpoint and restore without the provider, as well as per-object
ENOTSUP fallback.

Keep the existing IPv4/IPv6 address expression scoped to its
case-insensitive match so the spelling check accepts the expression.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Describe the inherited provider FD, request protocol, fallback
behavior, memory-object requirements, and restore ordering.

Assisted-by: Codex:GPT-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
@dfeigin-nv
dfeigin-nv force-pushed the extmem-provider-upstream branch from 217b7fd to 78ef07f Compare September 2, 2026 13:58
@dfeigin-nv
dfeigin-nv marked this pull request as ready for review September 3, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants