Skip to content

Commit

Permalink
Use blkid instead of lsblk to get disk info when udev is not present
Browse files Browse the repository at this point in the history
- OSBuild does not allow udev rules in loop
devices, for this reason can not rely on labels on
the partitions to create the osmet image, due it
use blkid instead of lsblk that relys on udev.

Signed-off-by: Renata Ravanelli <[email protected]>
  • Loading branch information
ravanelli committed Sep 2, 2024
1 parent 85ba425 commit 0c30375
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 25 deletions.
1 change: 1 addition & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Minor changes:

Internal changes:

- osmet: Use blkid to get partition information if udev is unavailable

Packaging changes:

Expand Down
84 changes: 59 additions & 25 deletions src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,34 @@ impl Disk {
if devinfo.get("TYPE").map(|s| s.as_str()) != Some("part") {
continue;
}
let (mountpoint, swap) = match devinfo.get("MOUNTPOINT") {
Some(mp) if mp == "[SWAP]" => (None, true),
Some(mp) => (Some(mp.to_string()), false),
None => (None, false),
};
result.push(Partition {
path: name.to_owned(),
label: devinfo.get("LABEL").map(<_>::to_string),
fstype: devinfo.get("FSTYPE").map(<_>::to_string),
parent: self.path.to_owned(),
mountpoint,
swap,
});
// only trust lsblk output for the following fields if we have udev
if have_udev() {
let (mountpoint, swap) = match devinfo.get("MOUNTPOINT") {
Some(mp) if mp == "[SWAP]" => (None, true),
Some(mp) => (Some(mp.to_string()), false),
None => (None, false),
};
result.push(Partition {
path: name.to_owned(),
label: devinfo.get("LABEL").map(<_>::to_string),
fstype: devinfo.get("FSTYPE").map(<_>::to_string),
parent: self.path.to_owned(),
mountpoint,
swap,
});
} else {
let devinfo = blkid_single(Path::new(name))?;
// note TYPE here: blkid uses TYPE instead of FSTYPE
let fstype = devinfo.get("TYPE").map(<_>::to_string);
result.push(Partition {
path: name.to_owned(),
label: devinfo.get("LABEL").map(<_>::to_string),
fstype: fstype.to_owned(),
parent: self.path.to_owned(),
mountpoint: None,
swap: fstype.is_some_and(|s| s == "swap"),
});
}
}
}
Ok(result)
Expand Down Expand Up @@ -800,6 +815,17 @@ pub fn lsblk_single(dev: &Path) -> Result<HashMap<String, String>> {
Ok(devinfos.remove(0))
}

pub fn blkid_single(dev: &Path) -> Result<HashMap<String, String>> {
let mut devinfos = blkid(Some(vec![dev]))?;
if devinfos.len() != 1 {
bail!(
"expected one blkid result for {}, got: {:?}",
dev.display(),
devinfos
);
}
Ok(devinfos.remove(0))
}
/// Returns all available filesystems.
/// rereadpt mitigates possible issue with outdated UUIDs on different
/// paths to the same disk: after 'ignition-ostree-firstboot-uuid'
Expand All @@ -822,7 +848,7 @@ fn get_all_filesystems(rereadpt: bool) -> Result<Vec<HashMap<String, String>>> {
}
udev_settle()?;
}
blkid()
blkid(None)
}

/// Returns filesystems with given label.
Expand Down Expand Up @@ -884,7 +910,7 @@ fn split_blkid_line(line: &str) -> HashMap<String, String> {
fields
}

fn blkid() -> Result<Vec<HashMap<String, String>>> {
fn blkid(devs: Option<Vec<&Path>>) -> Result<Vec<HashMap<String, String>>> {
// Run blkid with a clean cache to avoid collecting old devices which no
// longer exist.
// https://github.com/coreos/coreos-installer/pull/1288#discussion_r1312008111
Expand All @@ -893,19 +919,24 @@ fn blkid() -> Result<Vec<HashMap<String, String>>> {
// the blkid -p below, which we use to probe the devices to not rely on
// the blkid cache:
// https://github.com/coreos/fedora-coreos-config/pull/2181#issuecomment-1397386896
let devices = {
let mut cmd = Command::new("blkid");
cmd.arg("--cache-file");
cmd.arg("/dev/null");
cmd.arg("-o");
cmd.arg("device");
cmd_output(&mut cmd)?
let devices;
let cmd_dev: Vec<&Path> = if let Some(paths) = devs {
paths
} else {
devices = {
let mut cmd = Command::new("blkid");
cmd.arg("--cache-file");
cmd.arg("/dev/null");
cmd.arg("-o");
cmd.arg("device");
cmd_output(&mut cmd)?
};
devices.lines().map(|line| Path::new(line.trim())).collect()
};

let output = {
let mut cmd = Command::new("blkid");
cmd.arg("-p");
cmd.args(devices.lines());
cmd.args(cmd_dev);
cmd_output(&mut cmd)?
};

Expand Down Expand Up @@ -1141,10 +1172,13 @@ fn disk_has_mbr(file: &mut (impl Read + Seek)) -> Result<bool> {
Ok(sig == [0x55, 0xaa])
}

pub fn have_udev() -> bool {
Path::new("/run/udev/control").exists()
}
pub fn udev_settle() -> Result<()> {
// "udevadm settle" silently no-ops if the udev socket is missing, and
// then lsblk can't find partition labels. Catch this early.
if !Path::new("/run/udev/control").exists() {
if !have_udev() {
bail!("udevd socket missing; are we running in a container without /run/udev mounted?");
}

Expand Down

0 comments on commit 0c30375

Please sign in to comment.