Repository navigation
fc: resume a VM restored under another name from its own disk - #1283
Merged
Merged
Conversation
A firecracker snapshot records its drives' and vsock socket's absolute paths, in the VM directory it was taken in. A vmDir copied in under a new name (boxctl-vms's restore with --name) still pointed there, so resume either failed -- "No such file or directory .../<old>/rootfs.ext4" once the original was gone, as it did on boxctl.io on 2026-10-29 -- or, with the original still there, loaded the original VM's live disk. Firecracker 1.16 can override a vsock path at load but not a drive's. So when the snapshot names another VM's directory, Resume starts firecracker in a mount namespace of its own with this VM's directory bind-mounted over that one, loads the snapshot paused with the vsock overridden, PATCHes the drives to this VM's own files, then resumes. The host's view of the other directory is never changed; one made only to mount on is removed after the load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ba6Vc3WGrS3q5htT56ED8S
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1283 +/- ##
==========================================
+ Coverage 50.85% 50.97% +0.11%
==========================================
Files 83 83
Lines 9888 9943 +55
==========================================
+ Hits 5029 5068 +39
- Misses 4859 4875 +16 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
boxctl-vms's import rewrites a copied VM's rootfs path but not its vsock or cache disk path, so Resume would have overridden the vsock with the original VM's socket and removed it as stale -- the live socket of an original VM still running there. Every metadata path under the snapshot's directory now moves to the VM's own before anything uses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ba6Vc3WGrS3q5htT56ED8S
…replace it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ba6Vc3WGrS3q5htT56ED8S
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
A Firecracker snapshot records the absolute paths of its drives and vsock socket, in the VM directory it was taken in. A VM directory copied in under a new name (boxctl-vms's restore with
--name) kept pointing at the old directory, soonctl resume:u06cadefc64-mg-box8-1:Block: ... No such file or directory /opt/fc-vms/vms/u06cadefc64-mg-box8/rootfs.ext4Fix
Firecracker 1.16's
/snapshot/loadhasnetwork_overridesandvsock_override, but no override for drives. So when the snapshot names a VM directory other than the box's own,Resume:unshare --mount --propagation slave), with this VM's directory bind-mounted over the recorded one. Only that process sees the mount; the host's view of the other directory is never changed.vsock_overridepointing at this VM's socket.PATCH /drives/rootfs(and/drives/cacheif the box has one) with this VM's own files.PATCH /vm {"state":"Resumed"}.If the recorded directory didn't exist, the empty directory created to mount on is removed after the load.
Finding the recorded directory (
snapshotTakenIn): bitcode stores string bytes back to back with no length prefix, so a full path can't be cut out reliably. A VM directory's name always ends at the next/, though, so matching<StateDir>/vms/<name>/is exact. A snapshot naming more than one other directory is refused, with a pointer toonctl restart.A box that was never moved keeps the old path: no mount, loaded with
resume_vm: true, no drive PATCH.Testing
make,go vet ./...,go test ./...pass.snapshotTakenIn.bindMountScriptwas dry-run withmountstubbed out.rt-origwas given asleepprocess (its PID kept in/dev/shm) and a disk marker, then hot-paused. Two copies were made the way boxctl-vms's restore makes them (directory copied; metadataname/socketPath/rootfsPath/snapshot paths rewritten;vsockPathleft pointing atrt-orig):rt-copy1resumed. Its firecracker had onlyrt-copy1/rootfs.ext4open. The bind mount was visible only in its own mount namespace (none on the host).rt-orig's directory, its vsock socket included, was byte-for-byte the same listing. In the guest: same boot ID,sleepstill alive, its own disk (it readsorig-disk;rt-orighad meanwhile writtenorig-changed), writes work, no I/O or ext4 errors.rt-copy1paths. The next resume took the normal path (no mount), and state survived.mainfailed with exactly the production error (No such file or directory /opt/fc/vms/rt-orig/rootfs.ext4). This branch resumedrt-copy2with memory and disk intact, and removed the temporaryrt-origmount directory afterwards.vsockPath/cachePath. Without it, resume would have used the original box's socket path and deleted that socket as stale, even while the original was running. Every metadata path under the snapshot's directory is now moved into the box's own directory first.onctl pausehung for more than 5 minutes influshGuestFilesystem's SSHsync. The guest had finished its sync, but the session never returned, and that SSH command has no timeout. Tracked separately.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ba6Vc3WGrS3q5htT56ED8S