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 00FA969FCF for ; Tue, 11 Aug 2020 10:51:31 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id EA8AC1B1D9 for ; Tue, 11 Aug 2020 10:51:00 +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) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 5BAB41B197 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 DE31A445AA for ; Tue, 11 Aug 2020 10:50:57 +0200 (CEST) From: Stefan Reiter To: pbs-devel@lists.proxmox.com Date: Tue, 11 Aug 2020 10:50:38 +0200 Message-Id: <20200811085042.30686-4-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.072 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. [datastore.rs] Subject: [pbs-devel] [PATCH v2 proxmox-backup 3/7] datastore: prevent in-use deletion with locks instead of heuristic 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:31 -0000 Attempt to lock the backup directory to be deleted, if it works keep the lock until the deletion is complete. This way we ensure that no other locking operation (e.g. using a snapshot as base for another backup) can happen concurrently. Signed-off-by: Stefan Reiter --- For this to actually work the following patches are obviously necessary, but I wanted to keep them seperate for review. src/backup/datastore.rs | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/src/backup/datastore.rs b/src/backup/datastore.rs index 01695f48..71544d20 100644 --- a/src/backup/datastore.rs +++ b/src/backup/datastore.rs @@ -11,7 +11,7 @@ use serde_json::Value; use proxmox::tools::fs::{replace_file, CreateOptions}; -use super::backup_info::{BackupGroup, BackupDir, BackupInfo}; +use super::backup_info::{BackupGroup, BackupDir}; use super::chunk_store::ChunkStore; use super::dynamic_index::{DynamicIndexReader, DynamicIndexWriter}; use super::fixed_index::{FixedIndexReader, FixedIndexWriter}; @@ -200,19 +200,7 @@ impl DataStore { let full_path = self.group_path(backup_group); - let mut snap_list = backup_group.list_backups(&self.base_path())?; - BackupInfo::sort_list(&mut snap_list, false); - for snap in snap_list { - if snap.is_finished() { - break; - } else { - bail!( - "cannot remove backup group {:?}, contains potentially running backup: {}", - full_path, - snap.backup_dir - ); - } - } + let _guard = tools::fs::lock_dir_noblock(&full_path, "backup group", "possible running backup")?; log::info!("removing backup group {:?}", full_path); std::fs::remove_dir_all(&full_path) @@ -232,29 +220,9 @@ impl DataStore { let full_path = self.snapshot_path(backup_dir); + let _guard; if !force { - let mut snap_list = backup_dir.group().list_backups(&self.base_path())?; - BackupInfo::sort_list(&mut snap_list, false); - let mut prev_snap_finished = true; - for snap in snap_list { - let cur_snap_finished = snap.is_finished(); - if &snap.backup_dir == backup_dir { - if !cur_snap_finished { - bail!( - "cannot remove currently running snapshot: {:?}", - backup_dir - ); - } - if !prev_snap_finished { - bail!( - "cannot remove snapshot {:?}, successor is currently running and potentially based on it", - backup_dir - ); - } - break; - } - prev_snap_finished = cur_snap_finished; - } + _guard = lock_dir_noblock(&full_path, "snapshot", "possibly running or used as base")?; } log::info!("removing backup snapshot {:?}", full_path); -- 2.20.1