Skip to content

Commit 0e61edd

Browse files
committed
install: bind mount boot partition from /target/boot to
`/target/sysroot/boot` if detecting a separate boot partition 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 <hhei@redhat.com>
1 parent 2c220bf commit 0e61edd

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

crates/lib/src/install.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,20 @@ 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 let Some(target_root) = root_setup.target_root_path.as_ref() {
764+
if root_setup.boot.is_some() {
765+
let source_boot = target_root.join(BOOT);
766+
let target_boot = root_setup.physical_root_path.join(BOOT);
767+
tracing::debug!("Bind mounting {source_boot} to {target_boot}");
768+
Command::new("mount")
769+
.args(["--bind", source_boot.as_str(), target_boot.as_str()])
770+
.run_capture_stderr()
771+
.with_context(|| format!("Bind mounting {source_boot} to {target_boot}"))?;
772+
}
773+
}
774+
761775
// And also label /boot AKA xbootldr, if it exists
762776
if rootfs_dir.try_exists("boot")? {
763777
crate::lsm::ensure_dir_labeled(rootfs_dir, "boot", None, 0o755.into(), sepolicy)?;
@@ -970,6 +984,22 @@ async fn install_container(
970984
}
971985
}
972986

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

0 commit comments

Comments
 (0)