Re: [PATCH v3] rust: sync: Accept errors for Lock payload data
From: Gary Guo
Date: Mon Oct 19 2026 - 13:37:32 EST
On Fri Oct 16, 2026 at 1:09 PM BST, Philipp Stanner wrote:
> The `Lock` baseclass currently does not allow for fallible user-data.
> This can cause conflicts when used with other primitives, for example
> when a lock shall be pin-initialized with payload data that is fallible.
>
> Add support for the lock base class so that it works with
> try_pin_init!(). Adjust spinlock and mutex accordingly.
>
> Signed-off-by: Philipp Stanner <phasta@xxxxxxxxxx>
> ---
> Changes in v3:
> - Vertical formatting for imports
>
> Changes in v2:
> - Don't import prelude in doctests. (Gary)
> - Keep using pin_init! over try_pin_init! in Lock::new(). (Gary)
> ---
> rust/kernel/sync/lock.rs | 23 +++++++++++++++++------
> rust/kernel/sync/lock/mutex.rs | 6 +++---
> rust/kernel/sync/lock/spinlock.rs | 17 +++++++----------
> 3 files changed, 27 insertions(+), 19 deletions(-)
>
> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> index 10b6b5e9b024..5bff5228ac16 100644
> --- a/rust/kernel/sync/lock.rs
> +++ b/rust/kernel/sync/lock.rs
> @@ -7,11 +7,17 @@
>
> use super::LockClassKey;
> use crate::{
> - str::{CStr, CStrExt as _},
> + str::CStr,
> types::{NotThreadSafe, Opaque, ScopeGuard},
> };
> use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
> -use pin_init::{pin_data, pin_init, PinInit, Wrapper};
> +use pin_init::{
> + pin_data,
> + PinInit,
> + Wrapper, //
> +};
> +
> +use kernel::prelude::*;
This should be part of the `crate::` import.
>
> pub mod mutex;
> pub mod spinlock;
> @@ -126,13 +132,18 @@ unsafe impl<T: ?Sized + Send, B: Backend> Send for Lock<T, B> {}
> // data it protects is `Send`.
> unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
>
> +use core::convert::Infallible;
Should be part of import above.
> +
> impl<T, B: Backend> Lock<T, B> {
> /// Constructs a new lock initialiser.
> - pub fn new(
> - t: impl PinInit<T>,
> + pub fn new<E>(
> + t: impl PinInit<T, E>,
> name: &'static CStr,
> key: Pin<&'static LockClassKey>,
> - ) -> impl PinInit<Self> {
> + ) -> impl PinInit<Self, E>
> + where
> + E: From<Infallible>,
> + {
> pin_init!(Self {
> data <- UnsafeCell::pin_init(t),
> _pin: PhantomPinned,
> @@ -141,7 +152,7 @@ pub fn new(
> state <- Opaque::ffi_init(|slot| unsafe {
> B::init(slot, name.as_char_ptr(), key.as_ptr())
> }),
> - })
> + }? E)
> }
> }
>
> diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs
> index cda0203efefb..38d8fb9dad5d 100644
> --- a/rust/kernel/sync/lock/mutex.rs
> +++ b/rust/kernel/sync/lock/mutex.rs
> @@ -49,8 +49,8 @@ macro_rules! new_mutex {
> /// }
> ///
> /// impl Example {
> -/// fn new() -> impl PinInit<Self> {
> -/// pin_init!(Self {
> +/// fn new() -> impl PinInit<Self, Error> {
> +/// try_pin_init!(Self {
The example don't need to be changed? The existing API would still work with
`pin_init!` with just `E` inferred to be `Infallible`.
Best,
Gary
> /// c: 10,
> /// d <- new_mutex!(Inner { a: 20, b: 30 }),
> /// })
> @@ -58,7 +58,7 @@ macro_rules! new_mutex {
> /// }
> ///
> /// // Allocate a boxed `Example`.
> -/// let e = KBox::pin_init(Example::new(), GFP_KERNEL)?;
> +/// let e = KBox::try_pin_init(Example::new(), GFP_KERNEL)?;
> /// assert_eq!(e.c, 10);
> /// assert_eq!(e.d.lock().a, 20);
> /// assert_eq!(e.d.lock().b, 30);