Re: [PATCH v17 03/10] rust: implement `ForeignOwnable` for `Owned`
From: "Gary Guo" <gary@garyguo.net>
Date: 2026-06-16 11:55:58
Also in:
dri-devel, driver-core, linux-block, linux-fsdevel, linux-mm, linux-pci, linux-pm, lkml, rust-for-linux
On Thu Jun 4, 2026 at 9:11 PM BST, Andreas Hindborg wrote:
quoted hunk ↗ jump to hunk
Implement `ForeignOwnable` for `Owned<T>`. This allows use of `Owned<T>` in places such as the `XArray`. Note that `T` does not need to implement `ForeignOwnable` for `Owned<T>` to implement `ForeignOwnable`. Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org> --- rust/kernel/owned.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 456e239e906e..5eacdf327d12 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs@@ -15,6 +15,8 @@ ptr::NonNull, // }; +use kernel::types::ForeignOwnable; + /// Types that specify their own way of performing allocation and destruction. Typically, this trait /// is implemented on types from the C side. ///@@ -108,6 +110,7 @@ pub trait Ownable { /// /// - Until `T::release` is called, this `Owned<T>` exclusively owns the underlying `T`. /// - The `T` value is pinned. +#[repr(transparent)]
AFAIT this `#[repr(transparent)]` isn't actually needed.
quoted hunk ↗ jump to hunk
pub struct Owned<T: Ownable> { ptr: NonNull<T>, }@@ -185,3 +188,46 @@ fn drop(&mut self) { unsafe { T::release(self.ptr.as_mut()) }; } } + +// SAFETY: We derive the pointer to `T` from a valid `T`, so the returned +// pointer satisfy alignment requirements of `T`. +unsafe impl<T: Ownable + 'static> ForeignOwnable for Owned<T> {
You should drop the `'static` bound and put where bound on the GAT below instead. See how `Box` is doing it. Best, Gary
+ const FOREIGN_ALIGN: usize = core::mem::align_of::<Owned<T>>();
+
+ type Borrowed<'a> = &'a T;
+ type BorrowedMut<'a> = Pin<&'a mut T>;
+
+ #[inline]
+ fn into_foreign(self) -> *mut kernel::ffi::c_void {
+ let ptr = self.ptr.as_ptr().cast();
+ core::mem::forget(self);
+ ptr
+ }
+
+ #[inline]
+ unsafe fn from_foreign(ptr: *mut kernel::ffi::c_void) -> Self {
+ Self {
+ // SAFETY: By function safety contract, `ptr` came from
+ // `into_foreign` and cannot be null.
+ ptr: unsafe { NonNull::new_unchecked(ptr.cast()) },
+ }
+ }
+
+ #[inline]
+ unsafe fn borrow<'a>(ptr: *mut kernel::ffi::c_void) -> Self::Borrowed<'a> {
+ // SAFETY: By function safety requirements, `ptr` is valid for use as a
+ // reference for `'a`.
+ unsafe { &*ptr.cast() }
+ }
+
+ #[inline]
+ unsafe fn borrow_mut<'a>(ptr: *mut kernel::ffi::c_void) -> Self::BorrowedMut<'a> {
+ // SAFETY: By function safety requirements, `ptr` is valid for use as a
+ // unique reference for `'a`.
+ let inner = unsafe { &mut *ptr.cast() };
+
+ // SAFETY: We never move out of inner, and we do not hand out mutable
+ // references when `T: !Unpin`.
+ unsafe { Pin::new_unchecked(inner) }
+ }
+}