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 7414B69FC6 for ; Tue, 11 Aug 2020 10:51:01 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 707E91B1E9 for ; Tue, 11 Aug 2020 10:51:01 +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 BBB3A1B1B3 for ; Tue, 11 Aug 2020 10:50:58 +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 7FC3C4457F for ; Tue, 11 Aug 2020 10:50:58 +0200 (CEST) From: Stefan Reiter To: pbs-devel@lists.proxmox.com Date: Tue, 11 Aug 2020 10:50:39 +0200 Message-Id: <20200811085042.30686-5-s.reiter@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200811085042.30686-1-s.reiter@proxmox.com> References: <20200811085042.30686-1-s.reiter@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.070 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, pull.rs, datastore.rs] Subject: [pbs-devel] [PATCH v2 proxmox-backup 4/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, 11 Aug 2020 08:51:01 -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 backups unrelated to the currently running to be forgotten/pruned). Signed-off-by: Stefan Reiter --- src/api2/backup.rs | 3 ++- src/backup/datastore.rs | 13 +++++++++---- src/client/pull.rs | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/api2/backup.rs b/src/api2/backup.rs index 4b019007..f541eb97 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), userid.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 71544d20..37f581bc 100644 --- a/src/backup/datastore.rs +++ b/src/backup/datastore.rs @@ -334,15 +334,20 @@ 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, DirLockGuard), Error> + { let relative_path = backup_dir.relative_path(); let mut full_path = self.base_path(); full_path.push(&relative_path); + let lock = || + lock_dir_noblock(&full_path, "snapshot", "internal error - tried creating snapshot that's already in use"); + 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 05b7c66c..2428051a 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