Skip to content

Commit 3680bcb

Browse files
p5Johan-Liebert1
authored andcommitted
composefs-backend: store boot assets in ESP during install
Signed-off-by: Robert Sturla <[email protected]> install: create temporary directory for ESP bls mount Plus additional review comments: - Created constant for EFI/LINUX - Switched from Task to Command - Create efi_dir as Utf8PathBuf Signed-off-by: Robert Sturla <[email protected]>
1 parent 2c5c22f commit 3680bcb

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
@@ -99,6 +99,8 @@ use bootc_mount::{inspect_filesystem, Filesystem};
9999

100100
/// The toplevel boot directory
101101
const BOOT: &str = "boot";
102+
/// The EFI Linux directory
103+
const EFI_LINUX: &str = "EFI/Linux";
102104
/// Directory for transient runtime state
103105
#[cfg(feature = "install-to-disk")]
104106
const RUN_BOOTC: &str = "/run/bootc";
@@ -1715,7 +1717,7 @@ pub(crate) fn setup_composefs_bls_boot(
17151717
) -> Result<String> {
17161718
let id_hex = id.to_hex();
17171719

1718-
let (root_path, cmdline_refs) = match setup_type {
1720+
let (esp_device, cmdline_refs) = match setup_type {
17191721
BootSetupType::Setup((root_setup, state)) => {
17201722
// root_setup.kargs has [root=UUID=<UUID>, "rw"]
17211723
let mut cmdline_options = String::from(root_setup.kargs.join(" "));
@@ -1729,23 +1731,53 @@ pub(crate) fn setup_composefs_bls_boot(
17291731
}
17301732
};
17311733

1732-
(root_setup.physical_root_path.clone(), cmdline_options)
1734+
// Locate ESP partition device
1735+
let esp_part = root_setup
1736+
.device_info
1737+
.partitions
1738+
.iter()
1739+
.find(|p| p.parttype.as_str() == ESP_GUID)
1740+
.ok_or_else(|| anyhow::anyhow!("ESP partition not found"))?;
1741+
1742+
(esp_part.node.clone(), cmdline_options)
17331743
}
17341744

1735-
BootSetupType::Upgrade => (
1736-
Utf8PathBuf::from("/sysroot"),
1737-
vec![
1738-
format!("root=UUID={DPS_UUID}"),
1739-
RW_KARG.to_string(),
1740-
format!("{COMPOSEFS_CMDLINE}={id_hex}"),
1741-
]
1742-
.join(" "),
1743-
),
1745+
BootSetupType::Upgrade => {
1746+
let sysroot = Utf8PathBuf::from("/sysroot");
1747+
1748+
let fsinfo = inspect_filesystem(&sysroot)?;
1749+
let parent_devices = find_parent_devices(&fsinfo.source)?;
1750+
1751+
let Some(parent) = parent_devices.into_iter().next() else {
1752+
anyhow::bail!("Could not find parent device for mountpoint /sysroot");
1753+
};
1754+
1755+
(
1756+
get_esp_partition(&parent)?.0,
1757+
vec![
1758+
format!("root=UUID={DPS_UUID}"),
1759+
RW_KARG.to_string(),
1760+
format!("{COMPOSEFS_CMDLINE}={id_hex}"),
1761+
]
1762+
.join(" "),
1763+
)
1764+
}
17441765
};
17451766

1746-
let boot_dir = root_path.join("boot");
1767+
let temp_efi_dir = tempfile::tempdir()
1768+
.map_err(|e| anyhow::anyhow!("Failed to create temporary directory for EFI mount: {e}"))?;
1769+
let mounted_efi = temp_efi_dir.path().to_path_buf();
1770+
1771+
Command::new("mount")
1772+
.args([&PathBuf::from(&esp_device), &mounted_efi])
1773+
.log_debug()
1774+
.run_inherited_with_cmd_context()
1775+
.context("Mounting EFI")?;
1776+
17471777
let is_upgrade = matches!(setup_type, BootSetupType::Upgrade);
17481778

1779+
let efi_dir = Utf8PathBuf::from_path_buf(mounted_efi.join(EFI_LINUX))
1780+
.map_err(|_| anyhow::anyhow!("EFI dir is not valid UTF-8"))?;
17491781
let (bls_config, boot_digest) = match &entry {
17501782
ComposefsBootEntry::Type1(..) => unimplemented!(),
17511783
ComposefsBootEntry::Type2(..) => unimplemented!(),
@@ -1759,16 +1791,16 @@ pub(crate) fn setup_composefs_bls_boot(
17591791
bls_config.title = Some(id_hex.clone());
17601792
bls_config.sort_key = Some("1".into());
17611793
bls_config.machine_id = None;
1762-
bls_config.linux = format!("/boot/{id_hex}/vmlinuz");
1763-
bls_config.initrd = vec![format!("/boot/{id_hex}/initrd")];
1794+
bls_config.linux = format!("/{EFI_LINUX}/{id_hex}/vmlinuz");
1795+
bls_config.initrd = vec![format!("/{EFI_LINUX}/{id_hex}/initrd")];
17641796
bls_config.options = Some(cmdline_refs);
17651797
bls_config.extra = HashMap::new();
17661798

17671799
if let Some(symlink_to) = find_vmlinuz_initrd_duplicates(&boot_digest)? {
1768-
bls_config.linux = format!("/boot/{symlink_to}/vmlinuz");
1769-
bls_config.initrd = vec![format!("/boot/{symlink_to}/initrd")];
1800+
bls_config.linux = format!("/{EFI_LINUX}/{symlink_to}/vmlinuz");
1801+
bls_config.initrd = vec![format!("/{EFI_LINUX}/{symlink_to}/initrd")];
17701802
} else {
1771-
write_bls_boot_entries_to_disk(&boot_dir, id, usr_lib_modules_vmlinuz, &repo)?;
1803+
write_bls_boot_entries_to_disk(&efi_dir, id, usr_lib_modules_vmlinuz, &repo)?;
17721804
}
17731805

17741806
(bls_config, boot_digest)
@@ -1781,43 +1813,55 @@ pub(crate) fn setup_composefs_bls_boot(
17811813

17821814
// This will be atomically renamed to 'loader/entries' on shutdown/reboot
17831815
(
1784-
boot_dir.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
1816+
mounted_efi.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
17851817
Some(booted_bls),
17861818
)
17871819
} else {
1788-
(boot_dir.join(format!("loader/{BOOT_LOADER_ENTRIES}")), None)
1820+
(
1821+
mounted_efi.join(format!("loader/{BOOT_LOADER_ENTRIES}")),
1822+
None,
1823+
)
17891824
};
17901825

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

1793-
let loader_entries_dir =
1794-
cap_std::fs::Dir::open_ambient_dir(&entries_path, cap_std::ambient_authority())
1795-
.with_context(|| format!("Opening {entries_path}"))?;
1796-
1797-
loader_entries_dir.atomic_write(
1798-
// SAFETY: We set sort_key above
1799-
format!(
1800-
"bootc-composefs-{}.conf",
1801-
bls_config.sort_key.as_ref().unwrap()
1802-
),
1803-
bls_config.to_string().as_bytes(),
1804-
)?;
1828+
// Scope to allow for proper unmounting
1829+
{
1830+
let loader_entries_dir =
1831+
cap_std::fs::Dir::open_ambient_dir(&entries_path, cap_std::ambient_authority())
1832+
.with_context(|| format!("Opening {entries_path:?}"))?;
18051833

1806-
if let Some(booted_bls) = booted_bls {
18071834
loader_entries_dir.atomic_write(
18081835
// SAFETY: We set sort_key above
18091836
format!(
18101837
"bootc-composefs-{}.conf",
1811-
booted_bls.sort_key.as_ref().unwrap()
1838+
bls_config.sort_key.as_ref().unwrap()
18121839
),
1813-
booted_bls.to_string().as_bytes(),
1840+
bls_config.to_string().as_bytes(),
18141841
)?;
1842+
1843+
if let Some(booted_bls) = booted_bls {
1844+
loader_entries_dir.atomic_write(
1845+
// SAFETY: We set sort_key above
1846+
format!(
1847+
"bootc-composefs-{}.conf",
1848+
booted_bls.sort_key.as_ref().unwrap()
1849+
),
1850+
booted_bls.to_string().as_bytes(),
1851+
)?;
1852+
}
1853+
1854+
let owned_loader_entries_fd = loader_entries_dir
1855+
.reopen_as_ownedfd()
1856+
.context("Reopening as owned fd")?;
1857+
rustix::fs::fsync(owned_loader_entries_fd).context("fsync")?;
18151858
}
18161859

1817-
let owned_loader_entries_fd = loader_entries_dir
1818-
.reopen_as_ownedfd()
1819-
.context("Reopening as owned fd")?;
1820-
rustix::fs::fsync(owned_loader_entries_fd).context("fsync")?;
1860+
Command::new("umount")
1861+
.arg(&mounted_efi)
1862+
.log_debug()
1863+
.run_inherited_with_cmd_context()
1864+
.context("Unmounting EFI")?;
18211865

18221866
Ok(boot_digest)
18231867
}
@@ -1892,13 +1936,12 @@ pub(crate) fn setup_composefs_uki_boot(
18921936
}
18931937
};
18941938

1895-
let mounted_esp: PathBuf = root_path.join("esp").into();
1896-
let esp_mount_point_existed = mounted_esp.exists();
1897-
1898-
create_dir_all(&mounted_esp).context("Failed to create dir {mounted_esp:?}")?;
1939+
let temp_efi_dir = tempfile::tempdir()
1940+
.map_err(|e| anyhow::anyhow!("Failed to create temporary directory for EFI mount: {e}"))?;
1941+
let mounted_efi = temp_efi_dir.path().to_path_buf();
18991942

19001943
Task::new("Mounting ESP", "mount")
1901-
.args([&PathBuf::from(&esp_device), &mounted_esp.clone()])
1944+
.args([&PathBuf::from(&esp_device), &mounted_efi.clone()])
19021945
.run()?;
19031946

19041947
let boot_label = match entry {
@@ -1940,7 +1983,7 @@ pub(crate) fn setup_composefs_uki_boot(
19401983
}
19411984

19421985
// Write the UKI to ESP
1943-
let efi_linux_path = mounted_esp.join("EFI/Linux");
1986+
let efi_linux_path = mounted_efi.join(EFI_LINUX);
19441987
create_dir_all(&efi_linux_path).context("Creating EFI/Linux")?;
19451988

19461989
let efi_linux =
@@ -1962,16 +2005,11 @@ pub(crate) fn setup_composefs_uki_boot(
19622005
}
19632006
};
19642007

1965-
Task::new("Unmounting ESP", "umount")
1966-
.arg(&mounted_esp)
1967-
.run()?;
1968-
1969-
if !esp_mount_point_existed {
1970-
// This shouldn't be a fatal error
1971-
if let Err(e) = std::fs::remove_dir(&mounted_esp) {
1972-
tracing::error!("Failed to remove mount point '{mounted_esp:?}': {e}");
1973-
}
1974-
}
2008+
Command::new("umount")
2009+
.arg(&mounted_efi)
2010+
.log_debug()
2011+
.run_inherited_with_cmd_context()
2012+
.context("Unmounting ESP")?;
19752013

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

0 commit comments

Comments
 (0)