// SPDX-License-Identifier: GPL-2.012//! Maple trees.3//!4//! C header: [`include/linux/maple_tree.h`](srctree/include/linux/maple_tree.h)5//!6//! Reference: <https://docs.kernel.org/core-api/maple_tree.html>78use core::{9marker::PhantomData,10ops::{Bound, RangeBounds},11ptr,12};1314use kernel::{15alloc::Flags,16error::to_result,17prelude::*,18types::{ForeignOwnable, Opaque},19};2021/// A maple tree optimized for storing non-overlapping ranges.22///23/// # Invariants24///25/// Each range in the maple tree owns an instance of `T`.26#[pin_data(PinnedDrop)]27#[repr(transparent)]28pub struct MapleTree<T: ForeignOwnable> {29#[pin]30tree: Opaque<bindings::maple_tree>,31_p: PhantomData<T>,32}3334/// A maple tree with `MT_FLAGS_ALLOC_RANGE` set.35///36/// All methods on [`MapleTree`] are also accessible on this type.37#[pin_data]38#[repr(transparent)]39pub struct MapleTreeAlloc<T: ForeignOwnable> {40#[pin]41tree: MapleTree<T>,42}4344// Make MapleTree methods usable on MapleTreeAlloc.45impl<T: ForeignOwnable> core::ops::Deref for MapleTreeAlloc<T> {46type Target = MapleTree<T>;4748#[inline]49fn deref(&self) -> &MapleTree<T> {50&self.tree51}52}5354#[inline]55fn to_maple_range(range: impl RangeBounds<usize>) -> Option<(usize, usize)> {56let first = match range.start_bound() {57Bound::Included(start) => *start,58Bound::Excluded(start) => start.checked_add(1)?,59Bound::Unbounded => 0,60};6162let last = match range.end_bound() {63Bound::Included(end) => *end,64Bound::Excluded(end) => end.checked_sub(1)?,65Bound::Unbounded => usize::MAX,66};6768if last < first {69return None;70}7172Some((first, last))73}7475impl<T: ForeignOwnable> MapleTree<T> {76/// Create a new maple tree.77///78/// The tree will use the regular implementation with a higher branching factor, rather than79/// the allocation tree.80#[inline]81pub fn new() -> impl PinInit<Self> {82pin_init!(MapleTree {83// SAFETY: This initializes a maple tree into a pinned slot. The maple tree will be84// destroyed in Drop before the memory location becomes invalid.85tree <- Opaque::ffi_init(|slot| unsafe { bindings::mt_init_flags(slot, 0) }),86_p: PhantomData,87})88}8990/// Insert the value at the given index.91///92/// # Errors93///94/// If the maple tree already contains a range using the given index, then this call will95/// return an [`InsertErrorKind::Occupied`]. It may also fail if memory allocation fails.96///97/// # Examples98///99/// ```100/// use kernel::maple_tree::{InsertErrorKind, MapleTree};101///102/// let tree = KBox::pin_init(MapleTree::<KBox<i32>>::new(), GFP_KERNEL)?;103///104/// let ten = KBox::new(10, GFP_KERNEL)?;105/// let twenty = KBox::new(20, GFP_KERNEL)?;106/// let the_answer = KBox::new(42, GFP_KERNEL)?;107///108/// // These calls will succeed.109/// tree.insert(100, ten, GFP_KERNEL)?;110/// tree.insert(101, twenty, GFP_KERNEL)?;111///112/// // This will fail because the index is already in use.113/// assert_eq!(114/// tree.insert(100, the_answer, GFP_KERNEL).unwrap_err().cause,115/// InsertErrorKind::Occupied,116/// );117/// # Ok::<_, Error>(())118/// ```119#[inline]120pub fn insert(&self, index: usize, value: T, gfp: Flags) -> Result<(), InsertError<T>> {121self.insert_range(index..=index, value, gfp)122}123124/// Insert a value to the specified range, failing on overlap.125///126/// This accepts the usual types of Rust ranges using the `..` and `..=` syntax for exclusive127/// and inclusive ranges respectively. The range must not be empty, and must not overlap with128/// any existing range.129///130/// # Errors131///132/// If the maple tree already contains an overlapping range, then this call will return an133/// [`InsertErrorKind::Occupied`]. It may also fail if memory allocation fails or if the134/// requested range is invalid (e.g. empty).135///136/// # Examples137///138/// ```139/// use kernel::maple_tree::{InsertErrorKind, MapleTree};140///141/// let tree = KBox::pin_init(MapleTree::<KBox<i32>>::new(), GFP_KERNEL)?;142///143/// let ten = KBox::new(10, GFP_KERNEL)?;144/// let twenty = KBox::new(20, GFP_KERNEL)?;145/// let the_answer = KBox::new(42, GFP_KERNEL)?;146/// let hundred = KBox::new(100, GFP_KERNEL)?;147///148/// // Insert the value 10 at the indices 100 to 499.149/// tree.insert_range(100..500, ten, GFP_KERNEL)?;150///151/// // Insert the value 20 at the indices 500 to 1000.152/// tree.insert_range(500..=1000, twenty, GFP_KERNEL)?;153///154/// // This will fail due to overlap with the previous range on index 1000.155/// assert_eq!(156/// tree.insert_range(1000..1200, the_answer, GFP_KERNEL).unwrap_err().cause,157/// InsertErrorKind::Occupied,158/// );159///160/// // When using .. to specify the range, you must be careful to ensure that the range is161/// // non-empty.162/// assert_eq!(163/// tree.insert_range(72..72, hundred, GFP_KERNEL).unwrap_err().cause,164/// InsertErrorKind::InvalidRequest,165/// );166/// # Ok::<_, Error>(())167/// ```168pub fn insert_range<R>(&self, range: R, value: T, gfp: Flags) -> Result<(), InsertError<T>>169where170R: RangeBounds<usize>,171{172let Some((first, last)) = to_maple_range(range) else {173return Err(InsertError {174value,175cause: InsertErrorKind::InvalidRequest,176});177};178179let ptr = T::into_foreign(value);180181// SAFETY: The tree is valid, and we are passing a pointer to an owned instance of `T`.182let res = to_result(unsafe {183bindings::mtree_insert_range(self.tree.get(), first, last, ptr, gfp.as_raw())184});185186if let Err(err) = res {187// SAFETY: As `mtree_insert_range` failed, it is safe to take back ownership.188let value = unsafe { T::from_foreign(ptr) };189190let cause = if err == ENOMEM {191InsertErrorKind::AllocError(kernel::alloc::AllocError)192} else if err == EEXIST {193InsertErrorKind::Occupied194} else {195InsertErrorKind::InvalidRequest196};197Err(InsertError { value, cause })198} else {199Ok(())200}201}202203/// Erase the range containing the given index.204///205/// # Examples206///207/// ```208/// use kernel::maple_tree::MapleTree;209///210/// let tree = KBox::pin_init(MapleTree::<KBox<i32>>::new(), GFP_KERNEL)?;211///212/// let ten = KBox::new(10, GFP_KERNEL)?;213/// let twenty = KBox::new(20, GFP_KERNEL)?;214///215/// tree.insert_range(100..500, ten, GFP_KERNEL)?;216/// tree.insert(67, twenty, GFP_KERNEL)?;217///218/// assert_eq!(tree.erase(67).map(|v| *v), Some(20));219/// assert_eq!(tree.erase(275).map(|v| *v), Some(10));220///221/// // The previous call erased the entire range, not just index 275.222/// assert!(tree.erase(127).is_none());223/// # Ok::<_, Error>(())224/// ```225#[inline]226pub fn erase(&self, index: usize) -> Option<T> {227// SAFETY: `self.tree` contains a valid maple tree.228let ret = unsafe { bindings::mtree_erase(self.tree.get(), index) };229230// SAFETY: If the pointer is not null, then we took ownership of a valid instance of `T`231// from the tree.232unsafe { T::try_from_foreign(ret) }233}234235/// Lock the internal spinlock.236#[inline]237pub fn lock(&self) -> MapleGuard<'_, T> {238// SAFETY: It's safe to lock the spinlock in a maple tree.239unsafe { bindings::spin_lock(self.ma_lock()) };240241// INVARIANT: We just took the spinlock.242MapleGuard(self)243}244245#[inline]246fn ma_lock(&self) -> *mut bindings::spinlock_t {247// SAFETY: This pointer offset operation stays in-bounds.248let lock_ptr = unsafe { &raw mut (*self.tree.get()).__bindgen_anon_1.ma_lock };249lock_ptr.cast()250}251252/// Free all `T` instances in this tree.253///254/// # Safety255///256/// This frees Rust data referenced by the maple tree without removing it from the maple tree,257/// leaving it in an invalid state. The caller must ensure that this invalid state cannot be258/// observed by the end-user.259unsafe fn free_all_entries(self: Pin<&mut Self>) {260// SAFETY: The caller provides exclusive access to the entire maple tree, so we have261// exclusive access to the entire maple tree despite not holding the lock.262let mut ma_state = unsafe { MaState::new_raw(self.into_ref().get_ref(), 0, usize::MAX) };263264loop {265// This uses the raw accessor because we're destroying pointers without removing them266// from the maple tree, which is only valid because this is the destructor.267//268// Take the rcu lock because mas_find_raw() requires that you hold either the spinlock269// or the rcu read lock. This is only really required if memory reclaim might270// reallocate entries in the tree, as we otherwise have exclusive access. That feature271// doesn't exist yet, so for now, taking the rcu lock only serves the purpose of272// silencing lockdep.273let ptr = {274let _rcu = kernel::sync::rcu::Guard::new();275ma_state.mas_find_raw(usize::MAX)276};277if ptr.is_null() {278break;279}280// SAFETY: By the type invariants, this pointer references a valid value of type `T`.281// By the safety requirements, it is okay to free it without removing it from the maple282// tree.283drop(unsafe { T::from_foreign(ptr) });284}285}286}287288#[pinned_drop]289impl<T: ForeignOwnable> PinnedDrop for MapleTree<T> {290#[inline]291fn drop(mut self: Pin<&mut Self>) {292// We only iterate the tree if the Rust value has a destructor.293if core::mem::needs_drop::<T>() {294// SAFETY: Other than the below `mtree_destroy` call, the tree will not be accessed295// after this call.296unsafe { self.as_mut().free_all_entries() };297}298299// SAFETY: The tree is valid, and will not be accessed after this call.300unsafe { bindings::mtree_destroy(self.tree.get()) };301}302}303304/// A reference to a [`MapleTree`] that owns the inner lock.305///306/// # Invariants307///308/// This guard owns the inner spinlock.309#[must_use = "if unused, the lock will be immediately unlocked"]310pub struct MapleGuard<'tree, T: ForeignOwnable>(&'tree MapleTree<T>);311312impl<'tree, T: ForeignOwnable> Drop for MapleGuard<'tree, T> {313#[inline]314fn drop(&mut self) {315// SAFETY: By the type invariants, we hold this spinlock.316unsafe { bindings::spin_unlock(self.0.ma_lock()) };317}318}319320impl<'tree, T: ForeignOwnable> MapleGuard<'tree, T> {321/// Create a [`MaState`] protected by this lock guard.322pub fn ma_state(&mut self, first: usize, end: usize) -> MaState<'_, T> {323// SAFETY: The `MaState` borrows this `MapleGuard`, so it can also borrow the `MapleGuard`s324// read/write permissions to the maple tree.325unsafe { MaState::new_raw(self.0, first, end) }326}327328/// Load the value at the given index.329///330/// # Examples331///332/// Read the value while holding the spinlock.333///334/// ```335/// use kernel::maple_tree::MapleTree;336///337/// let tree = KBox::pin_init(MapleTree::<KBox<i32>>::new(), GFP_KERNEL)?;338///339/// let ten = KBox::new(10, GFP_KERNEL)?;340/// let twenty = KBox::new(20, GFP_KERNEL)?;341/// tree.insert(100, ten, GFP_KERNEL)?;342/// tree.insert(200, twenty, GFP_KERNEL)?;343///344/// let mut lock = tree.lock();345/// assert_eq!(lock.load(100).map(|v| *v), Some(10));346/// assert_eq!(lock.load(200).map(|v| *v), Some(20));347/// assert_eq!(lock.load(300).map(|v| *v), None);348/// # Ok::<_, Error>(())349/// ```350///351/// Increment refcount under the lock, to keep value alive afterwards.352///353/// ```354/// use kernel::maple_tree::MapleTree;355/// use kernel::sync::Arc;356///357/// let tree = KBox::pin_init(MapleTree::<Arc<i32>>::new(), GFP_KERNEL)?;358///359/// let ten = Arc::new(10, GFP_KERNEL)?;360/// let twenty = Arc::new(20, GFP_KERNEL)?;361/// tree.insert(100, ten, GFP_KERNEL)?;362/// tree.insert(200, twenty, GFP_KERNEL)?;363///364/// // Briefly take the lock to increment the refcount.365/// let value = tree.lock().load(100).map(Arc::from);366///367/// // At this point, another thread might remove the value.368/// tree.erase(100);369///370/// // But we can still access it because we took a refcount.371/// assert_eq!(value.map(|v| *v), Some(10));372/// # Ok::<_, Error>(())373/// ```374#[inline]375pub fn load(&mut self, index: usize) -> Option<T::BorrowedMut<'_>> {376// SAFETY: `self.tree` contains a valid maple tree.377let ret = unsafe { bindings::mtree_load(self.0.tree.get(), index) };378if ret.is_null() {379return None;380}381382// SAFETY: If the pointer is not null, then it references a valid instance of `T`. It is383// safe to borrow the instance mutably because the signature of this function enforces that384// the mutable borrow is not used after the spinlock is dropped.385Some(unsafe { T::borrow_mut(ret) })386}387}388389impl<T: ForeignOwnable> MapleTreeAlloc<T> {390/// Create a new allocation tree.391pub fn new() -> impl PinInit<Self> {392let tree = pin_init!(MapleTree {393// SAFETY: This initializes a maple tree into a pinned slot. The maple tree will be394// destroyed in Drop before the memory location becomes invalid.395tree <- Opaque::ffi_init(|slot| unsafe {396bindings::mt_init_flags(slot, bindings::MT_FLAGS_ALLOC_RANGE)397}),398_p: PhantomData,399});400401pin_init!(MapleTreeAlloc { tree <- tree })402}403404/// Insert an entry with the given size somewhere in the given range.405///406/// The maple tree will search for a location in the given range where there is space to insert407/// the new range. If there is not enough available space, then an error will be returned.408///409/// The index of the new range is returned.410///411/// # Examples412///413/// ```414/// use kernel::maple_tree::{MapleTreeAlloc, AllocErrorKind};415///416/// let tree = KBox::pin_init(MapleTreeAlloc::<KBox<i32>>::new(), GFP_KERNEL)?;417///418/// let ten = KBox::new(10, GFP_KERNEL)?;419/// let twenty = KBox::new(20, GFP_KERNEL)?;420/// let thirty = KBox::new(30, GFP_KERNEL)?;421/// let hundred = KBox::new(100, GFP_KERNEL)?;422///423/// // Allocate three ranges.424/// let idx1 = tree.alloc_range(100, ten, ..1000, GFP_KERNEL)?;425/// let idx2 = tree.alloc_range(100, twenty, ..1000, GFP_KERNEL)?;426/// let idx3 = tree.alloc_range(100, thirty, ..1000, GFP_KERNEL)?;427///428/// assert_eq!(idx1, 0);429/// assert_eq!(idx2, 100);430/// assert_eq!(idx3, 200);431///432/// // This will fail because the remaining space is too small.433/// assert_eq!(434/// tree.alloc_range(800, hundred, ..1000, GFP_KERNEL).unwrap_err().cause,435/// AllocErrorKind::Busy,436/// );437/// # Ok::<_, Error>(())438/// ```439pub fn alloc_range<R>(440&self,441size: usize,442value: T,443range: R,444gfp: Flags,445) -> Result<usize, AllocError<T>>446where447R: RangeBounds<usize>,448{449let Some((min, max)) = to_maple_range(range) else {450return Err(AllocError {451value,452cause: AllocErrorKind::InvalidRequest,453});454};455456let ptr = T::into_foreign(value);457let mut index = 0;458459// SAFETY: The tree is valid, and we are passing a pointer to an owned instance of `T`.460let res = to_result(unsafe {461bindings::mtree_alloc_range(462self.tree.tree.get(),463&mut index,464ptr,465size,466min,467max,468gfp.as_raw(),469)470});471472if let Err(err) = res {473// SAFETY: As `mtree_alloc_range` failed, it is safe to take back ownership.474let value = unsafe { T::from_foreign(ptr) };475476let cause = if err == ENOMEM {477AllocErrorKind::AllocError(kernel::alloc::AllocError)478} else if err == EBUSY {479AllocErrorKind::Busy480} else {481AllocErrorKind::InvalidRequest482};483Err(AllocError { value, cause })484} else {485Ok(index)486}487}488}489490/// A helper type used for navigating a [`MapleTree`].491///492/// # Invariants493///494/// For the duration of `'tree`:495///496/// * The `ma_state` references a valid `MapleTree<T>`.497/// * The `ma_state` has read/write access to the tree.498pub struct MaState<'tree, T: ForeignOwnable> {499state: bindings::ma_state,500_phantom: PhantomData<&'tree mut MapleTree<T>>,501}502503impl<'tree, T: ForeignOwnable> MaState<'tree, T> {504/// Initialize a new `MaState` with the given tree.505///506/// # Safety507///508/// The caller must ensure that this `MaState` has read/write access to the maple tree.509#[inline]510unsafe fn new_raw(mt: &'tree MapleTree<T>, first: usize, end: usize) -> Self {511// INVARIANT:512// * Having a reference ensures that the `MapleTree<T>` is valid for `'tree`.513// * The caller ensures that we have read/write access.514Self {515state: bindings::ma_state {516tree: mt.tree.get(),517index: first,518last: end,519node: ptr::null_mut(),520status: bindings::maple_status_ma_start,521min: 0,522max: usize::MAX,523alloc: ptr::null_mut(),524mas_flags: 0,525store_type: bindings::store_type_wr_invalid,526..Default::default()527},528_phantom: PhantomData,529}530}531532#[inline]533fn as_raw(&mut self) -> *mut bindings::ma_state {534&raw mut self.state535}536537#[inline]538fn mas_find_raw(&mut self, max: usize) -> *mut c_void {539// SAFETY: By the type invariants, the `ma_state` is active and we have read/write access540// to the tree.541unsafe { bindings::mas_find(self.as_raw(), max) }542}543544/// Find the next entry in the maple tree.545///546/// # Examples547///548/// Iterate the maple tree.549///550/// ```551/// use kernel::maple_tree::MapleTree;552/// use kernel::sync::Arc;553///554/// let tree = KBox::pin_init(MapleTree::<Arc<i32>>::new(), GFP_KERNEL)?;555///556/// let ten = Arc::new(10, GFP_KERNEL)?;557/// let twenty = Arc::new(20, GFP_KERNEL)?;558/// tree.insert(100, ten, GFP_KERNEL)?;559/// tree.insert(200, twenty, GFP_KERNEL)?;560///561/// let mut ma_lock = tree.lock();562/// let mut iter = ma_lock.ma_state(0, usize::MAX);563///564/// assert_eq!(iter.find(usize::MAX).map(|v| *v), Some(10));565/// assert_eq!(iter.find(usize::MAX).map(|v| *v), Some(20));566/// assert!(iter.find(usize::MAX).is_none());567/// # Ok::<_, Error>(())568/// ```569#[inline]570pub fn find(&mut self, max: usize) -> Option<T::BorrowedMut<'_>> {571let ret = self.mas_find_raw(max);572if ret.is_null() {573return None;574}575576// SAFETY: If the pointer is not null, then it references a valid instance of `T`. It's577// safe to access it mutably as the returned reference borrows this `MaState`, and the578// `MaState` has read/write access to the maple tree.579Some(unsafe { T::borrow_mut(ret) })580}581}582583/// Error type for failure to insert a new value.584pub struct InsertError<T> {585/// The value that could not be inserted.586pub value: T,587/// The reason for the failure to insert.588pub cause: InsertErrorKind,589}590591/// The reason for the failure to insert.592#[derive(PartialEq, Eq, Copy, Clone, Debug)]593pub enum InsertErrorKind {594/// There is already a value in the requested range.595Occupied,596/// Failure to allocate memory.597AllocError(kernel::alloc::AllocError),598/// The insertion request was invalid.599InvalidRequest,600}601602impl From<InsertErrorKind> for Error {603#[inline]604fn from(kind: InsertErrorKind) -> Error {605match kind {606InsertErrorKind::Occupied => EEXIST,607InsertErrorKind::AllocError(kernel::alloc::AllocError) => ENOMEM,608InsertErrorKind::InvalidRequest => EINVAL,609}610}611}612613impl<T> From<InsertError<T>> for Error {614#[inline]615fn from(insert_err: InsertError<T>) -> Error {616Error::from(insert_err.cause)617}618}619620/// Error type for failure to insert a new value.621pub struct AllocError<T> {622/// The value that could not be inserted.623pub value: T,624/// The reason for the failure to insert.625pub cause: AllocErrorKind,626}627628/// The reason for the failure to insert.629#[derive(PartialEq, Eq, Copy, Clone)]630pub enum AllocErrorKind {631/// There is not enough space for the requested allocation.632Busy,633/// Failure to allocate memory.634AllocError(kernel::alloc::AllocError),635/// The insertion request was invalid.636InvalidRequest,637}638639impl From<AllocErrorKind> for Error {640#[inline]641fn from(kind: AllocErrorKind) -> Error {642match kind {643AllocErrorKind::Busy => EBUSY,644AllocErrorKind::AllocError(kernel::alloc::AllocError) => ENOMEM,645AllocErrorKind::InvalidRequest => EINVAL,646}647}648}649650impl<T> From<AllocError<T>> for Error {651#[inline]652fn from(insert_err: AllocError<T>) -> Error {653Error::from(insert_err.cause)654}655}656657658