lvm: PV also match udev filter

This commit is contained in:
Mikaël Cluseau
2026-02-10 17:30:16 +01:00
parent 74c8ae293d
commit dff9142bdc

View File

@ -1,11 +1,11 @@
use eyre::{Result, format_err}; use eyre::{format_err, Result};
use log::{error, info, warn}; use log::{error, info, warn};
use tokio::process::Command; 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::fs::walk_dir;
use crate::{blockdev, lvm}; 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) { pub async fn setup(cfg: &Config) {
if cfg.lvm.is_empty() { 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)"); info!("setting up LVM VG {vg_name} ({dev_done}/{dev_needed} devices configured)");
} }
let regexps: Vec<regex::Regex> = (vg.pvs.regexps.iter()) let matching_devs = find_devs(&vg.pvs).await?;
.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 devs: Vec<_> = if dev_needed == TAKE_ALL { let devs: Vec<_> = if dev_needed == TAKE_ALL {
matching_devs.collect() matching_devs
} else { } else {
matching_devs.take(missing_count!()).collect() matching_devs.into_iter().take(missing_count!()).collect()
}; };
let cmd = if dev_done == 0 { let cmd = if dev_done == 0 {
@ -109,7 +97,7 @@ async fn setup_vg(vg: &LvmVG) -> Result<()> {
} }
dev_done += devs.len(); 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) { if dev_needed != TAKE_ALL && dev_done < (dev_needed as usize) {
return Err(format_err!( return Err(format_err!(
@ -213,3 +201,33 @@ async fn install_package(pkg: &str) -> Result<()> {
Err(format_err!("failed to install package {pkg}: {status}")) Err(format_err!("failed to install package {pkg}: {status}"))
} }
} }
async fn find_devs(pvs: &LvmPV) -> Result<Vec<String>> {
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<regex::Regex> = (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)
}