[pbs-devel] [PATCH proxmox-backup v2 1/2] fix #5439: allow to reuse existing datastore
Fabian Grünbichler
f.gruenbichler at proxmox.com
Thu Jul 18 13:05:03 CEST 2024
On July 18, 2024 11:27 am, Gabriel Goller wrote:
> On 15.07.2024 13:23, Fabian Grünbichler wrote:
>>On July 12, 2024 1:57 pm, Gabriel Goller wrote:
>>> On 10.07.2024 15:28, Fabian Grünbichler wrote:
>>>>On June 12, 2024 3:22 pm, Gabriel Goller wrote:
>>>>> Disallow creating datastores in non-empty directories. Allow adding
>>>>> existing datastores via a 'reuse-datastore' checkmark. This only checks
>>>>> if all the necessary directories (.chunks + subdirectories and .lock)
>>>>> are existing and have the correct permissions, then opens the
>>>>> datastore.
>>>>>
>>>>> Signed-off-by: Gabriel Goller <g.goller at proxmox.com>
>>>>> ---
>>>>>
>>>>> v2, thanks @Fabian:
>>>>> - also check on frontend for root
>>>>> - forbid datastore creation if dir not empty
>>>>> - add reuse-datastore option
>>>>> - verify chunkstore directories permissions and owners
>>>>>
>>>>> pbs-datastore/src/chunk_store.rs | 49 ++++++++++++++++++++++++++++-
>>>>> src/api2/config/datastore.rs | 54 +++++++++++++++++++++++++-------
>>>>> src/api2/node/disks/directory.rs | 1 +
>>>>> src/api2/node/disks/zfs.rs | 1 +
>>>>> 4 files changed, 93 insertions(+), 12 deletions(-)
>>>>>
>>>>> diff --git a/pbs-datastore/src/chunk_store.rs b/pbs-datastore/src/chunk_store.rs
>>>>> index 9f6289c9..077bc316 100644
>>>>> --- a/pbs-datastore/src/chunk_store.rs
>>>>> +++ b/pbs-datastore/src/chunk_store.rs
>>>>> @@ -164,7 +164,7 @@ impl ChunkStore {
>>>>> /// Note that this must be used with care, as it's dangerous to create two instances on the
>>>>> /// same base path, as closing the underlying ProcessLocker drops all locks from this process
>>>>> /// on the lockfile (even if separate FDs)
>>>>
>>>>given this ^
>>
>>this part here was important ;)
>>
>>>>
>>>>> - pub(crate) fn open<P: Into<PathBuf>>(
>>>>> + pub fn open<P: Into<PathBuf>>(
>>>>
>>>>wouldn't it make more sense to split out the path checks and call them
>>>>both in open and in verify_chunkstore below
>>>
>>> Why call them both in open and verify_chunkstore? create_datastore
>>> always calls the verify method before open, so we could move this to
>>> the verify function? I think I don't understand this correctly...
>>
>>see below..
>>
>>>>> name: &str,
>>>>> base: P,
>>>>> sync_level: DatastoreFSyncLevel,
>>>>> @@ -563,6 +563,53 @@ impl ChunkStore {
>>>>> // unwrap: only `None` in unit tests
>>>>> ProcessLocker::try_exclusive_lock(self.locker.clone().unwrap())
>>>>> }
>>>
>>>>> +
>>>>> let tuning: DatastoreTuning = serde_json::from_value(
>>>>> DatastoreTuning::API_SCHEMA
>>>>> .parse_property_string(datastore.tuning.as_deref().unwrap_or(""))?,
>>>>> )?;
>>>>> - let backup_user = pbs_config::backup_user()?;
>>>>> - let _store = ChunkStore::create(
>>>>> - &datastore.name,
>>>>> - path,
>>>>> - backup_user.uid,
>>>>> - backup_user.gid,
>>>>> - worker,
>>>>> - tuning.sync_level.unwrap_or_default(),
>>>>> - )?;
>>>>> +
>>>>> + if !datastore_empty && !reuse_datastore {
>>>>> + bail!("Directory is not empty!");
>>>>> + } else if !datastore_empty && reuse_datastore {
>>>>> + ChunkStore::verify_chunkstore(&path)?;
>>>>> +
>>>>> + let _store =
>>>>> + ChunkStore::open(&datastore.name, path, tuning.sync_level.unwrap_or_default())?;
>>>>
>>>>(continued from first comment above) and leave out this call here?
>>
>>this was the continuation ;) if we drop the open call here (to avoid
>>side-effects via the process locker), then we need the path checks in
>>verify *and* open. hope that makes sense now :)
>>
>
> Ooh, I think I got it...
> So basically we could just call `ChunkStore::verify_chunkstore` in
> `ChunkStore::open` and drop the `open` call above, right?
no, what I meant is:
in open, split out the checks there (that base is absolute, and that the
chunk dir is accessible) into a new helper fn. then call that new helper
fn in open (so that the behaviour of open stays the same).
then, also call this helper in your patch here - it doesn't really give
much extra benefit atm, but it makes it less easy to miss that this
should be done in both places when adding new checks.
I don't think we want to do the full verification on each open, but when
creating a datastore config entry with an existing datastore, we want to
do both the extensive checks and those we'd do when opening it.
of course another option would be to have a single helper, and a
parameter that controls whether the extensive checks should be done or
not. even harder to miss that there are two related sets of checks then
;)
>>>>
>>>>> + } else {
>>>>> + let backup_user = pbs_config::backup_user()?;
>>>>> + let _store = ChunkStore::create(
>>>>> + &datastore.name,
>>>>> + path,
>>>>> + backup_user.uid,
>>>>> + backup_user.gid,
>>>>> + worker,
>>>>> + tuning.sync_level.unwrap_or_default(),
>>>>> + )?;
>>>>> + }
>>
>>
>>_______________________________________________
>>pbs-devel mailing list
>>pbs-devel at lists.proxmox.com
>>https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
>
>
> _______________________________________________
> pbs-devel mailing list
> pbs-devel at lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
>
More information about the pbs-devel
mailing list