Skip to content

Commit 4fcc336

Browse files
committed
composefs-backend: store boot assets in ESP during install
Signed-off-by: Robert Sturla <[email protected]>
1 parent 017206d commit 4fcc336

File tree

1 file changed

+87
-38
lines changed

1 file changed

+87
-38
lines changed

crates/lib/src/install.rs

Lines changed: 87 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,7 @@ pub(crate) fn setup_composefs_bls_boot(
16911691
) -> Result<String> {
16921692
let id_hex = id.to_hex();
16931693

1694-
let (root_path, cmdline_refs) = match setup_type {
1694+
let (root_path, esp_device, cmdline_refs) = match setup_type {
16951695
BootSetupType::Setup((root_setup, state)) => {
16961696
// root_setup.kargs has [root=UUID=<UUID>, "rw"]
16971697
let mut cmdline_options = String::from(root_setup.kargs.join(" "));
@@ -1705,23 +1705,56 @@ pub(crate) fn setup_composefs_bls_boot(
17051705
}
17061706
};
17071707

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

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-
),
1723+
BootSetupType::Upgrade => {
1724+
let sysroot = Utf8PathBuf::from("/sysroot");
1725+
1726+
let fsinfo = inspect_filesystem(&sysroot)?;
1727+
let parent_devices = find_parent_devices(&fsinfo.source)?;
1728+
1729+
let Some(parent) = parent_devices.into_iter().next() else {
1730+
anyhow::bail!("Could not find parent device for mountpoint /sysroot");
1731+
};
1732+
1733+
(
1734+
sysroot,
1735+
get_esp_partition(&parent)?.0,
1736+
vec![
1737+
format!("root=UUID={DPS_UUID}"),
1738+
RW_KARG.to_string(),
1739+
format!("{COMPOSEFS_CMDLINE}={id_hex}"),
1740+
]
1741+
.join(" "),
1742+
)
1743+
}
17201744
};
17211745

1722-
let boot_dir = root_path.join("boot");
1746+
let mounted_esp: PathBuf = root_path.join("esp").into();
1747+
let esp_mount_point_existed = mounted_esp.exists();
1748+
1749+
create_dir_all(&mounted_esp).context("Failed to create dir {mounted_esp:?}")?;
1750+
1751+
Task::new("Mounting ESP", "mount")
1752+
.args([&PathBuf::from(&esp_device), &mounted_esp.clone()])
1753+
.run()?;
1754+
17231755
let is_upgrade = matches!(setup_type, BootSetupType::Upgrade);
17241756

1757+
let efi_dir = mounted_esp.join(format!("EFI/Linux"));
17251758
let (bls_config, boot_digest) = match &entry {
17261759
ComposefsBootEntry::Type1(..) => unimplemented!(),
17271760
ComposefsBootEntry::Type2(..) => unimplemented!(),
@@ -1735,16 +1768,18 @@ pub(crate) fn setup_composefs_bls_boot(
17351768
bls_config.title = Some(id_hex.clone());
17361769
bls_config.sort_key = Some("1".into());
17371770
bls_config.machine_id = None;
1738-
bls_config.linux = format!("/boot/{id_hex}/vmlinuz");
1739-
bls_config.initrd = vec![format!("/boot/{id_hex}/initrd")];
1771+
bls_config.linux = format!("/EFI/Linux/{id_hex}/vmlinuz");
1772+
bls_config.initrd = vec![format!("/EFI/Linux/{id_hex}/initrd")];
17401773
bls_config.options = Some(cmdline_refs);
17411774
bls_config.extra = HashMap::new();
17421775

17431776
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")];
1777+
bls_config.linux = format!("/EFI/Linux/{symlink_to}/vmlinuz");
1778+
bls_config.initrd = vec![format!("/EFI/Linux/{symlink_to}/initrd")];
17461779
} else {
1747-
write_bls_boot_entries_to_disk(&boot_dir, id, usr_lib_modules_vmlinuz, &repo)?;
1780+
let efi_dir_utf8 = Utf8PathBuf::from_path_buf(efi_dir.clone())
1781+
.map_err(|_| anyhow::anyhow!("EFI dir is not valid UTF-8"))?;
1782+
write_bls_boot_entries_to_disk(&efi_dir_utf8, id, usr_lib_modules_vmlinuz, &repo)?;
17481783
}
17491784

17501785
(bls_config, boot_digest)
@@ -1757,43 +1792,57 @@ pub(crate) fn setup_composefs_bls_boot(
17571792

17581793
// This will be atomically renamed to 'loader/entries' on shutdown/reboot
17591794
(
1760-
boot_dir.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
1795+
efi_dir.join(format!("loader/{STAGED_BOOT_LOADER_ENTRIES}")),
17611796
Some(booted_bls),
17621797
)
17631798
} else {
1764-
(boot_dir.join(format!("loader/{BOOT_LOADER_ENTRIES}")), None)
1799+
(efi_dir.join(format!("loader/{BOOT_LOADER_ENTRIES}")), None)
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+
Task::new("Unmounting ESP", "umount")
1837+
.arg(&mounted_esp)
1838+
.run()?;
1839+
1840+
if !esp_mount_point_existed {
1841+
// This shouldn't be a fatal error
1842+
if let Err(e) = std::fs::remove_dir(&mounted_esp) {
1843+
tracing::error!("Failed to remove mount point '{mounted_esp:?}': {e}");
1844+
}
1845+
}
17971846

17981847
Ok(boot_digest)
17991848
}

0 commit comments

Comments
 (0)