Skip to content

Commit a7c5788

Browse files
authored
Merge pull request #1048 from cgwalters/blockdev-no-task
install/blockdev: Break cyclic build dependency
2 parents e8bb9f7 + b23777f commit a7c5788

File tree

3 files changed

+45
-43
lines changed

3 files changed

+45
-43
lines changed

lib/src/blockdev.rs

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ use fn_error_context::context;
1414
use regex::Regex;
1515
use serde::Deserialize;
1616

17-
#[cfg(feature = "install-to-disk")]
18-
use crate::install::run_in_host_mountns;
19-
use crate::task::Task;
2017
use bootc_utils::CommandRunExt;
2118

2219
#[derive(Debug, Deserialize)]
@@ -91,16 +88,6 @@ impl Device {
9188
}
9289
}
9390

94-
#[context("Failed to wipe {dev}")]
95-
#[cfg(feature = "install-to-disk")]
96-
pub(crate) fn wipefs(dev: &Utf8Path) -> Result<()> {
97-
Task::new_and_run(
98-
format!("Wiping device {dev}"),
99-
"wipefs",
100-
["-a", dev.as_str()],
101-
)
102-
}
103-
10491
#[context("Listing device {dev}")]
10592
pub(crate) fn list_dev(dev: &Utf8Path) -> Result<Device> {
10693
let mut devs: DevicesOutput = Command::new("lsblk")
@@ -187,10 +174,9 @@ impl Partition {
187174

188175
#[context("Listing partitions of {dev}")]
189176
pub(crate) fn partitions_of(dev: &Utf8Path) -> Result<PartitionTable> {
190-
let o = Task::new_quiet("sfdisk")
177+
let o: SfDiskOutput = Command::new("sfdisk")
191178
.args(["-J", dev.as_str()])
192-
.read()?;
193-
let o: SfDiskOutput = serde_json::from_str(&o).context("Parsing sfdisk output")?;
179+
.run_and_parse_json()?;
194180
Ok(o.partitiontable)
195181
}
196182

@@ -214,16 +200,15 @@ impl LoopbackDevice {
214200
Err(_e) => "off",
215201
};
216202

217-
let dev = Task::new("losetup", "losetup")
203+
let dev = Command::new("losetup")
218204
.args([
219205
"--show",
220206
format!("--direct-io={direct_io}").as_str(),
221207
"-P",
222208
"--find",
223209
])
224210
.arg(path)
225-
.quiet()
226-
.read()?;
211+
.run_get_string()?;
227212
let dev = Utf8PathBuf::from(dev.trim());
228213
tracing::debug!("Allocated loopback {dev}");
229214
Ok(Self { dev: Some(dev) })
@@ -242,10 +227,7 @@ impl LoopbackDevice {
242227
tracing::trace!("loopback device already deallocated");
243228
return Ok(());
244229
};
245-
Task::new("losetup", "losetup")
246-
.args(["-d", dev.as_str()])
247-
.quiet()
248-
.run()
230+
Command::new("losetup").args(["-d", dev.as_str()]).run()
249231
}
250232

251233
/// Consume this device, unmounting it.
@@ -262,21 +244,6 @@ impl Drop for LoopbackDevice {
262244
}
263245
}
264246

265-
#[cfg(feature = "install-to-disk")]
266-
pub(crate) fn udev_settle() -> Result<()> {
267-
// There's a potential window after rereading the partition table where
268-
// udevd hasn't yet received updates from the kernel, settle will return
269-
// immediately, and lsblk won't pick up partition labels. Try to sleep
270-
// our way out of this.
271-
std::thread::sleep(std::time::Duration::from_millis(200));
272-
273-
let st = run_in_host_mountns("udevadm").arg("settle").status()?;
274-
if !st.success() {
275-
anyhow::bail!("Failed to run udevadm settle: {st:?}");
276-
}
277-
Ok(())
278-
}
279-
280247
/// Parse key-value pairs from lsblk --pairs.
281248
/// Newer versions of lsblk support JSON but the one in CentOS 7 doesn't.
282249
fn split_lsblk_line(line: &str) -> HashMap<String, String> {
@@ -293,15 +260,15 @@ fn split_lsblk_line(line: &str) -> HashMap<String, String> {
293260
/// hierarchy of `device` capable of containing other partitions. So e.g. parent devices of type
294261
/// "part" doesn't match, but "disk" and "mpath" does.
295262
pub(crate) fn find_parent_devices(device: &str) -> Result<Vec<String>> {
296-
let output = Task::new_quiet("lsblk")
263+
let output = Command::new("lsblk")
297264
// Older lsblk, e.g. in CentOS 7.6, doesn't support PATH, but --paths option
298265
.arg("--pairs")
299266
.arg("--paths")
300267
.arg("--inverse")
301268
.arg("--output")
302269
.arg("NAME,TYPE")
303270
.arg(device)
304-
.read()?;
271+
.run_get_string()?;
305272
let mut parents = Vec::new();
306273
// skip first line, which is the device itself
307274
for line in output.lines().skip(1) {

lib/src/install/baseline.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,31 @@ fn mkfs<'a>(
131131
Ok(u)
132132
}
133133

134+
#[context("Failed to wipe {dev}")]
135+
pub(crate) fn wipefs(dev: &Utf8Path) -> Result<()> {
136+
Task::new_and_run(
137+
format!("Wiping device {dev}"),
138+
"wipefs",
139+
["-a", dev.as_str()],
140+
)
141+
}
142+
143+
pub(crate) fn udev_settle() -> Result<()> {
144+
// There's a potential window after rereading the partition table where
145+
// udevd hasn't yet received updates from the kernel, settle will return
146+
// immediately, and lsblk won't pick up partition labels. Try to sleep
147+
// our way out of this.
148+
std::thread::sleep(std::time::Duration::from_millis(200));
149+
150+
let st = super::run_in_host_mountns("udevadm")
151+
.arg("settle")
152+
.status()?;
153+
if !st.success() {
154+
anyhow::bail!("Failed to run udevadm settle: {st:?}");
155+
}
156+
Ok(())
157+
}
158+
134159
#[context("Creating rootfs")]
135160
#[cfg(feature = "install-to-disk")]
136161
pub(crate) fn install_create_rootfs(
@@ -164,10 +189,10 @@ pub(crate) fn install_create_rootfs(
164189
for child in device.children.iter().flatten() {
165190
let child = child.path();
166191
println!("Wiping {child}");
167-
crate::blockdev::wipefs(Utf8Path::new(&child))?;
192+
wipefs(Utf8Path::new(&child))?;
168193
}
169194
println!("Wiping {dev}");
170-
crate::blockdev::wipefs(dev)?;
195+
wipefs(dev)?;
171196
} else if device.has_children() {
172197
anyhow::bail!(
173198
"Detected existing partitions on {}; use e.g. `wipefs` or --wipe if you intend to overwrite",
@@ -289,7 +314,7 @@ pub(crate) fn install_create_rootfs(
289314

290315
// Full udev sync; it'd obviously be better to await just the devices
291316
// we're targeting, but this is a simple coarse hammer.
292-
crate::blockdev::udev_settle()?;
317+
udev_settle()?;
293318

294319
// Re-read what we wrote into structured information
295320
let base_partitions = &crate::blockdev::partitions_of(&devpath)?;

utils/src/command.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub trait CommandRunExt {
2323
/// and will return an error if the child process exits abnormally.
2424
fn run_get_output(&mut self) -> Result<Box<dyn std::io::BufRead>>;
2525

26+
/// Execute the child process and capture its output as a string.
27+
fn run_get_string(&mut self) -> Result<String>;
28+
2629
/// Execute the child process, parsing its stdout as JSON. This uses `run` internally
2730
/// and will return an error if the child process exits abnormally.
2831
fn run_and_parse_json<T: serde::de::DeserializeOwned>(&mut self) -> Result<T>;
@@ -118,6 +121,13 @@ impl CommandRunExt for Command {
118121
Ok(Box::new(std::io::BufReader::new(stdout)))
119122
}
120123

124+
fn run_get_string(&mut self) -> Result<String> {
125+
let mut s = String::new();
126+
let mut o = self.run_get_output()?;
127+
o.read_to_string(&mut s)?;
128+
Ok(s)
129+
}
130+
121131
/// Synchronously execute the child, and parse its stdout as JSON.
122132
fn run_and_parse_json<T: serde::de::DeserializeOwned>(&mut self) -> Result<T> {
123133
let output = self.run_get_output()?;

0 commit comments

Comments
 (0)