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()));