From: Asahi Lina <lina@asahilina.net>
By analogy to AlwaysRefCounted and ARef, an Ownable type is a (typically
C FFI) type that *may* be owned by Rust, but need not be. Unlike
AlwaysRefCounted, this mechanism expects the reference to be unique
within Rust, and does not allow cloning.
Conceptually, this is similar to a KBox<T>, except that it delegates
resource management to the T instead of using a generic allocator.
Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/
Signed-off-by: Asahi Lina <lina@asahilina.net>
[ om: make from_raw() and into_raw() public, small fixes to documentation ]
Signed-off-by: Oliver Mangold <oliver.mangold@pm.me>
---
rust/kernel/types.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 55ddd50e8aaa075ac33d5f1088a7f72df05f74f4..65f6d0721f5f23c8db79c6735dc7d5e1ac984ea7 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -551,6 +551,115 @@ fn drop(&mut self) {
}
}
+/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code.
+///
+/// It allows such types to define their own custom destructor function to be called when
+/// a Rust-owned reference is dropped.
+///
+/// This is usually implemented by wrappers to existing structures on the C side of the code.
+///
+/// # Safety
+///
+/// Implementers must ensure that any objects borrowed directly as `&T` stay alive for the duration
+/// of the lifetime, and that any objects owned by Rust as [`Owned<T>`] stay alive while that owned
+/// reference exists, until the [`Ownable::release()`] trait method is called.
+pub unsafe trait Ownable {
+ /// Releases the object (frees it or returns it to foreign ownership).
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that the object is no longer referenced after this call.
+ unsafe fn release(this: NonNull<Self>);
+}
+
+/// A subtrait of Ownable that asserts that an [`Owned<T>`] Rust reference is not only unique
+/// within Rust and keeps the `T` alive, but also guarantees that the C code follows the
+/// usual mutable reference requirements. That is, the kernel will never mutate the
+/// `T` (excluding internal mutability that follows the usual rules) while Rust owns it.
+///
+/// When this type is implemented for an [`Ownable`] type, it allows [`Owned<T>`] to be
+/// dereferenced into a &mut T.
+///
+/// # Safety
+///
+/// Implementers must ensure that the kernel never mutates the underlying type while
+/// Rust owns it.
+pub unsafe trait OwnableMut: Ownable {}
+
+/// An owned reference to an ownable kernel object.
+///
+/// The object is automatically freed or released when an instance of [`Owned`] is
+/// dropped.
+///
+/// # Invariants
+///
+/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance.
+pub struct Owned<T: Ownable> {
+ ptr: NonNull<T>,
+ _p: PhantomData<T>,
+}
+
+// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because
+// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`).
+unsafe impl<T: Ownable + Send> Send for Owned<T> {}
+
+// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync`
+// because it effectively means sharing `&T` (which is safe because `T` is `Sync`).
+unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
+
+impl<T: Ownable> Owned<T> {
+ /// Creates a new instance of [`Owned`].
+ ///
+ /// It takes over ownership of the underlying object.
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that the underlying object is acquired and can be considered owned by
+ /// Rust.
+ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
+ // INVARIANT: The safety requirements guarantee that the new instance now owns the
+ // reference.
+ Self {
+ ptr,
+ _p: PhantomData,
+ }
+ }
+
+ /// Consumes the [`Owned`], returning a raw pointer.
+ ///
+ /// This function does not actually relinquish ownership of the object.
+ /// After calling this function, the caller is responsible for ownership previously managed
+ /// by the [`Owned`].
+ pub fn into_raw(me: Self) -> NonNull<T> {
+ ManuallyDrop::new(me).ptr
+ }
+}
+
+impl<T: Ownable> Deref for Owned<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ // SAFETY: The type invariants guarantee that the object is valid.
+ unsafe { self.ptr.as_ref() }
+ }
+}
+
+impl<T: OwnableMut> DerefMut for Owned<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ // SAFETY: The type invariants guarantee that the object is valid,
+ // and that we can safely return a mutable reference to it.
+ unsafe { self.ptr.as_mut() }
+ }
+}
+
+impl<T: Ownable> Drop for Owned<T> {
+ fn drop(&mut self) {
+ // SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
+ // release.
+ unsafe { T::release(self.ptr) };
+ }
+}
+
/// A sum type that always holds either a value of type `L` or `R`.
///
/// # Examples
--
2.48.1
"Oliver Mangold" <oliver.mangold@pm.me> writes: > From: Asahi Lina <lina@asahilina.net> > > By analogy to AlwaysRefCounted and ARef, an Ownable type is a (typically > C FFI) type that *may* be owned by Rust, but need not be. Unlike > AlwaysRefCounted, this mechanism expects the reference to be unique > within Rust, and does not allow cloning. > > Conceptually, this is similar to a KBox<T>, except that it delegates > resource management to the T instead of using a generic allocator. > > Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/ > Signed-off-by: Asahi Lina <lina@asahilina.net> > [ om: make from_raw() and into_raw() public, small fixes to documentation ] > Signed-off-by: Oliver Mangold <oliver.mangold@pm.me> Please see review comments for the original posting of the patch from Alice [1] and me [2]. Best regards, Andreas Hindborg [1] https://lore.kernel.org/all/CAH5fLggscATtCgQwCYSms77oSFOMkjTscRDqAOZsSgoHsOoPQw@mail.gmail.com [2] https://lore.kernel.org/all/87h64qe3dt.fsf@kernel.org
On Thu, Mar 13, 2025 at 07:00:04AM +0000, Oliver Mangold wrote:
> From: Asahi Lina <lina@asahilina.net>
>
> By analogy to AlwaysRefCounted and ARef, an Ownable type is a (typically
> C FFI) type that *may* be owned by Rust, but need not be. Unlike
> AlwaysRefCounted, this mechanism expects the reference to be unique
> within Rust, and does not allow cloning.
>
> Conceptually, this is similar to a KBox<T>, except that it delegates
> resource management to the T instead of using a generic allocator.
>
> Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/
> Signed-off-by: Asahi Lina <lina@asahilina.net>
> [ om: make from_raw() and into_raw() public, small fixes to documentation ]
> Signed-off-by: Oliver Mangold <oliver.mangold@pm.me>
> ---
> rust/kernel/types.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
> index 55ddd50e8aaa075ac33d5f1088a7f72df05f74f4..65f6d0721f5f23c8db79c6735dc7d5e1ac984ea7 100644
> --- a/rust/kernel/types.rs
> +++ b/rust/kernel/types.rs
> @@ -551,6 +551,115 @@ fn drop(&mut self) {
> }
> }
>
> +/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code.
> +///
> +/// It allows such types to define their own custom destructor function to be called when
> +/// a Rust-owned reference is dropped.
> +///
> +/// This is usually implemented by wrappers to existing structures on the C side of the code.
> +///
> +/// # Safety
> +///
> +/// Implementers must ensure that any objects borrowed directly as `&T` stay alive for the duration
It may be more clear to use `&Ownable` instead of `&T`, but I will wait
and see if others have better ideas.
> +/// of the lifetime, and that any objects owned by Rust as [`Owned<T>`] stay alive while that owned
> +/// reference exists, until the [`Ownable::release()`] trait method is called.
> +pub unsafe trait Ownable {
> + /// Releases the object (frees it or returns it to foreign ownership).
> + ///
> + /// # Safety
> + ///
> + /// Callers must ensure that the object is no longer referenced after this call.
> + unsafe fn release(this: NonNull<Self>);
> +}
> +
> +/// A subtrait of Ownable that asserts that an [`Owned<T>`] Rust reference is not only unique
> +/// within Rust and keeps the `T` alive, but also guarantees that the C code follows the
> +/// usual mutable reference requirements. That is, the kernel will never mutate the
> +/// `T` (excluding internal mutability that follows the usual rules) while Rust owns it.
> +///
> +/// When this type is implemented for an [`Ownable`] type, it allows [`Owned<T>`] to be
> +/// dereferenced into a &mut T.
> +///
> +/// # Safety
> +///
> +/// Implementers must ensure that the kernel never mutates the underlying type while
> +/// Rust owns it.
> +pub unsafe trait OwnableMut: Ownable {}
> +
> +/// An owned reference to an ownable kernel object.
> +///
> +/// The object is automatically freed or released when an instance of [`Owned`] is
> +/// dropped.
> +///
> +/// # Invariants
> +///
> +/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance.
> +pub struct Owned<T: Ownable> {
This can be:
pub struct Owned<T: Ownable + ?Sized>
right? Hmm.. but `ARef` doesn't support trait objects yet. Maybe it
makes sense to support for both `Owned` and `ARef` later?
> + ptr: NonNull<T>,
> + _p: PhantomData<T>,
> +}
> +
> +// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because
> +// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`).
> +unsafe impl<T: Ownable + Send> Send for Owned<T> {}
> +
> +// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync`
> +// because it effectively means sharing `&T` (which is safe because `T` is `Sync`).
> +unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
> +
> +impl<T: Ownable> Owned<T> {
> + /// Creates a new instance of [`Owned`].
> + ///
> + /// It takes over ownership of the underlying object.
> + ///
> + /// # Safety
> + ///
> + /// Callers must ensure that the underlying object is acquired and can be considered owned by
> + /// Rust.
> + pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
> + // INVARIANT: The safety requirements guarantee that the new instance now owns the
> + // reference.
> + Self {
> + ptr,
> + _p: PhantomData,
> + }
> + }
> +
> + /// Consumes the [`Owned`], returning a raw pointer.
> + ///
> + /// This function does not actually relinquish ownership of the object.
> + /// After calling this function, the caller is responsible for ownership previously managed
> + /// by the [`Owned`].
> + pub fn into_raw(me: Self) -> NonNull<T> {
> + ManuallyDrop::new(me).ptr
> + }
> +}
> +
> +impl<T: Ownable> Deref for Owned<T> {
> + type Target = T;
> +
> + fn deref(&self) -> &Self::Target {
> + // SAFETY: The type invariants guarantee that the object is valid.
> + unsafe { self.ptr.as_ref() }
> + }
> +}
> +
> +impl<T: OwnableMut> DerefMut for Owned<T> {
> + fn deref_mut(&mut self) -> &mut Self::Target {
> + // SAFETY: The type invariants guarantee that the object is valid,
> + // and that we can safely return a mutable reference to it.
> + unsafe { self.ptr.as_mut() }
> + }
> +}
> +
> +impl<T: Ownable> Drop for Owned<T> {
> + fn drop(&mut self) {
> + // SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
> + // release.
> + unsafe { T::release(self.ptr) };
> + }
> +}
> +
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Regards,
Boqun
> /// A sum type that always holds either a value of type `L` or `R`.
> ///
> /// # Examples
>
> --
> 2.48.1
>
>
On 250321 0908, Boqun Feng wrote: > > Reviewed-by: Boqun Feng <boqun.feng@gmail.com> > > Regards, > Boqun Hi, I only added the Reviewed-By tag to the Owned/Ownable commit from Asahi Lina for now, as you added this comment only to the reply to this commit. Let me know, if you want it added to the other commits, too. Best regards, Oliver
© 2016 - 2025 Red Hat, Inc.