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 BF82D1FF13B for ; Wed, 22 Apr 2026 15:40:06 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 935CB2048D; Wed, 22 Apr 2026 15:40:06 +0200 (CEST) From: Hannes Laimer To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v8 03/13] datastore: have BackupGroup::destroy consume the group lock Date: Wed, 22 Apr 2026 15:39:41 +0200 Message-ID: <20260422133951.192862-4-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260422133951.192862-1-h.laimer@proxmox.com> References: <20260422133951.192862-1-h.laimer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1776865112890 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.081 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: 3WMMP6HM4CZQPBGHKDCTXMQU2W4NEMGJ X-Message-ID-Hash: 3WMMP6HM4CZQPBGHKDCTXMQU2W4NEMGJ X-MailFrom: h.laimer@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: Take ownership of the group lock guard instead of acquiring it internally, so callers that already hold the lock (e.g. the upcoming move-group) can delegate final cleanup without a second lock attempt and without duplicating the steps. Signed-off-by: Hannes Laimer --- pbs-datastore/src/backup_info.rs | 9 +++++---- pbs-datastore/src/datastore.rs | 10 ++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pbs-datastore/src/backup_info.rs b/pbs-datastore/src/backup_info.rs index c33eb307..3f7f7c90 100644 --- a/pbs-datastore/src/backup_info.rs +++ b/pbs-datastore/src/backup_info.rs @@ -217,17 +217,18 @@ impl BackupGroup { crate::ListSnapshots::new(self.clone()) } - /// Destroy the group inclusive all its backup snapshots (BackupDir's) + /// Destroy the group inclusive all its backup snapshots (BackupDir's). + /// + /// Consumes the group lock. The caller is responsible for acquiring it via + /// [`Self::lock`] beforehand. /// /// Returns `BackupGroupDeleteStats`, containing the number of deleted snapshots /// and number of protected snaphsots, which therefore were not removed. pub(crate) fn destroy( &self, + _lock_guard: BackupLockGuard, backend: &DatastoreBackend, ) -> Result { - let _guard = self - .lock() - .with_context(|| format!("while destroying group '{self:?}'"))?; let path = self.full_group_path(); log::info!("removing backup group {:?}", path); diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs index 5cdf6a4a..c1f2f8eb 100644 --- a/pbs-datastore/src/datastore.rs +++ b/pbs-datastore/src/datastore.rs @@ -1027,7 +1027,10 @@ impl DataStore { for group in self.iter_backup_groups(ns.to_owned())? { let group = group?; let backend = self.backend()?; - let delete_stats = group.destroy(&backend)?; + let guard = group + .lock() + .with_context(|| format!("while destroying group '{group:?}'"))?; + let delete_stats = group.destroy(guard, &backend)?; stats.add(&delete_stats); removed_all_groups = removed_all_groups && delete_stats.all_removed(); } @@ -1148,8 +1151,11 @@ impl DataStore { backup_group: &pbs_api_types::BackupGroup, ) -> Result { let backup_group = self.backup_group(ns.clone(), backup_group.clone()); + let guard = backup_group + .lock() + .with_context(|| format!("while destroying group '{backup_group:?}'"))?; - backup_group.destroy(&self.backend()?) + backup_group.destroy(guard, &self.backend()?) } /// Remove a backup directory including all content -- 2.47.3