oci: Generate composefs EROFS at pull time, track via config refs#263
oci: Generate composefs EROFS at pull time, track via config refs#263cgwalters merged 6 commits intocomposefs:mainfrom
Conversation
d62471b to
c141eeb
Compare
5d15c15 to
8876ea0
Compare
Johan-Liebert1
left a comment
There was a problem hiding this comment.
Skimming through the code and trying it out, LGTM
The merge-base changed after approval.
8876ea0 to
07cd372
Compare
|
Rebased and pushed |
While trying out composefs#263 locally, I found that Rust is rearranging the SplitStreamHeader struct's fields to the following ``` [32, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 112, 108, 105, 116, 83, 116, 114, 101, 97, 109, 0, 2, 12] ``` The first two U64 are the start and end of the field `info` when `info` is the last field in the struct; then comes the flags which is the third field... We probably don't want this undeterministic behaviour, which might also change from arch to arch Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
While trying out #263 locally, I found that Rust is rearranging the SplitStreamHeader struct's fields to the following ``` [32, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 112, 108, 105, 116, 83, 116, 114, 101, 97, 109, 0, 2, 12] ``` The first two U64 are the start and end of the field `info` when `info` is the last field in the struct; then comes the flags which is the third field... We probably don't want this undeterministic behaviour, which might also change from arch to arch Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
8567826 to
37b7da3
Compare
37b7da3 to
4672150
Compare
|
Needs another rebase |
0558c8d to
a341161
Compare
The clean recipe now refuses to delete the bootc checkout if there are any uncommitted changes, preventing accidental loss of in-progress work. The patch recipe had a bug where the grep for an existing [patch] section matched a commented-out example line, causing sed to replace the workspace dependency instead of appending a new [patch] section. Fix by anchoring the pattern to reject comment lines. Also drop the cargo update call which was rewriting Cargo.toml (the lockfile updates on the next build). Assisted-by: OpenCode (Claude Opus 4) Signed-off-by: Colin Walters <walters@verbum.org>
The unprivileged smoke test needs fs-verity enabled on the root filesystem to exercise verity-related code paths. Add tune2fs -O verity before the test steps. Assisted-by: OpenCode (Claude Opus 4) Signed-off-by: Colin Walters <walters@verbum.org>
The old sealing approach stored an fsverity digest in OCI config labels (containers.composefs.fsverity) and provided seal()/mount() functions to write and consume it. This is being replaced by EROFS image refs stored directly in config splitstreams, which integrates with the GC model and avoids mutating the OCI config. Remove the seal() and mount() library functions, the seal_digest() and is_sealed() methods on OciImage, the "sealed" field from ImageInfo, and the corresponding Seal/Mount CLI subcommands and SEALED table column. Also remove the now-obsolete implementation plan doc. Assisted-by: OpenCode (Claude claude-opus-4-6) Signed-off-by: Colin Walters <walters@verbum.org>
Describe the current OCI storage model: naming conventions for manifest/config/layer/blob splitstreams, how tags map to refs under streams/refs/oci/, the named_ref chains (manifest→config+layers, config→layers), and how the GC walks from tags to objects. Also notes the current gap: EROFS images derived from OCI content are not referenced by any splitstream, so their lifecycle must be managed separately. Assisted-by: OpenCode (Claude claude-opus-4-6) Signed-off-by: Colin Walters <walters@verbum.org>
Add test utilities for creating multi-layer OCI images from composefs dumpfile strings. This uses the real dumpfile format parsed by dumpfile_to_filesystem(), then walks the resulting FileSystem tree to emit tar bytes for import_layer(). Two convenience builders with versioned boot content: - create_base_image: 5-layer busybox-like app image - create_bootable_image(version): 20-layer bootable OS with kernel and UKI v1 and v2 share userspace layers (busybox, libs, systemd, configs) but differ in kernel version (6.1.0 vs 6.2.0), initramfs, modules, and UKI. When both are pulled into the same repo the shared layers deduplicate, exercising GC correctness with content referenced by multiple images. Prep for adding boot image management API. Assisted-by: OpenCode (Claude claude-opus-4-6) Signed-off-by: Colin Walters <walters@verbum.org>
When pulling an OCI container image, automatically generate the composefs EROFS image and reference it from the config splitstream. This creates a clean GC chain: tag → manifest → config → EROFS image, so all derived artifacts stay alive as long as the tag exists. For bootable images, a second "boot" EROFS variant is generated with transform_for_boot applied (clearing /boot to avoid circular UKI refs). The old seal/mount mechanism is replaced by a simpler Mount subcommand that looks up the EROFS ref from the config splitstream. OpenConfig struct replaces the (config, layer_map) tuple for richer open_config returns. Assisted-by: OpenCode (Claude Opus 4) Signed-off-by: Colin Walters <walters@verbum.org>
a341161 to
292a518
Compare
jeckersb
left a comment
There was a problem hiding this comment.
Approving but disabled auto-merge in case you want to address the one comment below. If not, send it.
| // Generate the composefs EROFS image and link it to the config splitstream. | ||
| // For container images this rewrites the config+manifest with the EROFS ref | ||
| // and tags the final manifest. Artifacts are skipped and tagged as-is. | ||
| let erofs = crate::ensure_oci_composefs_erofs( |
There was a problem hiding this comment.
Not necessarily a huge problem, but if I'm following correctly the code above is going to pull all of the layers onto disk, but if we fail to generate the EROFS here the pull is going to early exit and we're not going to tag the image below, which means the layers will sit in the repo unreachable by tag until some future GC is run.
There was a problem hiding this comment.
Good question, thanks for looking at this!
which means the layers will sit in the repo unreachable by tag until some future GC is run.
Your concern is resumption of partial pulls, right? As long as we don't GC, we should still reuse those cached layers because we do save the layer streams I believe. I don't think this is a new issue - but we should definitely have some tests for interrupted/partial pulls. I'll look at that!
…ld to ImageInfo These were part of the sealing-impl branch but were lost during conflict resolution of PR composefs#263 rebase. The oci mount subcommand needs signature verification flags for the sealed app container workflow, and ImageInfo needs the sealed field for oci images --json. Assisted-by: OpenCode (Claude Opus 4)
Depends
Motivation: For bootc I want to store both erofs images automatically
without needing to manually hold references.
But really what I want is that for generic OCI container images,
we want a clean model where a tag points to a manifest, which
in turn should reference everything else automatically.
With this change when pulling an OCI container image, we deafult
to generating the EROFS and reference it from the splitstream
for the config.
The next step here: bootable images, the config can be rewritten with additional refs
(e.g. "composefs.image.boot").