Skip to content
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
51 changes: 31 additions & 20 deletions crates/blockdev/src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub struct Device {
pub partlabel: Option<String>,
pub parttype: Option<String>,
pub partuuid: Option<String>,
/// Partition number (1-indexed). None for whole disk devices.
pub partn: Option<u32>,
pub children: Option<Vec<Device>>,
pub size: u64,
#[serde(rename = "maj:min")]
Expand Down Expand Up @@ -60,33 +62,42 @@ impl Device {
self.children.as_ref().is_some_and(|v| !v.is_empty())
}

// The "start" parameter was only added in a version of util-linux that's only
// in Fedora 40 as of this writing.
fn backfill_start(&mut self) -> Result<()> {
/// Read a sysfs property for this device and parse it as the target type.
fn read_sysfs_property<T>(&self, property: &str) -> Result<Option<T>>
where
T: std::str::FromStr,
T::Err: std::error::Error + Send + Sync + 'static,
{
let Some(majmin) = self.maj_min.as_deref() else {
// This shouldn't happen
return Ok(());
return Ok(None);
};
let sysfs_start_path = format!("/sys/dev/block/{majmin}/start");
if Utf8Path::new(&sysfs_start_path).try_exists()? {
let start = std::fs::read_to_string(&sysfs_start_path)
.with_context(|| format!("Reading {sysfs_start_path}"))?;
tracing::debug!("backfilled start to {start}");
self.start = Some(
start
.trim()
.parse()
.context("Parsing sysfs start property")?,
);
let sysfs_path = format!("/sys/dev/block/{majmin}/{property}");
if !Utf8Path::new(&sysfs_path).try_exists()? {
return Ok(None);
}
Ok(())
let value = std::fs::read_to_string(&sysfs_path)
.with_context(|| format!("Reading {sysfs_path}"))?;
let parsed = value
.trim()
.parse()
.with_context(|| format!("Parsing sysfs {property} property"))?;
tracing::debug!("backfilled {property} to {value}");
Ok(Some(parsed))
}

/// Older versions of util-linux may be missing some properties. Backfill them if they're missing.
pub fn backfill_missing(&mut self) -> Result<()> {
// Add new properties to backfill here
self.backfill_start()?;
// And recurse to child devices
// The "start" parameter was only added in a version of util-linux that's only
// in Fedora 40 as of this writing.
if self.start.is_none() {
self.start = self.read_sysfs_property("start")?;
}
// The "partn" column was added in util-linux 2.39, which is newer than
// what CentOS 9 / RHEL 9 ship (2.37). Note: sysfs uses "partition" not "partn".
if self.partn.is_none() {
self.partn = self.read_sysfs_property("partition")?;
}
// Recurse to child devices
for child in self.children.iter_mut().flatten() {
child.backfill_missing()?;
}
Expand Down
3 changes: 3 additions & 0 deletions crates/lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,9 @@ async fn prepare_install(
// In some cases we may create large files, and it's better not to have those
// in our overlayfs.
bootc_mount::ensure_mirrored_host_mount("/var/tmp")?;
// udev state is required for running lsblk during install to-disk
// see https://github.com/bootc-dev/bootc/pull/688
bootc_mount::ensure_mirrored_host_mount("/run/udev")?;
// We also always want /tmp to be a proper tmpfs on general principle.
setup_tmp_mount()?;
// Allocate a temporary directory we can use in various places to avoid
Expand Down