Skip to content

Commit 50adce8

Browse files
authored
Merge pull request #932 from HuijingHei/split-ensure-mounted-esp
efi: rewrite `ensure_mounted_esp()`
2 parents 0d7dd2c + f6ef3d1 commit 50adce8

File tree

5 files changed

+185
-121
lines changed

5 files changed

+185
-121
lines changed

src/bios.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ impl Bios {
9797
}
9898

9999
// check bios_boot partition on gpt type disk
100+
#[allow(dead_code)]
100101
fn get_bios_boot_partition(&self) -> Option<String> {
101102
match blockdev::get_single_device("/") {
102103
Ok(device) => {
@@ -147,24 +148,37 @@ impl Component for Bios {
147148
Ok(meta)
148149
}
149150

150-
fn query_adopt(&self) -> Result<Option<Adoptable>> {
151+
fn query_adopt(&self, devices: &Option<Vec<String>>) -> Result<Option<Adoptable>> {
151152
#[cfg(target_arch = "x86_64")]
152-
if crate::efi::is_efi_booted()? && self.get_bios_boot_partition().is_none() {
153+
if crate::efi::is_efi_booted()? && devices.is_none() {
153154
log::debug!("Skip BIOS adopt");
154155
return Ok(None);
155156
}
156157
crate::component::query_adopt_state()
157158
}
158159

159-
fn adopt_update(&self, _: &openat::Dir, update: &ContentMetadata) -> Result<InstalledContent> {
160-
let Some(meta) = self.query_adopt()? else {
160+
fn adopt_update(
161+
&self,
162+
rootcxt: &RootContext,
163+
update: &ContentMetadata,
164+
) -> Result<InstalledContent> {
165+
let bios_devices = blockdev::find_colocated_bios_boot(&rootcxt.devices)?;
166+
let Some(meta) = self.query_adopt(&bios_devices)? else {
161167
anyhow::bail!("Failed to find adoptable system")
162168
};
163169

164-
let target_root = "/";
165-
let device = blockdev::get_single_device(&target_root)?;
166-
self.run_grub_install(target_root, &device)?;
167-
log::debug!("Install grub modules on {device}");
170+
let mut parent_devices = rootcxt.devices.iter();
171+
let Some(parent) = parent_devices.next() else {
172+
anyhow::bail!("Failed to find parent device");
173+
};
174+
175+
if let Some(next) = parent_devices.next() {
176+
anyhow::bail!(
177+
"Found multiple parent devices {parent} and {next}; not currently supported"
178+
);
179+
}
180+
self.run_grub_install(rootcxt.path.as_str(), &parent)?;
181+
log::debug!("Installed grub modules on {parent}");
168182
Ok(InstalledContent {
169183
meta: update.clone(),
170184
filetree: None,
@@ -176,12 +190,12 @@ impl Component for Bios {
176190
get_component_update(sysroot, self)
177191
}
178192

179-
fn run_update(&self, sysroot: &RootContext, _: &InstalledContent) -> Result<InstalledContent> {
193+
fn run_update(&self, rootcxt: &RootContext, _: &InstalledContent) -> Result<InstalledContent> {
180194
let updatemeta = self
181-
.query_update(&sysroot.sysroot)?
195+
.query_update(&rootcxt.sysroot)?
182196
.expect("update available");
183197

184-
let mut parent_devices = sysroot.devices.iter();
198+
let mut parent_devices = rootcxt.devices.iter();
185199
let Some(parent) = parent_devices.next() else {
186200
anyhow::bail!("Failed to find parent device");
187201
};
@@ -192,7 +206,7 @@ impl Component for Bios {
192206
);
193207
}
194208

195-
self.run_grub_install(sysroot.path.as_str(), &parent)?;
209+
self.run_grub_install(rootcxt.path.as_str(), &parent)?;
196210
log::debug!("Install grub modules on {parent}");
197211

198212
let adopted_from = None;

src/blockdev.rs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub fn get_devices<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
2323
}
2424

2525
// Get single device for the target root
26+
#[allow(dead_code)]
2627
pub fn get_single_device<P: AsRef<Path>>(target_root: P) -> Result<String> {
2728
let mut devices = get_devices(&target_root)?.into_iter();
2829
let Some(parent) = devices.next() else {
@@ -37,7 +38,6 @@ pub fn get_single_device<P: AsRef<Path>>(target_root: P) -> Result<String> {
3738

3839
/// Find esp partition on the same device
3940
/// using sfdisk to get partitiontable
40-
#[allow(dead_code)]
4141
pub fn get_esp_partition(device: &str) -> Result<Option<String>> {
4242
const ESP_TYPE_GUID: &str = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B";
4343
let device_info: PartitionTable = bootc_blockdev::partitions_of(Utf8Path::new(device))?;
@@ -51,21 +51,20 @@ pub fn get_esp_partition(device: &str) -> Result<Option<String>> {
5151
Ok(None)
5252
}
5353

54-
/// Find all ESP partitions on the devices with mountpoint boot
55-
#[allow(dead_code)]
56-
pub fn find_colocated_esps<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
57-
// first, get the parent device
58-
let devices = get_devices(&target_root).with_context(|| "while looking for colocated ESPs")?;
59-
60-
// now, look for all ESPs on those devices
54+
/// Find all ESP partitions on the devices
55+
pub fn find_colocated_esps(devices: &Vec<String>) -> Result<Option<Vec<String>>> {
56+
// look for all ESPs on those devices
6157
let mut esps = Vec::new();
6258
for device in devices {
6359
if let Some(esp) = get_esp_partition(&device)? {
6460
esps.push(esp)
6561
}
6662
}
67-
log::debug!("Find esp partitions: {esps:?}");
68-
Ok(esps)
63+
if esps.is_empty() {
64+
return Ok(None);
65+
}
66+
log::debug!("Found esp partitions: {esps:?}");
67+
Ok(Some(esps))
6968
}
7069

7170
/// Find bios_boot partition on the same device
@@ -82,20 +81,18 @@ pub fn get_bios_boot_partition(device: &str) -> Result<Option<String>> {
8281
Ok(None)
8382
}
8483

85-
/// Find all bios_boot partitions on the devices with mountpoint boot
86-
#[allow(dead_code)]
87-
pub fn find_colocated_bios_boot<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
88-
// first, get the parent device
89-
let devices =
90-
get_devices(&target_root).with_context(|| "looking for colocated bios_boot parts")?;
91-
92-
// now, look for all bios_boot parts on those devices
84+
/// Find all bios_boot partitions on the devices
85+
pub fn find_colocated_bios_boot(devices: &Vec<String>) -> Result<Option<Vec<String>>> {
86+
// look for all bios_boot parts on those devices
9387
let mut bios_boots = Vec::new();
9488
for device in devices {
9589
if let Some(bios) = get_bios_boot_partition(&device)? {
9690
bios_boots.push(bios)
9791
}
9892
}
99-
log::debug!("Find bios_boot partitions: {bios_boots:?}");
100-
Ok(bios_boots)
93+
if bios_boots.is_empty() {
94+
return Ok(None);
95+
}
96+
log::debug!("Found bios_boot partitions: {bios_boots:?}");
97+
Ok(Some(bios_boots))
10198
}

src/bootupd.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ pub(crate) fn adopt_and_update(name: &str, rootcxt: &RootContext) -> Result<Cont
276276
SavedState::acquire_write_lock(sysroot).context("Failed to acquire write lock")?;
277277

278278
let inst = component
279-
.adopt_update(&state_guard.sysroot, &update)
279+
.adopt_update(&rootcxt, &update)
280280
.context("Failed adopt and update")?;
281281
state.installed.insert(component.name().into(), inst);
282282

@@ -327,8 +327,23 @@ pub(crate) fn status() -> Result<Status> {
327327

328328
// Process the remaining components not installed
329329
log::trace!("Remaining known components: {}", known_components.len());
330-
for (name, component) in known_components {
331-
if let Some(adopt_ver) = component.query_adopt()? {
330+
for (name, _) in known_components {
331+
// To determine if not-installed components can be adopted:
332+
//
333+
// `query_adopt_state()` checks for existing installation state,
334+
// such as a `version` in `/sysroot/.coreos-aleph-version.json`,
335+
// or the presence of `/ostree/deploy`.
336+
//
337+
// `component.query_adopt()` performs additional checks,
338+
// including hardware/device requirements.
339+
// For example, it will skip BIOS adoption if the system is booted via EFI
340+
// and lacks a BIOS_BOOT partition.
341+
//
342+
// Once a component is determined to be adoptable, it is added to the
343+
// adoptable list, and adoption proceeds automatically.
344+
//
345+
// Therefore, calling `query_adopt_state()` alone is sufficient.
346+
if let Some(adopt_ver) = crate::component::query_adopt_state()? {
332347
ret.adoptable.insert(name.to_string(), adopt_ver);
333348
} else {
334349
log::trace!("Not adoptable: {}", name);

src/component.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ pub(crate) trait Component {
2929
/// In an operating system whose initially booted disk image is not
3030
/// using bootupd, detect whether it looks like the component exists
3131
/// and "synthesize" content metadata from it.
32-
fn query_adopt(&self) -> Result<Option<Adoptable>>;
32+
fn query_adopt(&self, devices: &Option<Vec<String>>) -> Result<Option<Adoptable>>;
3333

3434
/// Given an adoptable system and an update, perform the update.
3535
fn adopt_update(
3636
&self,
37-
sysroot: &openat::Dir,
37+
rootcxt: &RootContext,
3838
update: &ContentMetadata,
3939
) -> Result<InstalledContent>;
4040

@@ -66,7 +66,7 @@ pub(crate) trait Component {
6666
/// Used on the client to run an update.
6767
fn run_update(
6868
&self,
69-
sysroot: &RootContext,
69+
rootcxt: &RootContext,
7070
current: &InstalledContent,
7171
) -> Result<InstalledContent>;
7272

0 commit comments

Comments
 (0)