kernel/
init.rs

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::raw_get(foo));
104//!
105//!                 // Try to enable it.
106//!                 let err = bindings::enable_foo(Opaque::raw_get(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::raw_get(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
129use crate::{
130    alloc::{AllocError, Flags},
131    error::{self, Error},
132};
133use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit};
134
135/// Smart pointer that can initialize memory in-place.
136pub 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]
222macro_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]
282macro_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}