From fd7f1b6ec4f2f2605b08c405287d8cd26a5b83af Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Thu, 8 Jan 2026 13:30:47 +0530 Subject: [PATCH] copy-to-storage: Fix deadlock in ostree path The sysroot lock was being taken by `get_host` before it was released by the caller. Move the `get_host` function up the stack of calls Signed-off-by: Pragyan Poudyal --- crates/lib/src/bootc_composefs/export.rs | 2 +- crates/lib/src/cli.rs | 5 +++++ crates/lib/src/image.rs | 13 +++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/lib/src/bootc_composefs/export.rs b/crates/lib/src/bootc_composefs/export.rs index e980bbbb..cef2c3ec 100644 --- a/crates/lib/src/bootc_composefs/export.rs +++ b/crates/lib/src/bootc_composefs/export.rs @@ -26,7 +26,7 @@ pub async fn export_repo_to_image( ) -> Result<()> { let host = get_composefs_status(storage, booted_cfs).await?; - let (source, dest_imgref) = get_imgrefs_for_copy(source, target).await?; + let (source, dest_imgref) = get_imgrefs_for_copy(&host, source, target).await?; let mut depl_verity = None; diff --git a/crates/lib/src/cli.rs b/crates/lib/src/cli.rs index b0f1833f..bf7cad78 100644 --- a/crates/lib/src/cli.rs +++ b/crates/lib/src/cli.rs @@ -47,6 +47,7 @@ use crate::podstorage::set_additional_image_store; use crate::progress_jsonl::{ProgressWriter, RawProgressFd}; use crate::spec::Host; use crate::spec::ImageReference; +use crate::status::get_host; use crate::store::{BootedOstree, Storage}; use crate::store::{BootedStorage, BootedStorageKind}; use crate::utils::sigpolicy_from_opt; @@ -1588,12 +1589,16 @@ async fn run_from_opt(opt: Opt) -> Result<()> { } => crate::image::list_entrypoint(list_type, list_format).await, ImageOpts::CopyToStorage { source, target } => { + // We get "host" here to avoid deadlock in the ostree path + let host = get_host().await?; + let storage = get_storage().await?; match storage.kind()? { BootedStorageKind::Ostree(..) => { crate::image::push_entrypoint( &storage, + &host, source.as_deref(), target.as_deref(), ) diff --git a/crates/lib/src/image.rs b/crates/lib/src/image.rs index b98d7202..4aaff294 100644 --- a/crates/lib/src/image.rs +++ b/crates/lib/src/image.rs @@ -15,7 +15,7 @@ use crate::{ boundimage::query_bound_images, cli::{ImageListFormat, ImageListType}, podstorage::CStorage, - status::get_host, + spec::Host, store::Storage, utils::async_task_with_spinner, }; @@ -145,6 +145,7 @@ pub(crate) async fn list_entrypoint( /// If the source isn't specified, we use booted image /// If the target isn't specified, we push to containers-storage with our default image pub(crate) async fn get_imgrefs_for_copy( + host: &Host, source: Option<&str>, target: Option<&str>, ) -> Result<(ImageReference, ImageReference)> { @@ -169,18 +170,17 @@ pub(crate) async fn get_imgrefs_for_copy( .context("Parsing source image")?, None => { - let host = get_host().await?; - let booted = host .status .booted + .as_ref() .ok_or_else(|| anyhow::anyhow!("Booted deployment not found"))?; - let booted_image = booted.image.unwrap().image; + let booted_image = &booted.image.as_ref().unwrap().image; ImageReference { transport: Transport::try_from(booted_image.transport.as_str()).unwrap(), - name: booted_image.image, + name: booted_image.image.clone(), } } }; @@ -192,10 +192,11 @@ pub(crate) async fn get_imgrefs_for_copy( #[context("Pushing image")] pub(crate) async fn push_entrypoint( storage: &Storage, + host: &Host, source: Option<&str>, target: Option<&str>, ) -> Result<()> { - let (source, target) = get_imgrefs_for_copy(source, target).await?; + let (source, target) = get_imgrefs_for_copy(host, source, target).await?; let ostree = storage.get_ostree()?; let repo = &ostree.repo();