Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/init.rs
29266 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Extensions to the [`pin-init`] crate.
4
//!
5
//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
6
//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
7
//!
8
//! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer
9
//! to its documentation to better understand how to use it. Additionally, there are many examples
10
//! throughout the kernel, such as the types from the [`sync`] module. And the ones presented
11
//! below.
12
//!
13
//! [`sync`]: crate::sync
14
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
15
//! [`pin-init`]: https://rust.docs.kernel.org/pin_init/
16
//!
17
//! # [`Opaque<T>`]
18
//!
19
//! For the special case where initializing a field is a single FFI-function call that cannot fail,
20
//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
21
//! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in
22
//! combination with [`pin_init!`].
23
//!
24
//! [`Opaque<T>`]: crate::types::Opaque
25
//! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init
26
//! [`pin_init!`]: pin_init::pin_init
27
//!
28
//! # Examples
29
//!
30
//! ## General Examples
31
//!
32
//! ```rust
33
//! # #![expect(clippy::disallowed_names, clippy::undocumented_unsafe_blocks)]
34
//! use kernel::types::Opaque;
35
//! use pin_init::pin_init_from_closure;
36
//!
37
//! // assume we have some `raw_foo` type in C:
38
//! #[repr(C)]
39
//! struct RawFoo([u8; 16]);
40
//! extern "C" {
41
//! fn init_foo(_: *mut RawFoo);
42
//! }
43
//!
44
//! #[pin_data]
45
//! struct Foo {
46
//! #[pin]
47
//! raw: Opaque<RawFoo>,
48
//! }
49
//!
50
//! impl Foo {
51
//! fn setup(self: Pin<&mut Self>) {
52
//! pr_info!("Setting up foo\n");
53
//! }
54
//! }
55
//!
56
//! let foo = pin_init!(Foo {
57
//! raw <- unsafe {
58
//! Opaque::ffi_init(|s| {
59
//! // note that this cannot fail.
60
//! init_foo(s);
61
//! })
62
//! },
63
//! }).pin_chain(|foo| {
64
//! foo.setup();
65
//! Ok(())
66
//! });
67
//! ```
68
//!
69
//! ```rust
70
//! # #![expect(unreachable_pub, clippy::disallowed_names)]
71
//! use kernel::{prelude::*, types::Opaque};
72
//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
73
//! # mod bindings {
74
//! # #![expect(non_camel_case_types, clippy::missing_safety_doc)]
75
//! # pub struct foo;
76
//! # pub unsafe fn init_foo(_ptr: *mut foo) {}
77
//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}
78
//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }
79
//! # }
80
//! /// # Invariants
81
//! ///
82
//! /// `foo` is always initialized
83
//! #[pin_data(PinnedDrop)]
84
//! pub struct RawFoo {
85
//! #[pin]
86
//! foo: Opaque<bindings::foo>,
87
//! #[pin]
88
//! _p: PhantomPinned,
89
//! }
90
//!
91
//! impl RawFoo {
92
//! pub fn new(flags: u32) -> impl PinInit<Self, Error> {
93
//! // SAFETY:
94
//! // - when the closure returns `Ok(())`, then it has successfully initialized and
95
//! // enabled `foo`,
96
//! // - when it returns `Err(e)`, then it has cleaned up before
97
//! unsafe {
98
//! pin_init::pin_init_from_closure(move |slot: *mut Self| {
99
//! // `slot` contains uninit memory, avoid creating a reference.
100
//! let foo = addr_of_mut!((*slot).foo);
101
//!
102
//! // Initialize the `foo`
103
//! bindings::init_foo(Opaque::cast_into(foo));
104
//!
105
//! // Try to enable it.
106
//! let err = bindings::enable_foo(Opaque::cast_into(foo), flags);
107
//! if err != 0 {
108
//! // Enabling has failed, first clean up the foo and then return the error.
109
//! bindings::destroy_foo(Opaque::cast_into(foo));
110
//! return Err(Error::from_errno(err));
111
//! }
112
//!
113
//! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
114
//! Ok(())
115
//! })
116
//! }
117
//! }
118
//! }
119
//!
120
//! #[pinned_drop]
121
//! impl PinnedDrop for RawFoo {
122
//! fn drop(self: Pin<&mut Self>) {
123
//! // SAFETY: Since `foo` is initialized, destroying is safe.
124
//! unsafe { bindings::destroy_foo(self.foo.get()) };
125
//! }
126
//! }
127
//! ```
128
129
use crate::{
130
alloc::{AllocError, Flags},
131
error::{self, Error},
132
};
133
use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit};
134
135
/// Smart pointer that can initialize memory in-place.
136
pub trait InPlaceInit<T>: Sized {
137
/// Pinned version of `Self`.
138
///
139
/// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
140
/// `Self`, otherwise just use `Pin<Self>`.
141
type PinnedSelf;
142
143
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
144
/// type.
145
///
146
/// If `T: !Unpin` it will not be able to move afterwards.
147
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
148
where
149
E: From<AllocError>;
150
151
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
152
/// type.
153
///
154
/// If `T: !Unpin` it will not be able to move afterwards.
155
fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
156
where
157
Error: From<E>,
158
{
159
// SAFETY: We delegate to `init` and only change the error type.
160
let init = unsafe {
161
pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
162
};
163
Self::try_pin_init(init, flags)
164
}
165
166
/// Use the given initializer to in-place initialize a `T`.
167
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
168
where
169
E: From<AllocError>;
170
171
/// Use the given initializer to in-place initialize a `T`.
172
fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
173
where
174
Error: From<E>,
175
{
176
// SAFETY: We delegate to `init` and only change the error type.
177
let init = unsafe {
178
init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
179
};
180
Self::try_init(init, flags)
181
}
182
}
183
184
/// Construct an in-place fallible initializer for `struct`s.
185
///
186
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
187
/// [`init!`].
188
///
189
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
190
/// append `? $type` after the `struct` initializer.
191
/// The safety caveats from [`try_pin_init!`] also apply:
192
/// - `unsafe` code must guarantee either full initialization or return an error and allow
193
/// deallocation of the memory.
194
/// - the fields are initialized in the order given in the initializer.
195
/// - no references to fields are allowed to be created inside of the initializer.
196
///
197
/// # Examples
198
///
199
/// ```rust
200
/// use kernel::error::Error;
201
/// use pin_init::init_zeroed;
202
/// struct BigBuf {
203
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
204
/// small: [u8; 1024 * 1024],
205
/// }
206
///
207
/// impl BigBuf {
208
/// fn new() -> impl Init<Self, Error> {
209
/// try_init!(Self {
210
/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,
211
/// small: [0; 1024 * 1024],
212
/// }? Error)
213
/// }
214
/// }
215
/// ```
216
///
217
/// [`Infallible`]: core::convert::Infallible
218
/// [`init!`]: pin_init::init
219
/// [`try_pin_init!`]: crate::try_pin_init!
220
/// [`Error`]: crate::error::Error
221
#[macro_export]
222
macro_rules! try_init {
223
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
224
$($fields:tt)*
225
}) => {
226
::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
227
$($fields)*
228
}? $crate::error::Error)
229
};
230
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
231
$($fields:tt)*
232
}? $err:ty) => {
233
::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
234
$($fields)*
235
}? $err)
236
};
237
}
238
239
/// Construct an in-place, fallible pinned initializer for `struct`s.
240
///
241
/// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
242
///
243
/// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
244
/// initialization and return the error.
245
///
246
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
247
/// initialization fails, the memory can be safely deallocated without any further modifications.
248
///
249
/// This macro defaults the error to [`Error`].
250
///
251
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
252
/// after the `struct` initializer to specify the error type you want to use.
253
///
254
/// # Examples
255
///
256
/// ```rust
257
/// # #![feature(new_uninit)]
258
/// use kernel::error::Error;
259
/// use pin_init::init_zeroed;
260
/// #[pin_data]
261
/// struct BigBuf {
262
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
263
/// small: [u8; 1024 * 1024],
264
/// ptr: *mut u8,
265
/// }
266
///
267
/// impl BigBuf {
268
/// fn new() -> impl PinInit<Self, Error> {
269
/// try_pin_init!(Self {
270
/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,
271
/// small: [0; 1024 * 1024],
272
/// ptr: core::ptr::null_mut(),
273
/// }? Error)
274
/// }
275
/// }
276
/// ```
277
///
278
/// [`Infallible`]: core::convert::Infallible
279
/// [`pin_init!`]: pin_init::pin_init
280
/// [`Error`]: crate::error::Error
281
#[macro_export]
282
macro_rules! try_pin_init {
283
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
284
$($fields:tt)*
285
}) => {
286
::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
287
$($fields)*
288
}? $crate::error::Error)
289
};
290
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
291
$($fields:tt)*
292
}? $err:ty) => {
293
::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
294
$($fields)*
295
}? $err)
296
};
297
}
298
299