From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id D73D41FF141 for ; Fri, 30 Jan 2026 17:46:59 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 0A8BE2F69; Fri, 30 Jan 2026 17:47:27 +0100 (CET) From: Robert Obkircher To: pbs-devel@lists.proxmox.com Subject: [PATCH v5 proxmox-backup 11/16] datastore: combine public FixedIndexWriter methods into add_chunk. Date: Fri, 30 Jan 2026 17:45:35 +0100 Message-ID: <20260130164552.281581-12-r.obkircher@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260130164552.281581-1-r.obkircher@proxmox.com> References: <20260130164552.281581-1-r.obkircher@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1769791544090 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.059 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy 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 Message-ID-Hash: L3RPASQISTHMGLUTNPKMUWVWQL42OCVJ X-Message-ID-Hash: L3RPASQISTHMGLUTNPKMUWVWQL42OCVJ X-MailFrom: r.obkircher@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: These operations were always performed together anyway, so it makes sense to simplify the public api. Signed-off-by: Robert Obkircher --- pbs-datastore/src/fixed_index.rs | 24 +++++++++++++++++++++--- src/api2/backup/environment.rs | 6 +----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pbs-datastore/src/fixed_index.rs b/pbs-datastore/src/fixed_index.rs index c4fe899d..f50f4517 100644 --- a/pbs-datastore/src/fixed_index.rs +++ b/pbs-datastore/src/fixed_index.rs @@ -380,7 +380,7 @@ impl FixedIndexWriter { /// The size also becomes fixed as soon as it is no longer divisible /// by the block size, to ensure that only the last block can be /// smaller. - pub fn grow_to_size(&mut self, requested_size: usize) -> Result<(), Error> { + fn grow_to_size(&mut self, requested_size: usize) -> Result<(), Error> { if self.size < requested_size { if !self.growable_size { bail!("refusing to resize from {} to {requested_size}", self.size); @@ -467,7 +467,7 @@ impl FixedIndexWriter { Ok(index_csum) } - pub fn check_chunk_alignment(&self, offset: usize, chunk_len: usize) -> Result { + fn check_chunk_alignment(&self, offset: usize, chunk_len: usize) -> Result { if offset < chunk_len { bail!("got chunk with small offset ({} < {}", offset, chunk_len); } @@ -497,7 +497,7 @@ impl FixedIndexWriter { Ok(pos / self.chunk_size) } - pub fn add_digest(&mut self, index: usize, digest: &[u8; 32]) -> Result<(), Error> { + fn add_digest(&mut self, index: usize, digest: &[u8; 32]) -> Result<(), Error> { if index >= self.index_length { bail!( "add digest failed - index out of range ({} >= {})", @@ -519,6 +519,24 @@ impl FixedIndexWriter { Ok(()) } + /// Write the digest of a chunk into this index file. + /// + /// The `start` and `size` parameters encode the range of + /// content that is backed up. It is verified that `start` is + /// aligned and that only the last chunk may be smaller. + /// + /// If this writer has been created without a fixed size, the + /// index capacity and content size are increased automatically + /// until an incomplete chunk is encountered. + pub fn add_chunk(&mut self, start: u64, size: u32, digest: &[u8; 32]) -> Result<(), Error> { + let Some(end) = start.checked_add(size.into()) else { + bail!("add_chunk: start and size are too large: {start}+{size}"); + }; + self.grow_to_size(end as usize)?; + let idx = self.check_chunk_alignment(end as usize, size as usize)?; + self.add_digest(idx, digest) + } + pub fn clone_data_from(&mut self, reader: &FixedIndexReader) -> Result<(), Error> { if self.growable_size { bail!("reusing the index is only supported with known input size"); diff --git a/src/api2/backup/environment.rs b/src/api2/backup/environment.rs index dc4f9bf5..04c5bf84 100644 --- a/src/api2/backup/environment.rs +++ b/src/api2/backup/environment.rs @@ -442,14 +442,10 @@ impl BackupEnvironment { ); } - let end = (offset as usize) + (size as usize); - data.index.grow_to_size(end)?; - let idx = data.index.check_chunk_alignment(end, size as usize)?; + data.index.add_chunk(offset, size, digest)?; data.chunk_count += 1; - data.index.add_digest(idx, digest)?; - Ok(()) } -- 2.47.3