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) server-digest SHA256) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 11B687101B for ; Mon, 17 May 2021 14:31:58 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 04F592BB47 for ; Mon, 17 May 2021 14:31:58 +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 515B82BB31 for ; Mon, 17 May 2021 14:31:53 +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 270D043681 for ; Mon, 17 May 2021 14:31:53 +0200 (CEST) From: Stefan Reiter To: pbs-devel@lists.proxmox.com Date: Mon, 17 May 2021 14:31:36 +0200 Message-Id: <20210517123137.25547-2-s.reiter@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210517123137.25547-1-s.reiter@proxmox.com> References: <20210517123137.25547-1-s.reiter@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.015 Adjusted score from AWL reputation of From: address 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 Subject: [pbs-devel] [PATCH proxmox-backup 2/3] file-restore-daemon: disk: allow arbitrary component count per bucket 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: Mon, 17 May 2021 12:31:58 -0000 A bucket might contain multiple (or 0) layers of components in its path specification, so allow a mapping between bucket type strings and expected component depth. For partitions, this is 1, as there is only the partition number layer below the "part" node. Signed-off-by: Stefan Reiter --- src/bin/proxmox_restore_daemon/disk.rs | 83 ++++++++++++++++++-------- 1 file changed, 59 insertions(+), 24 deletions(-) diff --git a/src/bin/proxmox_restore_daemon/disk.rs b/src/bin/proxmox_restore_daemon/disk.rs index a59d6360..8ad270fa 100644 --- a/src/bin/proxmox_restore_daemon/disk.rs +++ b/src/bin/proxmox_restore_daemon/disk.rs @@ -68,12 +68,17 @@ impl Bucket { fn filter_mut<'a, A: AsRef, B: AsRef>( haystack: &'a mut Vec, ty: A, - comp: B, + comp: &[B], ) -> Option<&'a mut Bucket> { let ty = ty.as_ref(); - let comp = comp.as_ref(); haystack.iter_mut().find(|b| match b { - Bucket::Partition(data) => ty == "part" && comp.parse::().unwrap() == data.number, + Bucket::Partition(data) => { + if let Some(comp) = comp.get(0) { + ty == "part" && comp.as_ref().parse::().unwrap() == data.number + } else { + false + } + } }) } @@ -83,10 +88,26 @@ impl Bucket { } } - fn component_string(&self) -> String { - match self { - Bucket::Partition(data) => data.number.to_string(), + fn component_string(&self, idx: usize) -> Result { + let max_depth = Self::component_depth(self.type_string())?; + if idx >= max_depth { + bail!( + "internal error: component index out of range {}/{} ({})", + idx, + max_depth, + self.type_string() + ); } + Ok(match self { + Bucket::Partition(data) => data.number.to_string(), + }) + } + + fn component_depth(type_string: &str) -> Result { + Ok(match type_string { + "part" => 1, + _ => bail!("invalid bucket type for component depth: {}", type_string), + }) } fn size(&self) -> u64 { @@ -299,27 +320,41 @@ impl DiskState { } }; - let component = match cmp.next() { - Some(Component::Normal(x)) => x.to_string_lossy(), - Some(c) => bail!("invalid bucket component in path: {:?}", c), - None => { - // list bucket components available - let comps = buckets - .iter() - .filter(|b| b.type_string() == bucket_type) - .map(|b| (b.component_string(), b.size())) - .collect(); - return Ok(ResolveResult::BucketComponents(comps)); - } - }; + let mut components = Vec::new(); + let component_count = Bucket::component_depth(&bucket_type)?; - let mut bucket = match Bucket::filter_mut(buckets, &bucket_type, &component) { + while components.len() < component_count { + let component = match cmp.next() { + Some(Component::Normal(x)) => x.to_string_lossy(), + Some(c) => bail!("invalid bucket component in path: {:?}", c), + None => { + // list bucket components available at this level + let comps = buckets + .iter() + .filter_map(|b| { + if b.type_string() != bucket_type { + return None; + } + match b.component_string(components.len()) { + Ok(cs) => Some((cs.to_owned(), b.size())), + Err(_) => None, + } + }) + .collect(); + return Ok(ResolveResult::BucketComponents(comps)); + } + }; + + components.push(component); + } + + let mut bucket = match Bucket::filter_mut(buckets, &bucket_type, &components) { Some(bucket) => bucket, None => bail!( - "bucket/component path not found: {}/{}/{}", + "bucket/component path not found: {}/{}/{:?}", req_fidx, bucket_type, - component + components ), }; @@ -329,10 +364,10 @@ impl DiskState { .ensure_mounted(&mut bucket) .map_err(|err| { format_err!( - "mounting '{}/{}/{}' failed: {}", + "mounting '{}/{}/{:?}' failed: {}", req_fidx, bucket_type, - component, + components, err ) })?; -- 2.20.1