Skip to content

Commit cac6062

Browse files
asahilinaintel-lab-lkp
authored andcommitted
rust: types: Add Ownable/Owned types
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: - split code into separate file and `pub use` it from types.rs - make from_raw() and into_raw() public - fixes to documentation ] Signed-off-by: Oliver Mangold <oliver.mangold@pm.me> Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
1 parent 4701f33 commit cac6062

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub mod miscdevice;
6161
#[cfg(CONFIG_NET)]
6262
pub mod net;
6363
pub mod of;
64+
pub mod ownable;
6465
pub mod page;
6566
#[cfg(CONFIG_PCI)]
6667
pub mod pci;

rust/kernel/ownable.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Owned reference types.
4+
5+
use core::{
6+
marker::PhantomData,
7+
mem::ManuallyDrop,
8+
ops::{Deref, DerefMut},
9+
ptr::NonNull,
10+
};
11+
12+
/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code.
13+
///
14+
/// It allows such types to define their own custom destructor function to be called when
15+
/// a Rust-owned reference is dropped.
16+
///
17+
/// This is usually implemented by wrappers to existing structures on the C side of the code.
18+
///
19+
/// # Safety
20+
///
21+
/// Implementers must ensure that:
22+
/// - Any objects owned by Rust as [`Owned<T>`] stay alive while that owned reference exists (i.e.
23+
/// until the [`release()`](Ownable::release) trait method is called).
24+
/// - That the C code follows the usual mutable reference requirements. That is, the kernel will
25+
/// never mutate the [`Ownable`] (excluding internal mutability that follows the usual rules)
26+
/// while Rust owns it.
27+
pub unsafe trait Ownable {
28+
/// Releases the object (frees it or returns it to foreign ownership).
29+
///
30+
/// # Safety
31+
///
32+
/// Callers must ensure that the object is no longer referenced after this call.
33+
unsafe fn release(this: NonNull<Self>);
34+
}
35+
36+
/// A subtrait of Ownable that asserts that an [`Owned<T>`] or `&mut Owned<T>` Rust reference
37+
/// may be dereferenced into a `&mut T`.
38+
///
39+
/// # Safety
40+
///
41+
/// Implementers must ensure that access to a `&mut T` is safe, implying that it is okay to call
42+
/// [`core::mem::swap`] on the `Ownable`. This excludes pinned types (meaning: most kernel types).
43+
pub unsafe trait OwnableMut: Ownable {}
44+
45+
/// An owned reference to an ownable kernel object.
46+
///
47+
/// The object is automatically freed or released when an instance of [`Owned`] is
48+
/// dropped.
49+
///
50+
/// # Invariants
51+
///
52+
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance.
53+
pub struct Owned<T: Ownable> {
54+
ptr: NonNull<T>,
55+
_p: PhantomData<T>,
56+
}
57+
58+
// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because
59+
// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`).
60+
unsafe impl<T: Ownable + Send> Send for Owned<T> {}
61+
62+
// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync`
63+
// because it effectively means sharing `&T` (which is safe because `T` is `Sync`).
64+
unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
65+
66+
impl<T: Ownable> Owned<T> {
67+
/// Creates a new instance of [`Owned`].
68+
///
69+
/// It takes over ownership of the underlying object.
70+
///
71+
/// # Safety
72+
///
73+
/// Callers must ensure that the underlying object is acquired and can be considered owned by
74+
/// Rust.
75+
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
76+
// INVARIANT: The safety requirements guarantee that the new instance now owns the
77+
// reference.
78+
Self {
79+
ptr,
80+
_p: PhantomData,
81+
}
82+
}
83+
84+
/// Consumes the [`Owned`], returning a raw pointer.
85+
///
86+
/// This function does not actually relinquish ownership of the object.
87+
/// After calling this function, the caller is responsible for ownership previously managed
88+
/// by the [`Owned`].
89+
pub fn into_raw(me: Self) -> NonNull<T> {
90+
ManuallyDrop::new(me).ptr
91+
}
92+
}
93+
94+
impl<T: Ownable> Deref for Owned<T> {
95+
type Target = T;
96+
97+
fn deref(&self) -> &Self::Target {
98+
// SAFETY: The type invariants guarantee that the object is valid.
99+
unsafe { self.ptr.as_ref() }
100+
}
101+
}
102+
103+
impl<T: OwnableMut> DerefMut for Owned<T> {
104+
fn deref_mut(&mut self) -> &mut Self::Target {
105+
// SAFETY: The type invariants guarantee that the object is valid,
106+
// and that we can safely return a mutable reference to it.
107+
unsafe { self.ptr.as_mut() }
108+
}
109+
}
110+
111+
impl<T: Ownable> Drop for Owned<T> {
112+
fn drop(&mut self) {
113+
// SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
114+
// release.
115+
unsafe { T::release(self.ptr) };
116+
}
117+
}

rust/kernel/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use core::{
1111
ptr::NonNull,
1212
};
1313

14+
pub use crate::ownable::{Ownable, OwnableMut, Owned};
15+
1416
/// Used to transfer ownership to and from foreign (non-Rust) languages.
1517
///
1618
/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and

0 commit comments

Comments
 (0)