Skip to content

Commit f74eab9

Browse files
authored
Merge pull request #680 from cgwalters/blockdev-updates
blockdev+install updates
2 parents 2a67685 + a08801b commit f74eab9

File tree

4 files changed

+64
-16
lines changed

4 files changed

+64
-16
lines changed

lib/src/blockdev.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@ pub(crate) struct Device {
2727
pub(crate) name: String,
2828
pub(crate) serial: Option<String>,
2929
pub(crate) model: Option<String>,
30+
pub(crate) partlabel: Option<String>,
31+
pub(crate) children: Option<Vec<Device>>,
32+
pub(crate) size: u64,
33+
#[serde(rename = "maj:min")]
34+
pub(crate) maj_min: Option<String>,
35+
// NOTE this one is not available on older util-linux, and
36+
// will also not exist for whole blockdevs (as opposed to partitions).
37+
pub(crate) start: Option<u64>,
38+
39+
// Filesystem-related properties
3040
pub(crate) label: Option<String>,
3141
pub(crate) fstype: Option<String>,
32-
pub(crate) children: Option<Vec<Device>>,
33-
pub(crate) size: Option<String>,
3442
}
3543

3644
impl Device {
@@ -43,6 +51,39 @@ impl Device {
4351
pub(crate) fn has_children(&self) -> bool {
4452
self.children.as_ref().map_or(false, |v| !v.is_empty())
4553
}
54+
55+
// The "start" parameter was only added in a version of util-linux that's only
56+
// in Fedora 40 as of this writing.
57+
fn backfill_start(&mut self) -> Result<()> {
58+
let Some(majmin) = self.maj_min.as_deref() else {
59+
// This shouldn't happen
60+
return Ok(());
61+
};
62+
let sysfs_start_path = format!("/sys/dev/block/{majmin}/start");
63+
if Utf8Path::new(&sysfs_start_path).try_exists()? {
64+
let start = std::fs::read_to_string(&sysfs_start_path)
65+
.with_context(|| format!("Reading {sysfs_start_path}"))?;
66+
tracing::debug!("backfilled start to {start}");
67+
self.start = Some(
68+
start
69+
.trim()
70+
.parse()
71+
.context("Parsing sysfs start property")?,
72+
);
73+
}
74+
Ok(())
75+
}
76+
77+
/// Older versions of util-linux may be missing some properties. Backfill them if they're missing.
78+
pub(crate) fn backfill_missing(&mut self) -> Result<()> {
79+
// Add new properties to backfill here
80+
self.backfill_start()?;
81+
// And recurse to child devices
82+
for child in self.children.iter_mut().flatten() {
83+
child.backfill_missing()?;
84+
}
85+
Ok(())
86+
}
4687
}
4788

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

5798
fn list_impl(dev: Option<&Utf8Path>) -> Result<Vec<Device>> {
5899
let o = Command::new("lsblk")
59-
.args(["-J", "-o", "NAME,SERIAL,MODEL,LABEL,FSTYPE,SIZE"])
100+
.args(["-J", "-b", "-O"])
60101
.args(dev)
61102
.output()?;
62103
if !o.status.success() {
63104
return Err(anyhow::anyhow!("Failed to list block devices"));
64105
}
65-
let devs: DevicesOutput = serde_json::from_reader(&*o.stdout)?;
106+
let mut devs: DevicesOutput = serde_json::from_reader(&*o.stdout)?;
107+
for dev in devs.blockdevices.iter_mut() {
108+
dev.backfill_missing()?;
109+
}
66110
Ok(devs.blockdevices)
67111
}
68112

lib/src/bootloader.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,27 @@ use anyhow::Result;
22
use camino::Utf8Path;
33
use fn_error_context::context;
44

5+
use crate::blockdev::Device;
56
use crate::task::Task;
67

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

1011
#[context("Installing bootloader")]
1112
pub(crate) fn install_via_bootupd(
12-
device: &Utf8Path,
13+
device: &Device,
1314
rootfs: &Utf8Path,
1415
configopts: &crate::install::InstallConfigOpts,
1516
) -> Result<()> {
1617
let verbose = std::env::var_os("BOOTC_BOOTLOADER_DEBUG").map(|_| "-vvvv");
1718
// bootc defaults to only targeting the platform boot method.
1819
let bootupd_opts = (!configopts.generic_image).then_some(["--update-firmware", "--auto"]);
20+
let devpath = device.path();
1921
let args = ["backend", "install", "--write-uuid"]
2022
.into_iter()
2123
.chain(verbose)
2224
.chain(bootupd_opts.iter().copied().flatten())
23-
.chain(["--device", device.as_str(), rootfs.as_str()]);
25+
.chain(["--device", devpath.as_str(), rootfs.as_str()]);
2426
Task::new("Running bootupctl to install bootloader", "bootupctl")
2527
.args(args)
2628
.verbose()

lib/src/install.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ fn require_skopeo_with_containers_storage() -> Result<()> {
823823

824824
pub(crate) struct RootSetup {
825825
luks_device: Option<String>,
826-
device: Utf8PathBuf,
826+
device_info: crate::blockdev::Device,
827827
rootfs: Utf8PathBuf,
828828
rootfs_fd: Dir,
829829
rootfs_uuid: Option<String>,
@@ -1240,7 +1240,11 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
12401240
.context("Writing aleph version")?;
12411241
}
12421242

1243-
crate::bootloader::install_via_bootupd(&rootfs.device, &rootfs.rootfs, &state.config_opts)?;
1243+
crate::bootloader::install_via_bootupd(
1244+
&rootfs.device_info,
1245+
&rootfs.rootfs,
1246+
&state.config_opts,
1247+
)?;
12441248
tracing::debug!("Installed bootloader");
12451249

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

15981603
let rootarg = format!("root={}", root_info.mount_spec);
15991604
let mut boot = if let Some(spec) = fsopts.boot_mount_spec {
@@ -1622,7 +1627,7 @@ pub(crate) async fn install_to_filesystem(
16221627
matches!(fsopts.replace, Some(ReplaceMode::Alongside)) || fsopts.skip_finalize;
16231628
let mut rootfs = RootSetup {
16241629
luks_device: None,
1625-
device: backing_device.into(),
1630+
device_info,
16261631
rootfs: fsopts.root_path,
16271632
rootfs_fd,
16281633
rootfs_uuid: inspect.uuid.clone(),

lib/src/install/baseline.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn mkfs<'a>(
125125
opts: impl IntoIterator<Item = &'a str>,
126126
) -> Result<uuid::Uuid> {
127127
let devinfo = crate::blockdev::list_dev(dev.into())?;
128-
let size = devinfo.size.as_deref().unwrap_or("(unknown)");
128+
let size = ostree_ext::glib::format_size(devinfo.size);
129129
let u = uuid::Uuid::new_v4();
130130
let mut t = Task::new(
131131
&format!("Creating {label} filesystem ({fs}) on device {dev} (size={size})"),
@@ -210,12 +210,8 @@ pub(crate) fn install_create_rootfs(
210210
};
211211
let serial = device.serial.as_deref().unwrap_or("<unknown>");
212212
let model = device.model.as_deref().unwrap_or("<unknown>");
213-
let size = device
214-
.size
215-
.as_deref()
216-
.ok_or_else(|| anyhow::anyhow!("Missing size for blockdev"))?;
217213
println!("Block setup: {block_setup}");
218-
println!(" Size: {size}",);
214+
println!(" Size: {}", device.size);
219215
println!(" Serial: {serial}");
220216
println!(" Model: {model}");
221217

@@ -443,9 +439,10 @@ pub(crate) fn install_create_rootfs(
443439
BlockSetup::Direct => None,
444440
BlockSetup::Tpm2Luks => Some(luks_name.to_string()),
445441
};
442+
let device_info = crate::blockdev::list_dev(&devpath)?;
446443
Ok(RootSetup {
447444
luks_device,
448-
device: devpath,
445+
device_info,
449446
rootfs,
450447
rootfs_fd,
451448
rootfs_uuid: Some(root_uuid.to_string()),

0 commit comments

Comments
 (0)