summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-01-21 17:48:03 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2025-01-21 17:48:03 -0800
commite3610441d1fb47b1f00e4c38bdf333176e824729 (patch)
tree569bb6398cf22a058201f621a7082a721f9b4e71 /rust/kernel
parent1d6d3992235ed08929846f98fecf79682e0b422c (diff)
parentceff0757f5dafb5be5205988171809c877b1d3e3 (diff)
Merge tag 'rust-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux
Pull rust updates from Miguel Ojeda: "Toolchain and infrastructure: - Finish the move to custom FFI integer types started in the previous cycle and finally map 'long' to 'isize' and 'char' to 'u8'. Do a few cleanups on top thanks to that. - Start to use 'derive(CoercePointee)' on Rust >= 1.84.0. This is a major milestone on the path to build the kernel using only stable Rust features. In particular, previously we were using the unstable features 'coerce_unsized', 'dispatch_from_dyn' and 'unsize', and now we will use the new 'derive_coerce_pointee' one, which is on track to stabilization. This new feature is a macro that essentially expands into code that internally uses the unstable features that we were using before, without having to expose those. With it, stable Rust users, including the kernel, will be able to build custom smart pointers that work with trait objects, e.g.: fn f(p: &Arc<dyn Display>) { pr_info!("{p}\n"); } let a: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?; let b: Arc<dyn Display> = Arc::new("hello there", GFP_KERNEL)?; f(&a); // Prints "42". f(&b); // Prints "hello there". Together with the 'arbitrary_self_types' feature that we started using in the previous cycle, using our custom smart pointers like 'Arc' will eventually only rely in stable Rust. - Introduce 'PROCMACROLDFLAGS' environment variable to allow to link Rust proc macros using different flags than those used for linking Rust host programs (e.g. when 'rustc' uses a different C library than the host programs' one), which Android needs. - Help kernel builds under macOS with Rust enabled by accomodating other naming conventions for dynamic libraries (i.e. '.so' vs. '.dylib') which are used for Rust procedural macros. The actual support for macOS (i.e. the rest of the pieces needed) is provided out-of-tree by others, following the policy used for other parts of the kernel by Kbuild. - Run Clippy for 'rusttest' code too and clean the bits it spotted. - Provide Clippy with the minimum supported Rust version to improve the suggestions it gives. - Document 'bindgen' 0.71.0 regression. 'kernel' crate: - 'build_error!': move users of the hidden function to the documented macro, prevent such uses in the future by moving the function elsewhere and add the macro to the prelude. - 'types' module: add improved version of 'ForeignOwnable::borrow_mut' (which was removed in the past since it was problematic); change 'ForeignOwnable' pointer type to '*mut'. - 'alloc' module: implement 'Display' for 'Box' and align the 'Debug' implementation to it; add example (doctest) for 'ArrayLayout::new()' - 'sync' module: document 'PhantomData' in 'Arc'; use 'NonNull::new_unchecked' in 'ForeignOwnable for Arc' impl. - 'uaccess' module: accept 'Vec's with different allocators in 'UserSliceReader::read_all'. - 'workqueue' module: enable run-testing a couple more doctests. - 'error' module: simplify 'from_errno()'. - 'block' module: fix formatting in code documentation (a lint to catch these is being implemented). - Avoid 'unwrap()'s in doctests, which also improves the examples by showing how kernel code is supposed to be written. - Avoid 'as' casts with 'cast{,_mut}' calls which are a bit safer. And a few other cleanups" * tag 'rust-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (32 commits) kbuild: rust: add PROCMACROLDFLAGS rust: uaccess: generalize userSliceReader to support any Vec rust: kernel: add improved version of `ForeignOwnable::borrow_mut` rust: kernel: reorder `ForeignOwnable` items rust: kernel: change `ForeignOwnable` pointer to mut rust: arc: split unsafe block, add missing comment rust: types: avoid `as` casts rust: arc: use `NonNull::new_unchecked` rust: use derive(CoercePointee) on rustc >= 1.84.0 rust: alloc: add doctest for `ArrayLayout::new()` rust: init: update `stack_try_pin_init` examples rust: error: import `kernel`'s `LayoutError` instead of `core`'s rust: str: replace unwraps with question mark operators rust: page: remove unnecessary helper function from doctest rust: rbtree: remove unwrap in asserts rust: init: replace unwraps with question mark operators rust: use host dylib naming convention to support macOS rust: add `build_error!` to the prelude rust: kernel: move `build_error` hidden function to prevent mistakes rust: use the `build_error!` macro, not the hidden function ...
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/alloc.rs2
-rw-r--r--rust/kernel/alloc/kbox.rs53
-rw-r--r--rust/kernel/alloc/layout.rs19
-rw-r--r--rust/kernel/block/mq/gen_disk.rs6
-rw-r--r--rust/kernel/block/mq/operations.rs3
-rw-r--r--rust/kernel/build_assert.rs12
-rw-r--r--rust/kernel/device.rs4
-rw-r--r--rust/kernel/error.rs23
-rw-r--r--rust/kernel/firmware.rs2
-rw-r--r--rust/kernel/init.rs30
-rw-r--r--rust/kernel/lib.rs13
-rw-r--r--rust/kernel/list/arc.rs9
-rw-r--r--rust/kernel/miscdevice.rs18
-rw-r--r--rust/kernel/net/phy.rs18
-rw-r--r--rust/kernel/page.rs6
-rw-r--r--rust/kernel/prelude.rs2
-rw-r--r--rust/kernel/print.rs4
-rw-r--r--rust/kernel/rbtree.rs46
-rw-r--r--rust/kernel/security.rs2
-rw-r--r--rust/kernel/seq_file.rs2
-rw-r--r--rust/kernel/str.rs38
-rw-r--r--rust/kernel/sync/arc.rs65
-rw-r--r--rust/kernel/types.rs93
-rw-r--r--rust/kernel/uaccess.rs33
-rw-r--r--rust/kernel/workqueue.rs3
25 files changed, 321 insertions, 185 deletions
diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
index f2f7f3a53d29..fc9c9c41cd79 100644
--- a/rust/kernel/alloc.rs
+++ b/rust/kernel/alloc.rs
@@ -123,7 +123,7 @@ pub mod flags {
/// [`Allocator`] is designed to be implemented as a ZST; [`Allocator`] functions do not operate on
/// an object instance.
///
-/// In order to be able to support `#[derive(SmartPointer)]` later on, we need to avoid a design
+/// In order to be able to support `#[derive(CoercePointee)]` later on, we need to avoid a design
/// that requires an `Allocator` to be instantiated, hence its functions must not contain any kind
/// of `self` parameter.
///
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 9ce414361c2c..cb4ebea3b074 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -354,22 +354,30 @@ where
A: Allocator,
{
type Borrowed<'a> = &'a T;
+ type BorrowedMut<'a> = &'a mut T;
- fn into_foreign(self) -> *const crate::ffi::c_void {
- Box::into_raw(self) as _
+ fn into_foreign(self) -> *mut crate::ffi::c_void {
+ Box::into_raw(self).cast()
}
- unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
+ unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> 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 as _) }
+ unsafe { Box::from_raw(ptr.cast()) }
}
- unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> &'a T {
+ unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> &'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 fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> &'a mut T {
+ let ptr = ptr.cast();
+ // 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>>
@@ -377,19 +385,20 @@ where
A: Allocator,
{
type Borrowed<'a> = Pin<&'a T>;
+ type BorrowedMut<'a> = Pin<&'a mut T>;
- fn into_foreign(self) -> *const crate::ffi::c_void {
+ fn into_foreign(self) -> *mut crate::ffi::c_void {
// SAFETY: We are still treating the box as pinned.
- Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _
+ Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast()
}
- unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
+ unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> 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 as _)) }
+ unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }
}
- unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Pin<&'a T> {
+ unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> 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
@@ -399,6 +408,18 @@ where
// 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();
+ // 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 { &mut *ptr };
+
+ // SAFETY: This pointer originates from a `Pin<Box<T>>`.
+ unsafe { Pin::new_unchecked(r) }
+ }
}
impl<T, A> Deref for Box<T, A>
@@ -427,13 +448,23 @@ where
}
}
+impl<T, A> fmt::Display for Box<T, A>
+where
+ T: ?Sized + fmt::Display,
+ A: Allocator,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <T as fmt::Display>::fmt(&**self, f)
+ }
+}
+
impl<T, A> fmt::Debug for Box<T, A>
where
T: ?Sized + fmt::Debug,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&**self, f)
+ <T as fmt::Debug>::fmt(&**self, f)
}
}
diff --git a/rust/kernel/alloc/layout.rs b/rust/kernel/alloc/layout.rs
index 4b3cd7fdc816..93ed514f7cc7 100644
--- a/rust/kernel/alloc/layout.rs
+++ b/rust/kernel/alloc/layout.rs
@@ -43,6 +43,25 @@ impl<T> ArrayLayout<T> {
/// # Errors
///
/// When `len * size_of::<T>()` overflows or when `len * size_of::<T>() > isize::MAX`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use kernel::alloc::layout::{ArrayLayout, LayoutError};
+ /// let layout = ArrayLayout::<i32>::new(15)?;
+ /// assert_eq!(layout.len(), 15);
+ ///
+ /// // Errors because `len * size_of::<T>()` overflows.
+ /// let layout = ArrayLayout::<i32>::new(isize::MAX as usize);
+ /// assert!(layout.is_err());
+ ///
+ /// // Errors because `len * size_of::<i32>() > isize::MAX`,
+ /// // even though `len < isize::MAX`.
+ /// let layout = ArrayLayout::<i32>::new(isize::MAX as usize / 2);
+ /// assert!(layout.is_err());
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
pub const fn new(len: usize) -> Result<Self, LayoutError> {
match len.checked_mul(core::mem::size_of::<T>()) {
Some(size) if size <= ISIZE_MAX => {
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 798c4ae0bded..14806e1997fd 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -174,9 +174,9 @@ impl GenDiskBuilder {
///
/// # Invariants
///
-/// - `gendisk` must always point to an initialized and valid `struct gendisk`.
-/// - `gendisk` was added to the VFS through a call to
-/// `bindings::device_add_disk`.
+/// - `gendisk` must always point to an initialized and valid `struct gendisk`.
+/// - `gendisk` was added to the VFS through a call to
+/// `bindings::device_add_disk`.
pub struct GenDisk<T: Operations> {
_tagset: Arc<TagSet<T>>,
gendisk: *mut bindings::gendisk,
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index c8646d0d9866..864ff379dc91 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -9,6 +9,7 @@ use crate::{
block::mq::request::RequestDataWrapper,
block::mq::Request,
error::{from_result, Result},
+ prelude::*,
types::ARef,
};
use core::{marker::PhantomData, sync::atomic::AtomicU64, sync::atomic::Ordering};
@@ -35,7 +36,7 @@ pub trait Operations: Sized {
/// Called by the kernel to poll the device for completed requests. Only
/// used for poll queues.
fn poll() -> bool {
- crate::build_error(crate::error::VTABLE_DEFAULT_ERROR)
+ build_error!(crate::error::VTABLE_DEFAULT_ERROR)
}
}
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index 9e37120bc69c..6331b15d7c4d 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -2,6 +2,9 @@
//! Build-time assert.
+#[doc(hidden)]
+pub use build_error::build_error;
+
/// Fails the build if the code path calling `build_error!` can possibly be executed.
///
/// If the macro is executed in const context, `build_error!` will panic.
@@ -11,7 +14,6 @@
/// # Examples
///
/// ```
-/// # use kernel::build_error;
/// #[inline]
/// fn foo(a: usize) -> usize {
/// a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
@@ -23,10 +25,10 @@
#[macro_export]
macro_rules! build_error {
() => {{
- $crate::build_error("")
+ $crate::build_assert::build_error("")
}};
($msg:expr) => {{
- $crate::build_error($msg)
+ $crate::build_assert::build_error($msg)
}};
}
@@ -73,12 +75,12 @@ macro_rules! build_error {
macro_rules! build_assert {
($cond:expr $(,)?) => {{
if !$cond {
- $crate::build_error(concat!("assertion failed: ", stringify!($cond)));
+ $crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
}
}};
($cond:expr, $msg:expr) => {{
if !$cond {
- $crate::build_error($msg);
+ $crate::build_assert::build_error($msg);
}
}};
}
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index c926e0c2b852..d5e6a19ff6b7 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -173,10 +173,10 @@ impl Device {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_dev_printk(
- klevel as *const _ as *const core::ffi::c_char,
+ klevel as *const _ as *const crate::ffi::c_char,
self.as_raw(),
c_str!("%pA").as_char_ptr(),
- &msg as *const _ as *const core::ffi::c_void,
+ &msg as *const _ as *const crate::ffi::c_void,
)
};
}
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 52c502432447..f6ecf09cb65f 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -4,9 +4,10 @@
//!
//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)
-use crate::{alloc::AllocError, str::CStr};
-
-use core::alloc::LayoutError;
+use crate::{
+ alloc::{layout::LayoutError, AllocError},
+ str::CStr,
+};
use core::fmt;
use core::num::NonZeroI32;
@@ -101,19 +102,16 @@ impl Error {
/// It is a bug to pass an out-of-range `errno`. `EINVAL` would
/// be returned in such a case.
pub fn from_errno(errno: crate::ffi::c_int) -> Error {
- if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
+ if let Some(error) = Self::try_from_errno(errno) {
+ error
+ } else {
// TODO: Make it a `WARN_ONCE` once available.
crate::pr_warn!(
"attempted to create `Error` with out of range `errno`: {}",
errno
);
- return code::EINVAL;
+ code::EINVAL
}
-
- // INVARIANT: The check above ensures the type invariant
- // will hold.
- // SAFETY: `errno` is checked above to be in a valid range.
- unsafe { Error::from_errno_unchecked(errno) }
}
/// Creates an [`Error`] from a kernel error code.
@@ -153,11 +151,8 @@ impl Error {
/// Returns the error encoded as a pointer.
pub fn to_ptr<T>(self) -> *mut T {
- #[cfg_attr(target_pointer_width = "32", allow(clippy::useless_conversion))]
// SAFETY: `self.0` is a valid error due to its invariant.
- unsafe {
- bindings::ERR_PTR(self.0.get().into()) as *mut _
- }
+ unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ }
}
/// Returns a string representing the error, if one exists.
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index 13a374a5cdb7..c5162fdc95ff 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -12,7 +12,7 @@ use core::ptr::NonNull;
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
struct FwFunc(
- unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32,
+ unsafe extern "C" fn(*mut *const bindings::firmware, *const u8, *mut bindings::device) -> i32,
);
impl FwFunc {
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 347049df556b..3f9236c1c9d5 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -290,9 +290,17 @@ macro_rules! stack_pin_init {
///
/// ```rust,ignore
/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
+/// # use kernel::{
+/// # init,
+/// # pin_init,
+/// # stack_try_pin_init,
+/// # init::*,
+/// # sync::Mutex,
+/// # new_mutex,
+/// # alloc::AllocError,
+/// # };
/// # use macros::pin_data;
-/// # use core::{alloc::AllocError, pin::Pin};
+/// # use core::pin::Pin;
/// #[pin_data]
/// struct Foo {
/// #[pin]
@@ -316,9 +324,17 @@ macro_rules! stack_pin_init {
///
/// ```rust,ignore
/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
+/// # use kernel::{
+/// # init,
+/// # pin_init,
+/// # stack_try_pin_init,
+/// # init::*,
+/// # sync::Mutex,
+/// # new_mutex,
+/// # alloc::AllocError,
+/// # };
/// # use macros::pin_data;
-/// # use core::{alloc::AllocError, pin::Pin};
+/// # use core::pin::Pin;
/// #[pin_data]
/// struct Foo {
/// #[pin]
@@ -1076,8 +1092,9 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
/// ```rust
/// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn};
/// let array: KBox<[usize; 1_000]> =
-/// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL).unwrap();
+/// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?;
/// assert_eq!(array.len(), 1_000);
+/// # Ok::<(), Error>(())
/// ```
pub fn init_array_from_fn<I, const N: usize, T, E>(
mut make_init: impl FnMut(usize) -> I,
@@ -1120,8 +1137,9 @@ where
/// ```rust
/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
/// let array: Arc<[Mutex<usize>; 1_000]> =
-/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL).unwrap();
+/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?;
/// assert_eq!(array.len(), 1_000);
+/// # Ok::<(), Error>(())
/// ```
pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
mut make_init: impl FnMut(usize) -> I,
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index e1065a7551a3..545d1170ee63 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -13,11 +13,12 @@
#![no_std]
#![feature(arbitrary_self_types)]
-#![feature(coerce_unsized)]
-#![feature(dispatch_from_dyn)]
+#![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))]
#![feature(inline_const)]
#![feature(lint_reasons)]
-#![feature(unsize)]
// Ensure conditional compilation based on the kernel configuration works;
// otherwise we may silently break things like initcall handling.
@@ -32,7 +33,8 @@ pub use ffi;
pub mod alloc;
#[cfg(CONFIG_BLOCK)]
pub mod block;
-mod build_assert;
+#[doc(hidden)]
+pub mod build_assert;
pub mod cred;
pub mod device;
pub mod error;
@@ -74,9 +76,6 @@ pub use bindings;
pub use macros;
pub use uapi;
-#[doc(hidden)]
-pub use build_error::build_error;
-
/// Prefix to appear before log messages printed from within the `kernel` crate.
const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
index 3483d8c232c4..13c50df37b89 100644
--- a/rust/kernel/list/arc.rs
+++ b/rust/kernel/list/arc.rs
@@ -7,7 +7,7 @@
use crate::alloc::{AllocError, Flags};
use crate::prelude::*;
use crate::sync::{Arc, ArcBorrow, UniqueArc};
-use core::marker::{PhantomPinned, Unsize};
+use core::marker::PhantomPinned;
use core::ops::Deref;
use core::pin::Pin;
use core::sync::atomic::{AtomicBool, Ordering};
@@ -159,6 +159,7 @@ pub use impl_list_arc_safe;
///
/// [`List`]: crate::list::List
#[repr(transparent)]
+#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
pub struct ListArc<T, const ID: u64 = 0>
where
T: ListArcSafe<ID> + ?Sized,
@@ -443,18 +444,20 @@ where
// This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
// dynamically-sized type (DST) `U`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
where
- T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+ T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
U: ListArcSafe<ID> + ?Sized,
{
}
// This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
// `ListArc<U>`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
where
- T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+ T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
U: ListArcSafe<ID> + ?Sized,
{
}
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 7e2a79b3ae26..b3a6cc50b240 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -11,16 +11,12 @@
use crate::{
bindings,
error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
+ ffi::{c_int, c_long, c_uint, c_ulong},
prelude::*,
str::CStr,
types::{ForeignOwnable, Opaque},
};
-use core::{
- ffi::{c_int, c_long, c_uint, c_ulong},
- marker::PhantomData,
- mem::MaybeUninit,
- pin::Pin,
-};
+use core::{marker::PhantomData, mem::MaybeUninit, pin::Pin};
/// Options for creating a misc device.
#[derive(Copy, Clone)]
@@ -120,7 +116,7 @@ pub trait MiscDevice {
_cmd: u32,
_arg: usize,
) -> Result<isize> {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Handler for ioctls.
@@ -136,7 +132,7 @@ pub trait MiscDevice {
_cmd: u32,
_arg: usize,
) -> Result<isize> {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
}
@@ -193,7 +189,7 @@ unsafe extern "C" fn fops_open<T: MiscDevice>(
};
// SAFETY: The open call of a file owns the private data.
- unsafe { (*file).private_data = ptr.into_foreign().cast_mut() };
+ unsafe { (*file).private_data = ptr.into_foreign() };
0
}
@@ -229,7 +225,7 @@ unsafe extern "C" fn fops_ioctl<T: MiscDevice>(
// SAFETY: Ioctl calls can borrow the private data of the file.
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
- match T::ioctl(device, cmd, arg as usize) {
+ match T::ioctl(device, cmd, arg) {
Ok(ret) => ret as c_long,
Err(err) => err.to_errno() as c_long,
}
@@ -249,7 +245,7 @@ unsafe extern "C" fn fops_compat_ioctl<T: MiscDevice>(
// SAFETY: Ioctl calls can borrow the private data of the file.
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
- match T::compat_ioctl(device, cmd, arg as usize) {
+ match T::compat_ioctl(device, cmd, arg) {
Ok(ret) => ret as c_long,
Err(err) => err.to_errno() as c_long,
}
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 2fbfb6a94c11..3ca36348a61b 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -587,17 +587,17 @@ pub trait Driver {
/// Issues a PHY software reset.
fn soft_reset(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Sets up device-specific structures during discovery.
fn probe(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Probes the hardware to determine what abilities it has.
fn get_features(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Returns true if this is a suitable driver for the given phydev.
@@ -609,32 +609,32 @@ pub trait Driver {
/// Configures the advertisement and resets auto-negotiation
/// if auto-negotiation is enabled.
fn config_aneg(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Determines the negotiated speed and duplex.
fn read_status(_dev: &mut Device) -> Result<u16> {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Suspends the hardware, saving state if needed.
fn suspend(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Resumes the hardware, restoring state if needed.
fn resume(_dev: &mut Device) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Overrides the default MMD read function for reading a MMD register.
fn read_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16) -> Result<u16> {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Overrides the default MMD write function for writing a MMD register.
fn write_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16, _val: u16) -> Result {
- kernel::build_error(VTABLE_DEFAULT_ERROR)
+ build_error!(VTABLE_DEFAULT_ERROR)
}
/// Callback for notification of link change.
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index fdac6c375fe4..f6126aca33a6 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -57,9 +57,8 @@ impl Page {
/// ```
/// use kernel::page::Page;
///
- /// # fn dox() -> Result<(), kernel::alloc::AllocError> {
/// let page = Page::alloc_page(GFP_KERNEL)?;
- /// # Ok(()) }
+ /// # Ok::<(), kernel::alloc::AllocError>(())
/// ```
///
/// Allocate memory for a page and zero its contents.
@@ -67,9 +66,8 @@ impl Page {
/// ```
/// use kernel::page::Page;
///
- /// # fn dox() -> Result<(), kernel::alloc::AllocError> {
/// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?;
- /// # Ok(()) }
+ /// # Ok::<(), kernel::alloc::AllocError>(())
/// ```
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
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 9ab4e0b6cbc9..dde2e0649790 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -19,7 +19,7 @@ pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec}
#[doc(no_inline)]
pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};
-pub use super::build_assert;
+pub use super::{build_assert, build_error};
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
#[doc(no_inline)]
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index a28077a7cb30..b19ee490be58 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -107,7 +107,7 @@ pub unsafe fn call_printk(
// SAFETY: TODO.
unsafe {
bindings::_printk(
- format_string.as_ptr() as _,
+ format_string.as_ptr(),
module_name.as_ptr(),
&args as *const _ as *const c_void,
);
@@ -128,7 +128,7 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
- format_strings::CONT.as_ptr() as _,
+ format_strings::CONT.as_ptr(),
&args as *const _ as *const c_void,
);
}
diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
index cb4415a12258..ee2731dad72d 100644
--- a/rust/kernel/rbtree.rs
+++ b/rust/kernel/rbtree.rs
@@ -36,17 +36,17 @@ use core::{
///
/// // Check the nodes we just inserted.
/// {
-/// assert_eq!(tree.get(&10).unwrap(), &100);
-/// assert_eq!(tree.get(&20).unwrap(), &200);
-/// assert_eq!(tree.get(&30).unwrap(), &300);
+/// assert_eq!(tree.get(&10), Some(&100));
+/// assert_eq!(tree.get(&20), Some(&200));
+/// assert_eq!(tree.get(&30), Some(&300));
/// }
///
/// // Iterate over the nodes we just inserted.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &100));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
-/// assert_eq!(iter.next().unwrap(), (&30, &300));
+/// assert_eq!(iter.next(), Some((&10, &100)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
+/// assert_eq!(iter.next(), Some((&30, &300)));
/// assert!(iter.next().is_none());
/// }
///
@@ -61,9 +61,9 @@ use core::{
/// // Check that the tree reflects the replacement.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &1000));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
-/// assert_eq!(iter.next().unwrap(), (&30, &300));
+/// assert_eq!(iter.next(), Some((&10, &1000)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
+/// assert_eq!(iter.next(), Some((&30, &300)));
/// assert!(iter.next().is_none());
/// }
///
@@ -73,9 +73,9 @@ use core::{
/// // Check that the tree reflects the update.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &1000));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
-/// assert_eq!(iter.next().unwrap(), (&30, &3000));
+/// assert_eq!(iter.next(), Some((&10, &1000)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
+/// assert_eq!(iter.next(), Some((&30, &3000)));
/// assert!(iter.next().is_none());
/// }
///
@@ -85,8 +85,8 @@ use core::{
/// // Check that the tree reflects the removal.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
-/// assert_eq!(iter.next().unwrap(), (&30, &3000));
+/// assert_eq!(iter.next(), Some((&20, &200)));
+/// assert_eq!(iter.next(), Some((&30, &3000)));
/// assert!(iter.next().is_none());
/// }
///
@@ -128,20 +128,20 @@ use core::{
/// // Check the nodes we just inserted.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &100));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
-/// assert_eq!(iter.next().unwrap(), (&30, &300));
+/// assert_eq!(iter.next(), Some((&10, &100)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
+/// assert_eq!(iter.next(), Some((&30, &300)));
/// assert!(iter.next().is_none());
/// }
///
/// // Remove a node, getting back ownership of it.
-/// let existing = tree.remove(&30).unwrap();
+/// let existing = tree.remove(&30);
///
/// // Check that the tree reflects the removal.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &100));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
+/// assert_eq!(iter.next(), Some((&10, &100)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
/// assert!(iter.next().is_none());
/// }
///
@@ -155,9 +155,9 @@ use core::{
/// // Check that the tree reflect the new insertion.
/// {
/// let mut iter = tree.iter();
-/// assert_eq!(iter.next().unwrap(), (&10, &100));
-/// assert_eq!(iter.next().unwrap(), (&15, &150));
-/// assert_eq!(iter.next().unwrap(), (&20, &200));
+/// assert_eq!(iter.next(), Some((&10, &100)));
+/// assert_eq!(iter.next(), Some((&15, &150)));
+/// assert_eq!(iter.next(), Some((&20, &200)));
/// assert!(iter.next().is_none());
/// }
///
diff --git a/rust/kernel/security.rs b/rust/kernel/security.rs
index 2522868862a1..ea4c58c81703 100644
--- a/rust/kernel/security.rs
+++ b/rust/kernel/security.rs
@@ -19,7 +19,7 @@ use crate::{
/// successful call to `security_secid_to_secctx`, that has not yet been destroyed by calling
/// `security_release_secctx`.
pub struct SecurityCtx {
- secdata: *mut core::ffi::c_char,
+ secdata: *mut crate::ffi::c_char,
seclen: usize,
}
diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs
index 6ca29d576d02..04947c672979 100644
--- a/rust/kernel/seq_file.rs
+++ b/rust/kernel/seq_file.rs
@@ -36,7 +36,7 @@ impl SeqFile {
bindings::seq_printf(
self.inner.get(),
c_str!("%pA").as_char_ptr(),
- &args as *const _ as *const core::ffi::c_void,
+ &args as *const _ as *const crate::ffi::c_void,
);
}
}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index d04c12a1426d..28e2201604d6 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -39,12 +39,13 @@ impl fmt::Display for BStr {
/// ```
/// # use kernel::{fmt, b_str, str::{BStr, CString}};
/// let ascii = b_str!("Hello, BStr!");
- /// let s = CString::try_from_fmt(fmt!("{}", ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
/// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());
///
/// let non_ascii = b_str!("🦀");
- /// let s = CString::try_from_fmt(fmt!("{}", non_ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{}", non_ascii))?;
/// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
+ /// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &b in &self.0 {
@@ -70,12 +71,13 @@ impl fmt::Debug for BStr {
/// # use kernel::{fmt, b_str, str::{BStr, CString}};
/// // Embedded double quotes are escaped.
/// let ascii = b_str!("Hello, \"BStr\"!");
- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
/// assert_eq!(s.as_bytes(), "\"Hello, \\\"BStr\\\"!\"".as_bytes());
///
/// let non_ascii = b_str!("😺");
- /// let s = CString::try_from_fmt(fmt!("{:?}", non_ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{:?}", non_ascii))?;
/// assert_eq!(s.as_bytes(), "\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
+ /// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
@@ -189,7 +191,7 @@ impl CStr {
// to a `NUL`-terminated C string.
let len = unsafe { bindings::strlen(ptr) } + 1;
// SAFETY: Lifetime guaranteed by the safety precondition.
- let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len as _) };
+ let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len) };
// SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.
// As we have added 1 to `len`, the last byte is known to be `NUL`.
unsafe { Self::from_bytes_with_nul_unchecked(bytes) }
@@ -248,7 +250,7 @@ impl CStr {
/// Returns a C pointer to the string.
#[inline]
pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
- self.0.as_ptr() as _
+ self.0.as_ptr()
}
/// Convert the string to a byte slice without the trailing `NUL` byte.
@@ -273,8 +275,9 @@ impl CStr {
///
/// ```
/// # use kernel::str::CStr;
- /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+ /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
/// assert_eq!(cstr.to_str(), Ok("foo"));
+ /// # Ok::<(), kernel::error::Error>(())
/// ```
#[inline]
pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
@@ -384,12 +387,13 @@ impl fmt::Display for CStr {
/// # use kernel::str::CStr;
/// # use kernel::str::CString;
/// let penguin = c_str!("🐧");
- /// let s = CString::try_from_fmt(fmt!("{}", penguin)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{}", penguin))?;
/// assert_eq!(s.as_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_bytes());
///
/// let ascii = c_str!("so \"cool\"");
- /// let s = CString::try_from_fmt(fmt!("{}", ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
/// assert_eq!(s.as_bytes_with_nul(), "so \"cool\"\0".as_bytes());
+ /// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &c in self.as_bytes() {
@@ -413,13 +417,14 @@ impl fmt::Debug for CStr {
/// # use kernel::str::CStr;
/// # use kernel::str::CString;
/// let penguin = c_str!("🐧");
- /// let s = CString::try_from_fmt(fmt!("{:?}", penguin)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{:?}", penguin))?;
/// assert_eq!(s.as_bytes_with_nul(), "\"\\xf0\\x9f\\x90\\xa7\"\0".as_bytes());
///
/// // Embedded double quotes are escaped.
/// let ascii = c_str!("so \"cool\"");
- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii)).unwrap();
+ /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
/// assert_eq!(s.as_bytes_with_nul(), "\"so \\\"cool\\\"\"\0".as_bytes());
+ /// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("\"")?;
@@ -522,6 +527,7 @@ macro_rules! c_str {
}
#[cfg(test)]
+#[expect(clippy::items_after_test_module)]
mod tests {
use super::*;
@@ -547,7 +553,7 @@ mod tests {
})
}
- const ALL_ASCII_CHARS: &'static str =
+ const ALL_ASCII_CHARS: &str =
"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\
\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f \
!\"#$%&'()*+,-./0123456789:;<=>?@\
@@ -581,6 +587,7 @@ mod tests {
fn test_cstr_as_str_unchecked() {
let good_bytes = b"\xf0\x9f\x90\xA7\0";
let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
+ // 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, "🐧");
}
@@ -799,16 +806,17 @@ impl fmt::Write for Formatter {
/// ```
/// use kernel::{str::CString, fmt};
///
-/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20)).unwrap();
+/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20))?;
/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
///
/// let tmp = "testing";
-/// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123)).unwrap();
+/// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123))?;
/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());
///
/// // This fails because it has an embedded `NUL` byte.
/// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));
/// assert_eq!(s.is_ok(), false);
+/// # Ok::<(), kernel::error::Error>(())
/// ```
pub struct CString {
buf: KVec<u8>,
@@ -838,7 +846,7 @@ impl CString {
// SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
// (which the minimum buffer size) and is non-zero (we wrote at least the `NUL` terminator)
// so `f.bytes_written() - 1` doesn't underflow.
- let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, (f.bytes_written() - 1) as _) };
+ let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, f.bytes_written() - 1) };
if !ptr.is_null() {
return Err(EINVAL);
}
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index fa4509406ee9..3cefda7a4372 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -26,7 +26,7 @@ use crate::{
use core::{
alloc::Layout,
fmt,
- marker::{PhantomData, Unsize},
+ marker::PhantomData,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
@@ -125,8 +125,18 @@ mod std_vendor;
/// let coerced: Arc<dyn MyTrait> = obj;
/// # Ok::<(), Error>(())
/// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
+ // NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as
+ // Drop>::drop`. Note that dropck already assumes that objects of type `T` may be used in
+ // `<Arc<T> as Drop>::drop` and the distinction between `T` and `ArcInner<T>` is not presently
+ // 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
+ // for more detail on the semantics of dropck in the presence of `PhantomData`.
_p: PhantomData<ArcInner<T>>,
}
@@ -172,10 +182,12 @@ impl<T: ?Sized> ArcInner<T> {
// This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
// dynamically-sized type (DST) `U`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
// This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
// SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
@@ -201,10 +213,11 @@ impl<T> Arc<T> {
};
let inner = KBox::new(value, flags)?;
+ let inner = KBox::leak(inner).into();
// SAFETY: We just created `inner` with a reference count of 1, which is owned by the new
// `Arc` object.
- Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) })
+ Ok(unsafe { Self::from_inner(inner) })
}
}
@@ -331,26 +344,37 @@ impl<T: ?Sized> Arc<T> {
impl<T: 'static> ForeignOwnable for Arc<T> {
type Borrowed<'a> = ArcBorrow<'a, T>;
+ type BorrowedMut<'a> = Self::Borrowed<'a>;
- fn into_foreign(self) -> *const crate::ffi::c_void {
- ManuallyDrop::new(self).ptr.as_ptr() as _
+ fn into_foreign(self) -> *mut crate::ffi::c_void {
+ ManuallyDrop::new(self).ptr.as_ptr().cast()
}
- unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> ArcBorrow<'a, T> {
- // By the safety requirement of this function, we know that `ptr` came from
- // a previous call to `Arc::into_foreign`.
- let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap();
+ unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> 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>>()) };
+
+ // 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
+ // holds a reference count increment that is transferrable to us.
+ unsafe { Self::from_inner(inner) }
+ }
+
+ unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> 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>>()) };
// 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 from_foreign(ptr: *const crate::ffi::c_void) -> Self {
- // 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
- // holds a reference count increment that is transferrable to us.
- unsafe { Self::from_inner(NonNull::new(ptr as _).unwrap()) }
+ unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> {
+ // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
+ // requirements for `borrow`.
+ unsafe { Self::borrow(ptr) }
}
}
@@ -372,10 +396,14 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
impl<T: ?Sized> Clone for Arc<T> {
fn clone(&self) -> Self {
+ // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
+ // safe to dereference it.
+ let refcount = unsafe { self.ptr.as_ref() }.refcount.get();
+
// INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
// safe to increment the refcount.
- unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) };
+ unsafe { bindings::refcount_inc(refcount) };
// SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`.
unsafe { Self::from_inner(self.ptr) }
@@ -471,6 +499,8 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
/// obj.as_arc_borrow().use_reference();
/// # Ok::<(), Error>(())
/// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
inner: NonNull<ArcInner<T>>,
_p: PhantomData<&'a ()>,
@@ -478,7 +508,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> {
// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
// `ArcBorrow<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
for ArcBorrow<'_, T>
{
}
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index ec6457bb3084..0dfaf45a755c 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -19,35 +19,34 @@ use core::{
/// 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 {
- /// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and
- /// [`ForeignOwnable::from_foreign`].
+ /// Type used to immutably borrow a value that is currently foreign-owned.
type Borrowed<'a>;
+ /// Type used to mutably borrow a value that is currently foreign-owned.
+ type BorrowedMut<'a>;
+
/// 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 [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`],
- /// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior.
- fn into_foreign(self) -> *const crate::ffi::c_void;
-
- /// Borrows a foreign-owned object.
- ///
- /// # Safety
+ /// any way except for [`from_foreign`], [`try_from_foreign`], [`borrow`], or [`borrow_mut`] can
+ /// result in undefined behavior.
///
- /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
- /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
- unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Self::Borrowed<'a>;
+ /// [`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;
/// Converts a foreign-owned object back to a Rust-owned one.
///
/// # Safety
///
- /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
- /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
- /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for
- /// this object must have been dropped.
- unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self;
+ /// The provided pointer must have been returned by a previous call to [`into_foreign`], and it
+ /// 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;
/// Tries to convert a foreign-owned object back to a Rust-owned one.
///
@@ -56,9 +55,10 @@ pub trait ForeignOwnable: Sized {
///
/// # Safety
///
- /// `ptr` must either be null or satisfy the safety requirements for
- /// [`ForeignOwnable::from_foreign`].
- unsafe fn try_from_foreign(ptr: *const crate::ffi::c_void) -> Option<Self> {
+ /// `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> {
if ptr.is_null() {
None
} else {
@@ -67,18 +67,63 @@ pub trait ForeignOwnable: Sized {
unsafe { Some(Self::from_foreign(ptr)) }
}
}
+
+ /// Borrows a foreign-owned object immutably.
+ ///
+ /// This method provides a way to access a foreign-owned value from Rust immutably. It provides
+ /// you with exactly the same abilities as an `&Self` when the value is Rust-owned.
+ ///
+ /// # Safety
+ ///
+ /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
+ /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
+ /// the lifetime 'a.
+ ///
+ /// [`into_foreign`]: Self::into_foreign
+ /// [`from_foreign`]: Self::from_foreign
+ unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Self::Borrowed<'a>;
+
+ /// Borrows a foreign-owned object mutably.
+ ///
+ /// This method provides a way to access a foreign-owned value from Rust mutably. It provides
+ /// you with exactly the same abilities as an `&mut Self` when the value is Rust-owned, except
+ /// that the address of the object must not be changed.
+ ///
+ /// Note that for types like [`Arc`], an `&mut Arc<T>` only gives you immutable access to the
+ /// inner value, so this method also only provides immutable access in that case.
+ ///
+ /// In the case of `Box<T>`, this method gives you the ability to modify the inner `T`, but it
+ /// does not let you change the box itself. That is, you cannot change which allocation the box
+ /// points at.
+ ///
+ /// # Safety
+ ///
+ /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
+ /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
+ /// the lifetime 'a.
+ ///
+ /// The lifetime 'a must not overlap with the lifetime of any other call to [`borrow`] or
+ /// `borrow_mut` on the same object.
+ ///
+ /// [`into_foreign`]: Self::into_foreign
+ /// [`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>;
}
impl ForeignOwnable for () {
type Borrowed<'a> = ();
+ type BorrowedMut<'a> = ();
- fn into_foreign(self) -> *const crate::ffi::c_void {
+ fn into_foreign(self) -> *mut crate::ffi::c_void {
core::ptr::NonNull::dangling().as_ptr()
}
- unsafe fn borrow<'a>(_: *const crate::ffi::c_void) -> Self::Borrowed<'a> {}
+ unsafe fn from_foreign(_: *mut crate::ffi::c_void) -> Self {}
- unsafe fn from_foreign(_: *const crate::ffi::c_void) -> 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> {}
}
/// Runs a cleanup function/closure when dropped.
@@ -434,7 +479,7 @@ impl<T: AlwaysRefCounted> ARef<T> {
/// }
///
/// let mut data = Empty {};
- /// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap();
+ /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();
/// # // SAFETY: TODO.
/// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
/// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index 05b0b8d13b10..719b0a48ff55 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -5,10 +5,10 @@
//! C header: [`include/linux/uaccess.h`](srctree/include/linux/uaccess.h)
use crate::{
- alloc::Flags,
+ alloc::{Allocator, Flags},
bindings,
error::Result,
- ffi::{c_ulong, c_void},
+ ffi::c_void,
prelude::*,
transmute::{AsBytes, FromBytes},
};
@@ -127,7 +127,7 @@ impl UserSlice {
/// Reads the entirety of the user slice, appending it to the end of the provided buffer.
///
/// Fails with [`EFAULT`] if the read happens on a bad address.
- pub fn read_all(self, buf: &mut KVec<u8>, flags: Flags) -> Result {
+ pub fn read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result {
self.reader().read_all(buf, flags)
}
@@ -224,13 +224,9 @@ impl UserSliceReader {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
- // SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write
+ // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
// that many bytes to it.
- let res =
- unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) };
+ let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) };
if res != 0 {
return Err(EFAULT);
}
@@ -259,9 +255,6 @@ impl UserSliceReader {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
let mut out: MaybeUninit<T> = MaybeUninit::uninit();
// SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes.
//
@@ -272,7 +265,7 @@ impl UserSliceReader {
bindings::_copy_from_user(
out.as_mut_ptr().cast::<c_void>(),
self.ptr as *const c_void,
- len_ulong,
+ len,
)
};
if res != 0 {
@@ -288,7 +281,7 @@ impl UserSliceReader {
/// Reads the entirety of the user slice, appending it to the end of the provided buffer.
///
/// Fails with [`EFAULT`] if the read happens on a bad address.
- pub fn read_all(mut self, buf: &mut KVec<u8>, flags: Flags) -> Result {
+ pub fn read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result {
let len = self.length;
buf.reserve(len, flags)?;
@@ -335,12 +328,9 @@ impl UserSliceWriter {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
- // SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read
+ // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read
// that many bytes from it.
- let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) };
+ let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) };
if res != 0 {
return Err(EFAULT);
}
@@ -359,9 +349,6 @@ impl UserSliceWriter {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
// SAFETY: The reference points to a value of type `T`, so it is valid for reading
// `size_of::<T>()` bytes.
//
@@ -372,7 +359,7 @@ impl UserSliceWriter {
bindings::_copy_to_user(
self.ptr as *mut c_void,
(value as *const T).cast::<c_void>(),
- len_ulong,
+ len,
)
};
if res != 0 {
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index fd3e97192ed8..0cd100d2aefb 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -69,6 +69,7 @@
//! fn print_later(val: Arc<MyStruct>) {
//! let _ = workqueue::system().enqueue(val);
//! }
+//! # print_later(MyStruct::new(42).unwrap());
//! ```
//!
//! The following example shows how multiple `work_struct` fields can be used:
@@ -126,6 +127,8 @@
//! fn print_2_later(val: Arc<MyStruct>) {
//! let _ = workqueue::system().enqueue::<Arc<MyStruct>, 2>(val);
//! }
+//! # print_1_later(MyStruct::new(24, 25).unwrap());
+//! # print_2_later(MyStruct::new(41, 42).unwrap());
//! ```
//!
//! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)