proxmox-rrd: add option to avoid page cache for load/save
use fadvice(.., POSIX_FADV_DONTNEED) for RRD files. We read those files only once, and always rewrite them. Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
parent
98eb435d90
commit
934c8724e2
|
@ -74,7 +74,7 @@ impl RRDMap {
|
||||||
if let Some(rrd) = self.map.get(rel_path) {
|
if let Some(rrd) = self.map.get(rel_path) {
|
||||||
let mut path = self.config.basedir.clone();
|
let mut path = self.config.basedir.clone();
|
||||||
path.push(rel_path);
|
path.push(rel_path);
|
||||||
rrd.save(&path, self.config.file_options.clone())
|
rrd.save(&path, self.config.file_options.clone(), true)
|
||||||
} else {
|
} else {
|
||||||
bail!("rrd file {} not loaded", rel_path);
|
bail!("rrd file {} not loaded", rel_path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,13 @@
|
||||||
//! * Arbitrary number of RRAs (dynamically changeable)
|
//! * Arbitrary number of RRAs (dynamically changeable)
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||||
|
|
||||||
use anyhow::{bail, format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use proxmox::tools::fs::{replace_file, CreateOptions};
|
use proxmox::tools::fs::{make_tmp_file, CreateOptions};
|
||||||
use proxmox_schema::api;
|
use proxmox_schema::api;
|
||||||
|
|
||||||
use crate::rrd_v1;
|
use crate::rrd_v1;
|
||||||
|
@ -321,8 +323,21 @@ impl RRD {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load data from a file
|
/// Load data from a file
|
||||||
pub fn load(path: &Path) -> Result<Self, std::io::Error> {
|
pub fn load(path: &Path, avoid_page_cache: bool) -> Result<Self, std::io::Error> {
|
||||||
let raw = std::fs::read(path)?;
|
|
||||||
|
let mut file = std::fs::File::open(path)?;
|
||||||
|
let buffer_size = file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0);
|
||||||
|
let mut raw = Vec::with_capacity(buffer_size);
|
||||||
|
file.read_to_end(&mut raw)?;
|
||||||
|
|
||||||
|
if avoid_page_cache {
|
||||||
|
nix::fcntl::posix_fadvise(
|
||||||
|
file.as_raw_fd(),
|
||||||
|
0,
|
||||||
|
buffer_size as i64,
|
||||||
|
nix::fcntl::PosixFadviseAdvice::POSIX_FADV_DONTNEED,
|
||||||
|
).map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))?;
|
||||||
|
}
|
||||||
|
|
||||||
match Self::from_raw(&raw) {
|
match Self::from_raw(&raw) {
|
||||||
Ok(rrd) => Ok(rrd),
|
Ok(rrd) => Ok(rrd),
|
||||||
|
@ -331,11 +346,48 @@ impl RRD {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store data into a file (atomic replace file)
|
/// Store data into a file (atomic replace file)
|
||||||
pub fn save(&self, filename: &Path, options: CreateOptions) -> Result<(), Error> {
|
pub fn save(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
options: CreateOptions,
|
||||||
|
avoid_page_cache: bool,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let (fd, tmp_path) = make_tmp_file(&path, options)?;
|
||||||
|
let mut file = unsafe { std::fs::File::from_raw_fd(fd.into_raw_fd()) };
|
||||||
|
|
||||||
|
let mut try_block = || -> Result<(), Error> {
|
||||||
let mut data: Vec<u8> = Vec::new();
|
let mut data: Vec<u8> = Vec::new();
|
||||||
data.extend(&PROXMOX_RRD_MAGIC_2_0);
|
data.extend(&PROXMOX_RRD_MAGIC_2_0);
|
||||||
serde_cbor::to_writer(&mut data, self)?;
|
serde_cbor::to_writer(&mut data, self)?;
|
||||||
replace_file(filename, &data, options)
|
file.write_all(&data)?;
|
||||||
|
|
||||||
|
if avoid_page_cache {
|
||||||
|
nix::fcntl::posix_fadvise(
|
||||||
|
file.as_raw_fd(),
|
||||||
|
0,
|
||||||
|
data.len() as i64,
|
||||||
|
nix::fcntl::PosixFadviseAdvice::POSIX_FADV_DONTNEED,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
match try_block() {
|
||||||
|
Ok(()) => (),
|
||||||
|
error => {
|
||||||
|
let _ = nix::unistd::unlink(&tmp_path);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = std::fs::rename(&tmp_path, &path) {
|
||||||
|
let _ = nix::unistd::unlink(&tmp_path);
|
||||||
|
bail!("Atomic rename failed - {}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_update(&self) -> f64 {
|
pub fn last_update(&self) -> f64 {
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn load_callback(
|
||||||
dst: DST,
|
dst: DST,
|
||||||
) -> RRD {
|
) -> RRD {
|
||||||
|
|
||||||
match RRD::load(path) {
|
match RRD::load(path, true) {
|
||||||
Ok(rrd) => rrd,
|
Ok(rrd) => rrd,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if err.kind() != std::io::ErrorKind::NotFound {
|
if err.kind() != std::io::ErrorKind::NotFound {
|
||||||
|
|
Loading…
Reference in New Issue