}
}
- 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| {
async move {
// keep flock until task ends
let _group_guard = _group_guard;
+ let _snap_guard = _snap_guard;
let res = select!{
req = req_fut => req,
/// 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())
}
}
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()));