Skip to content

Commit

Permalink
Merge pull request #680 from cgwalters/blockdev-updates
Browse files Browse the repository at this point in the history
blockdev+install updates
  • Loading branch information
jmarrero authored Jul 15, 2024
2 parents 2a67685 + a08801b commit f74eab9
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
52 changes: 48 additions & 4 deletions lib/src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,18 @@ pub(crate) struct Device {
pub(crate) name: String,
pub(crate) serial: Option<String>,
pub(crate) model: Option<String>,
pub(crate) partlabel: Option<String>,
pub(crate) children: Option<Vec<Device>>,
pub(crate) size: u64,
#[serde(rename = "maj:min")]
pub(crate) maj_min: Option<String>,
// NOTE this one is not available on older util-linux, and
// will also not exist for whole blockdevs (as opposed to partitions).
pub(crate) start: Option<u64>,

// Filesystem-related properties
pub(crate) label: Option<String>,
pub(crate) fstype: Option<String>,
pub(crate) children: Option<Vec<Device>>,
pub(crate) size: Option<String>,
}

impl Device {
Expand All @@ -43,6 +51,39 @@ impl Device {
pub(crate) fn has_children(&self) -> bool {
self.children.as_ref().map_or(false, |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<()> {
let Some(majmin) = self.maj_min.as_deref() else {
// This shouldn't happen
return Ok(());
};
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")?,
);
}
Ok(())
}

/// Older versions of util-linux may be missing some properties. Backfill them if they're missing.
pub(crate) fn backfill_missing(&mut self) -> Result<()> {
// Add new properties to backfill here
self.backfill_start()?;
// And recurse to child devices
for child in self.children.iter_mut().flatten() {
child.backfill_missing()?;
}
Ok(())
}
}

#[context("Failed to wipe {dev}")]
Expand All @@ -56,13 +97,16 @@ pub(crate) fn wipefs(dev: &Utf8Path) -> Result<()> {

fn list_impl(dev: Option<&Utf8Path>) -> Result<Vec<Device>> {
let o = Command::new("lsblk")
.args(["-J", "-o", "NAME,SERIAL,MODEL,LABEL,FSTYPE,SIZE"])
.args(["-J", "-b", "-O"])
.args(dev)
.output()?;
if !o.status.success() {
return Err(anyhow::anyhow!("Failed to list block devices"));
}
let devs: DevicesOutput = serde_json::from_reader(&*o.stdout)?;
let mut devs: DevicesOutput = serde_json::from_reader(&*o.stdout)?;
for dev in devs.blockdevices.iter_mut() {
dev.backfill_missing()?;
}
Ok(devs.blockdevices)
}

Expand Down
6 changes: 4 additions & 2 deletions lib/src/bootloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@ use anyhow::Result;
use camino::Utf8Path;
use fn_error_context::context;

use crate::blockdev::Device;
use crate::task::Task;

/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
pub(crate) const EFI_DIR: &str = "efi";

#[context("Installing bootloader")]
pub(crate) fn install_via_bootupd(
device: &Utf8Path,
device: &Device,
rootfs: &Utf8Path,
configopts: &crate::install::InstallConfigOpts,
) -> Result<()> {
let verbose = std::env::var_os("BOOTC_BOOTLOADER_DEBUG").map(|_| "-vvvv");
// bootc defaults to only targeting the platform boot method.
let bootupd_opts = (!configopts.generic_image).then_some(["--update-firmware", "--auto"]);
let devpath = device.path();
let args = ["backend", "install", "--write-uuid"]
.into_iter()
.chain(verbose)
.chain(bootupd_opts.iter().copied().flatten())
.chain(["--device", device.as_str(), rootfs.as_str()]);
.chain(["--device", devpath.as_str(), rootfs.as_str()]);
Task::new("Running bootupctl to install bootloader", "bootupctl")
.args(args)
.verbose()
Expand Down
11 changes: 8 additions & 3 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ fn require_skopeo_with_containers_storage() -> Result<()> {

pub(crate) struct RootSetup {
luks_device: Option<String>,
device: Utf8PathBuf,
device_info: crate::blockdev::Device,
rootfs: Utf8PathBuf,
rootfs_fd: Dir,
rootfs_uuid: Option<String>,
Expand Down Expand Up @@ -1240,7 +1240,11 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
.context("Writing aleph version")?;
}

crate::bootloader::install_via_bootupd(&rootfs.device, &rootfs.rootfs, &state.config_opts)?;
crate::bootloader::install_via_bootupd(
&rootfs.device_info,
&rootfs.rootfs,
&state.config_opts,
)?;
tracing::debug!("Installed bootloader");

// Finalize mounted filesystems
Expand Down Expand Up @@ -1594,6 +1598,7 @@ pub(crate) async fn install_to_filesystem(
dev
};
tracing::debug!("Backing device: {backing_device}");
let device_info = crate::blockdev::list_dev(Utf8Path::new(&backing_device))?;

let rootarg = format!("root={}", root_info.mount_spec);
let mut boot = if let Some(spec) = fsopts.boot_mount_spec {
Expand Down Expand Up @@ -1622,7 +1627,7 @@ pub(crate) async fn install_to_filesystem(
matches!(fsopts.replace, Some(ReplaceMode::Alongside)) || fsopts.skip_finalize;
let mut rootfs = RootSetup {
luks_device: None,
device: backing_device.into(),
device_info,
rootfs: fsopts.root_path,
rootfs_fd,
rootfs_uuid: inspect.uuid.clone(),
Expand Down
11 changes: 4 additions & 7 deletions lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ fn mkfs<'a>(
opts: impl IntoIterator<Item = &'a str>,
) -> Result<uuid::Uuid> {
let devinfo = crate::blockdev::list_dev(dev.into())?;
let size = devinfo.size.as_deref().unwrap_or("(unknown)");
let size = ostree_ext::glib::format_size(devinfo.size);
let u = uuid::Uuid::new_v4();
let mut t = Task::new(
&format!("Creating {label} filesystem ({fs}) on device {dev} (size={size})"),
Expand Down Expand Up @@ -210,12 +210,8 @@ pub(crate) fn install_create_rootfs(
};
let serial = device.serial.as_deref().unwrap_or("<unknown>");
let model = device.model.as_deref().unwrap_or("<unknown>");
let size = device
.size
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Missing size for blockdev"))?;
println!("Block setup: {block_setup}");
println!(" Size: {size}",);
println!(" Size: {}", device.size);
println!(" Serial: {serial}");
println!(" Model: {model}");

Expand Down Expand Up @@ -443,9 +439,10 @@ pub(crate) fn install_create_rootfs(
BlockSetup::Direct => None,
BlockSetup::Tpm2Luks => Some(luks_name.to_string()),
};
let device_info = crate::blockdev::list_dev(&devpath)?;
Ok(RootSetup {
luks_device,
device: devpath,
device_info,
rootfs,
rootfs_fd,
rootfs_uuid: Some(root_uuid.to_string()),
Expand Down

0 comments on commit f74eab9

Please sign in to comment.