all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Reiter <s.reiter@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 3/3] file-restore-daemon: disk: add RawFs bucket type
Date: Mon, 17 May 2021 14:31:37 +0200	[thread overview]
Message-ID: <20210517123137.25547-3-s.reiter@proxmox.com> (raw)
In-Reply-To: <20210517123137.25547-1-s.reiter@proxmox.com>

Used to specify a filesystem placed directly on a disk, without a
partition table inbetween. Detected by simply attempting to mount the
disk itself.

A helper "make_dev_node" is extracted to avoid code duplication.

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
 src/bin/proxmox_restore_daemon/disk.rs | 68 +++++++++++++++++++-------
 1 file changed, 50 insertions(+), 18 deletions(-)

diff --git a/src/bin/proxmox_restore_daemon/disk.rs b/src/bin/proxmox_restore_daemon/disk.rs
index 8ad270fa..1ff5468f 100644
--- a/src/bin/proxmox_restore_daemon/disk.rs
+++ b/src/bin/proxmox_restore_daemon/disk.rs
@@ -62,6 +62,7 @@ struct PartitionBucketData {
 /// e.g.: "/drive-scsi0/part/0/etc/passwd"
 enum Bucket {
     Partition(PartitionBucketData),
+    RawFs(PartitionBucketData),
 }
 
 impl Bucket {
@@ -79,12 +80,14 @@ impl Bucket {
                     false
                 }
             }
+            Bucket::RawFs(_) => ty == "raw",
         })
     }
 
     fn type_string(&self) -> &'static str {
         match self {
             Bucket::Partition(_) => "part",
+            Bucket::RawFs(_) => "raw",
         }
     }
 
@@ -100,19 +103,21 @@ impl Bucket {
         }
         Ok(match self {
             Bucket::Partition(data) => data.number.to_string(),
+            Bucket::RawFs(_) => "raw".to_owned(),
         })
     }
 
     fn component_depth(type_string: &str) -> Result<usize, Error> {
         Ok(match type_string {
             "part" => 1,
+            "raw" => 0,
             _ => bail!("invalid bucket type for component depth: {}", type_string),
         })
     }
 
     fn size(&self) -> u64 {
         match self {
-            Bucket::Partition(data) => data.size,
+            Bucket::Partition(data) | Bucket::RawFs(data) => data.size,
         }
     }
 }
@@ -145,8 +150,8 @@ impl Filesystems {
 
     fn ensure_mounted(&self, bucket: &mut Bucket) -> Result<PathBuf, Error> {
         match bucket {
-            Bucket::Partition(data) => {
-                // regular data partition à la "/dev/vdxN"
+            Bucket::Partition(data) | Bucket::RawFs(data) => {
+                // regular data partition à la "/dev/vdxN" or FS directly on a disk
                 if let Some(mp) = &data.mountpoint {
                     return Ok(mp.clone());
                 }
@@ -197,6 +202,8 @@ pub struct DiskState {
 impl DiskState {
     /// Scan all disks for supported buckets.
     pub fn scan() -> Result<Self, Error> {
+        let filesystems = Filesystems::scan()?;
+
         // create mapping for virtio drives and .fidx files (via serial description)
         // note: disks::DiskManager relies on udev, which we don't have
         let mut disk_map = HashMap::new();
@@ -223,6 +230,25 @@ impl DiskState {
                 }
             };
 
+            // attempt to mount device directly
+            let dev_node = format!("/dev/{}", name);
+            let size = Self::make_dev_node(&dev_node, &sys_path)?;
+            let mut dfs_bucket = Bucket::RawFs(PartitionBucketData {
+                dev_node: dev_node.clone(),
+                number: 0,
+                mountpoint: None,
+                size,
+            });
+            if let Ok(_) = filesystems.ensure_mounted(&mut dfs_bucket) {
+                // mount succeeded, add bucket and skip any other checks for the disk
+                info!(
+                    "drive '{}' ('{}', '{}') contains fs directly ({}B)",
+                    name, fidx, dev_node, size
+                );
+                disk_map.insert(fidx, vec![dfs_bucket]);
+                continue;
+            }
+
             let mut parts = Vec::new();
             for entry in proxmox_backup::tools::fs::scan_subdir(
                 libc::AT_FDCWD,
@@ -232,32 +258,23 @@ impl DiskState {
             .filter_map(Result::ok)
             {
                 let part_name = unsafe { entry.file_name_utf8_unchecked() };
-                let devnode = format!("/dev/{}", part_name);
+                let dev_node = format!("/dev/{}", part_name);
                 let part_path = format!("/sys/block/{}/{}", name, part_name);
 
                 // create partition device node for further use
-                let dev_num_str = fs::file_read_firstline(&format!("{}/dev", part_path))?;
-                let (major, minor) = dev_num_str.split_at(dev_num_str.find(':').unwrap());
-                Self::mknod_blk(&devnode, major.parse()?, minor[1..].trim_end().parse()?)?;
+                let size = Self::make_dev_node(&dev_node, &part_path)?;
 
                 let number = fs::file_read_firstline(&format!("{}/partition", part_path))?
                     .trim()
                     .parse::<i32>()?;
 
-                // this *always* contains the number of 512-byte sectors, regardless of the true
-                // blocksize of this disk - which should always be 512 here anyway
-                let size = fs::file_read_firstline(&format!("{}/size", part_path))?
-                    .trim()
-                    .parse::<u64>()?
-                    * 512;
-
                 info!(
                     "drive '{}' ('{}'): found partition '{}' ({}, {}B)",
-                    name, fidx, devnode, number, size
+                    name, fidx, dev_node, number, size
                 );
 
                 let bucket = Bucket::Partition(PartitionBucketData {
-                    dev_node: devnode,
+                    dev_node,
                     mountpoint: None,
                     number,
                     size,
@@ -266,11 +283,11 @@ impl DiskState {
                 parts.push(bucket);
             }
 
-            disk_map.insert(fidx.to_owned(), parts);
+            disk_map.insert(fidx, parts);
         }
 
         Ok(Self {
-            filesystems: Filesystems::scan()?,
+            filesystems,
             disk_map,
         })
     }
@@ -381,6 +398,21 @@ impl DiskState {
         Ok(ResolveResult::Path(local_path))
     }
 
+    fn make_dev_node(devnode: &str, sys_path: &str) -> Result<u64, Error> {
+        let dev_num_str = fs::file_read_firstline(&format!("{}/dev", sys_path))?;
+        let (major, minor) = dev_num_str.split_at(dev_num_str.find(':').unwrap());
+        Self::mknod_blk(&devnode, major.parse()?, minor[1..].trim_end().parse()?)?;
+
+        // this *always* contains the number of 512-byte sectors, regardless of the true
+        // blocksize of this disk - which should always be 512 here anyway
+        let size = fs::file_read_firstline(&format!("{}/size", sys_path))?
+            .trim()
+            .parse::<u64>()?
+            * 512;
+
+        Ok(size)
+    }
+
     fn mknod_blk(path: &str, maj: u64, min: u64) -> Result<(), Error> {
         use nix::sys::stat;
         let dev = stat::makedev(maj, min);
-- 
2.20.1





  parent reply	other threads:[~2021-05-17 12:31 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-17 12:31 [pbs-devel] [PATCH proxmox-backup 1/3] file-restore-daemon: disk: ignore "invalid fs" error Stefan Reiter
2021-05-17 12:31 ` [pbs-devel] [PATCH proxmox-backup 2/3] file-restore-daemon: disk: allow arbitrary component count per bucket Stefan Reiter
2021-05-17 12:31 ` Stefan Reiter [this message]
2021-05-25  5:55 ` [pbs-devel] applied-series: [PATCH proxmox-backup 1/3] file-restore-daemon: disk: ignore "invalid fs" error Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210517123137.25547-3-s.reiter@proxmox.com \
    --to=s.reiter@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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