diff --git a/src/cmd/init/lvm.rs b/src/cmd/init/lvm.rs index 5e5ada6..520669e 100644 --- a/src/cmd/init/lvm.rs +++ b/src/cmd/init/lvm.rs @@ -1,11 +1,11 @@ -use eyre::{Result, format_err}; +use eyre::{format_err, Result}; use log::{error, info, warn}; use tokio::process::Command; -use super::{USED_DEVS, exec, retry, retry_or_ignore}; +use super::{exec, retry, retry_or_ignore, USED_DEVS}; use crate::fs::walk_dir; use crate::{blockdev, lvm}; -use dkl::bootstrap::{Config, Filesystem, LvSize, LvmLV, LvmVG, TAKE_ALL}; +use dkl::bootstrap::{Config, Filesystem, LvSize, LvmLV, LvmPV, LvmVG, TAKE_ALL}; pub async fn setup(cfg: &Config) { if cfg.lvm.is_empty() { @@ -73,24 +73,12 @@ async fn setup_vg(vg: &LvmVG) -> Result<()> { info!("setting up LVM VG {vg_name} ({dev_done}/{dev_needed} devices configured)"); } - let regexps: Vec = (vg.pvs.regexps.iter()) - .filter_map(|re_str| { - (re_str.parse()) - .inspect_err(|e| error!("invalid regex ignored: {re_str:?}: {e}")) - .ok() - }) - .collect(); - - let mut used_devs = USED_DEVS.lock().await; - - let matching_devs = (walk_dir("/dev").await.into_iter()) - .filter(|path| !used_devs.contains(path.as_str())) - .filter(|path| regexps.iter().any(|re| re.is_match(path))); + let matching_devs = find_devs(&vg.pvs).await?; let devs: Vec<_> = if dev_needed == TAKE_ALL { - matching_devs.collect() + matching_devs } else { - matching_devs.take(missing_count!()).collect() + matching_devs.into_iter().take(missing_count!()).collect() }; let cmd = if dev_done == 0 { @@ -109,7 +97,7 @@ async fn setup_vg(vg: &LvmVG) -> Result<()> { } dev_done += devs.len(); - used_devs.extend(devs); + USED_DEVS.lock().await.extend(devs); if dev_needed != TAKE_ALL && dev_done < (dev_needed as usize) { return Err(format_err!( @@ -213,3 +201,33 @@ async fn install_package(pkg: &str) -> Result<()> { Err(format_err!("failed to install package {pkg}: {status}")) } } + +async fn find_devs(pvs: &LvmPV) -> Result> { + let mut results = if let Some(ref filter) = pvs.udev { + use crate::udev; + let filter: udev::Filter = filter.clone().into(); + (udev::all().await?.iter()) + .filter(|dev| dev.subsystem() == Some("block") && filter.matches(dev)) + .filter_map(|dev| dev.property("DEVNAME").map(|s| s.to_string())) + .collect() + } else if !pvs.regexps.is_empty() { + let regexps: Vec = (pvs.regexps.iter()) + .filter_map(|re_str| { + (re_str.parse()) + .inspect_err(|e| error!("invalid regex ignored: {re_str:?}: {e}")) + .ok() + }) + .collect(); + + (walk_dir("/dev").await.into_iter()) + .filter(|path| regexps.iter().any(|re| re.is_match(path))) + .collect() + } else { + warn!("no device filters, no matches"); + vec![] + }; + + let used_devs = USED_DEVS.lock().await; + results.retain(|path| !used_devs.contains(path.as_str())); + Ok(results) +}