diff --git a/proxmox/src/tools/mmap.rs b/proxmox/src/tools/mmap.rs new file mode 100644 index 00000000..dd2347aa --- /dev/null +++ b/proxmox/src/tools/mmap.rs @@ -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 { + data: *mut T, + len: usize, +} + +unsafe impl Send for Mmap where T: Send {} +unsafe impl Sync for Mmap where T: Sync {} + +impl Mmap { + pub unsafe fn map_fd( + fd: RawFd, + ofs: u64, + count: usize, + prot: mman::ProtFlags, + flags: mman::MapFlags, + ) -> io::Result { + let byte_len = count * mem::size_of::(); + 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 std::ops::Deref for Mmap { + type Target = [T]; + + #[inline] + fn deref(&self) -> &[T] { + unsafe { std::slice::from_raw_parts(self.data, self.len) } + } +} + +impl std::ops::DerefMut for Mmap { + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + unsafe { std::slice::from_raw_parts_mut(self.data, self.len) } + } +} + +impl Drop for Mmap { + 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::()); + } + } +} + +impl<'a, T> IntoIterator for &'a Mmap { + type Item = &'a T; + type IntoIter = <&'a [T] as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + <&'a [T] as IntoIterator>::into_iter(self) + } +} diff --git a/proxmox/src/tools/mod.rs b/proxmox/src/tools/mod.rs index 4e3095e7..6d39410c 100644 --- a/proxmox/src/tools/mod.rs +++ b/proxmox/src/tools/mod.rs @@ -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;