1 //! Memory based communication channel between proxy & daemon for things such as cache
4 use std
::os
::unix
::io
::AsRawFd
;
5 use std
::sync
::atomic
::{AtomicUsize, Ordering}
;
10 use nix
::sys
::mman
::{MapFlags, ProtFlags}
;
11 use nix
::sys
::stat
::Mode
;
12 use once_cell
::sync
::OnceCell
;
14 use proxmox
::tools
::fs
::CreateOptions
;
15 use proxmox
::tools
::mmap
::Mmap
;
17 /// In-memory communication channel.
24 // User (user.cfg) cache generation/version.
25 user_cache_generation
: AtomicUsize
,
28 static INSTANCE
: OnceCell
<Arc
<Memcom
>> = OnceCell
::new();
30 const MEMCOM_FILE_PATH
: &str = pbs_buildcfg
::rundir
!("/proxmox-backup-memcom");
31 const EMPTY_PAGE
: [u8; 4096] = [0u8; 4096];
34 /// Open the memory based communication channel singleton.
35 pub fn new() -> Result
<Arc
<Self>, Error
> {
36 INSTANCE
.get_or_try_init(Self::open
).map(Arc
::clone
)
39 // Actual work of `new`:
40 fn open() -> Result
<Arc
<Self>, Error
> {
41 let user
= pbs_config
::backup_user()?
;
42 let options
= CreateOptions
::new()
43 .perm(Mode
::from_bits_truncate(0o660))
47 let file
= proxmox
::tools
::fs
::atomic_open_or_create_file(
49 OFlag
::O_RDWR
| OFlag
::O_CLOEXEC
,
50 &EMPTY_PAGE
, options
)?
;
57 ProtFlags
::PROT_READ
| ProtFlags
::PROT_WRITE
,
58 MapFlags
::MAP_SHARED
| MapFlags
::MAP_NORESERVE
| MapFlags
::MAP_POPULATE
,
62 Ok(Arc
::new(Self { mmap }
))
65 // Shortcut to get the mapped `Head` as a `Head`.
66 fn head(&self) -> &Head
{
67 unsafe { &*(self.mmap.as_ptr() as *const u8 as *const Head) }
70 /// Returns the user cache generation number.
71 pub fn user_cache_generation(&self) -> usize {
72 self.head().user_cache_generation
.load(Ordering
::Acquire
)
75 /// Increase the user cache generation number.
76 pub fn increase_user_cache_generation(&self) {
78 .user_cache_generation
79 .fetch_add(1, Ordering
::AcqRel
);