* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox