From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 7A13A6918C for ; Tue, 4 Aug 2020 12:42:28 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 0CF30BE0E for ; Tue, 4 Aug 2020 12:42:28 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 6D20DBD9D for ; Tue, 4 Aug 2020 12:42:24 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 39AB543473 for ; Tue, 4 Aug 2020 12:42:24 +0200 (CEST) From: Stefan Reiter To: pbs-devel@lists.proxmox.com Date: Tue, 4 Aug 2020 12:42:03 +0200 Message-Id: <20200804104205.29540-6-s.reiter@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200804104205.29540-1-s.reiter@proxmox.com> References: <20200804104205.29540-1-s.reiter@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.057 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [backup.rs, datastore.rs, pull.rs] Subject: [pbs-devel] [PATCH proxmox-backup 5/7] backup: flock snapshot on backup start X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Aug 2020 10:42:28 -0000 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 --- 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