Commit 0307111
committed
unified-storage: implement the ostree three-store pipeline
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 pipeline into the ostree backend. When unified storage is
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 the 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) and the ostree repo config `[composefs] unified` key.
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 threading a CLI flag through every installer.
User-facing onboarding is a single verb with a required mode:
bootc image set-unified <composefs|full>
`composefs` enables the ostree↔composefs binding only: it is a flag-only
operation that writes `[composefs] unified = true` and does not fetch,
synthesize, or stage anything. The next `bootc upgrade` re-pulls through
the composefs pipeline, synthesizes the commit, and stages a deployment;
a reboot then activates bound-only mode. `full` additionally onboards the
booted image into containers-storage so it is visible to `podman run`.
`bootc image sync` reconciles every bootloader-pinned deployment into
bootc's containers-storage on a unified system.
For the binding to actually activate, the upgrade path had to learn that
a classic (non-synthesized) booted commit must be re-staged even when the
image's manifest digest is unchanged: the synthesized commit is a
*different* ostree commit. Without this, `bootc upgrade` after
`set-unified composefs` would report "No update available." and the
binding could never take effect.
`bootc internals fsck images` validates consistency across the stores.
On a bound-only system the OS image lives in the composefs repo and is
intentionally absent from containers-storage, so checks are driven from
the live ostree deployments. A booted-but-not-yet-synthesized live image
(the window between `set-unified composefs` and the activating reboot) is
reported as `pending` with `ok: true` — an expected transient state, not
a corruption. `--repair` restores a missing composefs tag when the
objects are still present.
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 Opus 4.8)
Signed-off-by: Colin Walters <walters@verbum.org>1 parent 6841360 commit 0307111
53 files changed
Lines changed: 5008 additions & 778 deletions
File tree
- .github/workflows
- ci
- contrib/packaging
- crates
- lib/src
- bootc_composefs
- install
- store
- ostree-ext/src
- xtask/src
- docs/src
- man
- tmt
- plans
- tests
- booted
- readonly
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
161 | 168 | | |
162 | 169 | | |
163 | 170 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
290 | 290 | | |
291 | 291 | | |
292 | 292 | | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
293 | 307 | | |
294 | 308 | | |
295 | 309 | | |
296 | 310 | | |
297 | 311 | | |
298 | 312 | | |
| 313 | + | |
299 | 314 | | |
300 | 315 | | |
301 | 316 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
| 14 | + | |
| 15 | + | |
29 | 16 | | |
30 | 17 | | |
31 | 18 | | |
| |||
35 | 22 | | |
36 | 23 | | |
37 | 24 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
55 | 31 | | |
56 | 32 | | |
57 | | - | |
58 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
59 | 69 | | |
60 | 70 | | |
61 | 71 | | |
0 commit comments