[pbs-devel] [RFC v2 proxmox-backup 02/21] datastore: mark groups as trash on destroy
Christian Ebner
c.ebner at proxmox.com
Thu May 8 15:05:36 CEST 2025
In order to implement the trash can functionality, mark all the
snapshots of the group and the group itself as trash instead of
deleting them right away. Cleanup of the group is deferred to the
garbage collection.
Groups and snapshots are marked by the trash marker file. New backups
to this group will check for the marker file (see subsequent
commits), clearing the whole group and all of the snapshots to
create a new snapshot within that group. Otherwise ownership
conflicts could arise. This implies that a new backup clears the
whole trashed group.
Snapshots already marked as trash within the same backup group will
be cleared as well when the group is requested to be destroyed with
skip trash.
Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
pbs-datastore/src/backup_info.rs | 19 ++++++++++++++++---
pbs-datastore/src/datastore.rs | 4 ++--
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/pbs-datastore/src/backup_info.rs b/pbs-datastore/src/backup_info.rs
index 76bcd15f5..9ce4cb0f8 100644
--- a/pbs-datastore/src/backup_info.rs
+++ b/pbs-datastore/src/backup_info.rs
@@ -215,7 +215,7 @@ impl BackupGroup {
///
/// Returns `BackupGroupDeleteStats`, containing the number of deleted snapshots
/// and number of protected snaphsots, which therefore were not removed.
- pub fn destroy(&self) -> Result<BackupGroupDeleteStats, Error> {
+ pub fn destroy(&self, skip_trash: bool) -> Result<BackupGroupDeleteStats, Error> {
let _guard = self
.lock()
.with_context(|| format!("while destroying group '{self:?}'"))?;
@@ -229,14 +229,20 @@ impl BackupGroup {
delete_stats.increment_protected_snapshots();
continue;
}
- snap.destroy(false, false)?;
+ snap.destroy(false, skip_trash)?;
delete_stats.increment_removed_snapshots();
}
// Note: make sure the old locking mechanism isn't used as `remove_dir_all` is not safe in
// that case
if delete_stats.all_removed() && !*OLD_LOCKING {
- self.remove_group_dir()?;
+ if skip_trash {
+ self.remove_group_dir()?;
+ } else {
+ let path = self.full_group_path().join(TRASH_MARKER_FILENAME);
+ let _trash_file =
+ std::fs::File::create(path).context("failed to set trash file")?;
+ }
delete_stats.increment_removed_groups();
}
@@ -245,6 +251,13 @@ impl BackupGroup {
/// Helper function, assumes that no more snapshots are present in the group.
fn remove_group_dir(&self) -> Result<(), Error> {
+ let trash_path = self.full_group_path().join(TRASH_MARKER_FILENAME);
+ if let Err(err) = std::fs::remove_file(&trash_path) {
+ if err.kind() != std::io::ErrorKind::NotFound {
+ bail!("removing the trash file '{trash_path:?}' failed - {err}")
+ }
+ }
+
let owner_path = self.store.owner_path(&self.ns, &self.group);
std::fs::remove_file(&owner_path).map_err(|err| {
diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs
index 6df26e825..e546bc532 100644
--- a/pbs-datastore/src/datastore.rs
+++ b/pbs-datastore/src/datastore.rs
@@ -581,7 +581,7 @@ impl DataStore {
let mut stats = BackupGroupDeleteStats::default();
for group in self.iter_backup_groups(ns.to_owned())? {
- let delete_stats = group?.destroy()?;
+ let delete_stats = group?.destroy(true)?;
stats.add(&delete_stats);
removed_all_groups = removed_all_groups && delete_stats.all_removed();
}
@@ -674,7 +674,7 @@ impl DataStore {
) -> Result<BackupGroupDeleteStats, Error> {
let backup_group = self.backup_group(ns.clone(), backup_group.clone());
- backup_group.destroy()
+ backup_group.destroy(true)
}
/// Remove a backup directory including all content
--
2.39.5
More information about the pbs-devel
mailing list