pbs-config: use new SharedMemory helpers from proxmox-shared-memory crate

depend on proxmox-shared-memory crate.

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
Dietmar Maurer 2021-11-12 18:44:28 +01:00
parent 1859a0eb8b
commit cb80ffc1de
9 changed files with 141 additions and 115 deletions

1
debian/control vendored
View File

@ -62,6 +62,7 @@ Build-Depends: debhelper (>= 12),
librust-proxmox-schema-1+default-dev, librust-proxmox-schema-1+default-dev,
librust-proxmox-schema-1+upid-api-impl-dev, librust-proxmox-schema-1+upid-api-impl-dev,
librust-proxmox-section-config-1+default-dev, librust-proxmox-section-config-1+default-dev,
librust-proxmox-shared-memory-dev,
librust-proxmox-tfa-1+default-dev, librust-proxmox-tfa-1+default-dev,
librust-proxmox-tfa-1+u2f-dev, librust-proxmox-tfa-1+u2f-dev,
librust-proxmox-time-1+default-dev, librust-proxmox-time-1+default-dev,

View File

@ -23,6 +23,7 @@ proxmox-router = { version = "1.1", default-features = false }
proxmox-schema = "1" proxmox-schema = "1"
proxmox-section-config = "1" proxmox-section-config = "1"
proxmox-time = "1" proxmox-time = "1"
proxmox-shared-memory = "0.1.0"
pbs-api-types = { path = "../pbs-api-types" } pbs-api-types = { path = "../pbs-api-types" }
pbs-buildcfg = { path = "../pbs-buildcfg" } pbs-buildcfg = { path = "../pbs-buildcfg" }

View File

@ -12,7 +12,7 @@ use proxmox_time::epoch_i64;
use pbs_api_types::{Authid, Userid, User, ApiToken, ROLE_ADMIN}; use pbs_api_types::{Authid, Userid, User, ApiToken, ROLE_ADMIN};
use crate::acl::{AclTree, ROLE_NAMES}; use crate::acl::{AclTree, ROLE_NAMES};
use crate::memcom::Memcom; use crate::ConfigVersionCache;
/// Cache User/Group/Token/Acl configuration data for fast permission tests /// Cache User/Group/Token/Acl configuration data for fast permission tests
pub struct CachedUserInfo { pub struct CachedUserInfo {
@ -38,8 +38,8 @@ impl CachedUserInfo {
pub fn new() -> Result<Arc<Self>, Error> { pub fn new() -> Result<Arc<Self>, Error> {
let now = epoch_i64(); let now = epoch_i64();
let memcom = Memcom::new()?; let version_cache = ConfigVersionCache::new()?;
let user_cache_generation = memcom.user_cache_generation(); let user_cache_generation = version_cache.user_cache_generation();
{ // limit scope { // limit scope
let cache = CACHED_CONFIG.read().unwrap(); let cache = CACHED_CONFIG.read().unwrap();

View File

@ -0,0 +1,121 @@
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::mem::MaybeUninit;
use anyhow::{bail, Error};
use once_cell::sync::OnceCell;
use nix::sys::stat::Mode;
use proxmox::tools::fs::{create_path, CreateOptions};
// openssl::sha::sha256(b"Proxmox Backup ConfigVersionCache v1.0")[0..8];
pub const PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0: [u8; 8] = [25, 198, 168, 230, 154, 132, 143, 131];
const FILE_PATH: &str = pbs_buildcfg::rundir!("/shmem/config-versions");
use proxmox_shared_memory::*;
#[derive(Debug)]
#[repr(C)]
struct ConfigVersionCacheData {
magic: [u8; 8],
// User (user.cfg) cache generation/version.
user_cache_generation: AtomicUsize,
// Traffic control (traffic-control.cfg) generation/version.
traffic_control_generation: AtomicUsize,
// Add further atomics here (and reduce padding size)
padding: [u8; 4096 - 3*8],
}
impl Init for ConfigVersionCacheData {
fn initialize(this: &mut MaybeUninit<Self>) {
unsafe {
let me = &mut *this.as_mut_ptr();
me.magic = PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0;
}
}
fn check_type_magic(this: &MaybeUninit<Self>) -> Result<(), Error> {
unsafe {
let me = &*this.as_ptr();
if me.magic != PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0 {
bail!("ConfigVersionCache: wrong magic number");
}
Ok(())
}
}
}
pub struct ConfigVersionCache {
shmem: SharedMemory<ConfigVersionCacheData>
}
static INSTANCE: OnceCell<Arc< ConfigVersionCache>> = OnceCell::new();
impl ConfigVersionCache {
/// Open the memory based communication channel singleton.
pub fn new() -> Result<Arc<Self>, Error> {
INSTANCE.get_or_try_init(Self::open).map(Arc::clone)
}
// Actual work of `new`:
fn open() -> Result<Arc<Self>, Error> {
let user = crate::backup_user()?;
let dir_opts = CreateOptions::new()
.perm(Mode::from_bits_truncate(0o770))
.owner(user.uid)
.group(user.gid);
let file_path = Path::new(FILE_PATH);
let dir_path = file_path.parent().unwrap();
create_path(
dir_path,
Some(dir_opts.clone()),
Some(dir_opts))?;
let file_opts = CreateOptions::new()
.perm(Mode::from_bits_truncate(0o660))
.owner(user.uid)
.group(user.gid);
let shmem: SharedMemory<ConfigVersionCacheData> =
SharedMemory::open(file_path, file_opts)?;
Ok(Arc::new(Self { shmem }))
}
/// Returns the user cache generation number.
pub fn user_cache_generation(&self) -> usize {
self.shmem.data()
.user_cache_generation.load(Ordering::Acquire)
}
/// Increase the user cache generation number.
pub fn increase_user_cache_generation(&self) {
self.shmem.data()
.user_cache_generation
.fetch_add(1, Ordering::AcqRel);
}
/// Returns the traffic control generation number.
pub fn traffic_control_generation(&self) -> usize {
self.shmem.data()
.traffic_control_generation.load(Ordering::Acquire)
}
/// Increase the traffic control generation number.
pub fn increase_traffic_control_generation(&self) {
self.shmem.data()
.traffic_control_generation
.fetch_add(1, Ordering::AcqRel);
}
}

View File

@ -16,7 +16,8 @@ pub mod traffic_control;
pub mod user; pub mod user;
pub mod verify; pub mod verify;
pub mod memcom; mod config_version_cache;
pub use config_version_cache::ConfigVersionCache;
use anyhow::{format_err, Error}; use anyhow::{format_err, Error};

View File

@ -1,98 +0,0 @@
//! Memory based communication channel between proxy & daemon for things such as cache
//! invalidation.
use std::os::unix::io::AsRawFd;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use anyhow::Error;
use nix::fcntl::OFlag;
use nix::sys::mman::{MapFlags, ProtFlags};
use nix::sys::stat::Mode;
use once_cell::sync::OnceCell;
use proxmox::tools::fs::CreateOptions;
use proxmox::tools::mmap::Mmap;
/// In-memory communication channel.
pub struct Memcom {
mmap: Mmap<u8>,
}
#[repr(C)]
struct Head {
// User (user.cfg) cache generation/version.
user_cache_generation: AtomicUsize,
// Traffic control (traffic-control.cfg) generation/version.
traffic_control_generation: AtomicUsize,
}
static INSTANCE: OnceCell<Arc<Memcom>> = OnceCell::new();
const MEMCOM_FILE_PATH: &str = pbs_buildcfg::rundir!("/proxmox-backup-memcom");
const EMPTY_PAGE: [u8; 4096] = [0u8; 4096];
impl Memcom {
/// Open the memory based communication channel singleton.
pub fn new() -> Result<Arc<Self>, Error> {
INSTANCE.get_or_try_init(Self::open).map(Arc::clone)
}
// Actual work of `new`:
fn open() -> Result<Arc<Self>, Error> {
let user = crate::backup_user()?;
let options = CreateOptions::new()
.perm(Mode::from_bits_truncate(0o660))
.owner(user.uid)
.group(user.gid);
let file = proxmox::tools::fs::atomic_open_or_create_file(
MEMCOM_FILE_PATH,
OFlag::O_RDWR | OFlag::O_CLOEXEC,
&EMPTY_PAGE,
options,
true,
)?;
let mmap = unsafe {
Mmap::<u8>::map_fd(
file.as_raw_fd(),
0,
4096,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_SHARED | MapFlags::MAP_NORESERVE | MapFlags::MAP_POPULATE,
)?
};
Ok(Arc::new(Self { mmap }))
}
// Shortcut to get the mapped `Head` as a `Head`.
fn head(&self) -> &Head {
unsafe { &*(self.mmap.as_ptr() as *const u8 as *const Head) }
}
/// Returns the user cache generation number.
pub fn user_cache_generation(&self) -> usize {
self.head().user_cache_generation.load(Ordering::Acquire)
}
/// Increase the user cache generation number.
pub fn increase_user_cache_generation(&self) {
self.head()
.user_cache_generation
.fetch_add(1, Ordering::AcqRel);
}
/// Returns the traffic control generation number.
pub fn traffic_control_generation(&self) -> usize {
self.head().traffic_control_generation.load(Ordering::Acquire)
}
/// Increase the traffic control generation number.
pub fn increase_traffic_control_generation(&self) {
self.head()
.traffic_control_generation
.fetch_add(1, Ordering::AcqRel);
}
}

View File

@ -10,7 +10,7 @@ use pbs_api_types::{TrafficControlRule, TRAFFIC_CONTROL_ID_SCHEMA};
use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin}; use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
use crate::memcom::Memcom; use crate::ConfigVersionCache;
use crate::{open_backup_lockfile, replace_backup_config, BackupLockGuard}; use crate::{open_backup_lockfile, replace_backup_config, BackupLockGuard};
lazy_static! { lazy_static! {
@ -57,10 +57,10 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
let raw = CONFIG.write(TRAFFIC_CONTROL_CFG_FILENAME, &config)?; let raw = CONFIG.write(TRAFFIC_CONTROL_CFG_FILENAME, &config)?;
replace_backup_config(TRAFFIC_CONTROL_CFG_FILENAME, raw.as_bytes())?; replace_backup_config(TRAFFIC_CONTROL_CFG_FILENAME, raw.as_bytes())?;
// increase traffic control generation // increase traffic control version
// We use this in TrafficControlCache // We use this in TrafficControlCache
let memcom = Memcom::new()?; let version_cache = ConfigVersionCache::new()?;
memcom.increase_traffic_control_generation(); version_cache.increase_traffic_control_generation();
Ok(()) Ok(())
} }

View File

@ -11,7 +11,7 @@ use pbs_api_types::{
Authid, Userid, ApiToken, User, Authid, Userid, ApiToken, User,
}; };
use crate::memcom::Memcom; use crate::ConfigVersionCache;
use crate::{open_backup_lockfile, replace_backup_config, BackupLockGuard}; use crate::{open_backup_lockfile, replace_backup_config, BackupLockGuard};
@ -120,10 +120,10 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
let raw = CONFIG.write(USER_CFG_FILENAME, &config)?; let raw = CONFIG.write(USER_CFG_FILENAME, &config)?;
replace_backup_config(USER_CFG_FILENAME, raw.as_bytes())?; replace_backup_config(USER_CFG_FILENAME, raw.as_bytes())?;
// increase user cache generation // increase user version
// We use this in CachedUserInfo // We use this in CachedUserInfo
let memcom = Memcom::new()?; let version_cache = ConfigVersionCache::new()?;
memcom.increase_user_cache_generation(); version_cache.increase_user_cache_generation();
Ok(()) Ok(())
} }

View File

@ -14,7 +14,7 @@ use proxmox_time::TmEditor;
use pbs_api_types::TrafficControlRule; use pbs_api_types::TrafficControlRule;
use pbs_config::memcom::Memcom; use pbs_config::ConfigVersionCache;
struct ParsedTcRule { struct ParsedTcRule {
config: TrafficControlRule, // original rule config config: TrafficControlRule, // original rule config
@ -97,15 +97,15 @@ impl TrafficControlCache {
} }
pub fn reload(&mut self, now: i64) { pub fn reload(&mut self, now: i64) {
let memcom = match Memcom::new() { let version_cache = match ConfigVersionCache::new() {
Ok(memcom) => memcom, Ok(cache) => cache,
Err(err) => { Err(err) => {
log::error!("TrafficControlCache::reload failed in Memcom::new: {}", err); log::error!("TrafficControlCache::reload failed in ConfigVersionCache::new: {}", err);
return; return;
} }
}; };
let traffic_control_generation = memcom.traffic_control_generation(); let traffic_control_generation = version_cache.traffic_control_generation();
if (self.last_update != 0) && if (self.last_update != 0) &&
(traffic_control_generation == self.last_traffic_control_generation) && (traffic_control_generation == self.last_traffic_control_generation) &&