Skip to content

Commit 54e254c

Browse files
authored
Merge pull request #1541 from rsturla/composefs-backend-boot-assets-to-esp
install: store boot assets in ESP for composefs bls install
2 parents 017206d + 83c25a9 commit 54e254c

File tree

1 file changed

+92
-54
lines changed

1 file changed

+92
-54
lines changed

crates/lib/src/install.rs

Lines changed: 92 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ use bootc_mount::{inspect_filesystem, Filesystem};
9898

9999
/// The toplevel boot directory
100100
const BOOT: &str = "boot";
101+
/// The EFI Linux directory
102+
const EFI_LINUX: &str = "EFI/Linux";
101103
/// Directory for transient runtime state
102104
#[cfg(feature = "install-to-disk")]
103105
const RUN_BOOTC: &str = "/run/bootc";
@@ -1691,7 +1693,7 @@ pub(crate) fn setup_composefs_bls_boot(
16911693
) -> Result<String> {
16921694
let id_hex = id.to_hex();
16931695

1694-
let (root_path, cmdline_refs) = match setup_type {
1696+
let (esp_device, cmdline_refs) = match setup_type {
16951697
BootSetupType::Setup((root_setup, state)) => {
16961698
// root_setup.kargs has [root=UUID=<UUID>, "rw"]
16971699
let mut cmdline_options = String::from(root_setup.kargs.join(" "));
@@ -1705,23 +1707,53 @@ pub(crate) fn setup_composefs_bls_boot(
17051707
}
17061708
};
17071709

1708-
(root_setup.physical_root_path.clone(), cmdline_options)
1710+
// Locate ESP partition device
1711+
let esp_part = root_setup
1712+
.device_info
1713+
.partitions
1714+
.iter()
1715+
.find(|p| p.parttype.as_str() == ESP_GUID)
1716+
.ok_or_else(|| anyhow::anyhow!("ESP partition not found"))?;
1717+
1718+
(esp_part.node.clone(), cmdline_options)
17091719
}
17101720

1711-
BootSetupType::Upgrade => (
1712-
Utf8PathBuf::from("/sysroot"),
1713-
vec![
1714-
format!("root=UUID={DPS_UUID}"),
1715-
RW_KARG.to_string(),
1716-
format!("{COMPOSEFS_CMDLINE}={id_hex}"),
1717-
]
1718-
.join(" "),
1719-
),
1721+
BootSetupType::Upgrade => {
1722+
let sysroot = Utf8PathBuf::from("/sysroot");
1723+
1724+
let fsinfo = inspect_filesystem(&sysroot)?;
1725+
let parent_devices = find_parent_devices(&fsinfo.source)?;
1726+
1727+
let Some(parent) = parent_devices.into_iter().next() else {
1728+
anyhow::bail!("Could not find parent device for mountpoint /sysroot");
1729+
};
1730+
1731+
(
1732+
get_esp_partition(&parent)?.0,
1733+
vec![
1734+
format!("root=UUID={DPS_UUID}"),
1735+
RW_KARG.to_string(),
1736+
format!("{COMPOSEFS_CMDLINE}={id_hex}"),
1737+
]
1738+
.join(" "),
1739+
)
1740+
}
17201741
};
17211742

1722-
let boot_dir = root_path.join("boot");
1743+
let temp_efi_dir = tempfile::tempdir()
1744+
.map_err(|e| anyhow::anyhow!("Failed to create temporary directory for EFI mount: {e}"))?;
1745+
let mounted_efi = temp_efi_dir.path().to_path_buf();
1746+
1747+
Command::new("mount")
1748+
.args([&PathBuf::from(&esp_device), &mounted_efi])
1749+
.log_debug()
1750+
.run_inherited_with_cmd_context()
1751+
.context("Mounting EFI")?;
1752+
17231753
let is_upgrade = matches!(setup_type, BootSetupType::Upgrade);
17241754

1755+
let efi_dir = Utf8PathBuf::from_path_buf(mounted_efi.join(EFI_LINUX))
1756+
.map_err(|_| anyhow::anyhow!("EFI dir is not valid UTF-8"))?;
17251757
let (bls_config, boot_digest) = match &entry {
17261758
ComposefsBootEntry::Type1(..) => unimplemented!(),
17271759
ComposefsBootEntry::Type2(..) => unimplemented!(),
@@ -1735,16 +1767,16 @@ pub(crate) fn setup_composefs_bls_boot(
17351767
bls_config.title = Some(id_hex.clone());
17361768
bls_config.sort_key = Some("1".into());
17371769
bls_config.machine_id = None;
1738-
bls_config.linux = format!("/boot/{id_hex}/vmlinuz");
1739-
bls_config.initrd = vec![format!("/boot/{id_hex}/initrd")];
1770+
bls_config.linux = format!("/{EFI_LINUX}/{id_hex}/vmlinuz");
1771+
bls_config.initrd = vec![format!("/{EFI_LINUX}/{id_hex}/initrd")];
17401772
bls_config.options = Some(cmdline_refs);
17411773
bls_config.extra = HashMap::new();
17421774

17431775
if let Some(symlink_to) = find_vmlinuz_initrd_duplicates(&boot_digest)? {
1744-
bls_config.linux = format!("/boot/{symlink_to}/vmlinuz");
1745-
bls_config.initrd = vec![format!("/boot/{symlink_to}/initrd")];
1776+
bls_config.linux = format!("/{EFI_LINUX}/{symlink_to}/vmlinuz");
1777+
bls_config.initrd = vec![format!("/{EFI_LINUX}/{symlink_to}/initrd")];
17461778
} else {
1747-
write_bls_boot_entries_to_disk(&boot_dir, id, usr_lib_modules_vmlinuz, &repo)?;
1779+
write_bls_boot_entries_to_disk(&efi_dir, id, usr_lib_modules_vmlinuz, &repo)?;
17481780
}
17491781

17501782
(bls_config, boot_digest)
@@ -1757,43 +1789,55 @@ pub(crate) fn setup_composefs_bls_boot(
17571789

17581790
// This will be atomically renamed to 'loader/entries' on shutdown/reboot
17591791
(
1760-
boot_dir.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
1792+
mounted_efi.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
17611793
Some(booted_bls),
17621794
)
17631795
} else {
1764-
(boot_dir.join(format!("loader/{BOOT_LOADER_ENTRIES}")), None)
1796+
(
1797+
mounted_efi.join(format!("loader/{BOOT_LOADER_ENTRIES}")),
1798+
None,
1799+
)
17651800
};
17661801

17671802
create_dir_all(&entries_path).with_context(|| format!("Creating {:?}", entries_path))?;
17681803

1769-
let loader_entries_dir =
1770-
cap_std::fs::Dir::open_ambient_dir(&entries_path, cap_std::ambient_authority())
1771-
.with_context(|| format!("Opening {entries_path}"))?;
1772-
1773-
loader_entries_dir.atomic_write(
1774-
// SAFETY: We set sort_key above
1775-
format!(
1776-
"bootc-composefs-{}.conf",
1777-
bls_config.sort_key.as_ref().unwrap()
1778-
),
1779-
bls_config.to_string().as_bytes(),
1780-
)?;
1804+
// Scope to allow for proper unmounting
1805+
{
1806+
let loader_entries_dir =
1807+
cap_std::fs::Dir::open_ambient_dir(&entries_path, cap_std::ambient_authority())
1808+
.with_context(|| format!("Opening {entries_path:?}"))?;
17811809

1782-
if let Some(booted_bls) = booted_bls {
17831810
loader_entries_dir.atomic_write(
17841811
// SAFETY: We set sort_key above
17851812
format!(
17861813
"bootc-composefs-{}.conf",
1787-
booted_bls.sort_key.as_ref().unwrap()
1814+
bls_config.sort_key.as_ref().unwrap()
17881815
),
1789-
booted_bls.to_string().as_bytes(),
1816+
bls_config.to_string().as_bytes(),
17901817
)?;
1818+
1819+
if let Some(booted_bls) = booted_bls {
1820+
loader_entries_dir.atomic_write(
1821+
// SAFETY: We set sort_key above
1822+
format!(
1823+
"bootc-composefs-{}.conf",
1824+
booted_bls.sort_key.as_ref().unwrap()
1825+
),
1826+
booted_bls.to_string().as_bytes(),
1827+
)?;
1828+
}
1829+
1830+
let owned_loader_entries_fd = loader_entries_dir
1831+
.reopen_as_ownedfd()
1832+
.context("Reopening as owned fd")?;
1833+
rustix::fs::fsync(owned_loader_entries_fd).context("fsync")?;
17911834
}
17921835

1793-
let owned_loader_entries_fd = loader_entries_dir
1794-
.reopen_as_ownedfd()
1795-
.context("Reopening as owned fd")?;
1796-
rustix::fs::fsync(owned_loader_entries_fd).context("fsync")?;
1836+
Command::new("umount")
1837+
.arg(&mounted_efi)
1838+
.log_debug()
1839+
.run_inherited_with_cmd_context()
1840+
.context("Unmounting EFI")?;
17971841

17981842
Ok(boot_digest)
17991843
}
@@ -1868,13 +1912,12 @@ pub(crate) fn setup_composefs_uki_boot(
18681912
}
18691913
};
18701914

1871-
let mounted_esp: PathBuf = root_path.join("esp").into();
1872-
let esp_mount_point_existed = mounted_esp.exists();
1873-
1874-
create_dir_all(&mounted_esp).context("Failed to create dir {mounted_esp:?}")?;
1915+
let temp_efi_dir = tempfile::tempdir()
1916+
.map_err(|e| anyhow::anyhow!("Failed to create temporary directory for EFI mount: {e}"))?;
1917+
let mounted_efi = temp_efi_dir.path().to_path_buf();
18751918

18761919
Task::new("Mounting ESP", "mount")
1877-
.args([&PathBuf::from(&esp_device), &mounted_esp.clone()])
1920+
.args([&PathBuf::from(&esp_device), &mounted_efi.clone()])
18781921
.run()?;
18791922

18801923
let boot_label = match entry {
@@ -1916,7 +1959,7 @@ pub(crate) fn setup_composefs_uki_boot(
19161959
}
19171960

19181961
// Write the UKI to ESP
1919-
let efi_linux_path = mounted_esp.join("EFI/Linux");
1962+
let efi_linux_path = mounted_efi.join(EFI_LINUX);
19201963
create_dir_all(&efi_linux_path).context("Creating EFI/Linux")?;
19211964

19221965
let efi_linux =
@@ -1938,16 +1981,11 @@ pub(crate) fn setup_composefs_uki_boot(
19381981
}
19391982
};
19401983

1941-
Task::new("Unmounting ESP", "umount")
1942-
.arg(&mounted_esp)
1943-
.run()?;
1944-
1945-
if !esp_mount_point_existed {
1946-
// This shouldn't be a fatal error
1947-
if let Err(e) = std::fs::remove_dir(&mounted_esp) {
1948-
tracing::error!("Failed to remove mount point '{mounted_esp:?}': {e}");
1949-
}
1950-
}
1984+
Command::new("umount")
1985+
.arg(&mounted_efi)
1986+
.log_debug()
1987+
.run_inherited_with_cmd_context()
1988+
.context("Unmounting ESP")?;
19511989

19521990
let boot_dir = root_path.join("boot");
19531991
create_dir_all(&boot_dir).context("Failed to create boot dir")?;

0 commit comments

Comments
 (0)