public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>,
	pbs-devel@lists.proxmox.com,
	"Robert Obkircher" <r.obkircher@proxmox.com>
Subject: Re: [PATCH v1 proxmox-backup 11/11] tape: media catalog: use Flock wrapper instead of deprecated function
Date: Thu, 5 Mar 2026 14:13:47 +0100	[thread overview]
Message-ID: <54a5a607-215c-44e8-bbb8-4f7219412934@proxmox.com> (raw)
In-Reply-To: <1772707888.l459trzwfo.astroid@yuna.none>



On 3/5/26 12:08 PM, Fabian Grünbichler wrote:
> On February 26, 2026 3:40 pm, Robert Obkircher wrote:
>> Switch to the new wrapper type to fix the deprecation warnings. Panic
>> if unlock fails, because there is no easy way to return the File that
>> was temporarily moved out of the field.
>>
>> An alternative to moving out of the optional field would be to use
>> `File::try_clone` but that isn't ideal either because duplicated file
>> descriptors share the same lock status. That also doesn't solve the
>> problem that propagating the error without leaking the locked file
>> descriptor requires unsafe code or a change to nix.
>>
>> [1] https://lore.proxmox.com/pbs-devel/1763634535.5sqd1r4buu.astroid@yuna.none/
>>
>> Signed-off-by: Robert Obkircher <r.obkircher@proxmox.com>
>> ---
>>   src/tape/media_catalog.rs | 49 +++++++++++++++++++++------------------
>>   1 file changed, 27 insertions(+), 22 deletions(-)
>>
>> diff --git a/src/tape/media_catalog.rs b/src/tape/media_catalog.rs
>> index 63329a65..372bf59d 100644
>> --- a/src/tape/media_catalog.rs
>> +++ b/src/tape/media_catalog.rs
>> @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
>>   
>>   use anyhow::{bail, format_err, Error};
>>   use endian_trait::Endian;
>> +use nix::fcntl::{Flock, FlockArg};
>>   
>>   use proxmox_sys::fs::read_subdir;
>>   
>> @@ -194,7 +195,7 @@ impl MediaCatalog {
>>           let me = proxmox_lang::try_block!({
>>               Self::create_basedir(base_path)?;
>>   
>> -            let mut file = std::fs::OpenOptions::new()
>> +            let file = std::fs::OpenOptions::new()
>>                   .read(true)
>>                   .write(write)
>>                   .create(create)
>> @@ -219,9 +220,10 @@ impl MediaCatalog {
>>               };
>>   
>>               // Note: lock file, to get a consistent view with load_catalog
>> -            nix::fcntl::flock(file.as_raw_fd(), nix::fcntl::FlockArg::LockExclusive)?;
>> +            let mut file = Flock::lock(file, FlockArg::LockExclusive)
>> +                .map_err(|e| format_err!("flock failed: {e:?}"))?;
>>               let result = me.load_catalog(&mut file, media_id.media_set_label.as_ref());
>> -            nix::fcntl::flock(file.as_raw_fd(), nix::fcntl::FlockArg::Unlock)?;
>> +            let file = file.unlock().expect("shouldn't fail for valid fd");
> 
> here we could just return an error instead of panicing? we only read
> from the file anyway, and bubbling up the error should be fine..

full agree, we bubbled up the error before, so we should keep that behavior

> 
>>   
>>               let (found_magic_number, _) = result?;
>>   
>> @@ -367,27 +369,30 @@ impl MediaCatalog {
>>               return Ok(());
>>           }
>>   
>> -        match self.file {
>> -            Some(ref mut file) => {
>> -                let pending = &self.pending;
>> -                // Note: lock file, to get a consistent view with load_catalog
>> -                nix::fcntl::flock(file.as_raw_fd(), nix::fcntl::FlockArg::LockExclusive)?;
>> -                let result: Result<(), Error> = proxmox_lang::try_block!({
>> -                    file.write_all(pending)?;
>> -                    file.flush()?;
>> -                    file.sync_data()?;
>> -                    Ok(())
>> -                });
>> -                nix::fcntl::flock(file.as_raw_fd(), nix::fcntl::FlockArg::Unlock)?;
>> -
>> -                result?;
>> -            }
>> -            None => bail!("media catalog not writable (opened read only)"),
>> -        }
>> +        let Some(file) = self.file.take() else {
>> +            bail!("media catalog not writable (opened read only)");
>> +        };
>> +
>> +        let mut file = Flock::lock(file, FlockArg::LockExclusive).map_err(|(f, e)| {
>> +            self.file = Some(f);
>> +            format_err!("flock failed: {:?} - {e:?}", self.file)
>> +        })?;
>>   
>> -        self.pending = Vec::new();
>> +        let pending = &self.pending;
>> +        // Note: lock file, to get a consistent view with load_catalog
>> +        let result: Result<(), Error> = proxmox_lang::try_block!({
>> +            file.write_all(pending)?;
>> +            file.flush()?;
>> +            file.sync_data()?;
>> +            Ok(())
>> +        });
>>   
>> -        Ok(())
>> +        self.file = Some(file.unlock().expect("shouldn't fail for valid fd"));
> 
> here the situation is a bit more complicated, since we wrote to the file
> above.. but looking at the call graphs/error behaviour, it seems to me
> that we are often operating on temporary files (though we do not seem to
> clean them up in the error path?), or failure to commit herer would
> bubble up and abort writing to tape anyway..
> 
> triggering a panic here doesn't help in any case - the possibly
> inconsistent writes/reads have already happened, at best we could maybe
> (try to) invalidate the catalog as part of error handling to force
> re-reading it from tape? or we could bubble up the error to abort
> whatever operation is attempting to commit, and log the error
> prominently - taking down the whole PBS instance doesn't buy us anything
> AFAICT?

also here agreeing regarding panicking, we did simply bubble up the
error before, no reason to change that IMO.

looking at the code  i think we should maybe revamp the catalog
handling?

out of scope for this series, but I think we should try to write the
catalog atomically, (meaning we should always writing into a tmp file 
and renaming into place, like we do with most of the other files we
write)

then I think we'd need no lock for reading the catalog at all,
but we'd have to copy the old catalog to a tmp one first when
we want to append data. (this might be a bad idea since
they can get quite large)

but as i wrote, not really relevant for this series, just
wanted it to point out

> 
>> +
>> +        if result.is_ok() {
>> +            self.pending = Vec::new();
>> +        }
>> +        result
>>       }
>>   
>>       /// Conditionally commit if in pending data is large (> 1Mb)
>> -- 
>> 2.47.3
>>
>>
>>
>>
>>
>>





  reply	other threads:[~2026-03-05 13:12 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-26 14:40 [PATCH v1 proxmox-backup 00/11] fix various warnings Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 01/11] datastore: remove allow(clippy::cast_ptr_alignment) attribute Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 02/11] api: use checked_div for compression ratio calculation Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 03/11] datastore+server: sort by key instead of using comparison functions Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 04/11] api: remove unnecessary ampersand to fix clippy warning Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 05/11] bin: debug: use pattern match instead of is_some+unwrap Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 06/11] bin: proxy: fix clippy warning about unnecesary use of find_map Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 07/11] datastore: silence warning about too many arguments Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 08/11] client: catalog shell: avoid unnecessary block_on in async code Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 09/11] client: catalog shell: combine multiple block_on calls into one Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 10/11] client: catalog shell: avoid unsafe transmute Robert Obkircher
2026-02-26 14:40 ` [PATCH v1 proxmox-backup 11/11] tape: media catalog: use Flock wrapper instead of deprecated function Robert Obkircher
2026-03-05 11:08   ` Fabian Grünbichler
2026-03-05 13:13     ` Dominik Csapak [this message]
2026-03-05 14:39       ` Robert Obkircher
2026-03-05 11:20 ` partially-applied: [PATCH v1 proxmox-backup 00/11] fix various warnings Fabian Grünbichler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54a5a607-215c-44e8-bbb8-4f7219412934@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=f.gruenbichler@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    --cc=r.obkircher@proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal