mirror of https://github.com/aya-rs/aya
init inode storage
parent
09442c2cbe
commit
932cef84b9
@ -0,0 +1,148 @@
|
|||||||
|
use core::{cell::UnsafeCell, marker::PhantomData, mem, ptr::NonNull};
|
||||||
|
|
||||||
|
use aya_ebpf_bindings::{
|
||||||
|
bindings::{
|
||||||
|
bpf_map_def,
|
||||||
|
bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_INODE_STORAGE},
|
||||||
|
BPF_LOCAL_STORAGE_GET_F_CREATE,
|
||||||
|
},
|
||||||
|
helpers::{bpf_inode_storage_delete, bpf_inode_storage_get},
|
||||||
|
};
|
||||||
|
use aya_ebpf_cty::{c_int, c_void};
|
||||||
|
|
||||||
|
use crate::maps::PinningType;
|
||||||
|
|
||||||
|
/// A BPF map of type BPF_MAP_TYPE_INODE_STORAGE, used for attaching local storage data to an inode.
|
||||||
|
/// See bpf_inode_storage_get in bpf-helpers(7) for details.
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct InodeStorage<V> {
|
||||||
|
def: UnsafeCell<bpf_map_def>,
|
||||||
|
_v: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> InodeStorage<V> {
|
||||||
|
/// Instantiate a [`InodeStorage`] map with the provided flags.
|
||||||
|
pub const fn new(flags: u32) -> InodeStorage<V> {
|
||||||
|
InodeStorage {
|
||||||
|
def: UnsafeCell::new(build_def::<V>(
|
||||||
|
BPF_MAP_TYPE_INODE_STORAGE,
|
||||||
|
flags,
|
||||||
|
PinningType::None,
|
||||||
|
)),
|
||||||
|
_v: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instantiate a pinned [`InodeStorage`] map with the provided flags.
|
||||||
|
pub const fn pinned(flags: u32) -> InodeStorage<V> {
|
||||||
|
InodeStorage {
|
||||||
|
def: UnsafeCell::new(build_def::<V>(
|
||||||
|
BPF_MAP_TYPE_INODE_STORAGE,
|
||||||
|
flags,
|
||||||
|
PinningType::ByName,
|
||||||
|
)),
|
||||||
|
_v: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a local storage entry associated with this inode, or insert the provided value and get
|
||||||
|
/// the mutable reference to the information stored within the inode. Returns [`None`] if there
|
||||||
|
/// was an issue with inserting the new value.
|
||||||
|
///
|
||||||
|
/// ## Safety
|
||||||
|
///
|
||||||
|
/// This function is marked unsafe as accessing the same inode's local storage multiple times
|
||||||
|
/// would create multiple mutable references to the same data, which is not supported by Rust's
|
||||||
|
/// memory model.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn get_or_insert(&self, inode: *mut c_void, initial: &V) -> Option<&mut V> {
|
||||||
|
self.get_or_insert_ptr(inode, initial).map(|p| &mut *p)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pointer to the local storage entry associated with this inode, or insert the provided
|
||||||
|
/// value and get the mutable reference to the information stored within the inode. Returns
|
||||||
|
/// [`None`] if there was an issue with inserting the new value.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_or_insert_ptr(&self, inode: *mut c_void, initial: &V) -> Option<*mut V> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bpf_inode_storage_get(
|
||||||
|
self.def.get() as *mut c_void,
|
||||||
|
inode,
|
||||||
|
initial as *const V as *const c_void as *mut c_void,
|
||||||
|
BPF_LOCAL_STORAGE_GET_F_CREATE as u64,
|
||||||
|
);
|
||||||
|
NonNull::new(ptr as *mut V).map(|p| p.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a local storage entry associated with this inode, or [`None`] if no such value exists.
|
||||||
|
///
|
||||||
|
/// ## Safety
|
||||||
|
///
|
||||||
|
/// This function is marked unsafe as accessing the same inode's local storage immutably at the
|
||||||
|
/// same time as mutably (e.g., but way of [`InodeStorage::get_mut`]) is not supported by Rust's
|
||||||
|
/// memory model.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn get(&self, inode: *mut c_void) -> Option<&V> {
|
||||||
|
self.get_ptr(inode).map(|p| &*p)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably access a local storage entry associated with this inode, or [`None`] if no such
|
||||||
|
/// value exists.
|
||||||
|
///
|
||||||
|
/// ## Safety
|
||||||
|
///
|
||||||
|
/// This function is marked unsafe as accessing the same inode's local storage mutably multiple
|
||||||
|
/// times is not supported by Rust's memory model.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn get_mut(&self, inode: *mut c_void) -> Option<&mut V> {
|
||||||
|
self.get_ptr_mut(inode).map(|p| &mut *p)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pointer to the local storage entry associated with this inode, or [`None`] if no such
|
||||||
|
/// value exists.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_ptr(&self, inode: *mut c_void) -> Option<*const V> {
|
||||||
|
self.get_ptr_mut(inode).map(|p| p as *const V)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable pointer to the local storage entry associated with this inode, or [`None`] if
|
||||||
|
/// no such value exists. You are responsible for ensuring that at most one mutable reference to
|
||||||
|
/// the same inode local storage exists at a given time.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_ptr_mut(&self, inode: *mut c_void) -> Option<*mut V> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bpf_inode_storage_get(
|
||||||
|
self.def.get() as *mut c_void,
|
||||||
|
inode,
|
||||||
|
core::ptr::null_mut(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
NonNull::new(ptr as *mut V).map(|p| p.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a local storage entry associated with this inode. Returns `Err(-ENOENT)` if no such
|
||||||
|
/// value was present.
|
||||||
|
#[inline]
|
||||||
|
pub fn remove(&self, inode: *mut c_void) -> Result<(), c_int> {
|
||||||
|
let ret = unsafe { bpf_inode_storage_delete(self.def.get() as *mut c_void, inode) };
|
||||||
|
if ret == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn build_def<V>(ty: u32, flags: u32, pin: PinningType) -> bpf_map_def {
|
||||||
|
bpf_map_def {
|
||||||
|
type_: ty,
|
||||||
|
key_size: mem::size_of::<c_int>() as u32,
|
||||||
|
value_size: mem::size_of::<V>() as u32,
|
||||||
|
max_entries: 0,
|
||||||
|
map_flags: flags,
|
||||||
|
id: 0,
|
||||||
|
pinning: pin as u32,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use aya_ebpf::{macros::map, maps::inode_storage::InodeStorage};
|
||||||
|
|
||||||
|
#[map]
|
||||||
|
static INODE_STORE: InodeStorage<usize> = InodeStorage::new(0);
|
Loading…
Reference in New Issue