[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250304225245.2033120-4-benno.lossin@proton.me>
Date: Tue, 04 Mar 2025 22:53:26 +0000
From: Benno Lossin <benno.lossin@...ton.me>
To: Benno Lossin <benno.lossin@...ton.me>, Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>, Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>, Björn Roy Baron <bjorn3_gh@...tonmail.com>, Andreas Hindborg <a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>, Danilo Krummrich <dakr@...nel.org>
Cc: linux-kernel@...r.kernel.org, rust-for-linux@...r.kernel.org
Subject: [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there
In preparation of splitting off the pin-init crate from the kernel
crate, move all kernel-specific documentation from pin-init back into
the kernel crate.
This new file will also be populated by kernel-specific extensions to
the pin-init crate by the next commits.
Signed-off-by: Benno Lossin <benno.lossin@...ton.me>
---
rust/kernel/init.rs | 135 +++++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 3 +
rust/pin-init/src/lib.rs | 14 ----
3 files changed, 138 insertions(+), 14 deletions(-)
create mode 100644 rust/kernel/init.rs
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
new file mode 100644
index 000000000000..322dfd9ec347
--- /dev/null
+++ b/rust/kernel/init.rs
@@ -0,0 +1,135 @@
+// 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!`]: crate::pin_init
+//!
+//! # Examples
+//!
+//! ## General Examples
+//!
+//! ```rust,ignore
+//! # #![allow(clippy::disallowed_names)]
+//! 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 {
+//! 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");
+//! }
+//! }
+//!
+//! 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,ignore
+//! # #![allow(unreachable_pub, clippy::disallowed_names)]
+//! use kernel::{prelude::*, types::Opaque};
+//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
+//! # mod bindings {
+//! # #![allow(non_camel_case_types)]
+//! # 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 }
+//! # }
+//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
+//! # trait FromErrno {
+//! # fn from_errno(errno: core::ffi::c_int) -> Error {
+//! # // Dummy error that can be constructed outside the `kernel` crate.
+//! # Error::from(core::fmt::Error)
+//! # }
+//! # }
+//! # impl FromErrno for Error {}
+//! /// # 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::raw_get(foo));
+//!
+//! // Try to enable it.
+//! let err = bindings::enable_foo(Opaque::raw_get(foo), flags);
+//! if err != 0 {
+//! // Enabling has failed, first clean up the foo and then return the error.
+//! bindings::destroy_foo(Opaque::raw_get(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()) };
+//! }
+//! }
+//! ```
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index c1b781371ba3..e3933f3dfc0b 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -52,6 +52,9 @@
pub mod fs;
#[path = "../pin-init/src/lib.rs"]
pub mod init;
+// momentarily use the name `init_ext` and set the path manually
+#[path = "init.rs"]
+pub mod init_ext;
pub mod io;
pub mod ioctl;
pub mod jump_label;
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index aa8df0595585..0307a08ccee9 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -5,9 +5,6 @@
//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
//! overflow.
//!
-//! 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.
-//!
//! # Overview
//!
//! To initialize a `struct` with an in-place constructor you will need two things:
@@ -188,15 +185,6 @@
//! }
//! ```
//!
-//! 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`] field by just delegating to the supplied closure. You can use these in combination
-//! with [`pin_init!`].
-//!
-//! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
-//! the `kernel` crate. The [`sync`] module is a good starting point.
-//!
-//! [`sync`]: kernel::sync
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
//! [structurally pinned fields]:
//! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
@@ -205,8 +193,6 @@
//! [`impl PinInit<Foo>`]: PinInit
//! [`impl PinInit<T, E>`]: PinInit
//! [`impl Init<T, E>`]: Init
-//! [`Opaque`]: kernel::types::Opaque
-//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init
//! [`pin_data`]: ::macros::pin_data
//! [`pin_init!`]: crate::pin_init!
--
2.47.2
Powered by blists - more mailing lists