src/api2/backup.rs: aquire backup lock earlier in create_locked_backup_group()
This commit is contained in:
parent
d2b0c78e23
commit
1fc82c41f2
@ -88,7 +88,10 @@ async move {
|
|||||||
let env_type = rpcenv.env_type();
|
let env_type = rpcenv.env_type();
|
||||||
|
|
||||||
let backup_group = BackupGroup::new(backup_type, backup_id);
|
let backup_group = BackupGroup::new(backup_type, backup_id);
|
||||||
let owner = datastore.create_backup_group(&backup_group, &username)?;
|
|
||||||
|
// lock backup group to only allow one backup per group at a time
|
||||||
|
let (owner, _group_guard) = datastore.create_locked_backup_group(&backup_group, &username)?;
|
||||||
|
|
||||||
// permission check
|
// permission check
|
||||||
if owner != username { // only the owner is allowed to create additional snapshots
|
if owner != username { // only the owner is allowed to create additional snapshots
|
||||||
bail!("backup owner check failed ({} != {})", username, owner);
|
bail!("backup owner check failed ({} != {})", username, owner);
|
||||||
@ -103,9 +106,6 @@ async move {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock backup group to only allow one backup per group at a time
|
|
||||||
let _group_guard = backup_group.lock(&datastore.base_path())?;
|
|
||||||
|
|
||||||
let (path, is_new) = datastore.create_backup_dir(&backup_dir)?;
|
let (path, is_new) = datastore.create_backup_dir(&backup_dir)?;
|
||||||
if !is_new { bail!("backup directory already exists."); }
|
if !is_new { bail!("backup directory already exists."); }
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use anyhow::{bail, format_err, Error};
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
use super::backup_info::{BackupGroup, BackupDir, BackupInfo};
|
use super::backup_info::{BackupGroup, BackupGroupGuard, BackupDir, BackupInfo};
|
||||||
use super::chunk_store::ChunkStore;
|
use super::chunk_store::ChunkStore;
|
||||||
use super::dynamic_index::{DynamicIndexReader, DynamicIndexWriter};
|
use super::dynamic_index::{DynamicIndexReader, DynamicIndexWriter};
|
||||||
use super::fixed_index::{FixedIndexReader, FixedIndexWriter};
|
use super::fixed_index::{FixedIndexReader, FixedIndexWriter};
|
||||||
@ -318,11 +318,13 @@ impl DataStore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a backup group if it does not already exists.
|
/// Create (if it does not already exists) and lock a backup group
|
||||||
///
|
///
|
||||||
/// And set the owner to 'userid'. If the group already exists, it returns the
|
/// And set the owner to 'userid'. If the group already exists, it returns the
|
||||||
/// current owner (instead of setting the owner).
|
/// current owner (instead of setting the owner).
|
||||||
pub fn create_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<String, Error> {
|
///
|
||||||
|
/// This also aquires an exclusive lock on the directory and returns the lock guard.
|
||||||
|
pub fn create_locked_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<(String, BackupGroupGuard), Error> {
|
||||||
|
|
||||||
// create intermediate path first:
|
// create intermediate path first:
|
||||||
let base_path = self.base_path();
|
let base_path = self.base_path();
|
||||||
@ -336,13 +338,15 @@ impl DataStore {
|
|||||||
// create the last component now
|
// create the last component now
|
||||||
match std::fs::create_dir(&full_path) {
|
match std::fs::create_dir(&full_path) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
let guard = backup_group.lock(&base_path)?;
|
||||||
self.set_owner(backup_group, userid, false)?;
|
self.set_owner(backup_group, userid, false)?;
|
||||||
let owner = self.get_owner(backup_group)?; // just to be sure
|
let owner = self.get_owner(backup_group)?; // just to be sure
|
||||||
Ok(owner)
|
Ok((owner, guard))
|
||||||
}
|
}
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {
|
Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {
|
||||||
|
let guard = backup_group.lock(&base_path)?;
|
||||||
let owner = self.get_owner(backup_group)?; // just to be sure
|
let owner = self.get_owner(backup_group)?; // just to be sure
|
||||||
Ok(owner)
|
Ok((owner, guard))
|
||||||
}
|
}
|
||||||
Err(err) => bail!("unable to create backup group {:?} - {}", full_path, err),
|
Err(err) => bail!("unable to create backup group {:?} - {}", full_path, err),
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ pub async fn pull_store(
|
|||||||
for item in list {
|
for item in list {
|
||||||
let group = BackupGroup::new(&item.backup_type, &item.backup_id);
|
let group = BackupGroup::new(&item.backup_type, &item.backup_id);
|
||||||
|
|
||||||
let owner = tgt_store.create_backup_group(&group, &username)?;
|
let (owner, _lock_guard) = tgt_store.create_locked_backup_group(&group, &username)?;
|
||||||
// permission check
|
// permission check
|
||||||
if owner != username { // only the owner is allowed to create additional snapshots
|
if owner != username { // only the owner is allowed to create additional snapshots
|
||||||
worker.log(format!("sync group {}/{} failed - owner check failed ({} != {})",
|
worker.log(format!("sync group {}/{} failed - owner check failed ({} != {})",
|
||||||
|
Loading…
Reference in New Issue
Block a user