public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dietmar Maurer <dietmar@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH backup] src/api2/backup.rs: aquire backup lock earlier in create_locked_backup_group()
Date: Thu, 30 Jul 2020 10:50:31 +0200	[thread overview]
Message-ID: <20200730085031.30790-1-dietmar@proxmox.com> (raw)

---
 src/api2/backup.rs      |  8 ++++----
 src/backup/datastore.rs | 14 +++++++++-----
 src/client/pull.rs      |  2 +-
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/api2/backup.rs b/src/api2/backup.rs
index b9dff1f..ad13faa 100644
--- a/src/api2/backup.rs
+++ b/src/api2/backup.rs
@@ -88,7 +88,10 @@ async move {
     let env_type = rpcenv.env_type();
 
     let backup_group = BackupGroup::new(backup_type, backup_id);
-    let owner = datastore.create_backup_group(&backup_group, &username)?;
+
+    // lock backup group to only allow one backup per group at a time
+    let (owner, _group_guard) = datastore.create_locked_backup_group(&backup_group, &username)?;
+
     // permission check
     if owner != username { // only the owner is allowed to create additional snapshots
         bail!("backup owner check failed ({} != {})", username, owner);
@@ -103,9 +106,6 @@ async move {
         }
     }
 
-    // lock backup group to only allow one backup per group at a time
-    let _group_guard = backup_group.lock(&datastore.base_path())?;
-
     let (path, is_new) = datastore.create_backup_dir(&backup_dir)?;
     if !is_new { bail!("backup directory already exists."); }
 
diff --git a/src/backup/datastore.rs b/src/backup/datastore.rs
index 9c2f285..af964f6 100644
--- a/src/backup/datastore.rs
+++ b/src/backup/datastore.rs
@@ -8,7 +8,7 @@ use anyhow::{bail, format_err, Error};
 use lazy_static::lazy_static;
 use chrono::{DateTime, Utc};
 
-use super::backup_info::{BackupGroup, BackupDir, BackupInfo};
+use super::backup_info::{BackupGroup, BackupGroupGuard, BackupDir, BackupInfo};
 use super::chunk_store::ChunkStore;
 use super::dynamic_index::{DynamicIndexReader, DynamicIndexWriter};
 use super::fixed_index::{FixedIndexReader, FixedIndexWriter};
@@ -318,11 +318,13 @@ impl DataStore {
         Ok(())
     }
 
-    /// Create a backup group if it does not already exists.
+    /// Create (if it does not already exists) and lock a backup group
     ///
     /// And set the owner to 'userid'. If the group already exists, it returns the
     /// current owner (instead of setting the owner).
-    pub fn create_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<String, Error> {
+    ///
+    /// This also aquires an exclusive lock on the directory and returns the lock guard.
+    pub fn create_locked_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<(String, BackupGroupGuard), Error> {
 
         // create intermediate path first:
         let base_path = self.base_path();
@@ -336,13 +338,15 @@ impl DataStore {
         // create the last component now
         match std::fs::create_dir(&full_path) {
             Ok(_) => {
+                let guard = backup_group.lock(&base_path)?;
                 self.set_owner(backup_group, userid, false)?;
                 let owner = self.get_owner(backup_group)?; // just to be sure
-                Ok(owner)
+                Ok((owner, guard))
             }
             Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {
+                let guard = backup_group.lock(&base_path)?;
                 let owner = self.get_owner(backup_group)?; // just to be sure
-                Ok(owner)
+                Ok((owner, guard))
             }
             Err(err) => bail!("unable to create backup group {:?} - {}", full_path, err),
         }
diff --git a/src/client/pull.rs b/src/client/pull.rs
index c44cb9f..fc193a8 100644
--- a/src/client/pull.rs
+++ b/src/client/pull.rs
@@ -406,7 +406,7 @@ pub async fn pull_store(
     for item in list {
         let group = BackupGroup::new(&item.backup_type, &item.backup_id);
 
-        let owner = tgt_store.create_backup_group(&group, &username)?;
+        let (owner, _lock_guard) = tgt_store.create_locked_backup_group(&group, &username)?;
         // permission check
         if owner != username { // only the owner is allowed to create additional snapshots
             worker.log(format!("sync group {}/{} failed - owner check failed ({} != {})",
-- 
2.20.1




             reply	other threads:[~2020-07-30  8:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-30  8:50 Dietmar Maurer [this message]
2020-07-30  9:31 ` Stefan Reiter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200730085031.30790-1-dietmar@proxmox.com \
    --to=dietmar@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal