From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 03A1C72AB1 for ; Wed, 16 Jun 2021 12:56:45 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 0016810B0E for ; Wed, 16 Jun 2021 12:56:44 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 892C710ADA for ; Wed, 16 Jun 2021 12:56:43 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5A23E42A54 for ; Wed, 16 Jun 2021 12:56:43 +0200 (CEST) From: Stefan Reiter To: pbs-devel@lists.proxmox.com Date: Wed, 16 Jun 2021 12:55:52 +0200 Message-Id: <20210616105552.2594536-6-s.reiter@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210616105552.2594536-1-s.reiter@proxmox.com> References: <20210616105552.2594536-1-s.reiter@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.796 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [busybox.net, data.name, disk.rs] Subject: [pbs-devel] [PATCH proxmox-backup 5/5] file-restore/disk: support ZFS subvols with mountpoint=legacy X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Jun 2021 10:56:45 -0000 These require mounting using the regular 'mount' syscall. Auto-generates an appropriate mount path. Note that subvols with mountpoint=none cannot be mounted this way, and would require setting the mountpoint property, which is not possible as the zpools have to be imported with readonly=on. Signed-off-by: Stefan Reiter --- src/bin/proxmox_restore_daemon/disk.rs | 43 ++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/bin/proxmox_restore_daemon/disk.rs b/src/bin/proxmox_restore_daemon/disk.rs index 5b66dd2f..9d0cbe32 100644 --- a/src/bin/proxmox_restore_daemon/disk.rs +++ b/src/bin/proxmox_restore_daemon/disk.rs @@ -228,6 +228,34 @@ impl Filesystems { cmd.args(["mount", "-a"].iter()); run_command(cmd, None)?; + // detect any datasets with 'legacy' mountpoints + let mut cmd = Command::new("/sbin/zfs"); + cmd.args(["list", "-Hpro", "name,mountpoint", &data.name].iter()); + let mps = run_command(cmd, None)?; + for subvol in mps.lines() { + let subvol = subvol.splitn(2, '\t').collect::>(); + if subvol.len() != 2 { + continue; + } + let name = subvol[0]; + let mp = subvol[1]; + + if mp == "legacy" { + let mut newmp = PathBuf::from(format!( + "{}/legacy-{}", + &mntpath, + name.replace('/', "_") + )); + let mut i = 1; + while newmp.exists() { + newmp.set_extension(i.to_string()); + i += 1; + } + create_dir_all(&newmp)?; + self.do_mount(Some(name), newmp.to_string_lossy().as_ref(), "zfs")?; + } + } + // Now that we have imported the pool, we can also query the size let mut cmd = Command::new("/sbin/zpool"); cmd.args(["list", "-o", "size", "-Hp", &data.name].iter()); @@ -244,19 +272,14 @@ impl Filesystems { } fn try_mount(&self, source: &str, target: &str) -> Result<(), Error> { - use nix::mount::*; - create_dir_all(target)?; // try all supported fs until one works - this is the way Busybox's 'mount' does it too: // https://git.busybox.net/busybox/tree/util-linux/mount.c?id=808d93c0eca49e0b22056e23d965f0d967433fbb#n2152 // note that ZFS is intentionally left out (see scan()) - let flags = - MsFlags::MS_RDONLY | MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID | MsFlags::MS_NODEV; for fs in &self.supported_fs { let fs: &str = fs.as_ref(); - let opts = FS_OPT_MAP.get(fs).copied(); - match mount(Some(source), target, Some(fs), flags, opts) { + match self.do_mount(Some(source), target, fs) { Ok(()) => { info!("mounting '{}' succeeded, fstype: '{}'", source, fs); return Ok(()); @@ -270,6 +293,14 @@ impl Filesystems { bail!("all mounts failed or no supported file system") } + + fn do_mount(&self, source: Option<&str>, target: &str, fs: &str) -> Result<(), nix::Error> { + use nix::mount::*; + let flags = + MsFlags::MS_RDONLY | MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID | MsFlags::MS_NODEV; + let opts = FS_OPT_MAP.get(fs).copied(); + mount(source, target, Some(fs), flags, opts) + } } pub struct DiskState { -- 2.30.2