install: reflink-capable filesystems with ostree pull through composefs first#2205
install: reflink-capable filesystems with ostree pull through composefs first#2205cgwalters wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a "composefs-first" import pipeline that allows synthesizing ostree commits directly from a composefs OCI repository using reflinks (FICLONE) to share disk blocks. This approach avoids tar round-trips and improves space efficiency on reflink-capable filesystems like XFS and btrfs. Key changes include a new pull_auto dispatcher, updated installation and upgrade logic to utilize the new pipeline, new fsck consistency checks for composefs-ostree alignment, and comprehensive integration tests. Review feedback identified a missing argument in a GIO stream constructor, a type mismatch in GVariant array creation, and potential fragility in internal CLI argument parsing for the cfsctl proxy.
0ecf7a0 to
4f3055d
Compare
268a7bc to
9ea4e48
Compare
Ostree sets the immutable ext4 attribute on each deployment checkout directory, which causes lsetfilecon() to return EPERM during the final SELinux relabeling pass even though those files are already correctly labeled by the earlier composefs import pass. Rather than skipping the entire ostree/deploy subtree (which would leave stateroot metadata and var directories unlabeled), enumerate the actual checkout directories under ostree/deploy/<stateroot>/deploy/ and skip only those immutable roots by dev/ino. Also generalise ensure_dir_labeled_recurse to accept a slice of (dev, ino) pairs to skip rather than a single Option, so multiple checkout directories can be excluded in one pass. Assisted-by: OpenCode (Claude Sonnet 4.6) Signed-off-by: Colin Walters <walters@verbum.org>
BOOTC_filesystem was silently ignored when BOOTC_variant=ostree because install_args() only emitted --filesystem inside the composefs_backend block. bcvk's --filesystem flag is not composefs-specific (the cache hash includes filesystem type and bcvk creates a fresh base disk per filesystem), so the guard was wrong. Move --filesystem before the composefs_backend block so that e.g. BOOTC_filesystem=ext4 just test-tmt-nobuild readonly actually installs on ext4, exercising the reflink-probe fallback path. Assisted-by: OpenCode (claude-sonnet-4-6@default) Signed-off-by: Colin Walters <walters@verbum.org>
Without this, `bootc internals cfsctl oci images` (and other cfsctl subcommands) would fall back to cfsctl's own default repo heuristic. While cfsctl already picks /sysroot/composefs when running as root, being explicit here documents the intent and makes the behaviour consistent regardless of uid. Pass --system rather than hardcoding the path so the constant lives in one place (cfsctl's system_path()). Users can still override with --repo, --user, or --system and the injected flag is skipped in that case. Assisted-by: OpenCode (claude-sonnet-4-6@default) Signed-off-by: Colin Walters <walters@verbum.org>
The goal of unified storage is to make the same on-disk layer data simultaneously visible to containers-storage (for \`podman run\`), composefs (for the boot overlay), and ostree (for deployment tracking), using reflinks so layers are stored once regardless of how many stores reference them. This wires the full pipeline into the ostree backend. When a system has unified storage enabled — either at install time via the [install.storage] config key, or post-install via \`bootc image set-unified\` — upgrades and switches route through pull_via_composefs: Stage 1: pull image into bootc-owned containers-storage Stage 2: zero-copy reflink import into the composefs OCI repo Stage 3: synthesize an ostree commit from the composefs tree Whether unified storage is active is tracked by composefs/bootc.json (BootcRepoMeta). This replaces the previous heuristic that checked per-image presence in containers-storage, which broke when switching to a new image reference. The install config gains a storage.unified key with three values: disabled (default), enabled (fail if reflinks unavailable), and enabled-with-copy (copy fallback). This lets an image opt into unified storage without requiring a CLI flag to be threaded through every installer. bootc image list cross-references composefs tags against containers-storage by config digest to report images as unified (in all three stores) or partial (cstorage only, composefs import pending). bootc internals fsck images checks consistency and --repair restores cstorage from composefs when needed. The cstorage GC is extended to protect images that have composefs tags, since the composefs splitstreams reference the cstorage layer data — pruning one without the other would corrupt the repo. Assisted-by: OpenCode (claude-sonnet-4-6@default) Signed-off-by: Colin Walters <walters@verbum.org>
9ea4e48 to
db2a36f
Compare
A spike of further work on #20 - basically, we control both ends of the composefs-rs and ostree sides, and if reflinks are enabled we can change things so we always pull into composefs first - making that the source of truth for image storage, and then just reflinking from there into ostree.