device_scan: Clean up udev code

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-11-30 15:28:45 -05:00
parent 9200be7c51
commit 166c245ee7

View File

@ -38,33 +38,25 @@ fn device_property_map(dev: &udev::Device) -> HashMap<String, String> {
rc rc
} }
fn udev_bcachefs_info() -> anyhow::Result<HashMap<String, Vec<String>>> { fn get_devices_by_uuid_udev(uuid: Uuid) -> anyhow::Result<Vec<String>> {
let mut info = HashMap::new();
if env::var("BCACHEFS_BLOCK_SCAN").is_ok() {
debug!("Checking all block devices for bcachefs super block!");
return Ok(info);
}
let mut udev = udev::Enumerator::new()?;
debug!("Walking udev db!"); debug!("Walking udev db!");
let mut udev = udev::Enumerator::new()?;
udev.match_subsystem("block")?; udev.match_subsystem("block")?;
udev.match_property("ID_FS_TYPE", "bcachefs")?; udev.match_property("ID_FS_TYPE", "bcachefs")?;
for m in udev let uuid = uuid.to_string();
Ok(udev
.scan_devices()? .scan_devices()?
.filter(udev::Device::is_initialized) .filter(udev::Device::is_initialized)
.map(|dev| device_property_map(&dev)) .map(|dev| device_property_map(&dev))
.filter(|m| m.contains_key("ID_FS_UUID") && m.contains_key("DEVNAME")) { .filter(|m|
let fs_uuid = m["ID_FS_UUID"].clone(); m.contains_key("ID_FS_UUID") &&
let dev_node = m["DEVNAME"].clone(); m["ID_FS_UUID"] == uuid &&
info.insert(dev_node.clone(), vec![fs_uuid.clone()]); m.contains_key("DEVNAME"))
info.entry(fs_uuid).or_insert(vec![]).push(dev_node.clone()); .map(|m| m["DEVNAME"].clone())
} .collect::<Vec<_>>())
Ok(info)
} }
fn get_all_block_devnodes() -> anyhow::Result<Vec<String>> { fn get_all_block_devnodes() -> anyhow::Result<Vec<String>> {
@ -84,29 +76,7 @@ fn get_all_block_devnodes() -> anyhow::Result<Vec<String>> {
Ok(devices) Ok(devices)
} }
fn get_devices_by_uuid( fn read_sbs_matching_uuid(uuid: Uuid, devices: &[String], opts: &bch_opts) -> Vec<(PathBuf, bch_sb_handle)> {
uuid: Uuid,
opts: &bch_opts
) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle)>> {
let udev_bcachefs = udev_bcachefs_info()?;
let devices = {
if !udev_bcachefs.is_empty() {
let uuid_string = uuid.hyphenated().to_string();
if let Some(devices) = udev_bcachefs.get(&uuid_string) {
devices.clone()
} else {
Vec::new()
}
} else {
get_all_block_devnodes()?
}
};
Ok(get_super_blocks(uuid, &devices, opts))
}
fn get_super_blocks(uuid: Uuid, devices: &[String], opts: &bch_opts) -> Vec<(PathBuf, bch_sb_handle)> {
devices devices
.iter() .iter()
.filter_map(|dev| { .filter_map(|dev| {
@ -118,9 +88,26 @@ fn get_super_blocks(uuid: Uuid, devices: &[String], opts: &bch_opts) -> Vec<(Pat
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
fn get_devices_by_uuid(
uuid: Uuid,
opts: &bch_opts,
use_udev: bool
) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle)>> {
let devs_from_udev = get_devices_by_uuid_udev(uuid)?;
let devices = if use_udev && !devs_from_udev.is_empty() {
devs_from_udev
} else {
get_all_block_devnodes()?
};
Ok(read_sbs_matching_uuid(uuid, &devices, opts))
}
fn devs_str_sbs_from_device( fn devs_str_sbs_from_device(
device: &Path, device: &Path,
opts: &bch_opts opts: &bch_opts,
use_udev: bool
) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle)>> { ) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle)>> {
if let Ok(metadata) = fs::metadata(device) { if let Ok(metadata) = fs::metadata(device) {
if metadata.is_dir() { if metadata.is_dir() {
@ -133,16 +120,12 @@ fn devs_str_sbs_from_device(
if dev_sb.sb().number_of_devices() == 1 { if dev_sb.sb().number_of_devices() == 1 {
Ok(vec![(device.to_path_buf(), dev_sb)]) Ok(vec![(device.to_path_buf(), dev_sb)])
} else { } else {
get_devices_by_uuid(dev_sb.sb().uuid(), opts) get_devices_by_uuid(dev_sb.sb().uuid(), opts, use_udev)
} }
} }
pub fn scan_sbs(device: &String, opts: &bch_opts) -> Result<Vec<(PathBuf, bch_sb_handle)>> { pub fn scan_sbs(device: &String, opts: &bch_opts) -> Result<Vec<(PathBuf, bch_sb_handle)>> {
if let Some(("UUID" | "OLD_BLKID_UUID", uuid)) = device.split_once('=') { if device.contains(':') {
let uuid = Uuid::parse_str(uuid)?;
get_devices_by_uuid(uuid, opts)
} else if device.contains(':') {
let mut opts = *opts; let mut opts = *opts;
opt_set!(opts, noexcl, 1); opt_set!(opts, noexcl, 1);
opt_set!(opts, no_version_check, 1); opt_set!(opts, no_version_check, 1);
@ -153,14 +136,22 @@ pub fn scan_sbs(device: &String, opts: &bch_opts) -> Result<Vec<(PathBuf, bch_sb
// part of the FS. This appears to be the case when we get called during // part of the FS. This appears to be the case when we get called during
// fstab mount processing and the fstab specifies a UUID. // fstab mount processing and the fstab specifies a UUID.
device.split(':') return device.split(':')
.map(PathBuf::from) .map(PathBuf::from)
.map(|path| .map(|path|
bch_bindgen::sb_io::read_super_opts(path.as_ref(), opts) bch_bindgen::sb_io::read_super_opts(path.as_ref(), opts)
.map(|sb| (path, sb))) .map(|sb| (path, sb)))
.collect::<Result<Vec<_>>>() .collect::<Result<Vec<_>>>()
}
let udev = !env::var("BCACHEFS_BLOCK_SCAN").is_ok();
if let Some(("UUID" | "OLD_BLKID_UUID", uuid)) = device.split_once('=') {
let uuid = Uuid::parse_str(uuid)?;
get_devices_by_uuid(uuid, opts, udev)
} else { } else {
devs_str_sbs_from_device(Path::new(device), opts) devs_str_sbs_from_device(Path::new(device), opts, udev)
} }
} }