297 lines · 9.7 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! Extensions to the [`pin-init`] crate.//!//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.//!//! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer//! to its documentation to better understand how to use it. Additionally, there are many examples//! throughout the kernel, such as the types from the [`sync`] module. And the ones presented//! below.//!//! [`sync`]: crate::sync//! [pinning]: https://doc.rust-lang.org/std/pin/index.html//! [`pin-init`]: https://rust.docs.kernel.org/pin_init///!//! # [`Opaque<T>`]//!//! For the special case where initializing a field is a single FFI-function call that cannot fail,//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single//! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in//! combination with [`pin_init!`].//!//! [`Opaque<T>`]: crate::types::Opaque//! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init//! [`pin_init!`]: pin_init::pin_init//!//! # Examples//!//! ## General Examples//!//! ```rust//! # #![expect(clippy::disallowed_names, clippy::undocumented_unsafe_blocks)]//! use kernel::types::Opaque;//! use pin_init::pin_init_from_closure;//!//! // assume we have some `raw_foo` type in C://! #[repr(C)]//! struct RawFoo([u8; 16]);//! extern "C" {//!     fn init_foo(_: *mut RawFoo);//! }//!//! #[pin_data]//! struct Foo {//!     #[pin]//!     raw: Opaque<RawFoo>,//! }//!//! impl Foo {//!     fn setup(self: Pin<&mut Self>) {//!         pr_info!("Setting up foo\n");//!     }//! }//!//! let foo = pin_init!(Foo {//!     raw <- unsafe {//!         Opaque::ffi_init(|s| {//!             // note that this cannot fail.//!             init_foo(s);//!         })//!     },//! }).pin_chain(|foo| {//!     foo.setup();//!     Ok(())//! });//! ```//!//! ```rust//! # #![expect(unreachable_pub, clippy::disallowed_names)]//! use kernel::{prelude::*, types::Opaque};//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};//! # mod bindings {//! #     #![expect(non_camel_case_types, clippy::missing_safety_doc)]//! #     pub struct foo;//! #     pub unsafe fn init_foo(_ptr: *mut foo) {}//! #     pub unsafe fn destroy_foo(_ptr: *mut foo) {}//! #     pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }//! # }//! /// # Invariants//! /////! /// `foo` is always initialized//! #[pin_data(PinnedDrop)]//! pub struct RawFoo {//!     #[pin]//!     foo: Opaque<bindings::foo>,//!     #[pin]//!     _p: PhantomPinned,//! }//!//! impl RawFoo {//!     pub fn new(flags: u32) -> impl PinInit<Self, Error> {//!         // SAFETY://!         // - when the closure returns `Ok(())`, then it has successfully initialized and//!         //   enabled `foo`,//!         // - when it returns `Err(e)`, then it has cleaned up before//!         unsafe {//!             pin_init::pin_init_from_closure(move |slot: *mut Self| {//!                 // `slot` contains uninit memory, avoid creating a reference.//!                 let foo = addr_of_mut!((*slot).foo);//!//!                 // Initialize the `foo`//!                 bindings::init_foo(Opaque::cast_into(foo));//!//!                 // Try to enable it.//!                 let err = bindings::enable_foo(Opaque::cast_into(foo), flags);//!                 if err != 0 {//!                     // Enabling has failed, first clean up the foo and then return the error.//!                     bindings::destroy_foo(Opaque::cast_into(foo));//!                     return Err(Error::from_errno(err));//!                 }//!//!                 // All fields of `RawFoo` have been initialized, since `_p` is a ZST.//!                 Ok(())//!             })//!         }//!     }//! }//!//! #[pinned_drop]//! impl PinnedDrop for RawFoo {//!     fn drop(self: Pin<&mut Self>) {//!         // SAFETY: Since `foo` is initialized, destroying is safe.//!         unsafe { bindings::destroy_foo(self.foo.get()) };//!     }//! }//! ``` use crate::{    alloc::{AllocError, Flags},    error::{self, Error},};use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit}; /// Smart pointer that can initialize memory in-place.pub trait InPlaceInit<T>: Sized {    /// Pinned version of `Self`.    ///    /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use    /// `Self`, otherwise just use `Pin<Self>`.    type PinnedSelf;     /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this    /// type.    ///    /// If `T: !Unpin` it will not be able to move afterwards.    fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>    where        E: From<AllocError>;     /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this    /// type.    ///    /// If `T: !Unpin` it will not be able to move afterwards.    fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>    where        Error: From<E>,    {        // SAFETY: We delegate to `init` and only change the error type.        let init = unsafe {            pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))        };        Self::try_pin_init(init, flags)    }     /// Use the given initializer to in-place initialize a `T`.    fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>    where        E: From<AllocError>;     /// Use the given initializer to in-place initialize a `T`.    fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>    where        Error: From<E>,    {        // SAFETY: We delegate to `init` and only change the error type.        let init = unsafe {            init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))        };        Self::try_init(init, flags)    }} /// Construct an in-place fallible initializer for `struct`s.////// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use/// [`init!`].////// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,/// append `? $type` after the `struct` initializer./// The safety caveats from [`try_pin_init!`] also apply:/// - `unsafe` code must guarantee either full initialization or return an error and allow///   deallocation of the memory./// - the fields are initialized in the order given in the initializer./// - no references to fields are allowed to be created inside of the initializer.////// # Examples////// ```rust/// use kernel::error::Error;/// use pin_init::init_zeroed;/// struct BigBuf {///     big: KBox<[u8; 1024 * 1024 * 1024]>,///     small: [u8; 1024 * 1024],/// }////// impl BigBuf {///     fn new() -> impl Init<Self, Error> {///         try_init!(Self {///             big: KBox::init(init_zeroed(), GFP_KERNEL)?,///             small: [0; 1024 * 1024],///         }? Error)///     }/// }/// ```////// [`Infallible`]: core::convert::Infallible/// [`init!`]: pin_init::init/// [`try_pin_init!`]: crate::try_pin_init!/// [`Error`]: crate::error::Error#[macro_export]macro_rules! try_init {    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {        $($fields:tt)*    }) => {        ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {            $($fields)*        }? $crate::error::Error)    };    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {        $($fields:tt)*    }? $err:ty) => {        ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {            $($fields)*        }? $err)    };} /// Construct an in-place, fallible pinned initializer for `struct`s.////// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].////// You can use the `?` operator or use `return Err(err)` inside the initializer to stop/// initialization and return the error.////// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when/// initialization fails, the memory can be safely deallocated without any further modifications.////// This macro defaults the error to [`Error`].////// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`/// after the `struct` initializer to specify the error type you want to use.////// # Examples////// ```rust/// # #![feature(new_uninit)]/// use kernel::error::Error;/// use pin_init::init_zeroed;/// #[pin_data]/// struct BigBuf {///     big: KBox<[u8; 1024 * 1024 * 1024]>,///     small: [u8; 1024 * 1024],///     ptr: *mut u8,/// }////// impl BigBuf {///     fn new() -> impl PinInit<Self, Error> {///         try_pin_init!(Self {///             big: KBox::init(init_zeroed(), GFP_KERNEL)?,///             small: [0; 1024 * 1024],///             ptr: core::ptr::null_mut(),///         }? Error)///     }/// }/// ```////// [`Infallible`]: core::convert::Infallible/// [`pin_init!`]: pin_init::pin_init/// [`Error`]: crate::error::Error#[macro_export]macro_rules! try_pin_init {    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {        $($fields:tt)*    }) => {        ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {            $($fields)*        }? $crate::error::Error)    };    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {        $($fields:tt)*    }? $err:ty) => {        ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {            $($fields)*        }? $err)    };}