Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/init.rs
49026 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::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
//! use kernel::{prelude::*, types::Opaque};
71
//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
72
//! # mod bindings {
73
//! # #![expect(non_camel_case_types, clippy::missing_safety_doc)]
74
//! # pub struct foo;
75
//! # pub unsafe fn init_foo(_ptr: *mut foo) {}
76
//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}
77
//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }
78
//! # }
79
//! /// # Invariants
80
//! ///
81
//! /// `foo` is always initialized
82
//! #[pin_data(PinnedDrop)]
83
//! pub struct RawFoo {
84
//! #[pin]
85
//! foo: Opaque<bindings::foo>,
86
//! #[pin]
87
//! _p: PhantomPinned,
88
//! }
89
//!
90
//! impl RawFoo {
91
//! pub fn new(flags: u32) -> impl PinInit<Self, Error> {
92
//! // SAFETY:
93
//! // - when the closure returns `Ok(())`, then it has successfully initialized and
94
//! // enabled `foo`,
95
//! // - when it returns `Err(e)`, then it has cleaned up before
96
//! unsafe {
97
//! pin_init::pin_init_from_closure(move |slot: *mut Self| {
98
//! // `slot` contains uninit memory, avoid creating a reference.
99
//! let foo = addr_of_mut!((*slot).foo);
100
//!
101
//! // Initialize the `foo`
102
//! bindings::init_foo(Opaque::cast_into(foo));
103
//!
104
//! // Try to enable it.
105
//! let err = bindings::enable_foo(Opaque::cast_into(foo), flags);
106
//! if err != 0 {
107
//! // Enabling has failed, first clean up the foo and then return the error.
108
//! bindings::destroy_foo(Opaque::cast_into(foo));
109
//! return Err(Error::from_errno(err));
110
//! }
111
//!
112
//! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
113
//! Ok(())
114
//! })
115
//! }
116
//! }
117
//! }
118
//!
119
//! #[pinned_drop]
120
//! impl PinnedDrop for RawFoo {
121
//! fn drop(self: Pin<&mut Self>) {
122
//! // SAFETY: Since `foo` is initialized, destroying is safe.
123
//! unsafe { bindings::destroy_foo(self.foo.get()) };
124
//! }
125
//! }
126
//! ```
127
128
use crate::{
129
alloc::{AllocError, Flags},
130
error::{self, Error},
131
};
132
use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit};
133
134
/// Smart pointer that can initialize memory in-place.
135
pub trait InPlaceInit<T>: Sized {
136
/// Pinned version of `Self`.
137
///
138
/// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
139
/// `Self`, otherwise just use `Pin<Self>`.
140
type PinnedSelf;
141
142
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
143
/// type.
144
///
145
/// If `T: !Unpin` it will not be able to move afterwards.
146
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
147
where
148
E: From<AllocError>;
149
150
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
151
/// type.
152
///
153
/// If `T: !Unpin` it will not be able to move afterwards.
154
fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
155
where
156
Error: From<E>,
157
{
158
// SAFETY: We delegate to `init` and only change the error type.
159
let init = unsafe {
160
pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
161
};
162
Self::try_pin_init(init, flags)
163
}
164
165
/// Use the given initializer to in-place initialize a `T`.
166
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
167
where
168
E: From<AllocError>;
169
170
/// Use the given initializer to in-place initialize a `T`.
171
fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
172
where
173
Error: From<E>,
174
{
175
// SAFETY: We delegate to `init` and only change the error type.
176
let init = unsafe {
177
init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
178
};
179
Self::try_init(init, flags)
180
}
181
}
182
183
/// Construct an in-place fallible initializer for `struct`s.
184
///
185
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
186
/// [`init!`].
187
///
188
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
189
/// append `? $type` after the `struct` initializer.
190
/// The safety caveats from [`try_pin_init!`] also apply:
191
/// - `unsafe` code must guarantee either full initialization or return an error and allow
192
/// deallocation of the memory.
193
/// - the fields are initialized in the order given in the initializer.
194
/// - no references to fields are allowed to be created inside of the initializer.
195
///
196
/// # Examples
197
///
198
/// ```rust
199
/// use kernel::error::Error;
200
/// use pin_init::init_zeroed;
201
/// struct BigBuf {
202
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
203
/// small: [u8; 1024 * 1024],
204
/// }
205
///
206
/// impl BigBuf {
207
/// fn new() -> impl Init<Self, Error> {
208
/// try_init!(Self {
209
/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,
210
/// small: [0; 1024 * 1024],
211
/// }? Error)
212
/// }
213
/// }
214
/// ```
215
///
216
/// [`Infallible`]: core::convert::Infallible
217
/// [`init!`]: pin_init::init
218
/// [`try_pin_init!`]: crate::try_pin_init!
219
/// [`Error`]: crate::error::Error
220
#[macro_export]
221
macro_rules! try_init {
222
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
223
$($fields:tt)*
224
}) => {
225
::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
226
$($fields)*
227
}? $crate::error::Error)
228
};
229
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
230
$($fields:tt)*
231
}? $err:ty) => {
232
::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
233
$($fields)*
234
}? $err)
235
};
236
}
237
238
/// Construct an in-place, fallible pinned initializer for `struct`s.
239
///
240
/// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
241
///
242
/// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
243
/// initialization and return the error.
244
///
245
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
246
/// initialization fails, the memory can be safely deallocated without any further modifications.
247
///
248
/// This macro defaults the error to [`Error`].
249
///
250
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
251
/// after the `struct` initializer to specify the error type you want to use.
252
///
253
/// # Examples
254
///
255
/// ```rust
256
/// # #![feature(new_uninit)]
257
/// use kernel::error::Error;
258
/// use pin_init::init_zeroed;
259
/// #[pin_data]
260
/// struct BigBuf {
261
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
262
/// small: [u8; 1024 * 1024],
263
/// ptr: *mut u8,
264
/// }
265
///
266
/// impl BigBuf {
267
/// fn new() -> impl PinInit<Self, Error> {
268
/// try_pin_init!(Self {
269
/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,
270
/// small: [0; 1024 * 1024],
271
/// ptr: core::ptr::null_mut(),
272
/// }? Error)
273
/// }
274
/// }
275
/// ```
276
///
277
/// [`Infallible`]: core::convert::Infallible
278
/// [`pin_init!`]: pin_init::pin_init
279
/// [`Error`]: crate::error::Error
280
#[macro_export]
281
macro_rules! try_pin_init {
282
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
283
$($fields:tt)*
284
}) => {
285
::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
286
$($fields)*
287
}? $crate::error::Error)
288
};
289
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
290
$($fields:tt)*
291
}? $err:ty) => {
292
::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
293
$($fields)*
294
}? $err)
295
};
296
}
297
298