Skip to content

install: reflink-capable filesystems with ostree pull through composefs first#2205

Draft
cgwalters wants to merge 4 commits into
bootc-dev:mainfrom
cgwalters:composefs-to-ostree
Draft

install: reflink-capable filesystems with ostree pull through composefs first#2205
cgwalters wants to merge 4 commits into
bootc-dev:mainfrom
cgwalters:composefs-to-ostree

Conversation

@cgwalters
Copy link
Copy Markdown
Collaborator

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.

@github-actions github-actions Bot added area/install Issues related to `bootc install` area/ostree Issues related to ostree area/documentation Updates to the documentation labels May 20, 2026
@bootc-bot bootc-bot Bot requested a review from jeckersb May 20, 2026 21:33
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread crates/ostree-ext/src/container/composefs_import.rs Outdated
Comment thread crates/ostree-ext/src/container/composefs_import.rs
Comment thread crates/lib/src/cli.rs
@cgwalters cgwalters force-pushed the composefs-to-ostree branch 2 times, most recently from 0ecf7a0 to 4f3055d Compare May 21, 2026 17:33
@cgwalters cgwalters added the ci/merge Run full CI suite (all OSes) — equivalent to merge queue label May 21, 2026
@cgwalters cgwalters force-pushed the composefs-to-ostree branch 2 times, most recently from 268a7bc to 9ea4e48 Compare May 25, 2026 12:32
cgwalters added 4 commits May 25, 2026 16:05
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>
@cgwalters cgwalters force-pushed the composefs-to-ostree branch from 9ea4e48 to db2a36f Compare May 25, 2026 22:02
@cgwalters cgwalters mentioned this pull request May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/documentation Updates to the documentation area/install Issues related to `bootc install` area/ostree Issues related to ostree ci/merge Run full CI suite (all OSes) — equivalent to merge queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant