Repository navigation
Conversation
This was referenced Sep 25, 2026
An EmptyDirVolume is an empty host directory at the same path an external volume would be published to, mounted into the sandbox the same way. It lets a golden actor warm up against a placeholder for an external volume it must not mount, so the snapshot's mount table matches the real actor's on both gVisor and microVM. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…/04-external-volume-refs
A template volume with external_volume_ref mounts an ExternalVolume instead of provisioning one per actor. The ref names the volume, or leaves the name empty so each actor binds it at creation through Actor.external_volume_bindings. Every actor referencing a volume is recorded in the volume's refs, with active set while the actor is resumed. Resume refuses a READ_WRITE_ONCE volume another actor holds active, pause and suspend mark the reference inactive, crash leaves it as is, and delete removes it and deletes a LAST_ACTOR volume that no actor references any more. Golden actors never reference a volume; they warm up against an empty directory at the same mount path. Depends on the empty_dir volume source and the ExternalVolume resource. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The golden actor warms up against a local empty directory in place of a shared volume, but runsc derives the disable_file_handle_sharing mount option from the bind source's filesystem and refuses a restore whose mount options differ from the checkpoint's. On NFS the first resume of every such actor therefore failed with "Mounts" does not match across checkpoint restore. Actors created from a template with an external_volume_ref no longer seed from the golden tag: the first resume boots from the image and later resumes restore the actor's own snapshot, which was taken over the real volume. An explicit source tag is refused for these templates. Golden restores for shared volumes remain follow-up work, tracked by TODO(shared-volumes). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hajiler
force-pushed
the
shared-volumes/03-external-volume
branch
from
October 13, 2026 15:59
b68483b to
1c24dc1
Compare
hajiler
force-pushed
the
shared-volumes/04-external-volume-refs
branch
from
October 13, 2026 15:59
7f19b87 to
41f90e9
Compare
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.
Summary
Completes Milestone 1 of go/substrate-shared-volumes: sequential sharing of an
ExternalVolumebetween actors.Volume.external_volume_ref { name }mounts an existingExternalVolume.namemay be empty, in which case the actor binds the slot at creation.Actor.external_volume_bindings(immutable map of template volume name →ExternalVolumename). Create validates that every unnamed slot is bound and that no binding targets a named ref or unknown volume.kubectl ate create actor --volume shared=ctx-42.status.refs, withactivetrue only while resumed.READ_WRITE_ONCEvolume with another active holder is refused with an error naming the holder. Inactive (paused/suspended) holders do not block.LAST_ACTORand no refs remain (idempotent on retry).DeleteExternalVolumeis refused while any ref exists, including inactive ones.empty_dirplaceholder at the same path (needs atelet: add the empty_dir volume source #9).docs/csi-volumes.md.M2 TODOs are left inline:
READ_WRITE_MANYclaims, passing access mode to CSI, moving refs out of the volume row.PR 4 of 4, stacked on #10 (
shared-volumes/03-external-volume) and merges #9 (shared-volumes/02-empty-dir-volume); the atelet commit shows in this diff until #9 lands.Test plan
go test ./cmd/ateapi/internal/controlapi/(newexternal_volume_refs_test.go, workload spec and volume tests)go test ./cmd/ateapi/internal/controlapi/functionaltest/(newTestExternalVolume_SequentialHandoff,TestExternalVolume_HeldByAnotherActor,TestDeleteExternalVolume_Referenced,TestCreateActor_ExternalVolumeBindings)go test ./cmd/kubectl-ate/... ./cmd/atelet/... ./internal/ocispec/...cd tools/apitool && go run . validate,hack/verify/{codegen,gofmt,boilerplate,golangci-lint}.shTestSharedExternalVolumeHandoff/TestSharedExternalVolumeMissingininternal/e2e/suites/combinedvolumes(compiles; not run locally, needs a cluster)hack/verify/proto-fmt.sh(clang-format not installed locally)🤖 Generated with Claude Code