Skip to content

Commit 2b66ad4

Browse files
committed
composefs: Short-circuit upgrade when image digest matches booted
If the pulled image results in the same composefs digest as the currently booted system, there is no new state to write. Attempting to re-write the state crashes with EEXIST on the /var symlink (now separately hardened). This safely updates the origin file to record the new image reference instead, which is the correct behaviour when switching transport (e.g. registry: to containers-storage:) for the exact same image content. Assisted-by: OpenCode (Claude Sonnet 4.5) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent f8ea035 commit 2b66ad4

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

crates/lib/src/bootc_composefs/update.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,16 @@ pub(crate) async fn do_upgrade(
275275
)
276276
.await?;
277277

278+
// If the pulled image has the same composefs digest as the booted system,
279+
// there's nothing to stage — just update the origin file to record the
280+
// new imgref (e.g. a transport change from registry: to containers-storage:).
281+
if id.to_hex() == *booted_cfs.cmdline.digest {
282+
println!("Image already deployed, updating image reference");
283+
return crate::bootc_composefs::state::update_target_imgref_in_origin(
284+
storage, booted_cfs, imgref,
285+
);
286+
}
287+
278288
let Some(entry) = entries.iter().next() else {
279289
anyhow::bail!("No boot entries!");
280290
};
@@ -413,11 +423,17 @@ pub(crate) async fn upgrade_composefs(
413423
let imgref = derived_image.as_ref().or(current_image);
414424
let mut booted_imgref = imgref.ok_or_else(|| anyhow::anyhow!("No image source specified"))?;
415425

416-
// Auto-detect unified storage: if the image is already in bootc-owned
417-
// containers-storage (e.g. from a previous `bootc image set-unified`),
418-
// use the zero-copy path.
419-
do_upgrade_opts.use_unified =
420-
crate::deploy::image_exists_in_unified_storage(storage, booted_imgref).await?;
426+
// Auto-detect unified storage: use the unified path if the target image is
427+
// already in bootc-owned containers-storage, OR if the booted image is —
428+
// the latter means the user has opted into unified storage and all
429+
// subsequent operations should use it.
430+
let current_unified = if let Some(current) = current_image {
431+
crate::deploy::image_exists_in_unified_storage(storage, current).await?
432+
} else {
433+
false
434+
};
435+
do_upgrade_opts.use_unified = current_unified
436+
|| crate::deploy::image_exists_in_unified_storage(storage, booted_imgref).await?;
421437

422438
let repo = &*composefs.repo;
423439

0 commit comments

Comments
 (0)