[PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor

Daniel Almeida posted 3 patches 1 month ago
[PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Daniel Almeida 1 month ago
In order for callers to be able to access the inner T safely if T: !Unpin,
there needs to be a way to get a Pin<&mut T>. Add this accessor and a
corresponding example to tell users how it works.

This is not useful on its own for now, because we do not support pin
projections yet. This means that the following is not going to compile:

    let mut data: MutexGuard<'_, Data> = mutex.lock();
    let mut data: Pin<&mut Data> = data.as_mut();
    let foo = &mut data.foo;

A future patch can enable the behavior above by implementing support for
pin projections. Said patch is in the works already and will possibly
land on 6.18.

Link: https://github.com/Rust-for-Linux/linux/issues/1181
Suggested-by: Benno Lossin <lossin@kernel.org>
Suggested-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
 rust/kernel/sync/lock.rs | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index 9242790d15dbf65d66518d060a8a777aac558cfc..7191804a244da05db74294fdec598f1a4732682c 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -245,6 +245,31 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
 
         cb()
     }
+
+    /// Returns a pinned mutable reference to the protected data.
+    ///
+    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
+    /// types [`DerefMut`] should be used instead of this function.
+    ///
+    /// [`DerefMut`]: core::ops::DerefMut
+    /// [`Unpin`]: core::marker::Unpin
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use kernel::sync::{Mutex, MutexGuard};
+    /// # use core::pin::Pin;
+    /// struct Data;
+    ///
+    /// fn example(mutex: &Mutex<Data>) {
+    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
+    ///   let mut data: Pin<&mut Data> = data.as_mut();
+    ///  }
+    /// ```
+    pub fn as_mut(&mut self) -> Pin<&mut T> {
+        // SAFETY: `self.lock.data` is structurally pinned.
+        unsafe { Pin::new_unchecked(&mut *self.lock.data.get()) }
+    }
 }
 
 impl<T: ?Sized, B: Backend> core::ops::Deref for Guard<'_, T, B> {

-- 
2.50.1
Re: [PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Benno Lossin 4 weeks, 1 day ago
On Thu Aug 28, 2025 at 10:52 PM CEST, Daniel Almeida wrote:
> In order for callers to be able to access the inner T safely if T: !Unpin,
> there needs to be a way to get a Pin<&mut T>. Add this accessor and a
> corresponding example to tell users how it works.
>
> This is not useful on its own for now, because we do not support pin
> projections yet. This means that the following is not going to compile:
>
>     let mut data: MutexGuard<'_, Data> = mutex.lock();
>     let mut data: Pin<&mut Data> = data.as_mut();
>     let foo = &mut data.foo;
>
> A future patch can enable the behavior above by implementing support for
> pin projections. Said patch is in the works already and will possibly
> land on 6.18.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1181
> Suggested-by: Benno Lossin <lossin@kernel.org>
> Suggested-by: Boqun Feng <boqun.feng@gmail.com>
> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
> Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>

Reviewed-by: Benno Lossin <lossin@kernel.org>

> ---
>  rust/kernel/sync/lock.rs | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> index 9242790d15dbf65d66518d060a8a777aac558cfc..7191804a244da05db74294fdec598f1a4732682c 100644
> --- a/rust/kernel/sync/lock.rs
> +++ b/rust/kernel/sync/lock.rs
> @@ -245,6 +245,31 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
>  
>          cb()
>      }
> +
> +    /// Returns a pinned mutable reference to the protected data.
> +    ///
> +    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
> +    /// types [`DerefMut`] should be used instead of this function.
> +    ///
> +    /// [`DerefMut`]: core::ops::DerefMut
> +    /// [`Unpin`]: core::marker::Unpin
> +    ///
> +    /// # Examples
> +    ///
> +    /// ```
> +    /// # use kernel::sync::{Mutex, MutexGuard};
> +    /// # use core::pin::Pin;
> +    /// struct Data;
> +    ///
> +    /// fn example(mutex: &Mutex<Data>) {
> +    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
> +    ///   let mut data: Pin<&mut Data> = data.as_mut();
> +    ///  }

The formatting looks off in this one, there should be 4 spaces of
indentation here; there are also 2 spaces in front of the `}`.

Also `Data` implements `Unpin`, so you're not following your own
recommendation from above :)

---
Cheers,
Benno

> +    /// ```
> +    pub fn as_mut(&mut self) -> Pin<&mut T> {
> +        // SAFETY: `self.lock.data` is structurally pinned.
> +        unsafe { Pin::new_unchecked(&mut *self.lock.data.get()) }
> +    }
>  }
>  
>  impl<T: ?Sized, B: Backend> core::ops::Deref for Guard<'_, T, B> {
Re: [PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Daniel Almeida 4 weeks, 1 day ago

> On 4 Sep 2025, at 12:13, Benno Lossin <lossin@kernel.org> wrote:
> 
> On Thu Aug 28, 2025 at 10:52 PM CEST, Daniel Almeida wrote:
>> In order for callers to be able to access the inner T safely if T: !Unpin,
>> there needs to be a way to get a Pin<&mut T>. Add this accessor and a
>> corresponding example to tell users how it works.
>> 
>> This is not useful on its own for now, because we do not support pin
>> projections yet. This means that the following is not going to compile:
>> 
>>    let mut data: MutexGuard<'_, Data> = mutex.lock();
>>    let mut data: Pin<&mut Data> = data.as_mut();
>>    let foo = &mut data.foo;
>> 
>> A future patch can enable the behavior above by implementing support for
>> pin projections. Said patch is in the works already and will possibly
>> land on 6.18.
>> 
>> Link: https://github.com/Rust-for-Linux/linux/issues/1181
>> Suggested-by: Benno Lossin <lossin@kernel.org>
>> Suggested-by: Boqun Feng <boqun.feng@gmail.com>
>> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
>> Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
> 
> Reviewed-by: Benno Lossin <lossin@kernel.org>
> 
>> ---
>> rust/kernel/sync/lock.rs | 25 +++++++++++++++++++++++++
>> 1 file changed, 25 insertions(+)
>> 
>> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
>> index 9242790d15dbf65d66518d060a8a777aac558cfc..7191804a244da05db74294fdec598f1a4732682c 100644
>> --- a/rust/kernel/sync/lock.rs
>> +++ b/rust/kernel/sync/lock.rs
>> @@ -245,6 +245,31 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
>> 
>>         cb()
>>     }
>> +
>> +    /// Returns a pinned mutable reference to the protected data.
>> +    ///
>> +    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
>> +    /// types [`DerefMut`] should be used instead of this function.
>> +    ///
>> +    /// [`DerefMut`]: core::ops::DerefMut
>> +    /// [`Unpin`]: core::marker::Unpin
>> +    ///
>> +    /// # Examples
>> +    ///
>> +    /// ```
>> +    /// # use kernel::sync::{Mutex, MutexGuard};
>> +    /// # use core::pin::Pin;
>> +    /// struct Data;
>> +    ///
>> +    /// fn example(mutex: &Mutex<Data>) {
>> +    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
>> +    ///   let mut data: Pin<&mut Data> = data.as_mut();
>> +    ///  }
> 
> The formatting looks off in this one, there should be 4 spaces of
> indentation here; there are also 2 spaces in front of the `}`.
> 
> Also `Data` implements `Unpin`, so you're not following your own
> recommendation from above :)

I’ll fix this :)

— Daniel

> 
> ---
> Cheers,
> Benno
> 
>> +    /// ```
>> +    pub fn as_mut(&mut self) -> Pin<&mut T> {
>> +        // SAFETY: `self.lock.data` is structurally pinned.
>> +        unsafe { Pin::new_unchecked(&mut *self.lock.data.get()) }
>> +    }
>> }
>> 
>> impl<T: ?Sized, B: Backend> core::ops::Deref for Guard<'_, T, B> {
Re: [PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Boqun Feng 3 weeks, 4 days ago
On Thu, Sep 04, 2025 at 12:15:43PM -0300, Daniel Almeida wrote:
> 
> 
> > On 4 Sep 2025, at 12:13, Benno Lossin <lossin@kernel.org> wrote:
> > 
> > On Thu Aug 28, 2025 at 10:52 PM CEST, Daniel Almeida wrote:
> >> In order for callers to be able to access the inner T safely if T: !Unpin,
> >> there needs to be a way to get a Pin<&mut T>. Add this accessor and a
> >> corresponding example to tell users how it works.
> >> 
> >> This is not useful on its own for now, because we do not support pin
> >> projections yet. This means that the following is not going to compile:
> >> 
> >>    let mut data: MutexGuard<'_, Data> = mutex.lock();
> >>    let mut data: Pin<&mut Data> = data.as_mut();
> >>    let foo = &mut data.foo;
> >> 
> >> A future patch can enable the behavior above by implementing support for
> >> pin projections. Said patch is in the works already and will possibly
> >> land on 6.18.
> >> 
> >> Link: https://github.com/Rust-for-Linux/linux/issues/1181
> >> Suggested-by: Benno Lossin <lossin@kernel.org>
> >> Suggested-by: Boqun Feng <boqun.feng@gmail.com>
> >> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
> >> Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
> > 
> > Reviewed-by: Benno Lossin <lossin@kernel.org>
> > 
> >> ---
> >> rust/kernel/sync/lock.rs | 25 +++++++++++++++++++++++++
> >> 1 file changed, 25 insertions(+)
> >> 
> >> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> >> index 9242790d15dbf65d66518d060a8a777aac558cfc..7191804a244da05db74294fdec598f1a4732682c 100644
> >> --- a/rust/kernel/sync/lock.rs
> >> +++ b/rust/kernel/sync/lock.rs
> >> @@ -245,6 +245,31 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
> >> 
> >>         cb()
> >>     }
> >> +
> >> +    /// Returns a pinned mutable reference to the protected data.
> >> +    ///
> >> +    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
> >> +    /// types [`DerefMut`] should be used instead of this function.
> >> +    ///
> >> +    /// [`DerefMut`]: core::ops::DerefMut
> >> +    /// [`Unpin`]: core::marker::Unpin
> >> +    ///
> >> +    /// # Examples
> >> +    ///
> >> +    /// ```
> >> +    /// # use kernel::sync::{Mutex, MutexGuard};
> >> +    /// # use core::pin::Pin;
> >> +    /// struct Data;
> >> +    ///
> >> +    /// fn example(mutex: &Mutex<Data>) {
> >> +    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
> >> +    ///   let mut data: Pin<&mut Data> = data.as_mut();
> >> +    ///  }
> > 
> > The formatting looks off in this one, there should be 4 spaces of
> > indentation here; there are also 2 spaces in front of the `}`.
> > 
> > Also `Data` implements `Unpin`, so you're not following your own
> > recommendation from above :)
> 
> I´ll fix this :)
> 

If the fix is small, feel free to send a diff and I can fold it when
queueing (i.e. no need to resend the whole series). I'm trying to send
it to tip before -rc6 so there will be some more tests. Thanks!

Regards,
Boqun

> - Daniel
> 
> > 
> > ---
> > Cheers,
> > Benno
> > 
> >> +    /// ```
> >> +    pub fn as_mut(&mut self) -> Pin<&mut T> {
> >> +        // SAFETY: `self.lock.data` is structurally pinned.
> >> +        unsafe { Pin::new_unchecked(&mut *self.lock.data.get()) }
> >> +    }
> >> }
> >> 
> >> impl<T: ?Sized, B: Backend> core::ops::Deref for Guard<'_, T, B> {
> 
> 
Re: [PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Daniel Almeida 3 weeks, 2 days ago
Hi Boqun, sorry for the delay,

>>>> +
>>>> +    /// Returns a pinned mutable reference to the protected data.
>>>> +    ///
>>>> +    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
>>>> +    /// types [`DerefMut`] should be used instead of this function.
>>>> +    ///
>>>> +    /// [`DerefMut`]: core::ops::DerefMut
>>>> +    /// [`Unpin`]: core::marker::Unpin
>>>> +    ///
>>>> +    /// # Examples
>>>> +    ///
>>>> +    /// ```
>>>> +    /// # use kernel::sync::{Mutex, MutexGuard};
>>>> +    /// # use core::pin::Pin;
>>>> +    /// struct Data;
>>>> +    ///
>>>> +    /// fn example(mutex: &Mutex<Data>) {
>>>> +    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
>>>> +    ///   let mut data: Pin<&mut Data> = data.as_mut();
>>>> +    ///  }
>>> 
>>> The formatting looks off in this one, there should be 4 spaces of
>>> indentation here; there are also 2 spaces in front of the `}`.
>>> 
>>> Also `Data` implements `Unpin`, so you're not following your own
>>> recommendation from above :)
>> 
>> I´ll fix this :)
>> 
> 
> If the fix is small, feel free to send a diff and I can fold it when
> queueing (i.e. no need to resend the whole series). I'm trying to send
> it to tip before -rc6 so there will be some more tests. Thanks!
> 
> Regards,
> Boqun
> 


This should address what Benno pointed out:


diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index 7191804a244d..cb00fdb94ffd 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -258,13 +258,13 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
     ///
     /// ```
     /// # use kernel::sync::{Mutex, MutexGuard};
-    /// # use core::pin::Pin;
-    /// struct Data;
+    /// # use core::{pin::Pin, marker::PhantomPinned};
+    /// struct Data(PhantomPinned);
     ///
     /// fn example(mutex: &Mutex<Data>) {
-    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
-    ///   let mut data: Pin<&mut Data> = data.as_mut();
-    ///  }
+    ///     let mut data: MutexGuard<'_, Data> = mutex.lock();
+    ///     let mut data: Pin<&mut Data> = data.as_mut();
+    /// }
     /// ```
     pub fn as_mut(&mut self) -> Pin<&mut T> {
         // SAFETY: `self.lock.data` is structurally pinned.
Re: [PATCH v2 3/3] rust: lock: add a Pin<&mut T> accessor
Posted by Boqun Feng 2 weeks, 4 days ago
On Tue, Sep 09, 2025 at 04:50:19PM -0300, Daniel Almeida wrote:
> Hi Boqun, sorry for the delay,
> 
> >>>> +
> >>>> +    /// Returns a pinned mutable reference to the protected data.
> >>>> +    ///
> >>>> +    /// The guard implements [`DerefMut`] when `T: Unpin`, so for [`Unpin`]
> >>>> +    /// types [`DerefMut`] should be used instead of this function.
> >>>> +    ///
> >>>> +    /// [`DerefMut`]: core::ops::DerefMut
> >>>> +    /// [`Unpin`]: core::marker::Unpin
> >>>> +    ///
> >>>> +    /// # Examples
> >>>> +    ///
> >>>> +    /// ```
> >>>> +    /// # use kernel::sync::{Mutex, MutexGuard};
> >>>> +    /// # use core::pin::Pin;
> >>>> +    /// struct Data;
> >>>> +    ///
> >>>> +    /// fn example(mutex: &Mutex<Data>) {
> >>>> +    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
> >>>> +    ///   let mut data: Pin<&mut Data> = data.as_mut();
> >>>> +    ///  }
> >>> 
> >>> The formatting looks off in this one, there should be 4 spaces of
> >>> indentation here; there are also 2 spaces in front of the `}`.
> >>> 
> >>> Also `Data` implements `Unpin`, so you're not following your own
> >>> recommendation from above :)
> >> 
> >> I´ll fix this :)
> >> 
> > 
> > If the fix is small, feel free to send a diff and I can fold it when
> > queueing (i.e. no need to resend the whole series). I'm trying to send
> > it to tip before -rc6 so there will be some more tests. Thanks!
> > 
> > Regards,
> > Boqun
> > 
> 
> 
> This should address what Benno pointed out:
> 
> 
> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> index 7191804a244d..cb00fdb94ffd 100644
> --- a/rust/kernel/sync/lock.rs
> +++ b/rust/kernel/sync/lock.rs
> @@ -258,13 +258,13 @@ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
>      ///
>      /// ```
>      /// # use kernel::sync::{Mutex, MutexGuard};
> -    /// # use core::pin::Pin;
> -    /// struct Data;
> +    /// # use core::{pin::Pin, marker::PhantomPinned};
> +    /// struct Data(PhantomPinned);
>      ///
>      /// fn example(mutex: &Mutex<Data>) {
> -    ///   let mut data: MutexGuard<'_, Data> = mutex.lock();
> -    ///   let mut data: Pin<&mut Data> = data.as_mut();
> -    ///  }
> +    ///     let mut data: MutexGuard<'_, Data> = mutex.lock();
> +    ///     let mut data: Pin<&mut Data> = data.as_mut();
> +    /// }
>      /// ```
>      pub fn as_mut(&mut self) -> Pin<&mut T> {
>          // SAFETY: `self.lock.data` is structurally pinned.

Applied and queued:

	git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git locking

I also remove the part in the commit log where it mentioned about pin
projection, since the pull request for that is already created and
merged. Thanks!

I will give it some tests and see if I could send a pull request to tip
early next week, so it can be in v6.18.

Regards,
Boqun