[pbs-devel] [PATCH/RFC v2 proxmox-backup 1/2] disks: refactor partition type handling

Fabian Ebner f.ebner at proxmox.com
Mon May 3 09:44:07 CEST 2021


in preparation to also get the file system type from lsblk.

Co-developed-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
Signed-off-by: Fabian Ebner <f.ebner at proxmox.com>
---

Changes from v1:
    * automate parsing with the help of serde (thanks to Wolfgang for the
      suggestion!)

 src/tools/disks.rs     | 37 ++++++++++++++++---------------------
 src/tools/disks/lvm.rs | 18 ++++++++++--------
 src/tools/disks/zfs.rs | 17 ++++++++---------
 3 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/src/tools/disks.rs b/src/tools/disks.rs
index 8573695d..885edf47 100644
--- a/src/tools/disks.rs
+++ b/src/tools/disks.rs
@@ -46,6 +46,16 @@ pub struct DiskManage {
     mounted_devices: OnceCell<HashSet<dev_t>>,
 }
 
+/// Information for a device as returned by lsblk.
+#[derive(Deserialize)]
+pub struct LsblkInfo {
+    /// Path to the device.
+    path: String,
+    /// Partition type GUID.
+    #[serde(rename = "parttype")]
+    partition_type: Option<String>,
+}
+
 impl DiskManage {
     /// Create a new disk management context.
     pub fn new() -> Arc<Self> {
@@ -556,31 +566,16 @@ pub struct BlockDevStat {
 }
 
 /// Use lsblk to read partition type uuids.
-pub fn get_partition_type_info() -> Result<HashMap<String, Vec<String>>, Error> {
+pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, Error> {
 
     let mut command = std::process::Command::new("lsblk");
     command.args(&["--json", "-o", "path,parttype"]);
 
     let output = crate::tools::run_command(command, None)?;
 
-    let mut res: HashMap<String, Vec<String>> = HashMap::new();
+    let mut output: serde_json::Value = output.parse()?;
 
-    let output: serde_json::Value = output.parse()?;
-    if let Some(list) = output["blockdevices"].as_array() {
-        for info in list {
-            let path = match info["path"].as_str() {
-                Some(p) => p,
-                None => continue,
-            };
-            let partition_type = match info["parttype"].as_str() {
-                Some(t) => t.to_owned(),
-                None => continue,
-            };
-            let devices = res.entry(partition_type).or_insert(Vec::new());
-            devices.push(path.to_string());
-        }
-    }
-    Ok(res)
+    Ok(serde_json::from_value(output["blockdevices"].take())?)
 }
 
 #[api()]
@@ -736,14 +731,14 @@ pub fn get_disks(
 
     let disk_manager = DiskManage::new();
 
-    let partition_type_map = get_partition_type_info()?;
+    let lsblk_info = get_lsblk_info()?;
 
-    let zfs_devices = zfs_devices(&partition_type_map, None).or_else(|err| -> Result<HashSet<u64>, Error> {
+    let zfs_devices = zfs_devices(&lsblk_info, None).or_else(|err| -> Result<HashSet<u64>, Error> {
         eprintln!("error getting zfs devices: {}", err);
         Ok(HashSet::new())
     })?;
 
-    let lvm_devices = get_lvm_devices(&partition_type_map)?;
+    let lvm_devices = get_lvm_devices(&lsblk_info)?;
 
     // fixme: ceph journals/volumes
 
diff --git a/src/tools/disks/lvm.rs b/src/tools/disks/lvm.rs
index 1e8f825d..1a81cea0 100644
--- a/src/tools/disks/lvm.rs
+++ b/src/tools/disks/lvm.rs
@@ -1,10 +1,12 @@
-use std::collections::{HashSet, HashMap};
+use std::collections::HashSet;
 use std::os::unix::fs::MetadataExt;
 
 use anyhow::{Error};
 use serde_json::Value;
 use lazy_static::lazy_static;
 
+use super::LsblkInfo;
+
 lazy_static!{
     static ref LVM_UUIDS: HashSet<&'static str> = {
         let mut set = HashSet::new();
@@ -17,7 +19,7 @@ lazy_static!{
 ///
 /// The set is indexed by using the unix raw device number (dev_t is u64)
 pub fn get_lvm_devices(
-    partition_type_map: &HashMap<String, Vec<String>>,
+    lsblk_info: &[LsblkInfo],
 ) -> Result<HashSet<u64>, Error> {
 
     const PVS_BIN_PATH: &str = "pvs";
@@ -29,12 +31,12 @@ pub fn get_lvm_devices(
 
     let mut device_set: HashSet<u64> = HashSet::new();
 
-    for device_list in partition_type_map.iter()
-        .filter_map(|(uuid, list)| if LVM_UUIDS.contains(uuid.as_str()) { Some(list) } else { None })
-    {
-        for device in device_list {
-            let meta = std::fs::metadata(device)?;
-            device_set.insert(meta.rdev());
+    for info in lsblk_info.iter() {
+        if let Some(partition_type) = &info.partition_type {
+            if LVM_UUIDS.contains(partition_type.as_str()) {
+                let meta = std::fs::metadata(&info.path)?;
+                device_set.insert(meta.rdev());
+            }
         }
     }
 
diff --git a/src/tools/disks/zfs.rs b/src/tools/disks/zfs.rs
index e0084939..55e0aa30 100644
--- a/src/tools/disks/zfs.rs
+++ b/src/tools/disks/zfs.rs
@@ -1,5 +1,5 @@
 use std::path::PathBuf;
-use std::collections::{HashMap, HashSet};
+use std::collections::HashSet;
 use std::os::unix::fs::MetadataExt;
 
 use anyhow::{bail, Error};
@@ -67,12 +67,11 @@ pub fn zfs_pool_stats(pool: &OsStr) -> Result<Option<BlockDevStat>, Error> {
     Ok(Some(stat))
 }
 
-
 /// Get set of devices used by zfs (or a specific zfs pool)
 ///
 /// The set is indexed by using the unix raw device number (dev_t is u64)
 pub fn zfs_devices(
-    partition_type_map: &HashMap<String, Vec<String>>,
+    lsblk_info: &[LsblkInfo],
     pool: Option<String>,
 ) -> Result<HashSet<u64>, Error> {
 
@@ -86,12 +85,12 @@ pub fn zfs_devices(
         }
     }
 
-    for device_list in partition_type_map.iter()
-        .filter_map(|(uuid, list)| if ZFS_UUIDS.contains(uuid.as_str()) { Some(list) } else { None })
-    {
-        for device in device_list {
-            let meta = std::fs::metadata(device)?;
-            device_set.insert(meta.rdev());
+    for info in lsblk_info.iter() {
+        if let Some(partition_type) = &info.partition_type {
+            if ZFS_UUIDS.contains(partition_type.as_str()) {
+                let meta = std::fs::metadata(&info.path)?;
+                device_set.insert(meta.rdev());
+            }
         }
     }
 
-- 
2.20.1






More information about the pbs-devel mailing list