tools: add mmap helper

Mmap<T> acts like a slice of `T`s, inhereting its `Send` and
`Sync` traits

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-06-12 13:53:24 +02:00
parent 3516c9e2ec
commit 2eaea4b9ea
2 changed files with 82 additions and 2 deletions

79
proxmox/src/tools/mmap.rs Normal file
View File

@ -0,0 +1,79 @@
//! Memory mapping helpers.
use std::convert::TryFrom;
use std::os::unix::io::RawFd;
use std::{io, mem, ptr};
use nix::sys::mman;
use crate::sys::error::{io_err_other, SysError};
pub struct Mmap<T> {
data: *mut T,
len: usize,
}
unsafe impl<T> Send for Mmap<T> where T: Send {}
unsafe impl<T> Sync for Mmap<T> where T: Sync {}
impl<T> Mmap<T> {
pub unsafe fn map_fd(
fd: RawFd,
ofs: u64,
count: usize,
prot: mman::ProtFlags,
flags: mman::MapFlags,
) -> io::Result<Self> {
let byte_len = count * mem::size_of::<T>();
let data = mman::mmap(
ptr::null_mut(),
libc::size_t::try_from(byte_len).map_err(io_err_other)?,
prot,
flags,
fd,
libc::off_t::try_from(ofs).map_err(io_err_other)?,
)
.map_err(SysError::into_io_error)?;
Ok(Self {
data: data as *mut T,
len: count,
})
}
}
impl<T> std::ops::Deref for Mmap<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.data, self.len) }
}
}
impl<T> std::ops::DerefMut for Mmap<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe { std::slice::from_raw_parts_mut(self.data, self.len) }
}
}
impl<T> Drop for Mmap<T> {
fn drop(&mut self) {
unsafe {
// In theory this can fail if too many memory mappings are already present and
// unmapping a smaller region inside a bigger one, causing it to become split into 2
// regions. But then we have bigger problems already anyway, so we'll just ignore this.
let _ = mman::munmap(self.data as *mut libc::c_void, self.len * mem::size_of::<T>());
}
}
}
impl<'a, T> IntoIterator for &'a Mmap<T> {
type Item = &'a T;
type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
<&'a [T] as IntoIterator>::into_iter(self)
}
}

View File

@ -8,15 +8,16 @@ use lazy_static::lazy_static;
pub mod as_any;
pub mod borrow;
pub mod common_regex;
pub mod constnamemap;
pub mod fd;
pub mod fs;
pub mod io;
pub mod mmap;
pub mod parse;
pub mod serde;
pub mod time;
pub mod uuid;
pub mod vec;
pub mod time;
pub mod constnamemap;
#[doc(inline)]
pub use uuid::Uuid;