[pbs-devel] [PATCH proxmox-backup v9 06/26] datastore: add helper for checking if a removable datastore is available

Wolfgang Bumiller w.bumiller at proxmox.com
Wed Apr 24 15:30:59 CEST 2024


On Tue, Apr 23, 2024 at 10:29:40AM +0200, Hannes Laimer wrote:
> Signed-off-by: Hannes Laimer <h.laimer at proxmox.com>
> ---
>  pbs-api-types/src/maintenance.rs |  2 +-
>  pbs-datastore/src/datastore.rs   | 44 ++++++++++++++++++++++++++++++++
>  pbs-datastore/src/lib.rs         |  2 +-
>  3 files changed, 46 insertions(+), 2 deletions(-)
> 
> diff --git a/pbs-api-types/src/maintenance.rs b/pbs-api-types/src/maintenance.rs
> index fd4d3416..4f653ec7 100644
> --- a/pbs-api-types/src/maintenance.rs
> +++ b/pbs-api-types/src/maintenance.rs
> @@ -81,7 +81,7 @@ impl MaintenanceMode {
>      /// Used for deciding whether the datastore is cleared from the internal cache after the last
>      /// task finishes, so all open files are closed.
>      pub fn is_offline(&self) -> bool {
> -        self.ty == MaintenanceType::Offline
> +        self.ty == MaintenanceType::Offline || self.ty == MaintenanceType::Unmount
>      }
>  
>      pub fn check(&self, operation: Option<Operation>) -> Result<(), Error> {
> diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs
> index f9b986c1..978ebb70 100644
> --- a/pbs-datastore/src/datastore.rs
> +++ b/pbs-datastore/src/datastore.rs
> @@ -14,6 +14,7 @@ use proxmox_schema::ApiType;
>  use proxmox_sys::error::SysError;
>  use proxmox_sys::fs::{file_read_optional_string, replace_file, CreateOptions};
>  use proxmox_sys::fs::{lock_dir_noblock, DirLockGuard};
> +use proxmox_sys::linux::procfs::MountInfo;
>  use proxmox_sys::process_locker::ProcessLockSharedGuard;
>  use proxmox_sys::WorkerTaskContext;
>  use proxmox_sys::{task_log, task_warn};
> @@ -49,6 +50,39 @@ pub fn check_backup_owner(owner: &Authid, auth_id: &Authid) -> Result<(), Error>
>      Ok(())
>  }
>  
> +/// check if a removable datastore is currently available/mounted by using the UUID
> +/// to find the `/dev/sdX` path and checking in /proc/self/mountinfo for entries containing it.
> +/// If it should mounted, but not in the expected path, so config.path, it is considered not
> +/// available.
> +pub fn is_datastore_available(config: &DataStoreConfig) -> bool {
> +    config.backing_device.as_ref().map_or(true, |uuid| {
> +        if let Ok(store_dev_path) = std::fs::read_link(Path::new("/dev/disk/by-uuid").join(uuid))
> +            .map(|p| p.to_string_lossy().into_owned())
> +            .map(|p| p.replace("../..", "/dev"))

^ Merge the two .maps together and you can drop the into_owned()

Also, this is very fragile!
`/proc/self/mountinfo` does NOT necessarily contain the final device
node.
For instance, for LVs you do NOT see `/dev/dm-xy`, but
`/dev/mapper/foo-bar`.

I pushed an alternative to my `staff` repo's
`removable-datastore-review` branch which worked for my testing.

There I instead `stat` the backing device and the source device found in
the MountInfo and compare their `st_rdev` values.

> +            .map(PathBuf::from)

^ Not strictly needed

> +        {
> +            let store_mount_point = config.get_mount_point().map(|mp| PathBuf::from(&mp));

^ The loop below only ever returns true if this is Some, so we can leave
early here if it is not.

> +
> +            MountInfo::read().map_or(false, |mount_info| {
> +                mount_info
> +                    .iter()
> +                    .filter_map(|(_, entry)| {
> +                        entry
> +                            .mount_source
> +                            .as_ref()
> +                            .map(|source| (&entry.mount_point, source))
> +                    })
> +                    .any(|(mount_point, mount_source)| {
> +                        Some(PathBuf::from(&mount_point)) == store_mount_point
> +                            && PathBuf::from(&mount_source) == store_dev_path

^Note that you can always use `Path` instead of allocating PathBufs if
all you want to do is comapre stuff.

> +                    })
> +            })
> +        } else {
> +            false
> +        }
> +    })
> +}




More information about the pbs-devel mailing list