]> git.proxmox.com Git - proxmox-backup.git/blame - src/tools/memcom.rs
cleanup User configuration: use Updater
[proxmox-backup.git] / src / tools / memcom.rs
CommitLineData
fda19dcc
DM
1//! Memory based communication channel between proxy & daemon for things such as cache
2//! invalidation.
3
fda19dcc
DM
4use std::os::unix::io::AsRawFd;
5use std::sync::atomic::{AtomicUsize, Ordering};
6use std::sync::Arc;
7
7526d864 8use anyhow::Error;
fda19dcc
DM
9use nix::fcntl::OFlag;
10use nix::sys::mman::{MapFlags, ProtFlags};
11use nix::sys::stat::Mode;
12use once_cell::sync::OnceCell;
13
7526d864 14use proxmox::tools::fs::CreateOptions;
fda19dcc
DM
15use proxmox::tools::mmap::Mmap;
16
17/// In-memory communication channel.
18pub struct Memcom {
19 mmap: Mmap<u8>,
20}
21
22#[repr(C)]
23struct Head {
24 // User (user.cfg) cache generation/version.
25 user_cache_generation: AtomicUsize,
26}
27
835d0e5d 28static INSTANCE: OnceCell<Arc<Memcom>> = OnceCell::new();
fda19dcc 29
af06decd 30const MEMCOM_FILE_PATH: &str = pbs_buildcfg::rundir!("/proxmox-backup-memcom");
7526d864 31const EMPTY_PAGE: [u8; 4096] = [0u8; 4096];
fda19dcc
DM
32
33impl Memcom {
fda19dcc 34 /// Open the memory based communication channel singleton.
835d0e5d 35 pub fn new() -> Result<Arc<Self>, Error> {
fda19dcc
DM
36 INSTANCE.get_or_try_init(Self::open).map(Arc::clone)
37 }
38
39 // Actual work of `new`:
835d0e5d 40 fn open() -> Result<Arc<Self>, Error> {
21211748 41 let user = pbs_config::backup_user()?;
7526d864
DM
42 let options = CreateOptions::new()
43 .perm(Mode::from_bits_truncate(0o660))
44 .owner(user.uid)
45 .group(user.gid);
46
47 let file = proxmox::tools::fs::atomic_open_or_create_file(
48 MEMCOM_FILE_PATH,
49 OFlag::O_RDWR | OFlag::O_CLOEXEC,
50 &EMPTY_PAGE, options)?;
fda19dcc
DM
51
52 let mmap = unsafe {
53 Mmap::<u8>::map_fd(
7526d864 54 file.as_raw_fd(),
fda19dcc
DM
55 0,
56 4096,
57 ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
58 MapFlags::MAP_SHARED | MapFlags::MAP_NORESERVE | MapFlags::MAP_POPULATE,
59 )?
60 };
835d0e5d 61
fda19dcc
DM
62 Ok(Arc::new(Self { mmap }))
63 }
64
65 // Shortcut to get the mapped `Head` as a `Head`.
835d0e5d 66 fn head(&self) -> &Head {
fda19dcc
DM
67 unsafe { &*(self.mmap.as_ptr() as *const u8 as *const Head) }
68 }
69
70 /// Returns the user cache generation number.
835d0e5d 71 pub fn user_cache_generation(&self) -> usize {
fda19dcc
DM
72 self.head().user_cache_generation.load(Ordering::Acquire)
73 }
74
75 /// Increase the user cache generation number.
76 pub fn increase_user_cache_generation(&self) {
77 self.head()
78 .user_cache_generation
79 .fetch_add(1, Ordering::AcqRel);
80 }
81}