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 added 3 commits May 21, 2026 08:24
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>
@cgwalters cgwalters force-pushed the composefs-to-ostree branch from a817bec to 0ecf7a0 Compare May 21, 2026 13:33
…y path

Add an end-to-end unified storage path for the ostree backend on reflink
filesystems. When the composefs repo is present and unified storage has been
enabled (via `bootc image set-unified`), `pull_auto` now routes through
`pull_via_composefs_unified` which:

1. Pulls the image into bootc-owned containers-storage via `pull_composefs_unified`
   (zero-copy reflinks from the registry blobs).
2. Synthesizes an ostree commit from the composefs repo via
   `import_from_composefs_repo` + FICLONE, marking it
   META_COMPOSEFS_SYNTHESIZED so downstream code knows no per-layer blob refs
   exist.

Unified storage mode is tracked by a new flag file
`/sysroot/composefs/bootc.json` (BootcRepoMeta), written atomically on the
first successful set-unified call and read cheaply on every pull_auto to
decide which path to take.  This avoids the previous heuristic that checked
per-image presence in containers-storage and broke across `bootc switch` to a
new image reference.

The old ostree-native unified pull path (new_importer_with_config /
check_disk_space_unified / prepare_for_pull_unified / pull_unified) is
removed — it was dead code since the composefs pipeline was introduced.

`bootc image copy-to-storage` is fixed for synthesized commits: because the
synthesized ostree commit carries no per-layer blob refs,
`ostree_ext::container::store::export()` would error out with "Refspec not
found". `push_entrypoint` now detects META_COMPOSEFS_SYNTHESIZED on the
resolved commit, reads the manifest and config from the commit metadata, and
delegates to the composefs layer-streaming export path instead.

The composefs export helper (`export_repo_to_image`) is refactored: the
streaming core is extracted into `export_composefs_to_dest` so it can be
called from both the composefs-boot and ostree-boot code paths.

A new TMT plan (plan-44-readonly-unified) onboards a system to unified
storage and then runs the full readonly test suite against it.

Assisted-by: OpenCode (Claude Sonnet 4.6)
Signed-off-by: Colin Walters <walters@verbum.org>
@cgwalters cgwalters force-pushed the composefs-to-ostree branch 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
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