Skip to content

Commit 9c05c61

Browse files
authored
Merge pull request #1006 from HuijingHei/fix-multipath
efi: Get the correct esp on multipath when install
2 parents b8fce50 + 24e327d commit 9c05c61

File tree

2 files changed

+59
-20
lines changed

2 files changed

+59
-20
lines changed

src/blockdev.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use camino::Utf8Path;
1+
use camino::{Utf8Path, Utf8PathBuf};
22
use std::path::Path;
33

44
use anyhow::{Context, Result};
@@ -99,3 +99,46 @@ pub fn find_colocated_bios_boot(devices: &Vec<String>) -> Result<Option<Vec<Stri
9999
log::debug!("Found bios_boot partitions: {bios_boots:?}");
100100
Ok(Some(bios_boots))
101101
}
102+
103+
// Check if the device is mpath
104+
fn is_mpath(device: &str) -> Result<bool> {
105+
let dm_path = Utf8PathBuf::from_path_buf(std::fs::canonicalize(device)?)
106+
.map_err(|_| anyhow::anyhow!("Non-UTF8 path"))?;
107+
let dm_name = dm_path.file_name().unwrap_or("");
108+
let uuid_path = Utf8PathBuf::from(format!("/sys/class/block/{dm_name}/dm/uuid"));
109+
110+
if uuid_path.exists() {
111+
let uuid = std::fs::read_to_string(&uuid_path)
112+
.with_context(|| format!("Failed to read {uuid_path}"))?;
113+
if uuid.trim_start().starts_with("mpath-") {
114+
return Ok(true);
115+
}
116+
}
117+
Ok(false)
118+
}
119+
120+
/// Get esp partition number from device
121+
pub fn get_esp_partition_number(device: &str) -> Result<String> {
122+
let esp_device =
123+
get_esp_partition(device)?.ok_or_else(|| anyhow::anyhow!("Failed to find ESP device"))?;
124+
125+
let devname = esp_device
126+
.rsplit_once('/')
127+
.ok_or_else(|| anyhow::anyhow!("Failed to parse {esp_device}"))?
128+
.1;
129+
130+
let partition_path = Utf8PathBuf::from(format!("/sys/class/block/{devname}/partition"));
131+
if partition_path.exists() {
132+
return std::fs::read_to_string(&partition_path)
133+
.with_context(|| format!("Failed to read {partition_path}"));
134+
}
135+
136+
// On multipath the partition attribute is not existing
137+
if is_mpath(device)? {
138+
if let Some(esp) = esp_device.strip_prefix(device) {
139+
let esp_num = esp.trim_start_matches(|c: char| !c.is_ascii_digit());
140+
return Ok(esp_num.to_string());
141+
}
142+
}
143+
anyhow::bail!("Not supported for {device}")
144+
}

src/efi.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,22 @@ impl Efi {
162162
return Ok(());
163163
}
164164

165+
// Check shim exists and return earlier if not
166+
let shim_path = format!("EFI/{vendordir}/{SHIM}");
167+
if !espdir.exists(&shim_path)? {
168+
anyhow::bail!("Failed to find {shim_path}");
169+
}
170+
let loader = format!("\\EFI\\{vendordir}\\{SHIM}");
171+
165172
let product_name = get_product_name(&sysroot)?;
166173
log::debug!("Get product name: '{product_name}'");
167174
assert!(product_name.len() > 0);
175+
176+
let esp_part_num = blockdev::get_esp_partition_number(device)?;
177+
168178
// clear all the boot entries that match the target name
169179
clear_efi_target(&product_name)?;
170-
create_efi_boot_entry(device, espdir, vendordir, &product_name)
180+
create_efi_boot_entry(device, esp_part_num.trim(), &loader, &product_name)
171181
}
172182
}
173183

@@ -669,34 +679,20 @@ pub(crate) fn clear_efi_target(target: &str) -> Result<()> {
669679
#[context("Adding new EFI boot entry")]
670680
pub(crate) fn create_efi_boot_entry(
671681
device: &str,
672-
espdir: &openat::Dir,
673-
vendordir: &str,
682+
esp_partition_number: &str,
683+
loader: &str,
674684
target: &str,
675685
) -> Result<()> {
676-
let fsinfo = crate::filesystem::inspect_filesystem(espdir, ".")?;
677-
let source = fsinfo.source;
678-
let devname = source
679-
.rsplit_once('/')
680-
.ok_or_else(|| anyhow::anyhow!("Failed to parse {source}"))?
681-
.1;
682-
let partition_path = format!("/sys/class/block/{devname}/partition");
683-
let partition_number = std::fs::read_to_string(&partition_path)
684-
.with_context(|| format!("Failed to read {partition_path}"))?;
685-
let shim = format!("{vendordir}/{SHIM}");
686-
if espdir.exists(&shim)? {
687-
anyhow::bail!("Failed to find {SHIM}");
688-
}
689-
let loader = format!("\\EFI\\{}\\{SHIM}", vendordir);
690686
log::debug!("Creating new EFI boot entry using '{target}'");
691687
let mut cmd = Command::new(EFIBOOTMGR);
692688
cmd.args([
693689
"--create",
694690
"--disk",
695691
device,
696692
"--part",
697-
partition_number.trim(),
693+
esp_partition_number,
698694
"--loader",
699-
loader.as_str(),
695+
loader,
700696
"--label",
701697
target,
702698
]);

0 commit comments

Comments
 (0)