Skip to content

Commit 9ff49ee

Browse files
committed
blockdev: Add find_all_roots and rename root_disk to find_single_root
This is prep for supporting multiple parent devices. Signed-off-by: ckyrouac <ckyrouac@redhat.com>
1 parent 1d4112a commit 9ff49ee

File tree

5 files changed

+37
-6
lines changed

5 files changed

+37
-6
lines changed

crates/blockdev/src/blockdev.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ impl Device {
292292
/// Returns the root device with its children (partitions) populated.
293293
/// If this device is already a root device, returns a clone of `self`.
294294
/// Fails if the device has multiple parents at any level.
295-
pub fn root_disk(&self) -> Result<Device> {
295+
pub fn find_single_root(&self) -> Result<Device> {
296296
let Some(parents) = self.list_parents()? else {
297297
// Already a root device; re-query to ensure children are populated
298298
return list_dev(Utf8Path::new(&self.path()));
@@ -316,6 +316,34 @@ impl Device {
316316
}
317317
}
318318
}
319+
320+
/// Walk the parent chain to find all root (whole disk) devices.
321+
///
322+
/// Returns all root devices with their children (partitions) populated.
323+
/// Unlike find_single_root, this handles devices backed by multiple
324+
/// parents (e.g. RAID arrays) by following all branches of the parent tree.
325+
/// If this device is already a root device, returns a single-element list.
326+
pub fn find_all_roots(&self) -> Result<Vec<Device>> {
327+
let Some(parents) = self.list_parents()? else {
328+
// Already a root device; re-query to ensure children are populated
329+
return Ok(vec![list_dev(Utf8Path::new(&self.path()))?]);
330+
};
331+
332+
let mut roots = Vec::new();
333+
let mut queue = parents;
334+
while let Some(mut device) = queue.pop() {
335+
match device.children.take() {
336+
Some(grandparents) if !grandparents.is_empty() => {
337+
queue.extend(grandparents);
338+
}
339+
_ => {
340+
// Found a root; re-query to populate its actual children
341+
roots.push(list_dev(Utf8Path::new(&device.path()))?);
342+
}
343+
}
344+
}
345+
Ok(roots)
346+
}
319347
}
320348

321349
#[context("Listing device {dev}")]

crates/lib/src/bootc_composefs/boot.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,8 @@ pub(crate) fn setup_composefs_bls_boot(
545545
cmdline.add_or_modify(&param);
546546

547547
// Locate ESP partition device
548-
let root_dev = bootc_blockdev::list_dev_by_dir(&storage.physical_root)?.root_disk()?;
548+
let root_dev =
549+
bootc_blockdev::list_dev_by_dir(&storage.physical_root)?.find_single_root()?;
549550
let esp_dev = root_dev.find_partition_of_esp()?;
550551

551552
(
@@ -1083,7 +1084,8 @@ pub(crate) fn setup_composefs_uki_boot(
10831084
let bootloader = host.require_composefs_booted()?.bootloader.clone();
10841085

10851086
// Locate ESP partition device
1086-
let root_dev = bootc_blockdev::list_dev_by_dir(&storage.physical_root)?.root_disk()?;
1087+
let root_dev =
1088+
bootc_blockdev::list_dev_by_dir(&storage.physical_root)?.find_single_root()?;
10871089
let esp_dev = root_dev.find_partition_of_esp()?;
10881090

10891091
(

crates/lib/src/bootloader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub(crate) fn mount_esp_part(root: &Dir, root_path: &Utf8Path, is_ostree: bool)
4545
root
4646
};
4747

48-
let dev = bootc_blockdev::list_dev_by_dir(physical_root)?.root_disk()?;
48+
let dev = bootc_blockdev::list_dev_by_dir(physical_root)?.find_single_root()?;
4949
if let Some(esp_dev) = dev.find_partition_of_type(bootc_blockdev::ESP) {
5050
let esp_path = esp_dev.path();
5151
bootc_mount::mount(&esp_path, &root_path.join(&efi_path))?;

crates/lib/src/install.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2514,7 +2514,7 @@ pub(crate) async fn install_to_filesystem(
25142514
// Find the real underlying backing device for the root. This is currently just required
25152515
// for GRUB (BIOS) and in the future zipl (I think).
25162516
let device_info = {
2517-
let dev = bootc_blockdev::list_dev(Utf8Path::new(&inspect.source))?.root_disk()?;
2517+
let dev = bootc_blockdev::list_dev(Utf8Path::new(&inspect.source))?.find_single_root()?;
25182518
tracing::debug!("Backing device: {}", dev.path());
25192519
dev
25202520
};

crates/lib/src/store/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ impl BootedStorage {
196196
let composefs = Arc::new(composefs);
197197

198198
//TODO: this assumes a single ESP on the root device
199-
let root_dev = bootc_blockdev::list_dev_by_dir(&physical_root)?.root_disk()?;
199+
let root_dev =
200+
bootc_blockdev::list_dev_by_dir(&physical_root)?.find_single_root()?;
200201
let esp_dev = root_dev.find_partition_of_esp()?;
201202
let esp_mount = mount_esp(&esp_dev.path())?;
202203

0 commit comments

Comments
 (0)