Skip to content

Commit

Permalink
Merge pull request #700 from jlebon/pr/esp-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jlebon authored Dec 2, 2021
2 parents 221399b + be83b4d commit 78e2a7a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/bin/rdcore/rootmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ pub fn bind_boot(config: BindBootConfig) -> Result<()> {
write_boot_uuid_grub2_dropin(&boot_uuid, grub_bios_path)?;
}

for esp in find_esps()? {
for esp in find_colocated_esps(boot_mount.device())? {
let mount = Mount::try_mount(&esp, "vfat", mount::MsFlags::empty())?;
let vendor_dir = find_efi_vendor_dir(&mount)?;
let grub_efi_path = vendor_dir.join("bootuuid.cfg");
Expand Down
67 changes: 54 additions & 13 deletions src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,30 +877,71 @@ pub fn lsblk(dev: &Path, with_deps: bool) -> Result<Vec<HashMap<String, String>>
Ok(result)
}

pub fn find_esps() -> Result<Vec<String>> {
const ESP_TYPE_GUID: &str = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b";
/// This is a bit fuzzy, but... this function will return every block device in the parent
/// hierarchy of `device` capable of containing other partitions. So e.g. parent devices of type
/// "part" doesn't match, but "disk" and "mpath" does.
pub fn find_parent_devices(device: &str) -> Result<Vec<String>> {
let mut cmd = Command::new("lsblk");
// Older lsblk, e.g. in CentOS 7.6, doesn't support PATH, but --paths option
cmd.arg("--pairs")
.arg("--paths")
.arg("--inverse")
.arg("--output")
.arg("NAME,PARTTYPE");
.arg("NAME,TYPE")
.arg(device);
let output = cmd_output(&mut cmd)?;
output
.lines()
.filter_map(|line| {
let mut parents = Vec::new();
// skip first line, which is the device itself
for line in output.lines().skip(1) {
let dev = split_lsblk_line(line);
let name = dev
.get("NAME")
.ok_or_else(|| anyhow!("device in hierarchy of {} missing NAME", device))?;
let kind = dev
.get("TYPE")
.ok_or_else(|| anyhow!("device in hierarchy of {} missing TYPE", device))?;
if kind == "disk" {
parents.push(name.clone());
} else if kind == "mpath" {
parents.push(name.clone());
// we don't need to know what disks back the multipath
break;
}
}
if parents.is_empty() {
bail!("no parent devices found for {}", device);
}
Ok(parents)
}

/// Find ESP partitions which sit at the same hierarchy level as `device`.
pub fn find_colocated_esps(device: &str) -> Result<Vec<String>> {
const ESP_TYPE_GUID: &str = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b";

// first, get the parent device
let parent_devices = find_parent_devices(device)
.with_context(|| format!("while looking for colocated ESPs of '{}'", device))?;

// now, look for all ESPs on those devices
let mut esps = Vec::new();
for parent_device in parent_devices {
let mut cmd = Command::new("lsblk");
cmd.arg("--pairs")
.arg("--paths")
.arg("--output")
.arg("NAME,PARTTYPE")
.arg(parent_device);
for line in cmd_output(&mut cmd)?.lines() {
let dev = split_lsblk_line(line);
if dev.get("PARTTYPE").map(|t| t.as_str()) == Some(ESP_TYPE_GUID) {
Some(
esps.push(
dev.get("NAME")
.cloned()
.ok_or_else(|| anyhow!("ESP device with missing NAME")),
.ok_or_else(|| anyhow!("ESP device with missing NAME"))?,
)
} else {
None
}
})
.collect()
}
}
Ok(esps)
}

/// This is basically a Rust version of:
Expand Down

0 comments on commit 78e2a7a

Please sign in to comment.