Conversation
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
There are 4 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f50f3f9. Configure here.
sjmiller609
left a comment
There was a problem hiding this comment.
summary: There are a few concerns here to look into. Also keep in mind we don't have to go with this storage optimization at all if the complication of it is not worth the benefit.
the overall approach seems reasonable: share immutable layer files while keeping a reusable read-only disk for guest creation. Generally concerned on overhead for tons of loop devices and potentially-change-blocking guest disk IO performance.
cleanup / GC
lib/images/dm_linear_linux.go:151–157— successful loop detachments remain ind.loopsafter a partial failure. a later retry can detach a device number that has been reassigned. remove released resources from tracked state immediately.lib/images/fsmerge_runtime.go:121–126— cleanup treats an empty cache as no device. after a daemon restart, deleting an image before its next use leaves surviving mappings/loops behind.lib/images/tag.go:79–96— tag-replacement cleanup removes unreferenced content without closing its device. centralize reclamation across image-removal paths.lib/images/fsmerge_runtime.go:110–132— add startup reconciliation and periodic GC for owned mappings/orphan loops, including interrupted setup and manual directory deletion while stopped. use verifiable ownership, coordinate with create/restore, and retry busy devices without forcing removal. also reclaim unused materialized layers while preserving references from retained images, builds, guests, and snapshots.lib/images/dm_linear_linux.go:60–65— conditional hardening: failed setup callsClose()before owning the named mapping. separate managers racing on the same image could remove the winner’s device. clean up only resources this attempt owns.
tests
lib/images/fsmerge_test.go:20–41— the fixture occupies two blocks but declares one; expected offsets don’t match whole-file concatenation.- add one comprehensive real-tool integration test covering layer contents, overwrites/whiteouts/opaque directories, assembly, restore preparation, and restart/cleanup recovery. make it deterministic, concurrent-run compatible, self-cleaning on failure, with bounded waits. run it in Linux CI; missing prerequisites must fail, not skip.
potential performance issues
lib/images/fsmerge_runtime.go:40–41— the global mutex serializes setup across unrelated images. consider per-image deduplication and bounded concurrency with safe loop allocation.lib/images/dm_linear_linux.go:68–108— validate device counts at 1,000 active unique images: exporter cardinality/scrape cost, enumeration, startup/fork latency, and read overhead versus flattened files.
rollout note
guest-kernel compatibility is a deployment prerequisite, not a blocker assuming compatible kernel versions are enforced.

tldr
Adds the Hypeman-side implementation for deduplicated OCI layer -> rootfs storage. This uses the single device approach to EROFS's native sub-filesystem merging shown here. Hypeman assembles the metadata and shared layer artifacts into single read-only block devices using
dm-linear. The existing flattened image path is now a fallback when fsmerge generation or host/platform support is unavailable.This path requires a guest kernel configuration change to enable
CONFIG_EROFS_FS.what changed
guest-kernel dependency
The fsmerge runtime requires a separately released
kernel/linuxguest artifact with EROFS flattened-device support enabled. This PR contains the full Hypeman-side path but does not change the guest kernel repository. Until that artifact is deployed, fsmerge image execution must remain rollout-gated by the kernel release.No Firecracker change is required: the assembled host device is passed as the existing read-only root drive.
validation
GOCACHE=/tmp/hypeman-go-cache go test ./lib/images -run '^$'GOCACHE=/tmp/hypeman-go-cache go test ./lib/images -run 'Test(PatchFsmerge|ValidateDMName|ManifestModel)' -count=1GOCACHE=/tmp/hypeman-go-cache go vet ./lib/imagesbenchmark
Synthetic Firecracker benchmark using a 64 MiB shared base layer, two small unique layers, and ten image variants with a 1 MiB unique layer each:
Ten corrected fsmerge boots completed with 10/10 rootfs mounts. The benchmark shows no meaningful performance regression, but the sequential layout samples are not a controlled comparison and do not establish a speedup. Lazy dm setup on first VM creation, including read-only loop attachment and size discovery, was variable at roughly 1.3 s median; the resulting device is shared per image and reused by subsequent VMs.
The benchmark covers rootfs storage, lazy device assembly during VM creation, and guest mount readiness with a synthetic fixture. It does not measure a Chromium workload, the HTTP image-pull path, or snapshot/restore latency.