summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/alloc.rs4
-rw-r--r--rust/kernel/alloc/allocator_test.rs2
-rw-r--r--rust/kernel/alloc/kbox.rs80
-rw-r--r--rust/kernel/alloc/kvec.rs433
-rw-r--r--rust/kernel/alloc/kvec/errors.rs61
-rw-r--r--rust/kernel/auxiliary.rs8
-rw-r--r--rust/kernel/block/mq/gen_disk.rs2
-rw-r--r--rust/kernel/configfs.rs4
-rw-r--r--rust/kernel/cpufreq.rs4
-rw-r--r--rust/kernel/device.rs26
-rw-r--r--rust/kernel/device_id.rs4
-rw-r--r--rust/kernel/dma.rs2
-rw-r--r--rust/kernel/drm/device.rs2
-rw-r--r--rust/kernel/drm/gem/mod.rs6
-rw-r--r--rust/kernel/fs/file.rs10
-rw-r--r--rust/kernel/kunit.rs37
-rw-r--r--rust/kernel/lib.rs45
-rw-r--r--rust/kernel/list.rs115
-rw-r--r--rust/kernel/list/arc.rs6
-rw-r--r--rust/kernel/miscdevice.rs12
-rw-r--r--rust/kernel/mm.rs56
-rw-r--r--rust/kernel/mm/mmput_async.rs68
-rw-r--r--rust/kernel/page.rs2
-rw-r--r--rust/kernel/pci.rs17
-rw-r--r--rust/kernel/platform.rs11
-rw-r--r--rust/kernel/prelude.rs7
-rw-r--r--rust/kernel/print.rs27
-rw-r--r--rust/kernel/rbtree.rs23
-rw-r--r--rust/kernel/static_assert.rs9
-rw-r--r--rust/kernel/std_vendor.rs2
-rw-r--r--rust/kernel/str.rs82
-rw-r--r--rust/kernel/sync/arc.rs25
-rw-r--r--rust/kernel/time.rs167
-rw-r--r--rust/kernel/time/hrtimer.rs24
-rw-r--r--rust/kernel/time/hrtimer/arc.rs2
-rw-r--r--rust/kernel/time/hrtimer/pin.rs2
-rw-r--r--rust/kernel/time/hrtimer/pin_mut.rs4
-rw-r--r--rust/kernel/time/hrtimer/tbox.rs2
-rw-r--r--rust/kernel/types.rs46
-rw-r--r--rust/kernel/uaccess.rs6
-rw-r--r--rust/kernel/workqueue.rs50
-rw-r--r--rust/kernel/xarray.rs275
42 files changed, 1412 insertions, 358 deletions
diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
index fc9c9c41cd79..a2c49e5494d3 100644
--- a/rust/kernel/alloc.rs
+++ b/rust/kernel/alloc.rs
@@ -94,10 +94,10 @@ pub mod flags {
///
/// A lower watermark is applied to allow access to "atomic reserves". The current
/// implementation doesn't support NMI and few other strict non-preemptive contexts (e.g.
- /// raw_spin_lock). The same applies to [`GFP_NOWAIT`].
+ /// `raw_spin_lock`). The same applies to [`GFP_NOWAIT`].
pub const GFP_ATOMIC: Flags = Flags(bindings::GFP_ATOMIC);
- /// Typical for kernel-internal allocations. The caller requires ZONE_NORMAL or a lower zone
+ /// Typical for kernel-internal allocations. The caller requires `ZONE_NORMAL` or a lower zone
/// for direct access but can direct reclaim.
pub const GFP_KERNEL: Flags = Flags(bindings::GFP_KERNEL);
diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/allocator_test.rs
index c37d4c0c64e9..d19c06ef0498 100644
--- a/rust/kernel/alloc/allocator_test.rs
+++ b/rust/kernel/alloc/allocator_test.rs
@@ -4,7 +4,7 @@
//! of those types (e.g. `CString`) use kernel allocators for instantiation.
//!
//! In order to allow userspace test cases to make use of such types as well, implement the
-//! `Cmalloc` allocator within the allocator_test module and type alias all kernel allocators to
+//! `Cmalloc` allocator within the `allocator_test` module and type alias all kernel allocators to
//! `Cmalloc`. The `Cmalloc` allocator uses libc's `realloc()` function as allocator backend.
#![allow(missing_docs)]
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index b77d32f3a58b..c386ff771d50 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -57,12 +57,50 @@ use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
/// assert!(KVBox::<Huge>::new_uninit(GFP_KERNEL).is_ok());
/// ```
///
+/// [`Box`]es can also be used to store trait objects by coercing their type:
+///
+/// ```
+/// trait FooTrait {}
+///
+/// struct FooStruct;
+/// impl FooTrait for FooStruct {}
+///
+/// let _ = KBox::new(FooStruct, GFP_KERNEL)? as KBox<dyn FooTrait>;
+/// # Ok::<(), Error>(())
+/// ```
+///
/// # Invariants
///
/// `self.0` is always properly aligned and either points to memory allocated with `A` or, for
/// zero-sized types, is a dangling, well aligned pointer.
#[repr(transparent)]
-pub struct Box<T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
+#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
+pub struct Box<#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, pointee)] T: ?Sized, A: Allocator>(
+ NonNull<T>,
+ PhantomData<A>,
+);
+
+// This is to allow coercion from `Box<T, A>` to `Box<U, A>` if `T` can be converted to the
+// dynamically-sized type (DST) `U`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T, U, A> core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
+where
+ T: ?Sized + core::marker::Unsize<U>,
+ U: ?Sized,
+ A: Allocator,
+{
+}
+
+// This is to allow `Box<U, A>` to be dispatched on when `Box<T, A>` can be coerced into `Box<U,
+// A>`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T, U, A> core::ops::DispatchFromDyn<Box<U, A>> for Box<T, A>
+where
+ T: ?Sized + core::marker::Unsize<U>,
+ U: ?Sized,
+ A: Allocator,
+{
+}
/// Type alias for [`Box`] with a [`Kmalloc`] allocator.
///
@@ -101,7 +139,7 @@ pub type VBox<T> = Box<T, super::allocator::Vmalloc>;
pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
-// https://doc.rust-lang.org/stable/std/option/index.html#representation).
+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
unsafe impl<T, A: Allocator> ZeroableOption for Box<T, A> {}
// SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`.
@@ -360,68 +398,70 @@ where
}
}
-impl<T: 'static, A> ForeignOwnable for Box<T, A>
+// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
+unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>
where
A: Allocator,
{
+ type PointedTo = T;
type Borrowed<'a> = &'a T;
type BorrowedMut<'a> = &'a mut T;
- fn into_foreign(self) -> *mut crate::ffi::c_void {
- Box::into_raw(self).cast()
+ fn into_foreign(self) -> *mut Self::PointedTo {
+ Box::into_raw(self)
}
- unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
+ unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
- unsafe { Box::from_raw(ptr.cast()) }
+ unsafe { Box::from_raw(ptr) }
}
- unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> &'a T {
+ unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> &'a T {
// SAFETY: The safety requirements of this method ensure that the object remains alive and
// immutable for the duration of 'a.
- unsafe { &*ptr.cast() }
+ unsafe { &*ptr }
}
- unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> &'a mut T {
- let ptr = ptr.cast();
+ unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> &'a mut T {
// SAFETY: The safety requirements of this method ensure that the pointer is valid and that
// nothing else will access the value for the duration of 'a.
unsafe { &mut *ptr }
}
}
-impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
+// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
+unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
where
A: Allocator,
{
+ type PointedTo = T;
type Borrowed<'a> = Pin<&'a T>;
type BorrowedMut<'a> = Pin<&'a mut T>;
- fn into_foreign(self) -> *mut crate::ffi::c_void {
+ fn into_foreign(self) -> *mut Self::PointedTo {
// SAFETY: We are still treating the box as pinned.
- Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast()
+ Box::into_raw(unsafe { Pin::into_inner_unchecked(self) })
}
- unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
+ unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
- unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }
+ unsafe { Pin::new_unchecked(Box::from_raw(ptr)) }
}
- unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a T> {
+ unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a T> {
// SAFETY: The safety requirements for this function ensure that the object is still alive,
// so it is safe to dereference the raw pointer.
// The safety requirements of `from_foreign` also ensure that the object remains alive for
// the lifetime of the returned value.
- let r = unsafe { &*ptr.cast() };
+ let r = unsafe { &*ptr };
// SAFETY: This pointer originates from a `Pin<Box<T>>`.
unsafe { Pin::new_unchecked(r) }
}
- unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a mut T> {
- let ptr = ptr.cast();
+ unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a mut T> {
// SAFETY: The safety requirements for this function ensure that the object is still alive,
// so it is safe to dereference the raw pointer.
// The safety requirements of `from_foreign` also ensure that the object remains alive for
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index 87a71fd40c3c..1a0dd852a468 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -2,9 +2,6 @@
//! Implementation of [`Vec`].
-// May not be needed in Rust 1.87.0 (pending beta backport).
-#![allow(clippy::ptr_eq)]
-
use super::{
allocator::{KVmalloc, Kmalloc, Vmalloc},
layout::ArrayLayout,
@@ -24,6 +21,9 @@ use core::{
slice::SliceIndex,
};
+mod errors;
+pub use self::errors::{InsertError, PushError, RemoveError};
+
/// Create a [`KVec`] containing the arguments.
///
/// New memory is allocated with `GFP_KERNEL`.
@@ -93,6 +93,8 @@ macro_rules! kvec {
/// without re-allocation. For ZSTs `self.layout`'s capacity is zero. However, it is legal for the
/// backing buffer to be larger than `layout`.
///
+/// - `self.len()` is always less than or equal to `self.capacity()`.
+///
/// - The `Allocator` type `A` of the vector is the exact same `Allocator` type the backing buffer
/// was allocated with (and must be freed with).
pub struct Vec<T, A: Allocator> {
@@ -186,17 +188,38 @@ where
self.len
}
- /// Forcefully sets `self.len` to `new_len`.
+ /// Increments `self.len` by `additional`.
///
/// # Safety
///
- /// - `new_len` must be less than or equal to [`Self::capacity`].
- /// - If `new_len` is greater than `self.len`, all elements within the interval
- /// [`self.len`,`new_len`) must be initialized.
+ /// - `additional` must be less than or equal to `self.capacity - self.len`.
+ /// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized.
#[inline]
- pub unsafe fn set_len(&mut self, new_len: usize) {
- debug_assert!(new_len <= self.capacity());
- self.len = new_len;
+ pub unsafe fn inc_len(&mut self, additional: usize) {
+ // Guaranteed by the type invariant to never underflow.
+ debug_assert!(additional <= self.capacity() - self.len());
+ // INVARIANT: By the safety requirements of this method this represents the exact number of
+ // elements stored within `self`.
+ self.len += additional;
+ }
+
+ /// Decreases `self.len` by `count`.
+ ///
+ /// Returns a mutable slice to the elements forgotten by the vector. It is the caller's
+ /// responsibility to drop these elements if necessary.
+ ///
+ /// # Safety
+ ///
+ /// - `count` must be less than or equal to `self.len`.
+ unsafe fn dec_len(&mut self, count: usize) -> &mut [T] {
+ debug_assert!(count <= self.len());
+ // INVARIANT: We relinquish ownership of the elements within the range `[self.len - count,
+ // self.len)`, hence the updated value of `set.len` represents the exact number of elements
+ // stored within `self`.
+ self.len -= count;
+ // SAFETY: The memory after `self.len()` is guaranteed to contain `count` initialized
+ // elements of type `T`.
+ unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().add(self.len), count) }
}
/// Returns a slice of the entire vector.
@@ -262,8 +285,8 @@ where
/// Returns a slice of `MaybeUninit<T>` for the remaining spare capacity of the vector.
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
// SAFETY:
- // - `self.len` is smaller than `self.capacity` and hence, the resulting pointer is
- // guaranteed to be part of the same allocated object.
+ // - `self.len` is smaller than `self.capacity` by the type invariant and hence, the
+ // resulting pointer is guaranteed to be part of the same allocated object.
// - `self.len` can not overflow `isize`.
let ptr = unsafe { self.as_mut_ptr().add(self.len) } as *mut MaybeUninit<T>;
@@ -287,24 +310,170 @@ where
/// ```
pub fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> {
self.reserve(1, flags)?;
+ // SAFETY: The call to `reserve` was successful, so the capacity is at least one greater
+ // than the length.
+ unsafe { self.push_within_capacity_unchecked(v) };
+ Ok(())
+ }
- // SAFETY:
- // - `self.len` is smaller than `self.capacity` and hence, the resulting pointer is
- // guaranteed to be part of the same allocated object.
- // - `self.len` can not overflow `isize`.
- let ptr = unsafe { self.as_mut_ptr().add(self.len) };
+ /// Appends an element to the back of the [`Vec`] instance without reallocating.
+ ///
+ /// Fails if the vector does not have capacity for the new element.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = KVec::with_capacity(10, GFP_KERNEL)?;
+ /// for i in 0..10 {
+ /// v.push_within_capacity(i)?;
+ /// }
+ ///
+ /// assert!(v.push_within_capacity(10).is_err());
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn push_within_capacity(&mut self, v: T) -> Result<(), PushError<T>> {
+ if self.len() < self.capacity() {
+ // SAFETY: The length is less than the capacity.
+ unsafe { self.push_within_capacity_unchecked(v) };
+ Ok(())
+ } else {
+ Err(PushError(v))
+ }
+ }
- // SAFETY:
- // - `ptr` is properly aligned and valid for writes.
- unsafe { core::ptr::write(ptr, v) };
+ /// Appends an element to the back of the [`Vec`] instance without reallocating.
+ ///
+ /// # Safety
+ ///
+ /// The length must be less than the capacity.
+ unsafe fn push_within_capacity_unchecked(&mut self, v: T) {
+ let spare = self.spare_capacity_mut();
+
+ // SAFETY: By the safety requirements, `spare` is non-empty.
+ unsafe { spare.get_unchecked_mut(0) }.write(v);
// SAFETY: We just initialised the first spare entry, so it is safe to increase the length
- // by 1. We also know that the new length is <= capacity because of the previous call to
- // `reserve` above.
- unsafe { self.set_len(self.len() + 1) };
+ // by 1. We also know that the new length is <= capacity because the caller guarantees that
+ // the length is less than the capacity at the beginning of this function.
+ unsafe { self.inc_len(1) };
+ }
+
+ /// Inserts an element at the given index in the [`Vec`] instance.
+ ///
+ /// Fails if the vector does not have capacity for the new element. Panics if the index is out
+ /// of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::alloc::kvec::InsertError;
+ ///
+ /// let mut v = KVec::with_capacity(5, GFP_KERNEL)?;
+ /// for i in 0..5 {
+ /// v.insert_within_capacity(0, i)?;
+ /// }
+ ///
+ /// assert!(matches!(v.insert_within_capacity(0, 5), Err(InsertError::OutOfCapacity(_))));
+ /// assert!(matches!(v.insert_within_capacity(1000, 5), Err(InsertError::IndexOutOfBounds(_))));
+ /// assert_eq!(v, [4, 3, 2, 1, 0]);
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn insert_within_capacity(
+ &mut self,
+ index: usize,
+ element: T,
+ ) -> Result<(), InsertError<T>> {
+ let len = self.len();
+ if index > len {
+ return Err(InsertError::IndexOutOfBounds(element));
+ }
+
+ if len >= self.capacity() {
+ return Err(InsertError::OutOfCapacity(element));
+ }
+
+ // SAFETY: This is in bounds since `index <= len < capacity`.
+ let p = unsafe { self.as_mut_ptr().add(index) };
+ // INVARIANT: This breaks the Vec invariants by making `index` contain an invalid element,
+ // but we restore the invariants below.
+ // SAFETY: Both the src and dst ranges end no later than one element after the length.
+ // Since the length is less than the capacity, both ranges are in bounds of the allocation.
+ unsafe { ptr::copy(p, p.add(1), len - index) };
+ // INVARIANT: This restores the Vec invariants.
+ // SAFETY: The pointer is in-bounds of the allocation.
+ unsafe { ptr::write(p, element) };
+ // SAFETY: Index `len` contains a valid element due to the above copy and write.
+ unsafe { self.inc_len(1) };
Ok(())
}
+ /// Removes the last element from a vector and returns it, or `None` if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = KVec::new();
+ /// v.push(1, GFP_KERNEL)?;
+ /// v.push(2, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 2]);
+ ///
+ /// assert_eq!(v.pop(), Some(2));
+ /// assert_eq!(v.pop(), Some(1));
+ /// assert_eq!(v.pop(), None);
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn pop(&mut self) -> Option<T> {
+ if self.is_empty() {
+ return None;
+ }
+
+ let removed: *mut T = {
+ // SAFETY: We just checked that the length is at least one.
+ let slice = unsafe { self.dec_len(1) };
+ // SAFETY: The argument to `dec_len` was 1 so this returns a slice of length 1.
+ unsafe { slice.get_unchecked_mut(0) }
+ };
+
+ // SAFETY: The guarantees of `dec_len` allow us to take ownership of this value.
+ Some(unsafe { removed.read() })
+ }
+
+ /// Removes the element at the given index.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ /// assert_eq!(v.remove(1)?, 2);
+ /// assert_eq!(v, [1, 3]);
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn remove(&mut self, i: usize) -> Result<T, RemoveError> {
+ let value = {
+ let value_ref = self.get(i).ok_or(RemoveError)?;
+ // INVARIANT: This breaks the invariants by invalidating the value at index `i`, but we
+ // restore the invariants below.
+ // SAFETY: The value at index `i` is valid, because otherwise we would have already
+ // failed with `RemoveError`.
+ unsafe { ptr::read(value_ref) }
+ };
+
+ // SAFETY: We checked that `i` is in-bounds.
+ let p = unsafe { self.as_mut_ptr().add(i) };
+
+ // INVARIANT: After this call, the invalid value is at the last slot, so the Vec invariants
+ // are restored after the below call to `dec_len(1)`.
+ // SAFETY: `p.add(1).add(self.len - i - 1)` is `i+1+len-i-1 == len` elements after the
+ // beginning of the vector, so this is in-bounds of the vector's allocation.
+ unsafe { ptr::copy(p.add(1), p, self.len - i - 1) };
+
+ // SAFETY: Since the check at the beginning of this call did not fail with `RemoveError`,
+ // the length is at least one.
+ unsafe { self.dec_len(1) };
+
+ Ok(value)
+ }
+
/// Creates a new [`Vec`] instance with at least the given capacity.
///
/// # Examples
@@ -398,6 +567,26 @@ where
(ptr, len, capacity)
}
+ /// Clears the vector, removing all values.
+ ///
+ /// Note that this method has no effect on the allocated capacity
+ /// of the vector.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ ///
+ /// v.clear();
+ ///
+ /// assert!(v.is_empty());
+ /// # Ok::<(), Error>(())
+ /// ```
+ #[inline]
+ pub fn clear(&mut self) {
+ self.truncate(0);
+ }
+
/// Ensures that the capacity exceeds the length by at least `additional` elements.
///
/// # Examples
@@ -455,6 +644,80 @@ where
Ok(())
}
+
+ /// Shortens the vector, setting the length to `len` and drops the removed values.
+ /// If `len` is greater than or equal to the current length, this does nothing.
+ ///
+ /// This has no effect on the capacity and will not allocate.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ /// v.truncate(1);
+ /// assert_eq!(v.len(), 1);
+ /// assert_eq!(&v, &[1]);
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn truncate(&mut self, len: usize) {
+ if let Some(count) = self.len().checked_sub(len) {
+ // SAFETY: `count` is `self.len() - len` so it is guaranteed to be less than or
+ // equal to `self.len()`.
+ let ptr: *mut [T] = unsafe { self.dec_len(count) };
+
+ // SAFETY: the contract of `dec_len` guarantees that the elements in `ptr` are
+ // valid elements whose ownership has been transferred to the caller.
+ unsafe { ptr::drop_in_place(ptr) };
+ }
+ }
+
+ /// Takes ownership of all items in this vector without consuming the allocation.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![0, 1, 2, 3]?;
+ ///
+ /// for (i, j) in v.drain_all().enumerate() {
+ /// assert_eq!(i, j);
+ /// }
+ ///
+ /// assert!(v.capacity() >= 4);
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn drain_all(&mut self) -> DrainAll<'_, T> {
+ // SAFETY: This does not underflow the length.
+ let elems = unsafe { self.dec_len(self.len()) };
+ // INVARIANT: The first `len` elements of the spare capacity are valid values, and as we
+ // just set the length to zero, we may transfer ownership to the `DrainAll` object.
+ DrainAll {
+ elements: elems.iter_mut(),
+ }
+ }
+
+ /// Removes all elements that don't match the provided closure.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3, 4]?;
+ /// v.retain(|i| *i % 2 == 0);
+ /// assert_eq!(v, [2, 4]);
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn retain(&mut self, mut f: impl FnMut(&mut T) -> bool) {
+ let mut num_kept = 0;
+ let mut next_to_check = 0;
+ while let Some(to_check) = self.get_mut(next_to_check) {
+ if f(to_check) {
+ self.swap(num_kept, next_to_check);
+ num_kept += 1;
+ }
+ next_to_check += 1;
+ }
+ self.truncate(num_kept);
+ }
}
impl<T: Clone, A: Allocator> Vec<T, A> {
@@ -478,7 +741,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
// SAFETY:
// - `self.len() + n < self.capacity()` due to the call to reserve above,
// - the loop and the line above initialized the next `n` elements.
- unsafe { self.set_len(self.len() + n) };
+ unsafe { self.inc_len(n) };
Ok(())
}
@@ -509,7 +772,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
// the length by the same number.
// - `self.len() + other.len() <= self.capacity()` is guaranteed by the preceding `reserve`
// call.
- unsafe { self.set_len(self.len() + other.len()) };
+ unsafe { self.inc_len(other.len()) };
Ok(())
}
@@ -521,6 +784,33 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
Ok(v)
}
+
+ /// Resizes the [`Vec`] so that `len` is equal to `new_len`.
+ ///
+ /// If `new_len` is smaller than `len`, the `Vec` is [`Vec::truncate`]d.
+ /// If `new_len` is larger, each new slot is filled with clones of `value`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ /// v.resize(1, 42, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1]);
+ ///
+ /// v.resize(3, 42, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 42, 42]);
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn resize(&mut self, new_len: usize, value: T, flags: Flags) -> Result<(), AllocError> {
+ match new_len.checked_sub(self.len()) {
+ Some(n) => self.extend_with(n, value, flags),
+ None => {
+ self.truncate(new_len);
+ Ok(())
+ }
+ }
+ }
}
impl<T, A> Drop for Vec<T, A>
@@ -760,12 +1050,13 @@ where
unsafe { ptr::copy(ptr, buf.as_ptr(), len) };
ptr = buf.as_ptr();
- // SAFETY: `len` is guaranteed to be smaller than `self.layout.len()`.
+ // SAFETY: `len` is guaranteed to be smaller than `self.layout.len()` by the type
+ // invariant.
let layout = unsafe { ArrayLayout::<T>::new_unchecked(len) };
- // SAFETY: `buf` points to the start of the backing buffer and `len` is guaranteed to be
- // smaller than `cap`. Depending on `alloc` this operation may shrink the buffer or leaves
- // it as it is.
+ // SAFETY: `buf` points to the start of the backing buffer and `len` is guaranteed by
+ // the type invariant to be smaller than `cap`. Depending on `realloc` this operation
+ // may shrink the buffer or leave it as it is.
ptr = match unsafe {
A::realloc(Some(buf.cast()), layout.into(), old_layout.into(), flags)
} {
@@ -914,3 +1205,87 @@ where
}
}
}
+
+/// An iterator that owns all items in a vector, but does not own its allocation.
+///
+/// # Invariants
+///
+/// Every `&mut T` returned by the iterator references a `T` that the iterator may take ownership
+/// of.
+pub struct DrainAll<'vec, T> {
+ elements: slice::IterMut<'vec, T>,
+}
+
+impl<'vec, T> Iterator for DrainAll<'vec, T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ let elem: *mut T = self.elements.next()?;
+ // SAFETY: By the type invariants, we may take ownership of this value.
+ Some(unsafe { elem.read() })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.elements.size_hint()
+ }
+}
+
+impl<'vec, T> Drop for DrainAll<'vec, T> {
+ fn drop(&mut self) {
+ if core::mem::needs_drop::<T>() {
+ let iter = core::mem::take(&mut self.elements);
+ let ptr: *mut [T] = iter.into_slice();
+ // SAFETY: By the type invariants, we own these values so we may destroy them.
+ unsafe { ptr::drop_in_place(ptr) };
+ }
+ }
+}
+
+#[macros::kunit_tests(rust_kvec_kunit)]
+mod tests {
+ use super::*;
+ use crate::prelude::*;
+
+ #[test]
+ fn test_kvec_retain() {
+ /// Verify correctness for one specific function.
+ #[expect(clippy::needless_range_loop)]
+ fn verify(c: &[bool]) {
+ let mut vec1: KVec<usize> = KVec::with_capacity(c.len(), GFP_KERNEL).unwrap();
+ let mut vec2: KVec<usize> = KVec::with_capacity(c.len(), GFP_KERNEL).unwrap();
+
+ for i in 0..c.len() {
+ vec1.push_within_capacity(i).unwrap();
+ if c[i] {
+ vec2.push_within_capacity(i).unwrap();
+ }
+ }
+
+ vec1.retain(|i| c[*i]);
+
+ assert_eq!(vec1, vec2);
+ }
+
+ /// Add one to a binary integer represented as a boolean array.
+ fn add(value: &mut [bool]) {
+ let mut carry = true;
+ for v in value {
+ let new_v = carry != *v;
+ carry = carry && *v;
+ *v = new_v;
+ }
+ }
+
+ // This boolean array represents a function from index to boolean. We check that `retain`
+ // behaves correctly for all possible boolean arrays of every possible length less than
+ // ten.
+ let mut func = KVec::with_capacity(10, GFP_KERNEL).unwrap();
+ for len in 0..10 {
+ for _ in 0u32..1u32 << len {
+ verify(&func);
+ add(&mut func);
+ }
+ func.push_within_capacity(false).unwrap();
+ }
+ }
+}
diff --git a/rust/kernel/alloc/kvec/errors.rs b/rust/kernel/alloc/kvec/errors.rs
new file mode 100644
index 000000000000..348b8d27e102
--- /dev/null
+++ b/rust/kernel/alloc/kvec/errors.rs
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Errors for the [`Vec`] type.
+
+use core::fmt::{self, Debug, Formatter};
+use kernel::prelude::*;
+
+/// Error type for [`Vec::push_within_capacity`].
+pub struct PushError<T>(pub T);
+
+impl<T> Debug for PushError<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "Not enough capacity")
+ }
+}
+
+impl<T> From<PushError<T>> for Error {
+ fn from(_: PushError<T>) -> Error {
+ // Returning ENOMEM isn't appropriate because the system is not out of memory. The vector
+ // is just full and we are refusing to resize it.
+ EINVAL
+ }
+}
+
+/// Error type for [`Vec::remove`].
+pub struct RemoveError;
+
+impl Debug for RemoveError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "Index out of bounds")
+ }
+}
+
+impl From<RemoveError> for Error {
+ fn from(_: RemoveError) -> Error {
+ EINVAL
+ }
+}
+
+/// Error type for [`Vec::insert_within_capacity`].
+pub enum InsertError<T> {
+ /// The value could not be inserted because the index is out of bounds.
+ IndexOutOfBounds(T),
+ /// The value could not be inserted because the vector is out of capacity.
+ OutOfCapacity(T),
+}
+
+impl<T> Debug for InsertError<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match self {
+ InsertError::IndexOutOfBounds(_) => write!(f, "Index out of bounds"),
+ InsertError::OutOfCapacity(_) => write!(f, "Not enough capacity"),
+ }
+ }
+}
+
+impl<T> From<InsertError<T>> for Error {
+ fn from(_: InsertError<T>) -> Error {
+ EINVAL
+ }
+}
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 5c072960dee0..d2cfe1eeefb6 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -73,7 +73,9 @@ impl<T: Driver + 'static> Adapter<T> {
// Let the `struct auxiliary_device` own a reference of the driver's private data.
// SAFETY: By the type invariant `adev.as_raw` returns a valid pointer to a
// `struct auxiliary_device`.
- unsafe { bindings::auxiliary_set_drvdata(adev.as_raw(), data.into_foreign()) };
+ unsafe {
+ bindings::auxiliary_set_drvdata(adev.as_raw(), data.into_foreign().cast())
+ };
}
Err(err) => return Error::to_errno(err),
}
@@ -89,7 +91,7 @@ impl<T: Driver + 'static> Adapter<T> {
// SAFETY: `remove_callback` is only ever called after a successful call to
// `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
// `KBox<T>` pointer created through `KBox::into_foreign`.
- drop(unsafe { KBox::<T>::from_foreign(ptr) });
+ drop(unsafe { KBox::<T>::from_foreign(ptr.cast()) });
}
}
@@ -234,7 +236,7 @@ impl Device {
extern "C" fn release(dev: *mut bindings::device) {
// SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device`
// embedded in `struct auxiliary_device`.
- let adev = unsafe { container_of!(dev, bindings::auxiliary_device, dev) }.cast_mut();
+ let adev = unsafe { container_of!(dev, bindings::auxiliary_device, dev) };
// SAFETY: `adev` points to the memory that has been allocated in `Registration::new`, via
// `KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)`.
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 14806e1997fd..cd54cd64ea88 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -129,7 +129,7 @@ impl GenDiskBuilder {
get_unique_id: None,
// TODO: Set to THIS_MODULE. Waiting for const_refs_to_static feature to
// be merged (unstable in rustc 1.78 which is staged for linux 6.10)
- // https://github.com/rust-lang/rust/issues/119618
+ // <https://github.com/rust-lang/rust/issues/119618>
owner: core::ptr::null_mut(),
pr_ops: core::ptr::null_mut(),
free_disk: None,
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index b93ac7b0bebc..34d0bea4f9a5 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -554,7 +554,7 @@ where
let c_group: *mut bindings::config_group =
// SAFETY: By function safety requirements, `item` is embedded in a
// `config_group`.
- unsafe { container_of!(item, bindings::config_group, cg_item) }.cast_mut();
+ unsafe { container_of!(item, bindings::config_group, cg_item) };
// SAFETY: The function safety requirements for this function satisfy
// the conditions for this call.
@@ -588,7 +588,7 @@ where
let c_group: *mut bindings::config_group =
// SAFETY: By function safety requirements, `item` is embedded in a
// `config_group`.
- unsafe { container_of!(item, bindings::config_group, cg_item) }.cast_mut();
+ unsafe { container_of!(item, bindings::config_group, cg_item) };
// SAFETY: The function safety requirements for this function satisfy
// the conditions for this call.
diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
index 09b856bb297b..b0a9c6182aec 100644
--- a/rust/kernel/cpufreq.rs
+++ b/rust/kernel/cpufreq.rs
@@ -635,7 +635,7 @@ impl Policy {
None
} else {
// SAFETY: The data is earlier set from [`set_data`].
- Some(unsafe { T::borrow(self.as_ref().driver_data) })
+ Some(unsafe { T::borrow(self.as_ref().driver_data.cast()) })
}
}
@@ -662,7 +662,7 @@ impl Policy {
let data = Some(
// SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take
// back the ownership of the data from the foreign interface.
- unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data) },
+ unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data.cast()) },
);
self.as_mut_ref().driver_data = ptr::null_mut();
data
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index f08583fa39c9..dea06b79ecb5 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -345,7 +345,7 @@ macro_rules! impl_device_context_into_aref {
macro_rules! dev_printk {
($method:ident, $dev:expr, $($f:tt)*) => {
{
- ($dev).$method(core::format_args!($($f)*));
+ ($dev).$method(::core::format_args!($($f)*));
}
}
}
@@ -357,9 +357,10 @@ macro_rules! dev_printk {
/// Equivalent to the kernel's `dev_emerg` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -382,9 +383,10 @@ macro_rules! dev_emerg {
/// Equivalent to the kernel's `dev_alert` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -407,9 +409,10 @@ macro_rules! dev_alert {
/// Equivalent to the kernel's `dev_crit` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -432,9 +435,10 @@ macro_rules! dev_crit {
/// Equivalent to the kernel's `dev_err` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -457,9 +461,10 @@ macro_rules! dev_err {
/// Equivalent to the kernel's `dev_warn` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -482,9 +487,10 @@ macro_rules! dev_warn {
/// Equivalent to the kernel's `dev_notice` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -507,9 +513,10 @@ macro_rules! dev_notice {
/// Equivalent to the kernel's `dev_info` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -532,9 +539,10 @@ macro_rules! dev_info {
/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
-/// [`core::fmt`] and `alloc::format!`.
+/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index e5859217a579..0a4eb56d98f2 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -159,7 +159,7 @@ macro_rules! module_device_table {
"_", line!(),
"_", stringify!($table_name))
]
- static $module_table_name: [core::mem::MaybeUninit<u8>; $table_name.raw_ids().size()] =
- unsafe { core::mem::transmute_copy($table_name.raw_ids()) };
+ static $module_table_name: [::core::mem::MaybeUninit<u8>; $table_name.raw_ids().size()] =
+ unsafe { ::core::mem::transmute_copy($table_name.raw_ids()) };
};
}
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 605e01e35715..a33261c62e0c 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -94,7 +94,7 @@ pub mod attrs {
pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
/// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
- /// __GFP_NOWARN).
+ /// `__GFP_NOWARN`).
pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
/// Used to indicate that the buffer is fully accessible at an elevated privilege level (and
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 74c9a3dd719e..624d7a4c83ea 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -135,6 +135,8 @@ impl<T: drm::Driver> Device<T> {
///
/// `ptr` must be a valid pointer to a `struct device` embedded in `Self`.
unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self {
+ let ptr: *const Opaque<bindings::drm_device> = ptr.cast();
+
// SAFETY: By the safety requirements of this function `ptr` is a valid pointer to a
// `struct drm_device` embedded in `Self`.
unsafe { crate::container_of!(ptr, Self, dev) }.cast_mut()
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index d8765e61c6c2..4cd69fa84318 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -125,6 +125,8 @@ impl<T: DriverObject> IntoGEMObject for Object<T> {
}
unsafe fn as_ref<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self {
+ let self_ptr: *mut Opaque<bindings::drm_gem_object> = self_ptr.cast();
+
// SAFETY: `obj` is guaranteed to be in an `Object<T>` via the safety contract of this
// function
unsafe { &*crate::container_of!(self_ptr, Object<T>, obj) }
@@ -269,8 +271,10 @@ impl<T: DriverObject> Object<T> {
}
extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
+ let ptr: *mut Opaque<bindings::drm_gem_object> = obj.cast();
+
// SAFETY: All of our objects are of type `Object<T>`.
- let this = unsafe { crate::container_of!(obj, Self, obj) }.cast_mut();
+ let this = unsafe { crate::container_of!(ptr, Self, obj) };
// SAFETY: The C code only ever calls this callback with a valid pointer to a `struct
// drm_gem_object`.
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index 13a0e44cd1aa..72d84fb0e266 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -219,12 +219,13 @@ unsafe impl AlwaysRefCounted for File {
/// must be on the same thread as this file.
///
/// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos
+#[repr(transparent)]
pub struct LocalFile {
inner: Opaque<bindings::file>,
}
// SAFETY: The type invariants guarantee that `LocalFile` is always ref-counted. This implementation
-// makes `ARef<File>` own a normal refcount.
+// makes `ARef<LocalFile>` own a normal refcount.
unsafe impl AlwaysRefCounted for LocalFile {
#[inline]
fn inc_ref(&self) {
@@ -235,7 +236,8 @@ unsafe impl AlwaysRefCounted for LocalFile {
#[inline]
unsafe fn dec_ref(obj: ptr::NonNull<LocalFile>) {
// SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we
- // may drop it. The cast is okay since `File` has the same representation as `struct file`.
+ // may drop it. The cast is okay since `LocalFile` has the same representation as
+ // `struct file`.
unsafe { bindings::fput(obj.cast().as_ptr()) }
}
}
@@ -273,7 +275,7 @@ impl LocalFile {
#[inline]
pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a LocalFile {
// SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
- // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
+ // duration of `'a`. The cast is okay because `LocalFile` is `repr(transparent)`.
//
// INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
unsafe { &*ptr.cast() }
@@ -347,7 +349,7 @@ impl File {
#[inline]
pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a File {
// SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
- // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
+ // duration of `'a`. The cast is okay because `File` is `repr(transparent)`.
//
// INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
unsafe { &*ptr.cast() }
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 1604fb6a5b1b..4b8cdcb21e77 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -6,6 +6,7 @@
//!
//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>
+use crate::prelude::*;
use core::{ffi::c_void, fmt};
/// Prints a KUnit error-level message.
@@ -40,8 +41,6 @@ pub fn info(args: fmt::Arguments<'_>) {
}
}
-use macros::kunit_tests;
-
/// Asserts that a boolean expression is `true` at runtime.
///
/// Public but hidden since it should only be used from generated tests.
@@ -59,7 +58,7 @@ macro_rules! kunit_assert {
}
static FILE: &'static $crate::str::CStr = $crate::c_str!($file);
- static LINE: i32 = core::line!() as i32 - $diff;
+ static LINE: i32 = ::core::line!() as i32 - $diff;
static CONDITION: &'static $crate::str::CStr = $crate::c_str!(stringify!($condition));
// SAFETY: FFI call without safety requirements.
@@ -130,11 +129,11 @@ macro_rules! kunit_assert {
unsafe {
$crate::bindings::__kunit_do_failed_assertion(
kunit_test,
- core::ptr::addr_of!(LOCATION.0),
+ ::core::ptr::addr_of!(LOCATION.0),
$crate::bindings::kunit_assert_type_KUNIT_ASSERTION,
- core::ptr::addr_of!(ASSERTION.0.assert),
+ ::core::ptr::addr_of!(ASSERTION.0.assert),
Some($crate::bindings::kunit_unary_assert_format),
- core::ptr::null(),
+ ::core::ptr::null(),
);
}
@@ -164,6 +163,31 @@ macro_rules! kunit_assert_eq {
}};
}
+trait TestResult {
+ fn is_test_result_ok(&self) -> bool;
+}
+
+impl TestResult for () {
+ fn is_test_result_ok(&self) -> bool {
+ true
+ }
+}
+
+impl<T, E> TestResult for Result<T, E> {
+ fn is_test_result_ok(&self) -> bool {
+ self.is_ok()
+ }
+}
+
+/// Returns whether a test result is to be considered OK.
+///
+/// This will be `assert!`ed from the generated tests.
+#[doc(hidden)]
+#[expect(private_bounds)]
+pub fn is_test_result_ok(t: impl TestResult) -> bool {
+ t.is_test_result_ok()
+}
+
/// Represents an individual test case.
///
/// The [`kunit_unsafe_test_suite!`] macro expects a NULL-terminated list of valid test cases.
@@ -323,7 +347,6 @@ mod tests {
#[test]
fn rust_test_kunit_example_test() {
- #![expect(clippy::eq_op)]
assert_eq!(1 + 1, 2);
}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 911c72a0fc21..6b4774b2b1c3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -12,20 +12,34 @@
//! do so first instead of bypassing this crate.
#![no_std]
-#![feature(arbitrary_self_types)]
-#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
-#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
-#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
-#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
+//
+// Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
+// the unstable features in use.
+//
+// Stable since Rust 1.79.0.
#![feature(inline_const)]
+//
+// Stable since Rust 1.81.0.
#![feature(lint_reasons)]
-// Stable in Rust 1.82
+//
+// Stable since Rust 1.82.0.
#![feature(raw_ref_op)]
-// Stable in Rust 1.83
+//
+// Stable since Rust 1.83.0.
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_mut_refs)]
#![feature(const_ptr_write)]
#![feature(const_refs_to_cell)]
+//
+// Expected to become stable.
+#![feature(arbitrary_self_types)]
+//
+// `feature(derive_coerce_pointee)` is expected to become stable. Before Rust
+// 1.84.0, it did not exist, so enable the predecessor features.
+#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
// Ensure conditional compilation based on the kernel configuration works;
// otherwise we may silently break things like initcall handling.
@@ -102,6 +116,7 @@ pub mod transmute;
pub mod types;
pub mod uaccess;
pub mod workqueue;
+pub mod xarray;
#[doc(hidden)]
pub use bindings;
@@ -204,7 +219,7 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
/// }
///
/// let test = Test { a: 10, b: 20 };
-/// let b_ptr = &test.b;
+/// let b_ptr: *const _ = &test.b;
/// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be
/// // in-bounds of the same allocation as `b_ptr`.
/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
@@ -212,13 +227,19 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
/// ```
#[macro_export]
macro_rules! container_of {
- ($ptr:expr, $type:ty, $($f:tt)*) => {{
- let ptr = $ptr as *const _ as *const u8;
- let offset: usize = ::core::mem::offset_of!($type, $($f)*);
- ptr.sub(offset) as *const $type
+ ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
+ let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
+ let field_ptr = $field_ptr;
+ let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
+ $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
+ container_ptr
}}
}
+/// Helper for [`container_of!`].
+#[doc(hidden)]
+pub fn assert_same_type<T>(_: T, _: T) {}
+
/// Helper for `.rs.S` files.
#[doc(hidden)]
#[macro_export]
diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
index 2054682c5724..c391c30b80f8 100644
--- a/rust/kernel/list.rs
+++ b/rust/kernel/list.rs
@@ -4,9 +4,6 @@
//! A linked list implementation.
-// May not be needed in Rust 1.87.0 (pending beta backport).
-#![allow(clippy::ptr_eq)]
-
use crate::sync::ArcBorrow;
use crate::types::Opaque;
use core::iter::{DoubleEndedIterator, FusedIterator};
@@ -38,6 +35,114 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
/// * All prev/next pointers in `ListLinks` fields of items in the list are valid and form a cycle.
/// * For every item in the list, the list owns the associated [`ListArc`] reference and has
/// exclusive access to the `ListLinks` field.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::list::*;
+///
+/// #[pin_data]
+/// struct BasicItem {
+/// value: i32,
+/// #[pin]
+/// links: ListLinks,
+/// }
+///
+/// impl BasicItem {
+/// fn new(value: i32) -> Result<ListArc<Self>> {
+/// ListArc::pin_init(try_pin_init!(Self {
+/// value,
+/// links <- ListLinks::new(),
+/// }), GFP_KERNEL)
+/// }
+/// }
+///
+/// impl_has_list_links! {
+/// impl HasListLinks<0> for BasicItem { self.links }
+/// }
+/// impl_list_arc_safe! {
+/// impl ListArcSafe<0> for BasicItem { untracked; }
+/// }
+/// impl_list_item! {
+/// impl ListItem<0> for BasicItem { using ListLinks; }
+/// }
+///
+/// // Create a new empty list.
+/// let mut list = List::new();
+/// {
+/// assert!(list.is_empty());
+/// }
+///
+/// // Insert 3 elements using `push_back()`.
+/// list.push_back(BasicItem::new(15)?);
+/// list.push_back(BasicItem::new(10)?);
+/// list.push_back(BasicItem::new(30)?);
+///
+/// // Iterate over the list to verify the nodes were inserted correctly.
+/// // [15, 10, 30]
+/// {
+/// let mut iter = list.iter();
+/// assert_eq!(iter.next().unwrap().value, 15);
+/// assert_eq!(iter.next().unwrap().value, 10);
+/// assert_eq!(iter.next().unwrap().value, 30);
+/// assert!(iter.next().is_none());
+///
+/// // Verify the length of the list.
+/// assert_eq!(list.iter().count(), 3);
+/// }
+///
+/// // Pop the items from the list using `pop_back()` and verify the content.
+/// {
+/// assert_eq!(list.pop_back().unwrap().value, 30);
+/// assert_eq!(list.pop_back().unwrap().value, 10);
+/// assert_eq!(list.pop_back().unwrap().value, 15);
+/// }
+///
+/// // Insert 3 elements using `push_front()`.
+/// list.push_front(BasicItem::new(15)?);
+/// list.push_front(BasicItem::new(10)?);
+/// list.push_front(BasicItem::new(30)?);
+///
+/// // Iterate over the list to verify the nodes were inserted correctly.
+/// // [30, 10, 15]
+/// {
+/// let mut iter = list.iter();
+/// assert_eq!(iter.next().unwrap().value, 30);
+/// assert_eq!(iter.next().unwrap().value, 10);
+/// assert_eq!(iter.next().unwrap().value, 15);
+/// assert!(iter.next().is_none());
+///
+/// // Verify the length of the list.
+/// assert_eq!(list.iter().count(), 3);
+/// }
+///
+/// // Pop the items from the list using `pop_front()` and verify the content.
+/// {
+/// assert_eq!(list.pop_front().unwrap().value, 30);
+/// assert_eq!(list.pop_front().unwrap().value, 10);
+/// }
+///
+/// // Push `list2` to `list` through `push_all_back()`.
+/// // list: [15]
+/// // list2: [25, 35]
+/// {
+/// let mut list2 = List::new();
+/// list2.push_back(BasicItem::new(25)?);
+/// list2.push_back(BasicItem::new(35)?);
+///
+/// list.push_all_back(&mut list2);
+///
+/// // list: [15, 25, 35]
+/// // list2: []
+/// let mut iter = list.iter();
+/// assert_eq!(iter.next().unwrap().value, 15);
+/// assert_eq!(iter.next().unwrap().value, 25);
+/// assert_eq!(iter.next().unwrap().value, 35);
+/// assert!(iter.next().is_none());
+/// assert!(list2.is_empty());
+/// }
+/// # Result::<(), Error>::Ok(())
+/// ```
pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> {
first: *mut ListLinksFields,
_ty: PhantomData<ListArc<T, ID>>,
@@ -322,7 +427,7 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
/// Removes the last item from this list.
pub fn pop_back(&mut self) -> Option<ListArc<T, ID>> {
- if self.first.is_null() {
+ if self.is_empty() {
return None;
}
@@ -334,7 +439,7 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
/// Removes the first item from this list.
pub fn pop_front(&mut self) -> Option<ListArc<T, ID>> {
- if self.first.is_null() {
+ if self.is_empty() {
return None;
}
diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
index 13c50df37b89..d92bcf665c89 100644
--- a/rust/kernel/list/arc.rs
+++ b/rust/kernel/list/arc.rs
@@ -74,7 +74,7 @@ pub unsafe trait TryNewListArc<const ID: u64 = 0>: ListArcSafe<ID> {
///
/// * The `untracked` strategy does not actually keep track of whether a [`ListArc`] exists. When
/// using this strategy, the only way to create a [`ListArc`] is using a [`UniqueArc`].
-/// * The `tracked_by` strategy defers the tracking to a field of the struct. The user much specify
+/// * The `tracked_by` strategy defers the tracking to a field of the struct. The user must specify
/// which field to defer the tracking to. The field must implement [`ListArcSafe`]. If the field
/// implements [`TryNewListArc`], then the type will also implement [`TryNewListArc`].
///
@@ -96,7 +96,7 @@ macro_rules! impl_list_arc_safe {
} $($rest:tt)*) => {
impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
unsafe fn on_create_list_arc_from_unique(self: ::core::pin::Pin<&mut Self>) {
- $crate::assert_pinned!($t, $field, $fty, inline);
+ ::pin_init::assert_pinned!($t, $field, $fty, inline);
// SAFETY: This field is structurally pinned as per the above assertion.
let field = unsafe {
@@ -464,7 +464,7 @@ where
/// A utility for tracking whether a [`ListArc`] exists using an atomic.
///
-/// # Invariant
+/// # Invariants
///
/// If the boolean is `false`, then there is no [`ListArc`] for this value.
#[repr(transparent)]
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 9d9771247c38..f33c13c3ff97 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -217,7 +217,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
// type.
//
// SAFETY: The open call of a file can access the private data.
- unsafe { (*raw_file).private_data = ptr.into_foreign() };
+ unsafe { (*raw_file).private_data = ptr.into_foreign().cast() };
0
}
@@ -228,7 +228,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
/// must be associated with a `MiscDeviceRegistration<T>`.
unsafe extern "C" fn release(_inode: *mut bindings::inode, file: *mut bindings::file) -> c_int {
// SAFETY: The release call of a file owns the private data.
- let private = unsafe { (*file).private_data };
+ let private = unsafe { (*file).private_data }.cast();
// SAFETY: The release call of a file owns the private data.
let ptr = unsafe { <T::Ptr as ForeignOwnable>::from_foreign(private) };
@@ -253,7 +253,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
// SAFETY: This is a Rust Miscdevice, so we call `into_foreign` in `open` and
// `from_foreign` in `release`, and `fops_mmap` is guaranteed to be called between those
// two operations.
- let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
+ let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private.cast()) };
// SAFETY: The caller provides a vma that is undergoing initial VMA setup.
let area = unsafe { VmaNew::from_raw(vma) };
// SAFETY:
@@ -272,7 +272,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
/// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.
unsafe extern "C" fn ioctl(file: *mut bindings::file, cmd: c_uint, arg: c_ulong) -> c_long {
// SAFETY: The ioctl call of a file can access the private data.
- let private = unsafe { (*file).private_data };
+ let private = unsafe { (*file).private_data }.cast();
// SAFETY: Ioctl calls can borrow the private data of the file.
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
@@ -297,7 +297,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
arg: c_ulong,
) -> c_long {
// SAFETY: The compat ioctl call of a file can access the private data.
- let private = unsafe { (*file).private_data };
+ let private = unsafe { (*file).private_data }.cast();
// SAFETY: Ioctl calls can borrow the private data of the file.
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
@@ -318,7 +318,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
/// - `seq_file` must be a valid `struct seq_file` that we can write to.
unsafe extern "C" fn show_fdinfo(seq_file: *mut bindings::seq_file, file: *mut bindings::file) {
// SAFETY: The release call of a file owns the private data.
- let private = unsafe { (*file).private_data };
+ let private = unsafe { (*file).private_data }.cast();
// SAFETY: Ioctl calls can borrow the private data of the file.
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
// SAFETY:
diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs
index 615907a0f3b4..43f525c0d16c 100644
--- a/rust/kernel/mm.rs
+++ b/rust/kernel/mm.rs
@@ -10,7 +10,6 @@
//! control what happens when userspace reads or writes to that region of memory.
//!
//! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h)
-#![cfg(CONFIG_MMU)]
use crate::{
bindings,
@@ -21,6 +20,10 @@ use core::{ops::Deref, ptr::NonNull};
pub mod virt;
use virt::VmaRef;
+#[cfg(CONFIG_MMU)]
+pub use mmput_async::MmWithUserAsync;
+mod mmput_async;
+
/// A wrapper for the kernel's `struct mm_struct`.
///
/// This represents the address space of a userspace process, so each process has one `Mm`
@@ -111,50 +114,6 @@ impl Deref for MmWithUser {
}
}
-/// A wrapper for the kernel's `struct mm_struct`.
-///
-/// This type is identical to `MmWithUser` except that it uses `mmput_async` when dropping a
-/// refcount. This means that the destructor of `ARef<MmWithUserAsync>` is safe to call in atomic
-/// context.
-///
-/// # Invariants
-///
-/// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero.
-#[repr(transparent)]
-pub struct MmWithUserAsync {
- mm: MmWithUser,
-}
-
-// SAFETY: It is safe to call `mmput_async` on another thread than where `mmget` was called.
-unsafe impl Send for MmWithUserAsync {}
-// SAFETY: All methods on `MmWithUserAsync` can be called in parallel from several threads.
-unsafe impl Sync for MmWithUserAsync {}
-
-// SAFETY: By the type invariants, this type is always refcounted.
-unsafe impl AlwaysRefCounted for MmWithUserAsync {
- #[inline]
- fn inc_ref(&self) {
- // SAFETY: The pointer is valid since self is a reference.
- unsafe { bindings::mmget(self.as_raw()) };
- }
-
- #[inline]
- unsafe fn dec_ref(obj: NonNull<Self>) {
- // SAFETY: The caller is giving up their refcount.
- unsafe { bindings::mmput_async(obj.cast().as_ptr()) };
- }
-}
-
-// Make all `MmWithUser` methods available on `MmWithUserAsync`.
-impl Deref for MmWithUserAsync {
- type Target = MmWithUser;
-
- #[inline]
- fn deref(&self) -> &MmWithUser {
- &self.mm
- }
-}
-
// These methods are safe to call even if `mm_users` is zero.
impl Mm {
/// Returns a raw pointer to the inner `mm_struct`.
@@ -206,13 +165,6 @@ impl MmWithUser {
unsafe { &*ptr.cast() }
}
- /// Use `mmput_async` when dropping this refcount.
- #[inline]
- pub fn into_mmput_async(me: ARef<MmWithUser>) -> ARef<MmWithUserAsync> {
- // SAFETY: The layouts and invariants are compatible.
- unsafe { ARef::from_raw(ARef::into_raw(me).cast()) }
- }
-
/// Attempt to access a vma using the vma read lock.
///
/// This is an optimistic trylock operation, so it may fail if there is contention. In that
diff --git a/rust/kernel/mm/mmput_async.rs b/rust/kernel/mm/mmput_async.rs
new file mode 100644
index 000000000000..9289e05f7a67
--- /dev/null
+++ b/rust/kernel/mm/mmput_async.rs
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2024 Google LLC.
+
+//! Version of `MmWithUser` using `mmput_async`.
+//!
+//! This is a separate file from `mm.rs` due to the dependency on `CONFIG_MMU=y`.
+#![cfg(CONFIG_MMU)]
+
+use crate::{
+ bindings,
+ mm::MmWithUser,
+ types::{ARef, AlwaysRefCounted},
+};
+use core::{ops::Deref, ptr::NonNull};
+
+/// A wrapper for the kernel's `struct mm_struct`.
+///
+/// This type is identical to `MmWithUser` except that it uses `mmput_async` when dropping a
+/// refcount. This means that the destructor of `ARef<MmWithUserAsync>` is safe to call in atomic
+/// context.
+///
+/// # Invariants
+///
+/// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero.
+#[repr(transparent)]
+pub struct MmWithUserAsync {
+ mm: MmWithUser,
+}
+
+// SAFETY: It is safe to call `mmput_async` on another thread than where `mmget` was called.
+unsafe impl Send for MmWithUserAsync {}
+// SAFETY: All methods on `MmWithUserAsync` can be called in parallel from several threads.
+unsafe impl Sync for MmWithUserAsync {}
+
+// SAFETY: By the type invariants, this type is always refcounted.
+unsafe impl AlwaysRefCounted for MmWithUserAsync {
+ #[inline]
+ fn inc_ref(&self) {
+ // SAFETY: The pointer is valid since self is a reference.
+ unsafe { bindings::mmget(self.as_raw()) };
+ }
+
+ #[inline]
+ unsafe fn dec_ref(obj: NonNull<Self>) {
+ // SAFETY: The caller is giving up their refcount.
+ unsafe { bindings::mmput_async(obj.cast().as_ptr()) };
+ }
+}
+
+// Make all `MmWithUser` methods available on `MmWithUserAsync`.
+impl Deref for MmWithUserAsync {
+ type Target = MmWithUser;
+
+ #[inline]
+ fn deref(&self) -> &MmWithUser {
+ &self.mm
+ }
+}
+
+impl MmWithUser {
+ /// Use `mmput_async` when dropping this refcount.
+ #[inline]
+ pub fn into_mmput_async(me: ARef<MmWithUser>) -> ARef<MmWithUserAsync> {
+ // SAFETY: The layouts and invariants are compatible.
+ unsafe { ARef::from_raw(ARef::into_raw(me).cast()) }
+ }
+}
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index f6126aca33a6..7c1b17246ed5 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -69,6 +69,7 @@ impl Page {
/// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?;
/// # Ok::<(), kernel::alloc::AllocError>(())
/// ```
+ #[inline]
pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
// SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
// is always safe to call this method.
@@ -251,6 +252,7 @@ impl Page {
}
impl Drop for Page {
+ #[inline]
fn drop(&mut self) {
// SAFETY: By the type invariants, we have ownership of the page and can free it.
unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 38fc8d5ffbf9..8435f8132e38 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -89,7 +89,7 @@ impl<T: Driver + 'static> Adapter<T> {
extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) {
// SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a
// `struct pci_dev`.
- let ptr = unsafe { bindings::pci_get_drvdata(pdev) };
+ let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast();
// SAFETY: `remove_callback` is only ever called after a successful call to
// `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
@@ -118,7 +118,9 @@ macro_rules! module_pci_driver {
};
}
-/// Abstraction for bindings::pci_device_id.
+/// Abstraction for the PCI device ID structure ([`struct pci_device_id`]).
+///
+/// [`struct pci_device_id`]: https://docs.kernel.org/PCI/pci.html#c.pci_device_id
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct DeviceId(bindings::pci_device_id);
@@ -173,7 +175,7 @@ unsafe impl RawDeviceId for DeviceId {
}
}
-/// IdTable type for PCI
+/// `IdTable` type for PCI.
pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>;
/// Create a PCI `IdTable` with its alias for modpost.
@@ -224,10 +226,11 @@ macro_rules! pci_device_table {
/// `Adapter` documentation for an example.
pub trait Driver: Send {
/// The type holding information about each device id supported by the driver.
- ///
- /// TODO: Use associated_type_defaults once stabilized:
- ///
- /// type IdInfo: 'static = ();
+ // TODO: Use `associated_type_defaults` once stabilized:
+ //
+ // ```
+ // type IdInfo: 'static = ();
+ // ```
type IdInfo: 'static;
/// The table of device ids supported by the driver.
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 08849d92c074..5b21fa517e55 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -79,7 +79,7 @@ impl<T: Driver + 'static> Adapter<T> {
extern "C" fn remove_callback(pdev: *mut bindings::platform_device) {
// SAFETY: `pdev` is a valid pointer to a `struct platform_device`.
- let ptr = unsafe { bindings::platform_get_drvdata(pdev) };
+ let ptr = unsafe { bindings::platform_get_drvdata(pdev) }.cast();
// SAFETY: `remove_callback` is only ever called after a successful call to
// `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
@@ -150,10 +150,11 @@ macro_rules! module_platform_driver {
///```
pub trait Driver: Send {
/// The type holding driver private data about each device id supported by the driver.
- ///
- /// TODO: Use associated_type_defaults once stabilized:
- ///
- /// type IdInfo: 'static = ();
+ // TODO: Use associated_type_defaults once stabilized:
+ //
+ // ```
+ // type IdInfo: 'static = ();
+ // ```
type IdInfo: 'static;
/// The table of OF device ids supported by the driver.
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index baa774a351ce..2f30a398dddd 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -14,10 +14,15 @@
#[doc(no_inline)]
pub use core::pin::Pin;
+pub use ::ffi::{
+ c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,
+ c_ushort, c_void,
+};
+
pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
#[doc(no_inline)]
-pub use macros::{export, module, vtable};
+pub use macros::{export, kunit_tests, module, vtable};
pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index cf4714242e14..9783d960a97a 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -198,10 +198,11 @@ macro_rules! print_macro (
/// Equivalent to the kernel's [`pr_emerg`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_emerg`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_emerg
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -222,10 +223,11 @@ macro_rules! pr_emerg (
/// Equivalent to the kernel's [`pr_alert`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_alert`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_alert
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -246,10 +248,11 @@ macro_rules! pr_alert (
/// Equivalent to the kernel's [`pr_crit`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_crit`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_crit
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -270,10 +273,11 @@ macro_rules! pr_crit (
/// Equivalent to the kernel's [`pr_err`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_err`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_err
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -294,10 +298,11 @@ macro_rules! pr_err (
/// Equivalent to the kernel's [`pr_warn`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_warn`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_warn
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -318,10 +323,11 @@ macro_rules! pr_warn (
/// Equivalent to the kernel's [`pr_notice`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_notice`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_notice
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -342,10 +348,11 @@ macro_rules! pr_notice (
/// Equivalent to the kernel's [`pr_info`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_info`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_info
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -368,10 +375,11 @@ macro_rules! pr_info (
/// yet.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_debug`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_debug
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
@@ -395,11 +403,12 @@ macro_rules! pr_debug (
/// Equivalent to the kernel's [`pr_cont`] macro.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
-/// `alloc::format!` for information about the formatting syntax.
+/// [`std::format!`] for information about the formatting syntax.
///
/// [`pr_info!`]: crate::pr_info!
/// [`pr_cont`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_cont
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
///
/// # Examples
///
diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
index 5246b2c8a4ff..8d978c896747 100644
--- a/rust/kernel/rbtree.rs
+++ b/rust/kernel/rbtree.rs
@@ -424,7 +424,7 @@ where
while !node.is_null() {
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects.
- let this = unsafe { container_of!(node, Node<K, V>, links) }.cast_mut();
+ let this = unsafe { container_of!(node, Node<K, V>, links) };
// SAFETY: `this` is a non-null node so it is valid by the type invariants.
let this_key = unsafe { &(*this).key };
// SAFETY: `node` is a non-null node so it is valid by the type invariants.
@@ -496,7 +496,7 @@ impl<K, V> Drop for RBTree<K, V> {
// but it is not observable. The loop invariant is still maintained.
// SAFETY: `this` is valid per the loop invariant.
- unsafe { drop(KBox::from_raw(this.cast_mut())) };
+ unsafe { drop(KBox::from_raw(this)) };
}
}
}
@@ -761,7 +761,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
let next = self.get_neighbor_raw(Direction::Next);
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects.
- let this = unsafe { container_of!(self.current.as_ptr(), Node<K, V>, links) }.cast_mut();
+ let this = unsafe { container_of!(self.current.as_ptr(), Node<K, V>, links) };
// SAFETY: `this` is valid by the type invariants as described above.
let node = unsafe { KBox::from_raw(this) };
let node = RBTreeNode { node };
@@ -806,7 +806,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
unsafe { bindings::rb_erase(neighbor, addr_of_mut!(self.tree.root)) };
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects.
- let this = unsafe { container_of!(neighbor, Node<K, V>, links) }.cast_mut();
+ let this = unsafe { container_of!(neighbor, Node<K, V>, links) };
// SAFETY: `this` is valid by the type invariants as described above.
let node = unsafe { KBox::from_raw(this) };
return Some(RBTreeNode { node });
@@ -912,7 +912,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
unsafe fn to_key_value_raw<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, *mut V) {
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects.
- let this = unsafe { container_of!(node.as_ptr(), Node<K, V>, links) }.cast_mut();
+ let this = unsafe { container_of!(node.as_ptr(), Node<K, V>, links) };
// SAFETY: The passed `node` is the current node or a non-null neighbor,
// thus `this` is valid by the type invariants.
let k = unsafe { &(*this).key };
@@ -1021,7 +1021,7 @@ impl<K, V> Iterator for IterRaw<K, V> {
// SAFETY: By the type invariant of `IterRaw`, `self.next` is a valid node in an `RBTree`,
// and by the type invariant of `RBTree`, all nodes point to the links field of `Node<K, V>` objects.
- let cur = unsafe { container_of!(self.next, Node<K, V>, links) }.cast_mut();
+ let cur = unsafe { container_of!(self.next, Node<K, V>, links) };
// SAFETY: `self.next` is a valid tree node by the type invariants.
self.next = unsafe { bindings::rb_next(self.next) };
@@ -1216,7 +1216,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY:
// - `self.node_links` is a valid pointer to a node in the tree.
// - We have exclusive access to the underlying tree, and can thus give out a mutable reference.
- unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links).cast_mut())).value }
+ unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links))).value }
}
/// Converts the entry into a mutable reference to its value.
@@ -1226,7 +1226,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY:
// - `self.node_links` is a valid pointer to a node in the tree.
// - This consumes the `&'a mut RBTree<K, V>`, therefore it can give out a mutable reference that lives for `'a`.
- unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links).cast_mut())).value }
+ unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links))).value }
}
/// Remove this entry from the [`RBTree`].
@@ -1239,9 +1239,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
RBTreeNode {
// SAFETY: The node was a node in the tree, but we removed it, so we can convert it
// back into a box.
- node: unsafe {
- KBox::from_raw(container_of!(self.node_links, Node<K, V>, links).cast_mut())
- },
+ node: unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links)) },
}
}
@@ -1272,8 +1270,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY:
// - `self.node_ptr` produces a valid pointer to a node in the tree.
// - Now that we removed this entry from the tree, we can convert the node to a box.
- let old_node =
- unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links).cast_mut()) };
+ let old_node = unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links)) };
RBTreeNode { node: old_node }
}
diff --git a/rust/kernel/static_assert.rs b/rust/kernel/static_assert.rs
index 3115ee0ba8e9..a57ba14315a0 100644
--- a/rust/kernel/static_assert.rs
+++ b/rust/kernel/static_assert.rs
@@ -6,6 +6,10 @@
///
/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
///
+/// An optional panic message can be supplied after the expression.
+/// Currently only a string literal without formatting is supported
+/// due to constness limitations of the [`assert!`] macro.
+///
/// The feature may be added to Rust in the future: see [RFC 2790].
///
/// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
@@ -25,10 +29,11 @@
/// x + 2
/// }
/// static_assert!(f(40) == 42);
+/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
/// ```
#[macro_export]
macro_rules! static_assert {
- ($condition:expr) => {
- const _: () = core::assert!($condition);
+ ($condition:expr $(,$arg:literal)?) => {
+ const _: () = ::core::assert!($condition $(,$arg)?);
};
}
diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs
index 279bd353687a..abbab5050cc5 100644
--- a/rust/kernel/std_vendor.rs
+++ b/rust/kernel/std_vendor.rs
@@ -148,7 +148,7 @@ macro_rules! dbg {
};
($val:expr $(,)?) => {
// Use of `match` here is intentional because it affects the lifetimes
- // of temporaries - https://stackoverflow.com/a/48732525/1063961
+ // of temporaries - <https://stackoverflow.com/a/48732525/1063961>
match $val {
tmp => {
$crate::pr_info!("[{}:{}:{}] {} = {:#?}\n",
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index fb61ce81ea28..a927db8e079c 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -6,7 +6,7 @@ use crate::alloc::{flags::*, AllocError, KVec};
use core::fmt::{self, Write};
use core::ops::{self, Deref, DerefMut, Index};
-use crate::error::{code::*, Error};
+use crate::prelude::*;
/// Byte string without UTF-8 validity guarantee.
#[repr(transparent)]
@@ -572,30 +572,13 @@ macro_rules! c_str {
}};
}
-#[cfg(test)]
-#[expect(clippy::items_after_test_module)]
+#[kunit_tests(rust_kernel_str)]
mod tests {
use super::*;
- struct String(CString);
-
- impl String {
- fn from_fmt(args: fmt::Arguments<'_>) -> Self {
- String(CString::try_from_fmt(args).unwrap())
- }
- }
-
- impl Deref for String {
- type Target = str;
-
- fn deref(&self) -> &str {
- self.0.to_str().unwrap()
- }
- }
-
macro_rules! format {
($($f:tt)*) => ({
- &*String::from_fmt(kernel::fmt!($($f)*))
+ CString::try_from_fmt(::kernel::fmt!($($f)*))?.to_str()?
})
}
@@ -614,67 +597,72 @@ mod tests {
\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff";
#[test]
- fn test_cstr_to_str() {
+ fn test_cstr_to_str() -> Result {
let good_bytes = b"\xf0\x9f\xa6\x80\0";
- let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
- let checked_str = checked_cstr.to_str().unwrap();
+ let checked_cstr = CStr::from_bytes_with_nul(good_bytes)?;
+ let checked_str = checked_cstr.to_str()?;
assert_eq!(checked_str, "🦀");
+ Ok(())
}
#[test]
- #[should_panic]
- fn test_cstr_to_str_panic() {
+ fn test_cstr_to_str_invalid_utf8() -> Result {
let bad_bytes = b"\xc3\x28\0";
- let checked_cstr = CStr::from_bytes_with_nul(bad_bytes).unwrap();
- checked_cstr.to_str().unwrap();
+ let checked_cstr = CStr::from_bytes_with_nul(bad_bytes)?;
+ assert!(checked_cstr.to_str().is_err());
+ Ok(())
}
#[test]
- fn test_cstr_as_str_unchecked() {
+ fn test_cstr_as_str_unchecked() -> Result {
let good_bytes = b"\xf0\x9f\x90\xA7\0";
- let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
+ let checked_cstr = CStr::from_bytes_with_nul(good_bytes)?;
// SAFETY: The contents come from a string literal which contains valid UTF-8.
let unchecked_str = unsafe { checked_cstr.as_str_unchecked() };
assert_eq!(unchecked_str, "🐧");
+ Ok(())
}
#[test]
- fn test_cstr_display() {
- let hello_world = CStr::from_bytes_with_nul(b"hello, world!\0").unwrap();
+ fn test_cstr_display() -> Result {
+ let hello_world = CStr::from_bytes_with_nul(b"hello, world!\0")?;
assert_eq!(format!("{hello_world}"), "hello, world!");
- let non_printables = CStr::from_bytes_with_nul(b"\x01\x09\x0a\0").unwrap();
+ let non_printables = CStr::from_bytes_with_nul(b"\x01\x09\x0a\0")?;
assert_eq!(format!("{non_printables}"), "\\x01\\x09\\x0a");
- let non_ascii = CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0").unwrap();
+ let non_ascii = CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0")?;
assert_eq!(format!("{non_ascii}"), "d\\xe9j\\xe0 vu");
- let good_bytes = CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0").unwrap();
+ let good_bytes = CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0")?;
assert_eq!(format!("{good_bytes}"), "\\xf0\\x9f\\xa6\\x80");
+ Ok(())
}
#[test]
- fn test_cstr_display_all_bytes() {
+ fn test_cstr_display_all_bytes() -> Result {
let mut bytes: [u8; 256] = [0; 256];
// fill `bytes` with [1..=255] + [0]
for i in u8::MIN..=u8::MAX {
bytes[i as usize] = i.wrapping_add(1);
}
- let cstr = CStr::from_bytes_with_nul(&bytes).unwrap();
+ let cstr = CStr::from_bytes_with_nul(&bytes)?;
assert_eq!(format!("{cstr}"), ALL_ASCII_CHARS);
+ Ok(())
}
#[test]
- fn test_cstr_debug() {
- let hello_world = CStr::from_bytes_with_nul(b"hello, world!\0").unwrap();
+ fn test_cstr_debug() -> Result {
+ let hello_world = CStr::from_bytes_with_nul(b"hello, world!\0")?;
assert_eq!(format!("{hello_world:?}"), "\"hello, world!\"");
- let non_printables = CStr::from_bytes_with_nul(b"\x01\x09\x0a\0").unwrap();
+ let non_printables = CStr::from_bytes_with_nul(b"\x01\x09\x0a\0")?;
assert_eq!(format!("{non_printables:?}"), "\"\\x01\\x09\\x0a\"");
- let non_ascii = CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0").unwrap();
+ let non_ascii = CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0")?;
assert_eq!(format!("{non_ascii:?}"), "\"d\\xe9j\\xe0 vu\"");
- let good_bytes = CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0").unwrap();
+ let good_bytes = CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0")?;
assert_eq!(format!("{good_bytes:?}"), "\"\\xf0\\x9f\\xa6\\x80\"");
+ Ok(())
}
#[test]
- fn test_bstr_display() {
+ fn test_bstr_display() -> Result {
let hello_world = BStr::from_bytes(b"hello, world!");
assert_eq!(format!("{hello_world}"), "hello, world!");
let escapes = BStr::from_bytes(b"_\t_\n_\r_\\_\'_\"_");
@@ -685,10 +673,11 @@ mod tests {
assert_eq!(format!("{non_ascii}"), "d\\xe9j\\xe0 vu");
let good_bytes = BStr::from_bytes(b"\xf0\x9f\xa6\x80");
assert_eq!(format!("{good_bytes}"), "\\xf0\\x9f\\xa6\\x80");
+ Ok(())
}
#[test]
- fn test_bstr_debug() {
+ fn test_bstr_debug() -> Result {
let hello_world = BStr::from_bytes(b"hello, world!");
assert_eq!(format!("{hello_world:?}"), "\"hello, world!\"");
let escapes = BStr::from_bytes(b"_\t_\n_\r_\\_\'_\"_");
@@ -699,6 +688,7 @@ mod tests {
assert_eq!(format!("{non_ascii:?}"), "\"d\\xe9j\\xe0 vu\"");
let good_bytes = BStr::from_bytes(b"\xf0\x9f\xa6\x80");
assert_eq!(format!("{good_bytes:?}"), "\"\\xf0\\x9f\\xa6\\x80\"");
+ Ok(())
}
}
@@ -752,7 +742,7 @@ impl RawFormatter {
/// for the lifetime of the returned [`RawFormatter`].
pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
let pos = buf as usize;
- // INVARIANT: We ensure that `end` is never less then `buf`, and the safety requirements
+ // INVARIANT: We ensure that `end` is never less than `buf`, and the safety requirements
// guarantees that the memory region is valid for writes.
Self {
pos,
@@ -886,7 +876,7 @@ impl CString {
// SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is
// `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`.
- unsafe { buf.set_len(f.bytes_written()) };
+ unsafe { buf.inc_len(f.bytes_written()) };
// Check that there are no `NUL` bytes before the end.
// SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
@@ -944,5 +934,5 @@ impl fmt::Debug for CString {
/// A convenience alias for [`core::format_args`].
#[macro_export]
macro_rules! fmt {
- ($($f:tt)*) => ( core::format_args!($($f)*) )
+ ($($f:tt)*) => ( ::core::format_args!($($f)*) )
}
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 8484c814609a..c7af0aa48a0a 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -135,14 +135,15 @@ pub struct Arc<T: ?Sized> {
// meaningful with respect to dropck - but this may change in the future so this is left here
// out of an abundance of caution.
//
- // See https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking
+ // See <https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking>
// for more detail on the semantics of dropck in the presence of `PhantomData`.
_p: PhantomData<ArcInner<T>>,
}
+#[doc(hidden)]
#[pin_data]
#[repr(C)]
-struct ArcInner<T: ?Sized> {
+pub struct ArcInner<T: ?Sized> {
refcount: Opaque<bindings::refcount_t>,
data: T,
}
@@ -371,18 +372,20 @@ impl<T: ?Sized> Arc<T> {
}
}
-impl<T: 'static> ForeignOwnable for Arc<T> {
+// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
+unsafe impl<T: 'static> ForeignOwnable for Arc<T> {
+ type PointedTo = ArcInner<T>;
type Borrowed<'a> = ArcBorrow<'a, T>;
type BorrowedMut<'a> = Self::Borrowed<'a>;
- fn into_foreign(self) -> *mut crate::ffi::c_void {
- ManuallyDrop::new(self).ptr.as_ptr().cast()
+ fn into_foreign(self) -> *mut Self::PointedTo {
+ ManuallyDrop::new(self).ptr.as_ptr()
}
- unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
+ unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
- let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
+ let inner = unsafe { NonNull::new_unchecked(ptr) };
// SAFETY: By the safety requirement of this function, we know that `ptr` came from
// a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and
@@ -390,17 +393,17 @@ impl<T: 'static> ForeignOwnable for Arc<T> {
unsafe { Self::from_inner(inner) }
}
- unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> {
+ unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
- let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
+ let inner = unsafe { NonNull::new_unchecked(ptr) };
// SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
// for the lifetime of the returned value.
unsafe { ArcBorrow::new(inner) }
}
- unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> {
+ unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {
// SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
// requirements for `borrow`.
unsafe { Self::borrow(ptr) }
@@ -489,7 +492,7 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
/// There are no mutable references to the underlying [`Arc`], and it remains valid for the
/// lifetime of the [`ArcBorrow`] instance.
///
-/// # Example
+/// # Examples
///
/// ```
/// use kernel::sync::{Arc, ArcBorrow};
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index f509cb0eb71e..a8089a98da9e 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -5,14 +5,36 @@
//! This module contains the kernel APIs related to time and timers that
//! have been ported or wrapped for usage by Rust code in the kernel.
//!
+//! There are two types in this module:
+//!
+//! - The [`Instant`] type represents a specific point in time.
+//! - The [`Delta`] type represents a span of time.
+//!
+//! Note that the C side uses `ktime_t` type to represent both. However, timestamp
+//! and timedelta are different. To avoid confusion, we use two different types.
+//!
+//! A [`Instant`] object can be created by calling the [`Instant::now()`] function.
+//! It represents a point in time at which the object was created.
+//! By calling the [`Instant::elapsed()`] method, a [`Delta`] object representing
+//! the elapsed time can be created. The [`Delta`] object can also be created
+//! by subtracting two [`Instant`] objects.
+//!
+//! A [`Delta`] type supports methods to retrieve the duration in various units.
+//!
//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
pub mod hrtimer;
+/// The number of nanoseconds per microsecond.
+pub const NSEC_PER_USEC: i64 = bindings::NSEC_PER_USEC as i64;
+
/// The number of nanoseconds per millisecond.
pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
+/// The number of nanoseconds per second.
+pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
+
/// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
pub type Jiffies = crate::ffi::c_ulong;
@@ -27,59 +49,44 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
unsafe { bindings::__msecs_to_jiffies(msecs) }
}
-/// A Rust wrapper around a `ktime_t`.
+/// A specific point in time.
+///
+/// # Invariants
+///
+/// The `inner` value is in the range from 0 to `KTIME_MAX`.
#[repr(transparent)]
-#[derive(Copy, Clone)]
-pub struct Ktime {
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
+pub struct Instant {
inner: bindings::ktime_t,
}
-impl Ktime {
- /// Create a `Ktime` from a raw `ktime_t`.
- #[inline]
- pub fn from_raw(inner: bindings::ktime_t) -> Self {
- Self { inner }
- }
-
+impl Instant {
/// Get the current time using `CLOCK_MONOTONIC`.
#[inline]
- pub fn ktime_get() -> Self {
- // SAFETY: It is always safe to call `ktime_get` outside of NMI context.
- Self::from_raw(unsafe { bindings::ktime_get() })
- }
-
- /// Divide the number of nanoseconds by a compile-time constant.
- #[inline]
- fn divns_constant<const DIV: i64>(self) -> i64 {
- self.to_ns() / DIV
- }
-
- /// Returns the number of nanoseconds.
- #[inline]
- pub fn to_ns(self) -> i64 {
- self.inner
+ pub fn now() -> Self {
+ // INVARIANT: The `ktime_get()` function returns a value in the range
+ // from 0 to `KTIME_MAX`.
+ Self {
+ // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.
+ inner: unsafe { bindings::ktime_get() },
+ }
}
- /// Returns the number of milliseconds.
+ /// Return the amount of time elapsed since the [`Instant`].
#[inline]
- pub fn to_ms(self) -> i64 {
- self.divns_constant::<NSEC_PER_MSEC>()
+ pub fn elapsed(&self) -> Delta {
+ Self::now() - *self
}
}
-/// Returns the number of milliseconds between two ktimes.
-#[inline]
-pub fn ktime_ms_delta(later: Ktime, earlier: Ktime) -> i64 {
- (later - earlier).to_ms()
-}
-
-impl core::ops::Sub for Ktime {
- type Output = Ktime;
+impl core::ops::Sub for Instant {
+ type Output = Delta;
+ // By the type invariant, it never overflows.
#[inline]
- fn sub(self, other: Ktime) -> Ktime {
- Self {
- inner: self.inner - other.inner,
+ fn sub(self, other: Instant) -> Delta {
+ Delta {
+ nanos: self.inner - other.inner,
}
}
}
@@ -149,3 +156,85 @@ impl ClockId {
self as bindings::clockid_t
}
}
+
+/// A span of time.
+///
+/// This struct represents a span of time, with its value stored as nanoseconds.
+/// The value can represent any valid i64 value, including negative, zero, and
+/// positive numbers.
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
+pub struct Delta {
+ nanos: i64,
+}
+
+impl Delta {
+ /// A span of time equal to zero.
+ pub const ZERO: Self = Self { nanos: 0 };
+
+ /// Create a new [`Delta`] from a number of microseconds.
+ ///
+ /// The `micros` can range from -9_223_372_036_854_775 to 9_223_372_036_854_775.
+ /// If `micros` is outside this range, `i64::MIN` is used for negative values,
+ /// and `i64::MAX` is used for positive values due to saturation.
+ #[inline]
+ pub const fn from_micros(micros: i64) -> Self {
+ Self {
+ nanos: micros.saturating_mul(NSEC_PER_USEC),
+ }
+ }
+
+ /// Create a new [`Delta`] from a number of milliseconds.
+ ///
+ /// The `millis` can range from -9_223_372_036_854 to 9_223_372_036_854.
+ /// If `millis` is outside this range, `i64::MIN` is used for negative values,
+ /// and `i64::MAX` is used for positive values due to saturation.
+ #[inline]
+ pub const fn from_millis(millis: i64) -> Self {
+ Self {
+ nanos: millis.saturating_mul(NSEC_PER_MSEC),
+ }
+ }
+
+ /// Create a new [`Delta`] from a number of seconds.
+ ///
+ /// The `secs` can range from -9_223_372_036 to 9_223_372_036.
+ /// If `secs` is outside this range, `i64::MIN` is used for negative values,
+ /// and `i64::MAX` is used for positive values due to saturation.
+ #[inline]
+ pub const fn from_secs(secs: i64) -> Self {
+ Self {
+ nanos: secs.saturating_mul(NSEC_PER_SEC),
+ }
+ }
+
+ /// Return `true` if the [`Delta`] spans no time.
+ #[inline]
+ pub fn is_zero(self) -> bool {
+ self.as_nanos() == 0
+ }
+
+ /// Return `true` if the [`Delta`] spans a negative amount of time.
+ #[inline]
+ pub fn is_negative(self) -> bool {
+ self.as_nanos() < 0
+ }
+
+ /// Return the number of nanoseconds in the [`Delta`].
+ #[inline]
+ pub const fn as_nanos(self) -> i64 {
+ self.nanos
+ }
+
+ /// Return the smallest number of microseconds greater than or equal
+ /// to the value in the [`Delta`].
+ #[inline]
+ pub const fn as_micros_ceil(self) -> i64 {
+ self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC
+ }
+
+ /// Return the number of milliseconds in the [`Delta`].
+ #[inline]
+ pub const fn as_millis(self) -> i64 {
+ self.as_nanos() / NSEC_PER_MSEC
+ }
+}
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index ce53f8579d18..9df3dcd2fa39 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -68,10 +68,26 @@
//! `start` operation.
use super::ClockId;
-use crate::{prelude::*, time::Ktime, types::Opaque};
+use crate::{prelude::*, types::Opaque};
use core::marker::PhantomData;
use pin_init::PinInit;
+/// A Rust wrapper around a `ktime_t`.
+// NOTE: Ktime is going to be removed when hrtimer is converted to Instant/Delta.
+#[repr(transparent)]
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
+pub struct Ktime {
+ inner: bindings::ktime_t,
+}
+
+impl Ktime {
+ /// Returns the number of nanoseconds.
+ #[inline]
+ pub fn to_ns(self) -> i64 {
+ self.inner
+ }
+}
+
/// A timer backed by a C `struct hrtimer`.
///
/// # Invariants
@@ -384,11 +400,9 @@ pub unsafe trait HasHrTimer<T> {
#[repr(u32)]
pub enum HrTimerRestart {
/// Timer should not be restarted.
- #[allow(clippy::unnecessary_cast)]
- NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART as u32,
+ NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART,
/// Timer should be restarted.
- #[allow(clippy::unnecessary_cast)]
- Restart = bindings::hrtimer_restart_HRTIMER_RESTART as u32,
+ Restart = bindings::hrtimer_restart_HRTIMER_RESTART,
}
impl HrTimerRestart {
diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
index 4a984d85b4a1..ccf1e66e5b2d 100644
--- a/rust/kernel/time/hrtimer/arc.rs
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -5,10 +5,10 @@ use super::HrTimer;
use super::HrTimerCallback;
use super::HrTimerHandle;
use super::HrTimerPointer;
+use super::Ktime;
use super::RawHrTimerCallback;
use crate::sync::Arc;
use crate::sync::ArcBorrow;
-use crate::time::Ktime;
/// A handle for an `Arc<HasHrTimer<T>>` returned by a call to
/// [`HrTimerPointer::start`].
diff --git a/rust/kernel/time/hrtimer/pin.rs b/rust/kernel/time/hrtimer/pin.rs
index f760db265c7b..293ca9cf058c 100644
--- a/rust/kernel/time/hrtimer/pin.rs
+++ b/rust/kernel/time/hrtimer/pin.rs
@@ -4,9 +4,9 @@ use super::HasHrTimer;
use super::HrTimer;
use super::HrTimerCallback;
use super::HrTimerHandle;
+use super::Ktime;
use super::RawHrTimerCallback;
use super::UnsafeHrTimerPointer;
-use crate::time::Ktime;
use core::pin::Pin;
/// A handle for a `Pin<&HasHrTimer>`. When the handle exists, the timer might be
diff --git a/rust/kernel/time/hrtimer/pin_mut.rs b/rust/kernel/time/hrtimer/pin_mut.rs
index 90c0351d62e4..6033572d35ad 100644
--- a/rust/kernel/time/hrtimer/pin_mut.rs
+++ b/rust/kernel/time/hrtimer/pin_mut.rs
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
use super::{
- HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, RawHrTimerCallback, UnsafeHrTimerPointer,
+ HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, Ktime, RawHrTimerCallback,
+ UnsafeHrTimerPointer,
};
-use crate::time::Ktime;
use core::{marker::PhantomData, pin::Pin, ptr::NonNull};
/// A handle for a `Pin<&mut HasHrTimer>`. When the handle exists, the timer might
diff --git a/rust/kernel/time/hrtimer/tbox.rs b/rust/kernel/time/hrtimer/tbox.rs
index 2071cae07234..29526a5da203 100644
--- a/rust/kernel/time/hrtimer/tbox.rs
+++ b/rust/kernel/time/hrtimer/tbox.rs
@@ -5,9 +5,9 @@ use super::HrTimer;
use super::HrTimerCallback;
use super::HrTimerHandle;
use super::HrTimerPointer;
+use super::Ktime;
use super::RawHrTimerCallback;
use crate::prelude::*;
-use crate::time::Ktime;
use core::ptr::NonNull;
/// A handle for a [`Box<HasHrTimer<T>>`] returned by a call to
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index eee387727d1a..22985b6f6982 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -18,7 +18,19 @@ use pin_init::{PinInit, Zeroable};
///
/// This trait is meant to be used in cases when Rust objects are stored in C objects and
/// eventually "freed" back to Rust.
-pub trait ForeignOwnable: Sized {
+///
+/// # Safety
+///
+/// Implementers must ensure that [`into_foreign`] returns a pointer which meets the alignment
+/// requirements of [`PointedTo`].
+///
+/// [`into_foreign`]: Self::into_foreign
+/// [`PointedTo`]: Self::PointedTo
+pub unsafe trait ForeignOwnable: Sized {
+ /// Type used when the value is foreign-owned. In practical terms only defines the alignment of
+ /// the pointer.
+ type PointedTo;
+
/// Type used to immutably borrow a value that is currently foreign-owned.
type Borrowed<'a>;
@@ -27,16 +39,18 @@ pub trait ForeignOwnable: Sized {
/// Converts a Rust-owned object to a foreign-owned one.
///
- /// The foreign representation is a pointer to void. There are no guarantees for this pointer.
- /// For example, it might be invalid, dangling or pointing to uninitialized memory. Using it in
- /// any way except for [`from_foreign`], [`try_from_foreign`], [`borrow`], or [`borrow_mut`] can
- /// result in undefined behavior.
+ /// # Guarantees
+ ///
+ /// The return value is guaranteed to be well-aligned, but there are no other guarantees for
+ /// this pointer. For example, it might be null, dangling, or point to uninitialized memory.
+ /// Using it in any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`],
+ /// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior.
///
/// [`from_foreign`]: Self::from_foreign
/// [`try_from_foreign`]: Self::try_from_foreign
/// [`borrow`]: Self::borrow
/// [`borrow_mut`]: Self::borrow_mut
- fn into_foreign(self) -> *mut crate::ffi::c_void;
+ fn into_foreign(self) -> *mut Self::PointedTo;
/// Converts a foreign-owned object back to a Rust-owned one.
///
@@ -46,7 +60,7 @@ pub trait ForeignOwnable: Sized {
/// must not be passed to `from_foreign` more than once.
///
/// [`into_foreign`]: Self::into_foreign
- unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self;
+ unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self;
/// Tries to convert a foreign-owned object back to a Rust-owned one.
///
@@ -58,7 +72,7 @@ pub trait ForeignOwnable: Sized {
/// `ptr` must either be null or satisfy the safety requirements for [`from_foreign`].
///
/// [`from_foreign`]: Self::from_foreign
- unsafe fn try_from_foreign(ptr: *mut crate::ffi::c_void) -> Option<Self> {
+ unsafe fn try_from_foreign(ptr: *mut Self::PointedTo) -> Option<Self> {
if ptr.is_null() {
None
} else {
@@ -81,7 +95,7 @@ pub trait ForeignOwnable: Sized {
///
/// [`into_foreign`]: Self::into_foreign
/// [`from_foreign`]: Self::from_foreign
- unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Self::Borrowed<'a>;
+ unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>;
/// Borrows a foreign-owned object mutably.
///
@@ -109,21 +123,23 @@ pub trait ForeignOwnable: Sized {
/// [`from_foreign`]: Self::from_foreign
/// [`borrow`]: Self::borrow
/// [`Arc`]: crate::sync::Arc
- unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a>;
+ unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Self::BorrowedMut<'a>;
}
-impl ForeignOwnable for () {
+// SAFETY: The `into_foreign` function returns a pointer that is dangling, but well-aligned.
+unsafe impl ForeignOwnable for () {
+ type PointedTo = ();
type Borrowed<'a> = ();
type BorrowedMut<'a> = ();
- fn into_foreign(self) -> *mut crate::ffi::c_void {
+ fn into_foreign(self) -> *mut Self::PointedTo {
core::ptr::NonNull::dangling().as_ptr()
}
- unsafe fn from_foreign(_: *mut crate::ffi::c_void) -> Self {}
+ unsafe fn from_foreign(_: *mut Self::PointedTo) -> Self {}
- unsafe fn borrow<'a>(_: *mut crate::ffi::c_void) -> Self::Borrowed<'a> {}
- unsafe fn borrow_mut<'a>(_: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a> {}
+ unsafe fn borrow<'a>(_: *mut Self::PointedTo) -> Self::Borrowed<'a> {}
+ unsafe fn borrow_mut<'a>(_: *mut Self::PointedTo) -> Self::BorrowedMut<'a> {}
}
/// Runs a cleanup function/closure when dropped.
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index 80a9782b1c6e..6d70edd8086a 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -46,10 +46,9 @@ pub type UserPtr = usize;
///
/// ```no_run
/// use kernel::ffi::c_void;
-/// use kernel::error::Result;
/// use kernel::uaccess::{UserPtr, UserSlice};
///
-/// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result<()> {
+/// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result {
/// let (read, mut write) = UserSlice::new(uptr, len).reader_writer();
///
/// let mut buf = KVec::new();
@@ -68,7 +67,6 @@ pub type UserPtr = usize;
///
/// ```no_run
/// use kernel::ffi::c_void;
-/// use kernel::error::{code::EINVAL, Result};
/// use kernel::uaccess::{UserPtr, UserSlice};
///
/// /// Returns whether the data in this region is valid.
@@ -290,7 +288,7 @@ impl UserSliceReader {
// SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the
// vector have been initialized.
- unsafe { buf.set_len(buf.len() + len) };
+ unsafe { buf.inc_len(len) };
Ok(())
}
}
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index f98bd02b838f..d092112d843f 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -429,51 +429,28 @@ impl<T: ?Sized, const ID: u64> Work<T, ID> {
///
/// # Safety
///
-/// The [`OFFSET`] constant must be the offset of a field in `Self` of type [`Work<T, ID>`]. The
-/// methods on this trait must have exactly the behavior that the definitions given below have.
+/// The methods [`raw_get_work`] and [`work_container_of`] must return valid pointers and must be
+/// true inverses of each other; that is, they must satisfy the following invariants:
+/// - `work_container_of(raw_get_work(ptr)) == ptr` for any `ptr: *mut Self`.
+/// - `raw_get_work(work_container_of(ptr)) == ptr` for any `ptr: *mut Work<T, ID>`.
///
/// [`impl_has_work!`]: crate::impl_has_work
-/// [`OFFSET`]: HasWork::OFFSET
+/// [`raw_get_work`]: HasWork::raw_get_work
+/// [`work_container_of`]: HasWork::work_container_of
pub unsafe trait HasWork<T, const ID: u64 = 0> {
- /// The offset of the [`Work<T, ID>`] field.
- const OFFSET: usize;
-
- /// Returns the offset of the [`Work<T, ID>`] field.
- ///
- /// This method exists because the [`OFFSET`] constant cannot be accessed if the type is not
- /// [`Sized`].
- ///
- /// [`OFFSET`]: HasWork::OFFSET
- #[inline]
- fn get_work_offset(&self) -> usize {
- Self::OFFSET
- }
-
/// Returns a pointer to the [`Work<T, ID>`] field.
///
/// # Safety
///
/// The provided pointer must point at a valid struct of type `Self`.
- #[inline]
- unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID> {
- // SAFETY: The caller promises that the pointer is valid.
- unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut Work<T, ID> }
- }
+ unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID>;
/// Returns a pointer to the struct containing the [`Work<T, ID>`] field.
///
/// # Safety
///
/// The pointer must point at a [`Work<T, ID>`] field in a struct of type `Self`.
- #[inline]
- unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self
- where
- Self: Sized,
- {
- // SAFETY: The caller promises that the pointer points at a field of the right type in the
- // right kind of struct.
- unsafe { (ptr as *mut u8).sub(Self::OFFSET) as *mut Self }
- }
+ unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self;
}
/// Used to safely implement the [`HasWork<T, ID>`] trait.
@@ -504,8 +481,6 @@ macro_rules! impl_has_work {
// SAFETY: The implementation of `raw_get_work` only compiles if the field has the right
// type.
unsafe impl$(<$($generics)+>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self {
- const OFFSET: usize = ::core::mem::offset_of!(Self, $field) as usize;
-
#[inline]
unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> {
// SAFETY: The caller promises that the pointer is not dangling.
@@ -513,6 +488,15 @@ macro_rules! impl_has_work {
::core::ptr::addr_of_mut!((*ptr).$field)
}
}
+
+ #[inline]
+ unsafe fn work_container_of(
+ ptr: *mut $crate::workqueue::Work<$work_type $(, $id)?>,
+ ) -> *mut Self {
+ // SAFETY: The caller promises that the pointer points at a field of the right type
+ // in the right kind of struct.
+ unsafe { $crate::container_of!(ptr, Self, $field) }
+ }
}
)*};
}
diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs
new file mode 100644
index 000000000000..75719e7bb491
--- /dev/null
+++ b/rust/kernel/xarray.rs
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! XArray abstraction.
+//!
+//! C header: [`include/linux/xarray.h`](srctree/include/linux/xarray.h)
+
+use crate::{
+ alloc, bindings, build_assert,
+ error::{Error, Result},
+ types::{ForeignOwnable, NotThreadSafe, Opaque},
+};
+use core::{iter, marker::PhantomData, mem, pin::Pin, ptr::NonNull};
+use pin_init::{pin_data, pin_init, pinned_drop, PinInit};
+
+/// An array which efficiently maps sparse integer indices to owned objects.
+///
+/// This is similar to a [`crate::alloc::kvec::Vec<Option<T>>`], but more efficient when there are
+/// holes in the index space, and can be efficiently grown.
+///
+/// # Invariants
+///
+/// `self.xa` is always an initialized and valid [`bindings::xarray`] whose entries are either
+/// `XA_ZERO_ENTRY` or came from `T::into_foreign`.
+///
+/// # Examples
+///
+/// ```rust
+/// use kernel::alloc::KBox;
+/// use kernel::xarray::{AllocKind, XArray};
+///
+/// let xa = KBox::pin_init(XArray::new(AllocKind::Alloc1), GFP_KERNEL)?;
+///
+/// let dead = KBox::new(0xdead, GFP_KERNEL)?;
+/// let beef = KBox::new(0xbeef, GFP_KERNEL)?;
+///
+/// let mut guard = xa.lock();
+///
+/// assert_eq!(guard.get(0), None);
+///
+/// assert_eq!(guard.store(0, dead, GFP_KERNEL)?.as_deref(), None);
+/// assert_eq!(guard.get(0).copied(), Some(0xdead));
+///
+/// *guard.get_mut(0).unwrap() = 0xffff;
+/// assert_eq!(guard.get(0).copied(), Some(0xffff));
+///
+/// assert_eq!(guard.store(0, beef, GFP_KERNEL)?.as_deref().copied(), Some(0xffff));
+/// assert_eq!(guard.get(0).copied(), Some(0xbeef));
+///
+/// guard.remove(0);
+/// assert_eq!(guard.get(0), None);
+///
+/// # Ok::<(), Error>(())
+/// ```
+#[pin_data(PinnedDrop)]
+pub struct XArray<T: ForeignOwnable> {
+ #[pin]
+ xa: Opaque<bindings::xarray>,
+ _p: PhantomData<T>,
+}
+
+#[pinned_drop]
+impl<T: ForeignOwnable> PinnedDrop for XArray<T> {
+ fn drop(self: Pin<&mut Self>) {
+ self.iter().for_each(|ptr| {
+ let ptr = ptr.as_ptr();
+ // SAFETY: `ptr` came from `T::into_foreign`.
+ //
+ // INVARIANT: we own the only reference to the array which is being dropped so the
+ // broken invariant is not observable on function exit.
+ drop(unsafe { T::from_foreign(ptr) })
+ });
+
+ // SAFETY: `self.xa` is always valid by the type invariant.
+ unsafe { bindings::xa_destroy(self.xa.get()) };
+ }
+}
+
+/// Flags passed to [`XArray::new`] to configure the array's allocation tracking behavior.
+pub enum AllocKind {
+ /// Consider the first element to be at index 0.
+ Alloc,
+ /// Consider the first element to be at index 1.
+ Alloc1,
+}
+
+impl<T: ForeignOwnable> XArray<T> {
+ /// Creates a new initializer for this type.
+ pub fn new(kind: AllocKind) -> impl PinInit<Self> {
+ let flags = match kind {
+ AllocKind::Alloc => bindings::XA_FLAGS_ALLOC,
+ AllocKind::Alloc1 => bindings::XA_FLAGS_ALLOC1,
+ };
+ pin_init!(Self {
+ // SAFETY: `xa` is valid while the closure is called.
+ //
+ // INVARIANT: `xa` is initialized here to an empty, valid [`bindings::xarray`].
+ xa <- Opaque::ffi_init(|xa| unsafe {
+ bindings::xa_init_flags(xa, flags)
+ }),
+ _p: PhantomData,
+ })
+ }
+
+ fn iter(&self) -> impl Iterator<Item = NonNull<T::PointedTo>> + '_ {
+ let mut index = 0;
+
+ // SAFETY: `self.xa` is always valid by the type invariant.
+ iter::once(unsafe {
+ bindings::xa_find(self.xa.get(), &mut index, usize::MAX, bindings::XA_PRESENT)
+ })
+ .chain(iter::from_fn(move || {
+ // SAFETY: `self.xa` is always valid by the type invariant.
+ Some(unsafe {
+ bindings::xa_find_after(self.xa.get(), &mut index, usize::MAX, bindings::XA_PRESENT)
+ })
+ }))
+ .map_while(|ptr| NonNull::new(ptr.cast()))
+ }
+
+ /// Attempts to lock the [`XArray`] for exclusive access.
+ pub fn try_lock(&self) -> Option<Guard<'_, T>> {
+ // SAFETY: `self.xa` is always valid by the type invariant.
+ if (unsafe { bindings::xa_trylock(self.xa.get()) } != 0) {
+ Some(Guard {
+ xa: self,
+ _not_send: NotThreadSafe,
+ })
+ } else {
+ None
+ }
+ }
+
+ /// Locks the [`XArray`] for exclusive access.
+ pub fn lock(&self) -> Guard<'_, T> {
+ // SAFETY: `self.xa` is always valid by the type invariant.
+ unsafe { bindings::xa_lock(self.xa.get()) };
+
+ Guard {
+ xa: self,
+ _not_send: NotThreadSafe,
+ }
+ }
+}
+
+/// A lock guard.
+///
+/// The lock is unlocked when the guard goes out of scope.
+#[must_use = "the lock unlocks immediately when the guard is unused"]
+pub struct Guard<'a, T: ForeignOwnable> {
+ xa: &'a XArray<T>,
+ _not_send: NotThreadSafe,
+}
+
+impl<T: ForeignOwnable> Drop for Guard<'_, T> {
+ fn drop(&mut self) {
+ // SAFETY:
+ // - `self.xa.xa` is always valid by the type invariant.
+ // - The caller holds the lock, so it is safe to unlock it.
+ unsafe { bindings::xa_unlock(self.xa.xa.get()) };
+ }
+}
+
+/// The error returned by [`store`](Guard::store).
+///
+/// Contains the underlying error and the value that was not stored.
+pub struct StoreError<T> {
+ /// The error that occurred.
+ pub error: Error,
+ /// The value that was not stored.
+ pub value: T,
+}
+
+impl<T> From<StoreError<T>> for Error {
+ fn from(value: StoreError<T>) -> Self {
+ value.error
+ }
+}
+
+impl<'a, T: ForeignOwnable> Guard<'a, T> {
+ fn load<F, U>(&self, index: usize, f: F) -> Option<U>
+ where
+ F: FnOnce(NonNull<T::PointedTo>) -> U,
+ {
+ // SAFETY: `self.xa.xa` is always valid by the type invariant.
+ let ptr = unsafe { bindings::xa_load(self.xa.xa.get(), index) };
+ let ptr = NonNull::new(ptr.cast())?;
+ Some(f(ptr))
+ }
+
+ /// Provides a reference to the element at the given index.
+ pub fn get(&self, index: usize) -> Option<T::Borrowed<'_>> {
+ self.load(index, |ptr| {
+ // SAFETY: `ptr` came from `T::into_foreign`.
+ unsafe { T::borrow(ptr.as_ptr()) }
+ })
+ }
+
+ /// Provides a mutable reference to the element at the given index.
+ pub fn get_mut(&mut self, index: usize) -> Option<T::BorrowedMut<'_>> {
+ self.load(index, |ptr| {
+ // SAFETY: `ptr` came from `T::into_foreign`.
+ unsafe { T::borrow_mut(ptr.as_ptr()) }
+ })
+ }
+
+ /// Removes and returns the element at the given index.
+ pub fn remove(&mut self, index: usize) -> Option<T> {
+ // SAFETY:
+ // - `self.xa.xa` is always valid by the type invariant.
+ // - The caller holds the lock.
+ let ptr = unsafe { bindings::__xa_erase(self.xa.xa.get(), index) }.cast();
+ // SAFETY:
+ // - `ptr` is either NULL or came from `T::into_foreign`.
+ // - `&mut self` guarantees that the lifetimes of [`T::Borrowed`] and [`T::BorrowedMut`]
+ // borrowed from `self` have ended.
+ unsafe { T::try_from_foreign(ptr) }
+ }
+
+ /// Stores an element at the given index.
+ ///
+ /// May drop the lock if needed to allocate memory, and then reacquire it afterwards.
+ ///
+ /// On success, returns the element which was previously at the given index.
+ ///
+ /// On failure, returns the element which was attempted to be stored.
+ pub fn store(
+ &mut self,
+ index: usize,
+ value: T,
+ gfp: alloc::Flags,
+ ) -> Result<Option<T>, StoreError<T>> {
+ build_assert!(
+ mem::align_of::<T::PointedTo>() >= 4,
+ "pointers stored in XArray must be 4-byte aligned"
+ );
+ let new = value.into_foreign();
+
+ let old = {
+ let new = new.cast();
+ // SAFETY:
+ // - `self.xa.xa` is always valid by the type invariant.
+ // - The caller holds the lock.
+ //
+ // INVARIANT: `new` came from `T::into_foreign`.
+ unsafe { bindings::__xa_store(self.xa.xa.get(), index, new, gfp.as_raw()) }
+ };
+
+ // SAFETY: `__xa_store` returns the old entry at this index on success or `xa_err` if an
+ // error happened.
+ let errno = unsafe { bindings::xa_err(old) };
+ if errno != 0 {
+ // SAFETY: `new` came from `T::into_foreign` and `__xa_store` does not take
+ // ownership of the value on error.
+ let value = unsafe { T::from_foreign(new) };
+ Err(StoreError {
+ value,
+ error: Error::from_errno(errno),
+ })
+ } else {
+ let old = old.cast();
+ // SAFETY: `ptr` is either NULL or came from `T::into_foreign`.
+ //
+ // NB: `XA_ZERO_ENTRY` is never returned by functions belonging to the Normal XArray
+ // API; such entries present as `NULL`.
+ Ok(unsafe { T::try_from_foreign(old) })
+ }
+ }
+}
+
+// SAFETY: `XArray<T>` has no shared mutable state so it is `Send` iff `T` is `Send`.
+unsafe impl<T: ForeignOwnable + Send> Send for XArray<T> {}
+
+// SAFETY: `XArray<T>` serialises the interior mutability it provides so it is `Sync` iff `T` is
+// `Send`.
+unsafe impl<T: ForeignOwnable + Send> Sync for XArray<T> {}