all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling
@ 2021-04-20  9:53 Fabian Ebner
  2021-04-20  9:53 ` [pbs-devel] [PATCH/RFC proxmox-backup 2/2] disks: also check for file systems with lsblk Fabian Ebner
  2021-04-21 13:10 ` [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Wolfgang Bumiller
  0 siblings, 2 replies; 3+ messages in thread
From: Fabian Ebner @ 2021-04-20  9:53 UTC (permalink / raw)
  To: pbs-devel

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

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 src/tools/disks.rs     | 35 ++++++++++++++++++++++-------------
 src/tools/disks/lvm.rs | 18 ++++++++++--------
 src/tools/disks/zfs.rs | 17 ++++++++---------
 3 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/src/tools/disks.rs b/src/tools/disks.rs
index 8573695d..d374df0e 100644
--- a/src/tools/disks.rs
+++ b/src/tools/disks.rs
@@ -46,6 +46,14 @@ pub struct DiskManage {
     mounted_devices: OnceCell<HashSet<dev_t>>,
 }
 
+/// Information for a device as returned by lsblk.
+pub struct LsblkInfo {
+    /// Path to the device.
+    path: String,
+    /// Partition type GUID.
+    partition_type: Option<String>,
+}
+
 impl DiskManage {
     /// Create a new disk management context.
     pub fn new() -> Arc<Self> {
@@ -556,30 +564,31 @@ 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 output: serde_json::Value = output.parse()?;
+
+    let mut res = vec![];
+
     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(),
+                Some(p) => p.to_string(),
                 None => continue,
             };
-            let devices = res.entry(partition_type).or_insert(Vec::new());
-            devices.push(path.to_string());
+            let partition_type = info["parttype"].as_str().map(|t| t.to_string());
+            res.push(LsblkInfo {
+                path,
+                partition_type,
+            });
         }
     }
+
     Ok(res)
 }
 
@@ -736,14 +745,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





^ permalink raw reply	[flat|nested] 3+ messages in thread

* [pbs-devel] [PATCH/RFC proxmox-backup 2/2] disks: also check for file systems with lsblk
  2021-04-20  9:53 [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Fabian Ebner
@ 2021-04-20  9:53 ` Fabian Ebner
  2021-04-21 13:10 ` [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Wolfgang Bumiller
  1 sibling, 0 replies; 3+ messages in thread
From: Fabian Ebner @ 2021-04-20  9:53 UTC (permalink / raw)
  To: pbs-devel

so that whole disks with a file system that are not mounted are still detected
as in-use.

Reported-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---

Ideally, we'd also show the type in the result, but the api macro complained
when I tried using
    FileSystem(String)
    Mounted(String) // showing the fs type here would also be nice
in the enum. Is there a good way to do this? An alternative would be replacing
the DiskUsageType with a String in the DiskUsage struct, but that's not very
nice...

 src/tools/disks.rs | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/src/tools/disks.rs b/src/tools/disks.rs
index d374df0e..5eed723b 100644
--- a/src/tools/disks.rs
+++ b/src/tools/disks.rs
@@ -52,6 +52,8 @@ pub struct LsblkInfo {
     path: String,
     /// Partition type GUID.
     partition_type: Option<String>,
+    /// File system label.
+    file_system_type: Option<String>,
 }
 
 impl DiskManage {
@@ -563,11 +565,11 @@ pub struct BlockDevStat {
     pub io_ticks: u64, // milliseconds
 }
 
-/// Use lsblk to read partition type uuids.
+/// Use lsblk to read partition type uuids and file system types.
 pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, Error> {
 
     let mut command = std::process::Command::new("lsblk");
-    command.args(&["--json", "-o", "path,parttype"]);
+    command.args(&["--json", "-o", "path,parttype,fstype"]);
 
     let output = crate::tools::run_command(command, None)?;
 
@@ -582,9 +584,11 @@ pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, Error> {
                 None => continue,
             };
             let partition_type = info["parttype"].as_str().map(|t| t.to_string());
+            let file_system_type = info["fstype"].as_str().map(|t| t.to_string());
             res.push(LsblkInfo {
                 path,
                 partition_type,
+                file_system_type,
             });
         }
     }
@@ -592,6 +596,25 @@ pub fn get_lsblk_info() -> Result<Vec<LsblkInfo>, Error> {
     Ok(res)
 }
 
+/// Get set of devices with a file system label.
+///
+/// The set is indexed by using the unix raw device number (dev_t is u64)
+fn get_file_system_devices(
+    lsblk_info: &[LsblkInfo],
+) -> Result<HashSet<u64>, Error> {
+
+    let mut device_set: HashSet<u64> = HashSet::new();
+
+    for info in lsblk_info.iter() {
+        if info.file_system_type.is_some() {
+            let meta = std::fs::metadata(&info.path)?;
+            device_set.insert(meta.rdev());
+        }
+    }
+
+    Ok(device_set)
+}
+
 #[api()]
 #[derive(Debug, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all="lowercase")]
@@ -608,6 +631,8 @@ pub enum DiskUsageType {
     DeviceMapper,
     /// Disk has partitions
     Partitions,
+    /// Disk contains a file system label
+    FileSystem,
 }
 
 #[api(
@@ -754,6 +779,8 @@ pub fn get_disks(
 
     let lvm_devices = get_lvm_devices(&lsblk_info)?;
 
+    let file_system_devices = get_file_system_devices(&lsblk_info)?;
+
     // fixme: ceph journals/volumes
 
     let mut result = HashMap::new();
@@ -829,6 +856,10 @@ pub fn get_disks(
             };
         }
 
+        if usage == DiskUsageType::Unused && file_system_devices.contains(&devnum) {
+            usage = DiskUsageType::FileSystem;
+        }
+
         if usage == DiskUsageType::Unused && disk.has_holders()? {
             usage = DiskUsageType::DeviceMapper;
         }
-- 
2.20.1





^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling
  2021-04-20  9:53 [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Fabian Ebner
  2021-04-20  9:53 ` [pbs-devel] [PATCH/RFC proxmox-backup 2/2] disks: also check for file systems with lsblk Fabian Ebner
@ 2021-04-21 13:10 ` Wolfgang Bumiller
  1 sibling, 0 replies; 3+ messages in thread
From: Wolfgang Bumiller @ 2021-04-21 13:10 UTC (permalink / raw)
  To: Fabian Ebner; +Cc: pbs-devel

Looks fine, though I wonder if we should shorten this?

On Tue, Apr 20, 2021 at 11:53:44AM +0200, Fabian Ebner wrote:
> in preparation to also get the file system type from lsblk.
> 
> Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
> ---
>  src/tools/disks.rs     | 35 ++++++++++++++++++++++-------------
>  src/tools/disks/lvm.rs | 18 ++++++++++--------
>  src/tools/disks/zfs.rs | 17 ++++++++---------
>  3 files changed, 40 insertions(+), 30 deletions(-)
> 
> diff --git a/src/tools/disks.rs b/src/tools/disks.rs
> index 8573695d..d374df0e 100644
> --- a/src/tools/disks.rs
> +++ b/src/tools/disks.rs
> @@ -46,6 +46,14 @@ 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,30 +564,31 @@ 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 output: serde_json::Value = output.parse()?;

        let mut output: serde_json::Value = output.parse()?;
        Ok(serde_json::from_value(output["blockdevices"].take())?)
    }

And pretty much skip the rest of the function ;-)

> +
> +    let mut res = vec![];
> +
>      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(),
> +                Some(p) => p.to_string(),
>                  None => continue,
>              };
> -            let devices = res.entry(partition_type).or_insert(Vec::new());
> -            devices.push(path.to_string());
> +            let partition_type = info["parttype"].as_str().map(|t| t.to_string());
> +            res.push(LsblkInfo {
> +                path,
> +                partition_type,
> +            });
>          }
>      }
> +
>      Ok(res)
>  }
>  
> @@ -736,14 +745,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




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-04-21 13:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-20  9:53 [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Fabian Ebner
2021-04-20  9:53 ` [pbs-devel] [PATCH/RFC proxmox-backup 2/2] disks: also check for file systems with lsblk Fabian Ebner
2021-04-21 13:10 ` [pbs-devel] [PATCH/RFC proxmox-backup 1/2] disks: refactor partition type handling Wolfgang Bumiller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal