Repository navigation
fix(fc): reflink-copy base rootfs image instead of full byte copy - #1076
Conversation
DebugfsRootfsPreparer.Prepare did a plain io.Copy of the entire base rootfs image on every Deploy, dominating `onctl up` time for the fc provider (multi-second sys time copying a large image). The cache disk preparer already avoided this cost via a CoW reflink; the rootfs path now does the same, falling back to a full copy on filesystems without reflink support. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PVpF4aLeq6xpokgHiBCy4v
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e7000483c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
cp --reflink preserves the base image's own mode (typically world/group-readable), but the destination is a per-VM writable rootfs holding guest secrets under the shared StateDir. Chmod it to 0600 after a successful reflink, matching what copyFile's plain-copy fallback already did. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PVpF4aLeq6xpokgHiBCy4v
|
The Generated by Claude Code |
|
Generated by Claude Code |
|
Root cause and fix are outside this PR's scope (pre-existing test, unrelated file), so per the drive-to-green policy I'm not widening this PR to patch it. For whoever picks this up: swap the external call for an srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer srv.Close()
err := downloadFile(srv.URL, tempFile)That removes the external dependency entirely rather than just re-pointing it. I won't re-run this again (already used one re-run to rule out a transient flake); merging is blocked on this until it's fixed or the branch protection rule for Generated by Claude Code |
Measured against a real firecracker microVM: a failed dial while the guest is still booting fails in well under a millisecond once the OS gives up on it, so the 500ms sleep between attempts was pure detection-latency slop on top of actual guest boot time. Only affects the fc provider today (WaitForSSH's only caller); a slower/higher- latency SSH target just sees more frequent harmless retries, not a correctness risk. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PVpF4aLeq6xpokgHiBCy4v
Verified in productionDeployed and tested on both live fc-hosts (
Investigated further to shave the remaining ~1.8s (guest boot + SSH readiness) via SSH poll tuning, ARP pre-seeding, console-log-based readiness detection, and systemd unit reordering on a disposable clone of the golden image — all tested empirically, all had no measurable benefit beyond what's in this PR (the guest's own boot time and Ready to merge. |
|
Generated by Claude Code |
govulncheck flagged GO-2026-6355 and GO-2026-6354 (DoS on deadlocked ssh channels) reachable from tools.Remote.NewSSHConnection's ssh.Dial call in internal/tools/remote-run.go, the file this PR's WaitForSSH change touches. Both are fixed upstream in x/crypto v0.56.0. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsg3yjczdwMHsefNVYPd6J
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
This test hit https://httpstat.us/404 directly and had failed 4 consecutive CI runs on this PR with 502 Bad Gateway from that service, unrelated to any of this PR's own changes but blocking merge since Build (stable) is a required check. Serve the 404 from a local httptest.Server instead, removing the external dependency entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsg3yjczdwMHsefNVYPd6J
|
Pushed Generated by Claude Code |
Fixes GO-2026-6355 and GO-2026-6354, both DoS-via-deadlock issues in golang.org/x/crypto/ssh reachable through tools.Remote.NewSSHConnection's ssh.Dial call — the govulncheck CI job was failing on this across unrelated PRs (see #1076). Claude-Session: https://claude.ai/code/session_01PVpF4aLeq6xpokgHiBCy4v Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Summary
onctl up -n <name>for the fc provider was spending most of its wall time (~4.6s sys time observed) on a plainio.Copyof the entire base rootfs image on everyDeploy.cp --reflink=always); the rootfs preparer now does the same, falling back to a full byte-for-byte copy on filesystems that don't support reflinks.Test plan
go build ./...go vet ./...go test ./internal/providerfc/...gofmt -lclean🤖 Generated with Claude Code
https://claude.ai/code/session_01PVpF4aLeq6xpokgHiBCy4v