From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pbs-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id B45761FF165 for <inbox@lore.proxmox.com>; Thu, 8 May 2025 15:06:07 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6C15EFB4F; Thu, 8 May 2025 15:06:16 +0200 (CEST) From: Christian Ebner <c.ebner@proxmox.com> To: pbs-devel@lists.proxmox.com Date: Thu, 8 May 2025 15:05:37 +0200 Message-Id: <20250508130555.494782-4-c.ebner@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250508130555.494782-1-c.ebner@proxmox.com> References: <20250508130555.494782-1-c.ebner@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.029 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 Subject: [pbs-devel] [RFC v2 proxmox-backup 03/21] datastore: allow filtering of backups by their trash status X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion <pbs-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/> List-Post: <mailto:pbs-devel@lists.proxmox.com> List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox Backup Server development discussion <pbs-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" <pbs-devel-bounces@lists.proxmox.com> Extends the BackupGroup::list_backups method by an enum parameter to filter backup snapshots based on their trash status. This allows to reuse the same logic for listing active, trashed or all snapshots. Signed-off-by: Christian Ebner <c.ebner@proxmox.com> --- pbs-datastore/src/backup_info.rs | 33 +++++++++++++++++++++++++++++--- pbs-datastore/src/datastore.rs | 4 ++-- src/api2/admin/datastore.rs | 10 +++++----- src/api2/tape/backup.rs | 4 ++-- src/backup/verify.rs | 4 ++-- src/server/prune_job.rs | 3 ++- src/server/pull.rs | 3 ++- 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/pbs-datastore/src/backup_info.rs b/pbs-datastore/src/backup_info.rs index 9ce4cb0f8..a8c864ac8 100644 --- a/pbs-datastore/src/backup_info.rs +++ b/pbs-datastore/src/backup_info.rs @@ -52,6 +52,12 @@ impl fmt::Debug for BackupGroup { } } +pub enum ListBackupFilter { + Active, + All, + Trashed, +} + impl BackupGroup { pub(crate) fn new( store: Arc<DataStore>, @@ -99,7 +105,7 @@ impl BackupGroup { self.full_group_path().exists() } - pub fn list_backups(&self) -> Result<Vec<BackupInfo>, Error> { + pub fn list_backups(&self, filter: ListBackupFilter) -> Result<Vec<BackupInfo>, Error> { let mut list = vec![]; let path = self.full_group_path(); @@ -117,6 +123,19 @@ impl BackupGroup { let files = list_backup_files(l2_fd, backup_time)?; let protected = backup_dir.is_protected(); + match filter { + ListBackupFilter::All => (), + ListBackupFilter::Trashed => { + if !backup_dir.is_trashed() { + return Ok(()); + } + } + ListBackupFilter::Active => { + if backup_dir.is_trashed() { + return Ok(()); + } + } + } list.push(BackupInfo { backup_dir, @@ -132,7 +151,7 @@ impl BackupGroup { /// Finds the latest backup inside a backup group pub fn last_backup(&self, only_finished: bool) -> Result<Option<BackupInfo>, Error> { - let backups = self.list_backups()?; + let backups = self.list_backups(ListBackupFilter::Active)?; Ok(backups .into_iter() .filter(|item| !only_finished || item.is_finished()) @@ -480,6 +499,11 @@ impl BackupDir { path.exists() } + pub fn is_trashed(&self) -> bool { + let path = self.full_path().join(TRASH_MARKER_FILENAME); + path.exists() + } + pub fn backup_time_to_string(backup_time: i64) -> Result<String, Error> { // fixme: can this fail? (avoid unwrap) proxmox_time::epoch_to_rfc3339_utc(backup_time) @@ -637,7 +661,10 @@ impl BackupDir { // // Do not error out, as we have already removed the snapshot, there is nothing a user could // do to rectify the situation. - if guard.is_ok() && group.list_backups()?.is_empty() && !*OLD_LOCKING { + if guard.is_ok() + && group.list_backups(ListBackupFilter::All)?.is_empty() + && !*OLD_LOCKING + { group.remove_group_dir()?; } else if let Err(err) = guard { log::debug!("{err:#}"); diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs index e546bc532..867324380 100644 --- a/pbs-datastore/src/datastore.rs +++ b/pbs-datastore/src/datastore.rs @@ -28,7 +28,7 @@ use pbs_api_types::{ }; use pbs_config::BackupLockGuard; -use crate::backup_info::{BackupDir, BackupGroup, BackupInfo, OLD_LOCKING}; +use crate::backup_info::{BackupDir, BackupGroup, BackupInfo, ListBackupFilter, OLD_LOCKING}; use crate::chunk_store::ChunkStore; use crate::dynamic_index::{DynamicIndexReader, DynamicIndexWriter}; use crate::fixed_index::{FixedIndexReader, FixedIndexWriter}; @@ -1158,7 +1158,7 @@ impl DataStore { _ => bail!("exhausted retries and unexpected counter overrun"), }; - let mut snapshots = match group.list_backups() { + let mut snapshots = match group.list_backups(ListBackupFilter::All) { Ok(snapshots) => snapshots, Err(err) => { if group.exists() { diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index aafd1bbd7..133a6d658 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -51,7 +51,7 @@ use pbs_api_types::{ }; use pbs_client::pxar::{create_tar, create_zip}; use pbs_config::CachedUserInfo; -use pbs_datastore::backup_info::BackupInfo; +use pbs_datastore::backup_info::{BackupInfo, ListBackupFilter}; use pbs_datastore::cached_chunk_reader::CachedChunkReader; use pbs_datastore::catalog::{ArchiveEntry, CatalogReader}; use pbs_datastore::data_blob::DataBlob; @@ -223,7 +223,7 @@ pub fn list_groups( return Ok(group_info); } - let snapshots = match group.list_backups() { + let snapshots = match group.list_backups(ListBackupFilter::Active) { Ok(snapshots) => snapshots, Err(_) => return Ok(group_info), }; @@ -624,7 +624,7 @@ unsafe fn list_snapshots_blocking( return Ok(snapshots); } - let group_backups = group.list_backups()?; + let group_backups = group.list_backups(ListBackupFilter::Active)?; snapshots.extend( group_backups @@ -657,7 +657,7 @@ async fn get_snapshots_count( Ok(group) => group, Err(_) => return Ok(counts), // TODO: add this as error counts? }; - let snapshot_count = group.list_backups()?.len() as u64; + let snapshot_count = group.list_backups(ListBackupFilter::Active)?.len() as u64; // only include groups with snapshots, counting/displaying empty groups can confuse if snapshot_count > 0 { @@ -1042,7 +1042,7 @@ pub fn prune( } let mut prune_result: Vec<PruneResult> = Vec::new(); - let list = group.list_backups()?; + let list = group.list_backups(ListBackupFilter::Active)?; let mut prune_info = compute_prune_info(list, &keep_options)?; diff --git a/src/api2/tape/backup.rs b/src/api2/tape/backup.rs index 31293a9a9..923cb7834 100644 --- a/src/api2/tape/backup.rs +++ b/src/api2/tape/backup.rs @@ -17,7 +17,7 @@ use pbs_api_types::{ }; use pbs_config::CachedUserInfo; -use pbs_datastore::backup_info::{BackupDir, BackupInfo}; +use pbs_datastore::backup_info::{BackupDir, BackupInfo, ListBackupFilter}; use pbs_datastore::{DataStore, StoreProgress}; use crate::tape::TapeNotificationMode; @@ -433,7 +433,7 @@ fn backup_worker( progress.done_snapshots = 0; progress.group_snapshots = 0; - let snapshot_list = group.list_backups()?; + let snapshot_list = group.list_backups(ListBackupFilter::Active)?; // filter out unfinished backups let mut snapshot_list: Vec<_> = snapshot_list diff --git a/src/backup/verify.rs b/src/backup/verify.rs index 3d2cba8ac..1b5e8564b 100644 --- a/src/backup/verify.rs +++ b/src/backup/verify.rs @@ -14,7 +14,7 @@ use pbs_api_types::{ CryptMode, SnapshotVerifyState, VerifyState, PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_VERIFY, UPID, }; -use pbs_datastore::backup_info::{BackupDir, BackupGroup, BackupInfo}; +use pbs_datastore::backup_info::{BackupDir, BackupGroup, BackupInfo, ListBackupFilter}; use pbs_datastore::index::IndexFile; use pbs_datastore::manifest::{BackupManifest, FileInfo}; use pbs_datastore::{DataBlob, DataStore, StoreProgress}; @@ -411,7 +411,7 @@ pub fn verify_backup_group( filter: Option<&dyn Fn(&BackupManifest) -> bool>, ) -> Result<Vec<String>, Error> { let mut errors = Vec::new(); - let mut list = match group.list_backups() { + let mut list = match group.list_backups(ListBackupFilter::Active) { Ok(list) => list, Err(err) => { info!( diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs index 1c86647a0..596afe086 100644 --- a/src/server/prune_job.rs +++ b/src/server/prune_job.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use anyhow::Error; +use pbs_datastore::backup_info::ListBackupFilter; use tracing::{info, warn}; use pbs_api_types::{ @@ -54,7 +55,7 @@ pub fn prune_datastore( )? { let group = group?; let ns = group.backup_ns(); - let list = group.list_backups()?; + let list = group.list_backups(ListBackupFilter::Active)?; let mut prune_info = compute_prune_info(list, &prune_options.keep)?; prune_info.reverse(); // delete older snapshots first diff --git a/src/server/pull.rs b/src/server/pull.rs index b1724c142..50d7b0806 100644 --- a/src/server/pull.rs +++ b/src/server/pull.rs @@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use anyhow::{bail, format_err, Error}; +use pbs_datastore::backup_info::ListBackupFilter; use proxmox_human_byte::HumanByte; use tracing::info; @@ -660,7 +661,7 @@ async fn pull_group( .target .store .backup_group(target_ns.clone(), group.clone()); - let local_list = group.list_backups()?; + let local_list = group.list_backups(ListBackupFilter::Active)?; for info in local_list { let snapshot = info.backup_dir; if source_snapshots.contains(&snapshot.backup_time()) { -- 2.39.5 _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel