Skip to content

Commit 1f75c8d

Browse files
storage: Add boot_dir and esp fields
We have a lot of places where we mount the ESP temporarily and a lot of switch cases for Grub's vs SystemdBoot's 'boot' directory. We add a `boot_dir` field in Storage which points to `/sysroot/boot` for systems with Grub as the bootloader and points to the ESP for systems with SystemdBoot as the bootloader. Also we mount the ESP temporarily while creating the storage struct, which cleans up the code quite a bit. Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent f31b92b commit 1f75c8d

File tree

7 files changed

+111
-132
lines changed

7 files changed

+111
-132
lines changed

crates/lib/src/bootc_composefs/boot.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -408,23 +408,11 @@ pub(crate) fn setup_composefs_bls_boot(
408408
let sysroot_parent = get_sysroot_parent_dev(&storage.physical_root)?;
409409
let bootloader = host.require_composefs_booted()?.bootloader.clone();
410410

411-
let current_cfg = match bootloader {
412-
Bootloader::Grub => {
413-
let boot_dir = storage
414-
.physical_root
415-
.open_dir("boot")
416-
.context("Opening boot")?;
417-
418-
get_booted_bls(&boot_dir)?
419-
}
420-
421-
Bootloader::Systemd => {
422-
let esp = get_esp_partition(&sysroot_parent)?.0;
423-
let esp_mnt = mount_esp(&esp)?;
424-
425-
get_booted_bls(&esp_mnt.fd)?
426-
}
427-
};
411+
let boot_dir = storage
412+
.boot_dir
413+
.as_ref()
414+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
415+
let current_cfg = get_booted_bls(&boot_dir)?;
428416

429417
let mut cmdline = match current_cfg.cfg_type {
430418
BLSConfigType::NonEFI { options, .. } => {

crates/lib/src/bootc_composefs/delete.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ use composefs_boot::bootloader::{EFI_ADDON_DIR_EXT, EFI_EXT};
77

88
use crate::{
99
bootc_composefs::{
10-
boot::{
11-
find_vmlinuz_initrd_duplicates, get_efi_uuid_source, get_esp_partition,
12-
get_sysroot_parent_dev, mount_esp, BootType, SYSTEMD_UKI_DIR,
13-
},
10+
boot::{find_vmlinuz_initrd_duplicates, get_efi_uuid_source, BootType, SYSTEMD_UKI_DIR},
1411
gc::composefs_gc,
1512
repo::open_composefs_repo,
1613
rollback::{composefs_rollback, rename_exchange_user_cfg},
@@ -215,40 +212,37 @@ fn remove_grub_menucfg_entry(id: &str, boot_dir: &Dir, deleting_staged: bool) ->
215212
#[fn_error_context::context("Deleting boot entries for deployment {}", deployment.deployment.verity)]
216213
fn delete_depl_boot_entries(
217214
deployment: &DeploymentEntry,
218-
physical_root: &Dir,
215+
storage: &Storage,
219216
deleting_staged: bool,
220217
) -> Result<()> {
221-
match deployment.deployment.bootloader {
222-
Bootloader::Grub => {
223-
let boot_dir = physical_root.open_dir("boot").context("Opening boot dir")?;
218+
let boot_dir = storage
219+
.boot_dir
220+
.as_ref()
221+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
224222

225-
match deployment.deployment.boot_type {
226-
BootType::Bls => delete_type1_entry(deployment, &boot_dir, deleting_staged),
223+
match deployment.deployment.bootloader {
224+
Bootloader::Grub => match deployment.deployment.boot_type {
225+
BootType::Bls => delete_type1_entry(deployment, boot_dir, deleting_staged),
227226

228-
BootType::Uki => {
229-
let device = get_sysroot_parent_dev(physical_root)?;
230-
let (esp_part, ..) = get_esp_partition(&device)?;
231-
let esp_mount = mount_esp(&esp_part)?;
227+
BootType::Uki => {
228+
let esp = storage
229+
.esp
230+
.as_ref()
231+
.ok_or_else(|| anyhow::anyhow!("ESP not found"))?;
232232

233-
remove_grub_menucfg_entry(
234-
&deployment.deployment.verity,
235-
&boot_dir,
236-
deleting_staged,
237-
)?;
233+
remove_grub_menucfg_entry(
234+
&deployment.deployment.verity,
235+
boot_dir,
236+
deleting_staged,
237+
)?;
238238

239-
delete_uki(&deployment.deployment.verity, &esp_mount.fd)
240-
}
239+
delete_uki(&deployment.deployment.verity, &esp.fd)
241240
}
242-
}
241+
},
243242

244243
Bootloader::Systemd => {
245-
let device = get_sysroot_parent_dev(physical_root)?;
246-
let (esp_part, ..) = get_esp_partition(&device)?;
247-
248-
let esp_mount = mount_esp(&esp_part)?;
249-
250244
// For Systemd UKI as well, we use .conf files
251-
delete_type1_entry(deployment, &esp_mount.fd, deleting_staged)
245+
delete_type1_entry(deployment, boot_dir, deleting_staged)
252246
}
253247
}
254248
}
@@ -362,7 +356,7 @@ pub(crate) async fn delete_composefs_deployment(
362356

363357
tracing::info!("Deleting {kind}deployment '{deployment_id}'");
364358

365-
delete_depl_boot_entries(&depl_to_del, &storage.physical_root, deleting_staged)?;
359+
delete_depl_boot_entries(&depl_to_del, &storage, deleting_staged)?;
366360

367361
composefs_gc(storage, booted_cfs).await?;
368362

crates/lib/src/bootc_composefs/finalize.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::path::Path;
22

3-
use crate::bootc_composefs::boot::{
4-
get_esp_partition, get_sysroot_parent_dev, mount_esp, BootType,
5-
};
3+
use crate::bootc_composefs::boot::BootType;
64
use crate::bootc_composefs::rollback::{rename_exchange_bls_entries, rename_exchange_user_cfg};
75
use crate::bootc_composefs::status::get_composefs_status;
86
use crate::composefs_consts::STATE_DIR_ABS;
@@ -86,15 +84,15 @@ pub(crate) async fn composefs_backend_finalize(
8684
// Unmount EROFS
8785
drop(erofs_tmp_mnt);
8886

89-
let sysroot_parent = get_sysroot_parent_dev(&storage.physical_root)?;
90-
// NOTE: Assumption here that ESP will always be present
91-
let (esp_part, ..) = get_esp_partition(&sysroot_parent)?;
92-
93-
let esp_mount = mount_esp(&esp_part)?;
9487
let boot_dir = storage
95-
.physical_root
96-
.open_dir("boot")
97-
.context("Opening boot")?;
88+
.boot_dir
89+
.as_ref()
90+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
91+
92+
let esp_mount = storage
93+
.esp
94+
.as_ref()
95+
.ok_or_else(|| anyhow::anyhow!("ESP not found"))?;
9896

9997
// NOTE: Assuming here we won't have two bootloaders at the same time
10098
match booted_composefs.bootloader {
@@ -103,21 +101,17 @@ pub(crate) async fn composefs_backend_finalize(
103101
let entries_dir = boot_dir.open_dir("loader")?;
104102
rename_exchange_bls_entries(&entries_dir)?;
105103
}
106-
BootType::Uki => finalize_staged_grub_uki(&esp_mount.fd, &boot_dir)?,
104+
BootType::Uki => finalize_staged_grub_uki(&esp_mount.fd, boot_dir)?,
107105
},
108106

109-
Bootloader::Systemd => match staged_composefs.boot_type {
110-
BootType::Bls => {
111-
let entries_dir = esp_mount.fd.open_dir("loader")?;
112-
rename_exchange_bls_entries(&entries_dir)?;
113-
}
114-
BootType::Uki => {
107+
Bootloader::Systemd => {
108+
if matches!(staged_composefs.boot_type, BootType::Uki) {
115109
rename_staged_uki_entries(&esp_mount.fd)?;
116-
117-
let entries_dir = esp_mount.fd.open_dir("loader")?;
118-
rename_exchange_bls_entries(&entries_dir)?;
119110
}
120-
},
111+
112+
let entries_dir = boot_dir.open_dir("loader")?;
113+
rename_exchange_bls_entries(&entries_dir)?;
114+
}
121115
};
122116

123117
Ok(())

crates/lib/src/bootc_composefs/gc.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use composefs::fsverity::{FsVerityHashValue, Sha512HashValue};
1010

1111
use crate::{
1212
bootc_composefs::{
13-
boot::{get_esp_partition, get_sysroot_parent_dev, mount_esp},
1413
delete::{delete_image, delete_staged, delete_state_dir, get_image_objects},
1514
status::{
1615
get_bootloader, get_composefs_status, get_sorted_grub_uki_boot_entries,
@@ -44,28 +43,30 @@ fn list_erofs_images(sysroot: &Dir) -> Result<Vec<String>> {
4443
/// # Returns
4544
/// The fsverity of EROFS images corresponding to boot entries
4645
#[fn_error_context::context("Listing bootloader entries")]
47-
fn list_bootloader_entries(physical_root: &Dir) -> Result<Vec<String>> {
46+
fn list_bootloader_entries(storage: &Storage) -> Result<Vec<String>> {
4847
let bootloader = get_bootloader()?;
48+
let boot_dir = storage
49+
.boot_dir
50+
.as_ref()
51+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
4952

5053
let entries = match bootloader {
5154
Bootloader::Grub => {
52-
let boot_dir = physical_root.open_dir("boot").context("Opening boot dir")?;
53-
5455
// Grub entries are always in boot
5556
let grub_dir = boot_dir.open_dir("grub2").context("Opening grub dir")?;
5657

5758
if grub_dir.exists(USER_CFG) {
5859
// Grub UKI
5960
let mut s = String::new();
60-
let boot_entries = get_sorted_grub_uki_boot_entries(&boot_dir, &mut s)?;
61+
let boot_entries = get_sorted_grub_uki_boot_entries(boot_dir, &mut s)?;
6162

6263
boot_entries
6364
.into_iter()
6465
.map(|entry| entry.get_verity())
6566
.collect::<Result<Vec<_>, _>>()?
6667
} else {
6768
// Type1 Entry
68-
let boot_entries = get_sorted_type1_boot_entries(&boot_dir, true)?;
69+
let boot_entries = get_sorted_type1_boot_entries(boot_dir, true)?;
6970

7071
boot_entries
7172
.into_iter()
@@ -75,11 +76,7 @@ fn list_bootloader_entries(physical_root: &Dir) -> Result<Vec<String>> {
7576
}
7677

7778
Bootloader::Systemd => {
78-
let device = get_sysroot_parent_dev(physical_root)?;
79-
let (esp_part, ..) = get_esp_partition(&device)?;
80-
let esp_mount = mount_esp(&esp_part)?;
81-
82-
let boot_entries = get_sorted_type1_boot_entries(&esp_mount.fd, true)?;
79+
let boot_entries = get_sorted_type1_boot_entries(boot_dir, true)?;
8380

8481
boot_entries
8582
.into_iter()
@@ -175,7 +172,7 @@ pub(crate) async fn composefs_gc(storage: &Storage, booted_cfs: &BootedComposefs
175172

176173
let sysroot = &storage.physical_root;
177174

178-
let bootloader_entries = list_bootloader_entries(&storage.physical_root)?;
175+
let bootloader_entries = list_bootloader_entries(&storage)?;
179176
let images = list_erofs_images(&sysroot)?;
180177

181178
// Collect the deployments that have an image but no bootloader entry

crates/lib/src/bootc_composefs/rollback.rs

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use cap_std_ext::dirext::CapStdExtDirExt;
66
use fn_error_context::context;
77
use rustix::fs::{fsync, renameat_with, AtFlags, RenameFlags};
88

9-
use crate::bootc_composefs::boot::{
10-
get_esp_partition, get_sysroot_parent_dev, mount_esp, type1_entry_conf_file_name, BootType,
11-
};
9+
use crate::bootc_composefs::boot::{type1_entry_conf_file_name, BootType};
1210
use crate::bootc_composefs::status::{get_composefs_status, get_sorted_type1_boot_entries};
1311
use crate::composefs_consts::TYPE1_ENT_PATH_STAGED;
1412
use crate::spec::Bootloader;
@@ -196,31 +194,24 @@ pub(crate) async fn composefs_rollback(
196194
anyhow::bail!("Rollback deployment not a composefs deployment")
197195
};
198196

197+
let boot_dir = storage
198+
.boot_dir
199+
.as_ref()
200+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
201+
199202
match &rollback_entry.bootloader {
200-
Bootloader::Grub => {
201-
let boot_dir = storage
202-
.physical_root
203-
.open_dir("boot")
204-
.context("Opening boot dir")?;
205-
206-
match rollback_entry.boot_type {
207-
BootType::Bls => {
208-
rollback_composefs_entries(&boot_dir, rollback_entry.bootloader.clone())?;
209-
}
210-
211-
BootType::Uki => {
212-
rollback_grub_uki_entries(&boot_dir)?;
213-
}
203+
Bootloader::Grub => match rollback_entry.boot_type {
204+
BootType::Bls => {
205+
rollback_composefs_entries(boot_dir, rollback_entry.bootloader.clone())?;
214206
}
215-
}
207+
BootType::Uki => {
208+
rollback_grub_uki_entries(boot_dir)?;
209+
}
210+
},
216211

217212
Bootloader::Systemd => {
218-
let parent = get_sysroot_parent_dev(&storage.physical_root)?;
219-
let (esp_part, ..) = get_esp_partition(&parent)?;
220-
let esp_mount = mount_esp(&esp_part)?;
221-
222213
// We use BLS entries for systemd UKI as well
223-
rollback_composefs_entries(&esp_mount.fd, rollback_entry.bootloader.clone())?;
214+
rollback_composefs_entries(boot_dir, rollback_entry.bootloader.clone())?;
224215
}
225216
}
226217

crates/lib/src/bootc_composefs/status.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use bootc_kernel_cmdline::utf8::Cmdline;
55
use fn_error_context::context;
66

77
use crate::{
8-
bootc_composefs::boot::{get_esp_partition, get_sysroot_parent_dev, mount_esp, BootType},
8+
bootc_composefs::boot::BootType,
99
composefs_consts::{COMPOSEFS_CMDLINE, ORIGIN_KEY_BOOT_DIGEST, TYPE1_ENT_PATH, USER_CFG},
1010
install::EFI_LOADER_INFO,
1111
parsers::{
1212
bls_config::{parse_bls_config, BLSConfig, BLSConfigType},
1313
grub_menuconfig::{parse_grub_menuentry_file, MenuEntry},
1414
},
1515
spec::{BootEntry, BootOrder, Host, HostSpec, ImageReference, ImageStatus},
16+
store::Storage,
1617
utils::{read_uefi_var, EfiError},
1718
};
1819

@@ -254,17 +255,23 @@ pub(crate) async fn get_composefs_status(
254255
storage: &crate::store::Storage,
255256
booted_cfs: &crate::store::BootedComposefs,
256257
) -> Result<Host> {
257-
composefs_deployment_status_from(&storage.physical_root, booted_cfs.cmdline).await
258+
composefs_deployment_status_from(&storage, booted_cfs.cmdline).await
258259
}
259260

260261
#[context("Getting composefs deployment status")]
261262
pub(crate) async fn composefs_deployment_status_from(
262-
sysroot: &Dir,
263+
storage: &Storage,
263264
cmdline: &ComposefsCmdline,
264265
) -> Result<Host> {
265266
let composefs_digest = &cmdline.digest;
266267

267-
let deployments = sysroot
268+
let boot_dir = storage
269+
.boot_dir
270+
.as_ref()
271+
.ok_or_else(|| anyhow::anyhow!("Boot dir not found"))?;
272+
273+
let deployments = storage
274+
.physical_root
268275
.read_dir(STATE_DIR_RELATIVE)
269276
.with_context(|| format!("Reading sysroot {STATE_DIR_RELATIVE}"))?;
270277

@@ -348,30 +355,10 @@ pub(crate) async fn composefs_deployment_status_from(
348355

349356
let booted = host.require_composefs_booted()?;
350357

351-
let (boot_dir, _temp_guard) = match booted.bootloader {
352-
Bootloader::Grub => (sysroot.open_dir("boot").context("Opening boot dir")?, None),
353-
354-
// TODO: This is redundant as we should already have ESP mounted at `/efi/` accoding to
355-
// spec; currently we do not
356-
//
357-
// See: https://uapi-group.org/specifications/specs/boot_loader_specification/#mount-points
358-
Bootloader::Systemd => {
359-
let parent = get_sysroot_parent_dev(sysroot)?;
360-
let (esp_part, ..) = get_esp_partition(&parent)?;
361-
362-
let esp_mount = mount_esp(&esp_part)?;
363-
364-
let dir = esp_mount.fd.try_clone().context("Cloning fd")?;
365-
let guard = Some(esp_mount);
366-
367-
(dir, guard)
368-
}
369-
};
370-
371358
let is_rollback_queued = match booted.bootloader {
372359
Bootloader::Grub => match boot_type {
373360
BootType::Bls => {
374-
let bls_config = get_sorted_type1_boot_entries(&boot_dir, false)?;
361+
let bls_config = get_sorted_type1_boot_entries(boot_dir, false)?;
375362
let bls_config = bls_config
376363
.first()
377364
.ok_or(anyhow::anyhow!("First boot entry not found"))?;
@@ -392,7 +379,7 @@ pub(crate) async fn composefs_deployment_status_from(
392379
BootType::Uki => {
393380
let mut s = String::new();
394381

395-
!get_sorted_grub_uki_boot_entries(&boot_dir, &mut s)?
382+
!get_sorted_grub_uki_boot_entries(boot_dir, &mut s)?
396383
.first()
397384
.ok_or(anyhow::anyhow!("First boot entry not found"))?
398385
.body
@@ -403,7 +390,7 @@ pub(crate) async fn composefs_deployment_status_from(
403390

404391
// We will have BLS stuff and the UKI stuff in the same DIR
405392
Bootloader::Systemd => {
406-
let bls_config = get_sorted_type1_boot_entries(&boot_dir, false)?;
393+
let bls_config = get_sorted_type1_boot_entries(boot_dir, false)?;
407394
let bls_config = bls_config
408395
.first()
409396
.ok_or(anyhow::anyhow!("First boot entry not found"))?;

0 commit comments

Comments
 (0)