[pbs-devel] [PATCH proxmox-backup 5/7] backup: flock snapshot on backup start

Stefan Reiter s.reiter at proxmox.com
Tue Aug 4 12:42:03 CEST 2020


An flock on the snapshot dir itself is used in addition to the group dir
lock. The lock is used to avoid races with forget and prune, while
having more granularity than the group lock (i.e. the group lock is
necessary to prevent more than one backup per group, but the snapshot
lock still allows backup unrelated to the currently running to be
forgotten/pruned).

Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
 src/api2/backup.rs      |  3 ++-
 src/backup/datastore.rs | 14 ++++++++++----
 src/client/pull.rs      |  2 +-
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/api2/backup.rs b/src/api2/backup.rs
index aafea8fa..29b1a606 100644
--- a/src/api2/backup.rs
+++ b/src/api2/backup.rs
@@ -106,7 +106,7 @@ async move {
         }
     }
 
-    let (path, is_new) = datastore.create_backup_dir(&backup_dir)?;
+    let (path, is_new, _snap_guard) = datastore.create_locked_backup_dir(&backup_dir)?;
     if !is_new { bail!("backup directory already exists."); }
 
     WorkerTask::spawn("backup", Some(worker_id), &username.clone(), true, move |worker| {
@@ -146,6 +146,7 @@ async move {
         async move {
             // keep flock until task ends
             let _group_guard = _group_guard;
+            let _snap_guard = _snap_guard;
 
             let res = select!{
                 req = req_fut => req,
diff --git a/src/backup/datastore.rs b/src/backup/datastore.rs
index 3c374302..19fad4e1 100644
--- a/src/backup/datastore.rs
+++ b/src/backup/datastore.rs
@@ -331,15 +331,21 @@ impl DataStore {
     /// Creates a new backup snapshot inside a BackupGroup
     ///
     /// The BackupGroup directory needs to exist.
-    pub fn create_backup_dir(&self, backup_dir: &BackupDir) ->  Result<(PathBuf, bool), io::Error> {
+    pub fn create_locked_backup_dir(&self, backup_dir: &BackupDir)
+        -> Result<(PathBuf, bool, BackupLockGuard), Error>
+    {
         let relative_path = backup_dir.relative_path();
         let mut full_path = self.base_path();
         full_path.push(&relative_path);
 
+        let lock = || {
+            BackupInfo::new(&self.base_path(), backup_dir.clone())?.lock()
+        };
+
         match std::fs::create_dir(&full_path) {
-            Ok(_) => Ok((relative_path, true)),
-            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok((relative_path, false)),
-            Err(e) => Err(e)
+            Ok(_) => Ok((relative_path, true, lock()?)),
+            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok((relative_path, false, lock()?)),
+            Err(e) => Err(e.into())
         }
     }
 
diff --git a/src/client/pull.rs b/src/client/pull.rs
index 429ab458..2363dbfa 100644
--- a/src/client/pull.rs
+++ b/src/client/pull.rs
@@ -297,7 +297,7 @@ pub async fn pull_snapshot_from(
     snapshot: &BackupDir,
 ) -> Result<(), Error> {
 
-    let (_path, is_new) = tgt_store.create_backup_dir(&snapshot)?;
+    let (_path, is_new, _snap_lock) = tgt_store.create_locked_backup_dir(&snapshot)?;
 
     if is_new {
         worker.log(format!("sync snapshot {:?}", snapshot.relative_path()));
-- 
2.20.1






More information about the pbs-devel mailing list