Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bind-boot: look for ESPs on the same disk(s) as bootfs #700

Merged
merged 1 commit into from
Dec 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
bgilbert marked this conversation as resolved.
Show resolved Hide resolved
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