Skip to content

Commit d8217cd

Browse files
committed
install: bind mount boot /target/boot to /target/sysroot/boot
if detecting a separate boot partition on ostree When running `bootc install to-existing-root` on an ostree environment with a separate `/boot` partition, the physical root is detected as `/target/sysroot`, ostree tries to write bootloader entries to the wrong location `/target/sysroot/boot`. With this fix, detect when we're installing alongside existing ostree, if there's a separate boot partition, bind mount the actual boot partition from `/target/boot` to `/target/sysroot/boot`. This ensures that when ostree writes bootloader entries to `/target/sysroot/boot`, they actually end up on the separate `/boot` partition where they belong. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Huijing Hei <[email protected]>
1 parent 2c220bf commit d8217cd

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

crates/lib/src/install.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,22 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
758758
// Another implementation: https://github.com/coreos/coreos-assembler/blob/3cd3307904593b3a131b81567b13a4d0b6fe7c90/src/create_disk.sh#L295
759759
crate::lsm::ensure_dir_labeled(rootfs_dir, "", Some("/".into()), 0o755.into(), sepolicy)?;
760760

761+
// If we're installing alongside existing ostree and there's a separate boot partition,
762+
// we need to bind mount it to the sysroot's /boot so ostree can write bootloader entries there
763+
if has_ostree {
764+
if let Some(target_root) = root_setup.target_root_path.as_ref() {
765+
if root_setup.boot.is_some() {
766+
let source_boot = target_root.join(BOOT);
767+
let target_boot = root_setup.physical_root_path.join(BOOT);
768+
tracing::debug!("Bind mounting {source_boot} to {target_boot}");
769+
Command::new("mount")
770+
.args(["--bind", source_boot.as_str(), target_boot.as_str()])
771+
.run_capture_stderr()
772+
.with_context(|| format!("Bind mounting {source_boot} to {target_boot}"))?;
773+
}
774+
}
775+
}
776+
761777
// And also label /boot AKA xbootldr, if it exists
762778
if rootfs_dir.try_exists("boot")? {
763779
crate::lsm::ensure_dir_labeled(rootfs_dir, "boot", None, 0o755.into(), sepolicy)?;
@@ -970,6 +986,22 @@ async fn install_container(
970986
}
971987
}
972988

989+
// For seperate /boot filesystem, the better workaround is
990+
// to inject kernel arguments during installation.
991+
if let Some(boot) = root_setup.boot.as_ref() {
992+
if !boot.source.is_empty() {
993+
let mount_extra = format!(
994+
"systemd.mount-extra={}:{}:{}:{}",
995+
boot.source,
996+
boot.target,
997+
boot.fstype,
998+
boot.options.as_deref().unwrap_or("defaults")
999+
);
1000+
kargs.extend(&Cmdline::from(mount_extra.as_str()));
1001+
tracing::debug!("Add {mount_extra} to kargs");
1002+
}
1003+
}
1004+
9731005
// Finally map into &[&str] for ostree_container
9741006
let kargs_strs: Vec<&str> = kargs.iter_str().collect();
9751007

0 commit comments

Comments
 (0)