rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/22] make pin-init into a standalone crate
@ 2025-03-04 22:52 ` Benno Lossin
  2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
                     ` (23 more replies)
  0 siblings, 24 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:52 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux

This patch series extracts the pin-init API from the kernel crate and
turns it into a standalone crate used by the kernel crate. The reasoning
for this change is that the maintenance burden for me is too great
maintaining two (more and more) diverging versions of the same library.
At [1] you can find the user-space version of the pin-init library as a
Rust crate.

The reason for the difference between the two versions is that the
kernel does not use the `std` and `alloc` standard libraries as almost
every other user-space Rust crate does. This not only prevents the
kernel version from implementing features for the `Arc` type from
`alloc`, but also from any `std` types appearing in the documentation.
Additionally, the documentation text is different in several places as
it explicitly mentions the kernel's `Opaque<T>` type.

There are also minor changes in code that occurred due to the same
reason as the documentation changes or due to the non-optimal setup for
synchronizing changes between the two versions (the process it fully
manual, as no diffs can be ported between the two). For example, the
`try_[pin_]init!` macros in the kernel default to the kernel's own
`Error` type. The user-space version does not have such defaulting
behavior.

Since there are other projects outside of the kernel that have begun
using pin-init, the only sensible solution to this problem is to
synchronize both versions and then develop them simultaneously, ensuring
perpetual diff-compatibility. I have even had people contribute code on
github.

Additionally, I want to do some big changes to the pin-init library
internals. For example, porting the proc-macros over to `syn`. We will
probably get support for this later this year in the kernel and I want
to be ready to be able to make that switch as soon as possible. This is
because non-syn proc-macros are just pure hell and the current
implementation is a frankenstein-monster of a mix of declarative macros
and proc-macros that I'd rather replace by using `syn`. I already wrote
the code for that transition and will be submitting an RFC based on this
series shortly.

For these reasons, this patch series extracts all code of the pin-init
API and moves it into a new directory, making it its own crate. Since
the user-space version has some functional differences, these are also
introduced by this series. But in situations where the kernel has
special requirements, extensions to the pin-init crate are reintroduced
in/moved back into the kernel crate. To allow the dream of
diff-compatibility to be true, this series also introduces code files
from the user-space version.

`pin-init` is licensed under APACHE 2.0 OR MIT and almost all code that
is moved already was present with that license. There is a small license
change in patch #2, you can find the explanation in the commit message.

With this change also comes an entry in the MAINTAINERS file, since I
have to synchronize all changes with the user-space version and vice
versa.

For this series I would really appreciate some Tested-by's, by users of
the pin-init library within the kernel in order to ensure that I have
not broken anything.

Special thanks to Miguel for helping me a lot with getting the series
ready!

[1]: https://github.com/Rust-for-Linux/pin-init

---
Cheers,
Benno

Benno Lossin (21):
  rust: init: disable doctests
  rust: move pin-init API into its own directory
  rust: add extensions to the pin-init crate and move relevant
    documentation there
  rust: pin-init: move proc-macro documentation into pin-init crate
  rust: pin-init: change examples to the user-space version
  rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of
    `__init_internal!`
  rust: pin-init: move the default error behavior of `try_[pin_]init`
  rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into
    the kernel crate
  rust: pin-init: move impl `Zeroable` for `Opaque` and
    `Option<KBox<T>>` into the kernel crate
  rust: add `ZeroableOption` and implement it instead of `Zeroable` for
    `Option<Box<T, A>>`
  rust: pin-init: fix documentation links
  rust: pin-init: remove kernel-crate dependency
  rust: pin-init: change the way the `paste!` macro is called
  rust: make pin-init its own crate
  rust: pin-init: add `std` and `alloc` support from the user-space
    version
  rust: pin-init: synchronize documentation with the user-space version
  rust: pin-init: internal: synchronize with user-space version
  rust: pin-init: miscellaneous synchronization with the user-space
    version
  rust: pin-init: add miscellaneous files from the user-space version
  rust: pin-init: re-enable doctests
  MAINTAINERS: add entry for the `pin-init` crate

Miguel Ojeda (1):
  rust: add pin-init crate build infrastructure

 MAINTAINERS                                   |   13 +
 rust/Makefile                                 |   75 +-
 rust/kernel/alloc/kbox.rs                     |    9 +-
 rust/kernel/block/mq/tag_set.rs               |    5 +-
 rust/kernel/driver.rs                         |    6 +-
 rust/kernel/init.rs                           | 1450 ++--------------
 rust/kernel/lib.rs                            |    6 +-
 rust/kernel/list.rs                           |    2 +-
 rust/kernel/prelude.rs                        |    8 +-
 rust/kernel/sync/arc.rs                       |   68 +-
 rust/kernel/sync/condvar.rs                   |    6 +-
 rust/kernel/sync/lock.rs                      |    4 +-
 rust/kernel/sync/lock/mutex.rs                |    2 +-
 rust/kernel/sync/lock/spinlock.rs             |    2 +-
 rust/kernel/types.rs                          |   13 +-
 rust/macros/helpers.rs                        |  148 +-
 rust/macros/lib.rs                            |  127 +-
 rust/macros/module.rs                         |    2 +-
 rust/macros/quote.rs                          |    1 +
 rust/pin-init/CONTRIBUTING.md                 |   72 +
 rust/pin-init/README.md                       |  228 +++
 rust/pin-init/examples/big_struct_in_place.rs |   39 +
 rust/pin-init/examples/error.rs               |   27 +
 rust/pin-init/examples/linked_list.rs         |  161 ++
 rust/pin-init/examples/mutex.rs               |  209 +++
 rust/pin-init/examples/pthread_mutex.rs       |  178 ++
 rust/pin-init/examples/static_init.rs         |  122 ++
 rust/pin-init/internal/src/helpers.rs         |  152 ++
 rust/pin-init/internal/src/lib.rs             |   48 +
 .../internal/src}/pin_data.rs                 |    7 +-
 .../internal/src}/pinned_drop.rs              |    7 +-
 .../internal/src}/zeroable.rs                 |   11 +-
 .../init => pin-init/src}/__internal.rs       |   43 +-
 rust/pin-init/src/alloc.rs                    |  158 ++
 rust/pin-init/src/lib.rs                      | 1462 +++++++++++++++++
 rust/{kernel/init => pin-init/src}/macros.rs  |  129 +-
 scripts/Makefile.build                        |    2 +-
 scripts/generate_rust_analyzer.py             |   17 +-
 38 files changed, 3316 insertions(+), 1703 deletions(-)
 create mode 100644 rust/pin-init/CONTRIBUTING.md
 create mode 100644 rust/pin-init/README.md
 create mode 100644 rust/pin-init/examples/big_struct_in_place.rs
 create mode 100644 rust/pin-init/examples/error.rs
 create mode 100644 rust/pin-init/examples/linked_list.rs
 create mode 100644 rust/pin-init/examples/mutex.rs
 create mode 100644 rust/pin-init/examples/pthread_mutex.rs
 create mode 100644 rust/pin-init/examples/static_init.rs
 create mode 100644 rust/pin-init/internal/src/helpers.rs
 create mode 100644 rust/pin-init/internal/src/lib.rs
 rename rust/{macros => pin-init/internal/src}/pin_data.rs (97%)
 rename rust/{macros => pin-init/internal/src}/pinned_drop.rs (92%)
 rename rust/{macros => pin-init/internal/src}/zeroable.rs (88%)
 rename rust/{kernel/init => pin-init/src}/__internal.rs (86%)
 create mode 100644 rust/pin-init/src/alloc.rs
 create mode 100644 rust/pin-init/src/lib.rs
 rename rust/{kernel/init => pin-init/src}/macros.rs (92%)


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.47.2



^ permalink raw reply	[flat|nested] 103+ messages in thread

* [PATCH 01/22] rust: init: disable doctests
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  8:51     ` Andreas Hindborg
  2025-03-05  9:17     ` Fiona Behrens
  2025-03-04 22:53   ` [PATCH 02/22] rust: move pin-init API into its own directory Benno Lossin
                     ` (22 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

This is the first commit in a series that splits off the pin-init crate
from the kernel crate.

The build system cannot handle doctests in the kernel crate in files
outside of `rust/kernel/`. Since subsequent commits will move files out
of that directory, but will still compile them as part of the kernel
crate, ignore all doctests in the to-be-moved files.

The tests will be re-enabled later when the separation into its own
crate has been completed, since then the doctests of that new crate will
be handled as normal host doctests.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/init.rs | 40 ++++++++++++++++++++--------------------
 rust/macros/lib.rs  |  8 ++++----
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 7fd1ea8265a5..aa8df0595585 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -34,7 +34,7 @@
 //! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
 //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
 //!
-//! ```rust
+//! ```rust,ignore
 //! # #![expect(clippy::disallowed_names)]
 //! use kernel::sync::{new_mutex, Mutex};
 //! # use core::pin::Pin;
@@ -54,7 +54,7 @@
 //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
 //! (or just the stack) to actually initialize a `Foo`:
 //!
-//! ```rust
+//! ```rust,ignore
 //! # #![expect(clippy::disallowed_names)]
 //! # use kernel::sync::{new_mutex, Mutex};
 //! # use core::pin::Pin;
@@ -78,7 +78,7 @@
 //! Many types from the kernel supply a function/macro that returns an initializer, because the
 //! above method only works for types where you can access the fields.
 //!
-//! ```rust
+//! ```rust,ignore
 //! # use kernel::sync::{new_mutex, Arc, Mutex};
 //! let mtx: Result<Arc<Mutex<usize>>> =
 //!     Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);
@@ -86,7 +86,7 @@
 //!
 //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
 //!
-//! ```rust
+//! ```rust,ignore
 //! # use kernel::{sync::Mutex, new_mutex, init::PinInit, try_pin_init};
 //! #[pin_data]
 //! struct DriverData {
@@ -119,7 +119,7 @@
 //! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
 //!   `slot` gets called.
 //!
-//! ```rust
+//! ```rust,ignore
 //! # #![expect(unreachable_pub, clippy::disallowed_names)]
 //! use kernel::{init, types::Opaque};
 //! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
@@ -236,7 +236,7 @@
 ///
 /// # Examples
 ///
-/// ```rust
+/// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
 /// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex};
 /// # use core::pin::Pin;
@@ -382,7 +382,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// The syntax is almost identical to that of a normal `struct` initializer:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # use kernel::{init, pin_init, macros::pin_data, init::*};
 /// # use core::pin::Pin;
 /// #[pin_data]
@@ -426,7 +426,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// To create an initializer function, simply declare it like this:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # use kernel::{init, pin_init, init::*};
 /// # use core::pin::Pin;
 /// # #[pin_data]
@@ -452,7 +452,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// Users of `Foo` can now create it like this:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
 /// # use kernel::{init, pin_init, macros::pin_data, init::*};
 /// # use core::pin::Pin;
@@ -480,7 +480,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// They can also easily embed it into their own `struct`s:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # use kernel::{init, pin_init, macros::pin_data, init::*};
 /// # use core::pin::Pin;
 /// # #[pin_data]
@@ -539,7 +539,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// For instance:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # use kernel::{macros::{Zeroable, pin_data}, pin_init};
 /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
 /// #[pin_data]
@@ -602,7 +602,7 @@ macro_rules! pin_init {
 ///
 /// # Examples
 ///
-/// ```rust
+/// ```rust,ignore
 /// use kernel::{init::{self, PinInit}, error::Error};
 /// #[pin_data]
 /// struct BigBuf {
@@ -705,7 +705,7 @@ macro_rules! init {
 ///
 /// # Examples
 ///
-/// ```rust
+/// ```rust,ignore
 /// use kernel::{alloc::KBox, init::{PinInit, zeroed}, error::Error};
 /// struct BigBuf {
 ///     big: KBox<[u8; 1024 * 1024 * 1024]>,
@@ -761,7 +761,7 @@ macro_rules! try_init {
 /// # Example
 ///
 /// This will succeed:
-/// ```
+/// ```ignore
 /// use kernel::assert_pinned;
 /// #[pin_data]
 /// struct MyStruct {
@@ -787,7 +787,7 @@ macro_rules! try_init {
 /// Some uses of the macro may trigger the `can't use generic parameters from outer item` error. To
 /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
 /// only be used when the macro is invoked from a function body.
-/// ```
+/// ```ignore
 /// use kernel::assert_pinned;
 /// #[pin_data]
 /// struct Foo<T> {
@@ -865,7 +865,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```rust,ignore
     /// # #![expect(clippy::disallowed_names)]
     /// use kernel::{types::Opaque, init::pin_init_from_closure};
     /// #[repr(C)]
@@ -977,7 +977,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```rust,ignore
     /// # #![expect(clippy::disallowed_names)]
     /// use kernel::{types::Opaque, init::{self, init_from_closure}};
     /// struct Foo {
@@ -1089,7 +1089,7 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
 ///
 /// # Examples
 ///
-/// ```rust
+/// ```rust,ignore
 /// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn};
 /// let array: KBox<[usize; 1_000]> =
 ///     KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?;
@@ -1134,7 +1134,7 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
 ///
 /// # Examples
 ///
-/// ```rust
+/// ```rust,ignore
 /// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
 /// let array: Arc<[Mutex<usize>; 1_000]> =
 ///     Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?;
@@ -1323,7 +1323,7 @@ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Ini
 ///
 /// Use [`pinned_drop`] to implement this trait safely:
 ///
-/// ```rust
+/// ```rust,ignore
 /// # use kernel::sync::Mutex;
 /// use kernel::macros::pinned_drop;
 /// use core::pin::Pin;
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index d61bc6a56425..60a0226bad42 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -248,7 +248,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
 ///
 /// # Examples
 ///
-/// ```
+/// ```ignore
 /// # #![feature(lint_reasons)]
 /// # use kernel::prelude::*;
 /// # use std::{sync::Mutex, process::Command};
@@ -261,7 +261,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
 /// }
 /// ```
 ///
-/// ```
+/// ```ignore
 /// # #![feature(lint_reasons)]
 /// # use kernel::prelude::*;
 /// # use std::{sync::Mutex, process::Command};
@@ -302,7 +302,7 @@ pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
 ///
 /// # Examples
 ///
-/// ```
+/// ```ignore
 /// # #![feature(lint_reasons)]
 /// # use kernel::prelude::*;
 /// # use macros::{pin_data, pinned_drop};
@@ -478,7 +478,7 @@ pub fn paste(input: TokenStream) -> TokenStream {
 ///
 /// # Examples
 ///
-/// ```
+/// ```ignore
 /// use kernel::macros::Zeroable;
 ///
 /// #[derive(Zeroable)]
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 02/22] rust: move pin-init API into its own directory
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
  2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  9:03     ` Andreas Hindborg
  2025-03-05  9:17     ` Fiona Behrens
  2025-03-04 22:53   ` [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there Benno Lossin
                     ` (21 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

In preparation of splitting off the pin-init crate from the kernel
crate, move all pin-init API code (including proc-macros) into
`rust/pin-init`.

Moved modules have their import path adjusted via the `#[path = "..."]`
attribute. This allows the files to still be imported in the kernel
crate even though the files are in different directories.

Code that is moved out of files (but the file itself stays where it is)
is imported via the `include!` macro. This also allows the code to be
moved while still being part of the kernel crate.

Note that this commit moves the generics parsing code out of the GPL-2.0
file `rust/macros/helpers.rs` into the Apache-2.0 OR MIT file
`rust/pin_init/internal/src/helpers.rs`. I am the sole author of that
code and it already is available with that license at [1].
The same is true for the entry-points of the proc-macros `pin_data`,
`pinned_drop` and `derive_zeroable` in `rust/macros/lib.rs` that are
moved to `rust/pin_data/internal/src/lib.rs`. Although there are some
smaller patches that fix the doctests.

Link: https://github.com/Rust-for-Linux/pinned-init [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/lib.rs                            |   1 +
 rust/macros/helpers.rs                        | 146 +----------------
 rust/macros/lib.rs                            | 124 +--------------
 rust/pin-init/internal/src/helpers.rs         | 147 ++++++++++++++++++
 rust/pin-init/internal/src/lib.rs             | 122 +++++++++++++++
 .../internal/src}/pin_data.rs                 |   0
 .../internal/src}/pinned_drop.rs              |   0
 .../internal/src}/zeroable.rs                 |   0
 .../init => pin-init/src}/__internal.rs       |   0
 rust/{kernel/init.rs => pin-init/src/lib.rs}  |   0
 rust/{kernel/init => pin-init/src}/macros.rs  |   0
 11 files changed, 275 insertions(+), 265 deletions(-)
 create mode 100644 rust/pin-init/internal/src/helpers.rs
 create mode 100644 rust/pin-init/internal/src/lib.rs
 rename rust/{macros => pin-init/internal/src}/pin_data.rs (100%)
 rename rust/{macros => pin-init/internal/src}/pinned_drop.rs (100%)
 rename rust/{macros => pin-init/internal/src}/zeroable.rs (100%)
 rename rust/{kernel/init => pin-init/src}/__internal.rs (100%)
 rename rust/{kernel/init.rs => pin-init/src/lib.rs} (100%)
 rename rust/{kernel/init => pin-init/src}/macros.rs (100%)

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 398242f92a96..c1b781371ba3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -50,6 +50,7 @@
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
 pub mod firmware;
 pub mod fs;
+#[path = "../pin-init/src/lib.rs"]
 pub mod init;
 pub mod io;
 pub mod ioctl;
diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs
index 563dcd2b7ace..8e07703fcc16 100644
--- a/rust/macros/helpers.rs
+++ b/rust/macros/helpers.rs
@@ -70,148 +70,4 @@ pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
     }
 }
 
-/// Parsed generics.
-///
-/// See the field documentation for an explanation what each of the fields represents.
-///
-/// # Examples
-///
-/// ```rust,ignore
-/// # let input = todo!();
-/// let (Generics { decl_generics, impl_generics, ty_generics }, rest) = parse_generics(input);
-/// quote! {
-///     struct Foo<$($decl_generics)*> {
-///         // ...
-///     }
-///
-///     impl<$impl_generics> Foo<$ty_generics> {
-///         fn foo() {
-///             // ...
-///         }
-///     }
-/// }
-/// ```
-pub(crate) struct Generics {
-    /// The generics with bounds and default values (e.g. `T: Clone, const N: usize = 0`).
-    ///
-    /// Use this on type definitions e.g. `struct Foo<$decl_generics> ...` (or `union`/`enum`).
-    pub(crate) decl_generics: Vec<TokenTree>,
-    /// The generics with bounds (e.g. `T: Clone, const N: usize`).
-    ///
-    /// Use this on `impl` blocks e.g. `impl<$impl_generics> Trait for ...`.
-    pub(crate) impl_generics: Vec<TokenTree>,
-    /// The generics without bounds and without default values (e.g. `T, N`).
-    ///
-    /// Use this when you use the type that is declared with these generics e.g.
-    /// `Foo<$ty_generics>`.
-    pub(crate) ty_generics: Vec<TokenTree>,
-}
-
-/// Parses the given `TokenStream` into `Generics` and the rest.
-///
-/// The generics are not present in the rest, but a where clause might remain.
-pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec<TokenTree>) {
-    // The generics with bounds and default values.
-    let mut decl_generics = vec![];
-    // `impl_generics`, the declared generics with their bounds.
-    let mut impl_generics = vec![];
-    // Only the names of the generics, without any bounds.
-    let mut ty_generics = vec![];
-    // Tokens not related to the generics e.g. the `where` token and definition.
-    let mut rest = vec![];
-    // The current level of `<`.
-    let mut nesting = 0;
-    let mut toks = input.into_iter();
-    // If we are at the beginning of a generic parameter.
-    let mut at_start = true;
-    let mut skip_until_comma = false;
-    while let Some(tt) = toks.next() {
-        if nesting == 1 && matches!(&tt, TokenTree::Punct(p) if p.as_char() == '>') {
-            // Found the end of the generics.
-            break;
-        } else if nesting >= 1 {
-            decl_generics.push(tt.clone());
-        }
-        match tt.clone() {
-            TokenTree::Punct(p) if p.as_char() == '<' => {
-                if nesting >= 1 && !skip_until_comma {
-                    // This is inside of the generics and part of some bound.
-                    impl_generics.push(tt);
-                }
-                nesting += 1;
-            }
-            TokenTree::Punct(p) if p.as_char() == '>' => {
-                // This is a parsing error, so we just end it here.
-                if nesting == 0 {
-                    break;
-                } else {
-                    nesting -= 1;
-                    if nesting >= 1 && !skip_until_comma {
-                        // We are still inside of the generics and part of some bound.
-                        impl_generics.push(tt);
-                    }
-                }
-            }
-            TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' => {
-                if nesting == 1 {
-                    impl_generics.push(tt.clone());
-                    impl_generics.push(tt);
-                    skip_until_comma = false;
-                }
-            }
-            _ if !skip_until_comma => {
-                match nesting {
-                    // If we haven't entered the generics yet, we still want to keep these tokens.
-                    0 => rest.push(tt),
-                    1 => {
-                        // Here depending on the token, it might be a generic variable name.
-                        match tt.clone() {
-                            TokenTree::Ident(i) if at_start && i.to_string() == "const" => {
-                                let Some(name) = toks.next() else {
-                                    // Parsing error.
-                                    break;
-                                };
-                                impl_generics.push(tt);
-                                impl_generics.push(name.clone());
-                                ty_generics.push(name.clone());
-                                decl_generics.push(name);
-                                at_start = false;
-                            }
-                            TokenTree::Ident(_) if at_start => {
-                                impl_generics.push(tt.clone());
-                                ty_generics.push(tt);
-                                at_start = false;
-                            }
-                            TokenTree::Punct(p) if p.as_char() == ',' => {
-                                impl_generics.push(tt.clone());
-                                ty_generics.push(tt);
-                                at_start = true;
-                            }
-                            // Lifetimes begin with `'`.
-                            TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
-                                impl_generics.push(tt.clone());
-                                ty_generics.push(tt);
-                            }
-                            // Generics can have default values, we skip these.
-                            TokenTree::Punct(p) if p.as_char() == '=' => {
-                                skip_until_comma = true;
-                            }
-                            _ => impl_generics.push(tt),
-                        }
-                    }
-                    _ => impl_generics.push(tt),
-                }
-            }
-            _ => {}
-        }
-    }
-    rest.extend(toks);
-    (
-        Generics {
-            impl_generics,
-            decl_generics,
-            ty_generics,
-        },
-        rest,
-    )
-}
+include!("../pin-init/internal/src/helpers.rs");
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 60a0226bad42..7ff82c82ce0c 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -12,9 +12,12 @@
 mod helpers;
 mod module;
 mod paste;
+#[path = "../pin-init/internal/src/pin_data.rs"]
 mod pin_data;
+#[path = "../pin-init/internal/src/pinned_drop.rs"]
 mod pinned_drop;
 mod vtable;
+#[path = "../pin-init/internal/src/zeroable.rs"]
 mod zeroable;
 
 use proc_macro::TokenStream;
@@ -232,106 +235,6 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
     concat_idents::concat_idents(ts)
 }
 
-/// Used to specify the pinning information of the fields of a struct.
-///
-/// This is somewhat similar in purpose as
-/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
-/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
-/// field you want to structurally pin.
-///
-/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
-/// then `#[pin]` directs the type of initializer that is required.
-///
-/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
-/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
-/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
-///
-/// # Examples
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use kernel::macros::pin_data;
-/// #[pin_data]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-/// }
-/// ```
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # pub struct Info;
-/// # mod bindings {
-/// #     pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
-/// # }
-/// use kernel::macros::{pin_data, pinned_drop};
-///
-/// #[pin_data(PinnedDrop)]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut Info,
-/// }
-///
-/// #[pinned_drop]
-/// impl PinnedDrop for DriverData {
-///     fn drop(self: Pin<&mut Self>) {
-///         unsafe { bindings::destroy_info(self.raw_info) };
-///     }
-/// }
-/// # fn main() {}
-/// ```
-///
-/// [`pin_init!`]: ../kernel/macro.pin_init.html
-//  ^ cannot use direct link, since `kernel` is not a dependency of `macros`.
-#[proc_macro_attribute]
-pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
-    pin_data::pin_data(inner, item)
-}
-
-/// Used to implement `PinnedDrop` safely.
-///
-/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
-///
-/// # Examples
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use macros::{pin_data, pinned_drop};
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # mod bindings {
-/// #     pub struct Info;
-/// #     pub unsafe fn destroy_info(_ptr: *mut Info) {}
-/// # }
-/// #[pin_data(PinnedDrop)]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut bindings::Info,
-/// }
-///
-/// #[pinned_drop]
-/// impl PinnedDrop for DriverData {
-///     fn drop(self: Pin<&mut Self>) {
-///         unsafe { bindings::destroy_info(self.raw_info) };
-///     }
-/// }
-/// ```
-#[proc_macro_attribute]
-pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
-    pinned_drop::pinned_drop(args, input)
-}
-
 /// Paste identifiers together.
 ///
 /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
@@ -472,23 +375,4 @@ pub fn paste(input: TokenStream) -> TokenStream {
     tokens.into_iter().collect()
 }
 
-/// Derives the [`Zeroable`] trait for the given struct.
-///
-/// This can only be used for structs where every field implements the [`Zeroable`] trait.
-///
-/// # Examples
-///
-/// ```ignore
-/// use kernel::macros::Zeroable;
-///
-/// #[derive(Zeroable)]
-/// pub struct DriverData {
-///     id: i64,
-///     buf_ptr: *mut u8,
-///     len: usize,
-/// }
-/// ```
-#[proc_macro_derive(Zeroable)]
-pub fn derive_zeroable(input: TokenStream) -> TokenStream {
-    zeroable::derive(input)
-}
+include!("../pin-init/internal/src/lib.rs");
diff --git a/rust/pin-init/internal/src/helpers.rs b/rust/pin-init/internal/src/helpers.rs
new file mode 100644
index 000000000000..2f4fc75c014e
--- /dev/null
+++ b/rust/pin-init/internal/src/helpers.rs
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+/// Parsed generics.
+///
+/// See the field documentation for an explanation what each of the fields represents.
+///
+/// # Examples
+///
+/// ```rust,ignore
+/// # let input = todo!();
+/// let (Generics { decl_generics, impl_generics, ty_generics }, rest) = parse_generics(input);
+/// quote! {
+///     struct Foo<$($decl_generics)*> {
+///         // ...
+///     }
+///
+///     impl<$impl_generics> Foo<$ty_generics> {
+///         fn foo() {
+///             // ...
+///         }
+///     }
+/// }
+/// ```
+pub(crate) struct Generics {
+    /// The generics with bounds and default values (e.g. `T: Clone, const N: usize = 0`).
+    ///
+    /// Use this on type definitions e.g. `struct Foo<$decl_generics> ...` (or `union`/`enum`).
+    pub(crate) decl_generics: Vec<TokenTree>,
+    /// The generics with bounds (e.g. `T: Clone, const N: usize`).
+    ///
+    /// Use this on `impl` blocks e.g. `impl<$impl_generics> Trait for ...`.
+    pub(crate) impl_generics: Vec<TokenTree>,
+    /// The generics without bounds and without default values (e.g. `T, N`).
+    ///
+    /// Use this when you use the type that is declared with these generics e.g.
+    /// `Foo<$ty_generics>`.
+    pub(crate) ty_generics: Vec<TokenTree>,
+}
+
+/// Parses the given `TokenStream` into `Generics` and the rest.
+///
+/// The generics are not present in the rest, but a where clause might remain.
+pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec<TokenTree>) {
+    // The generics with bounds and default values.
+    let mut decl_generics = vec![];
+    // `impl_generics`, the declared generics with their bounds.
+    let mut impl_generics = vec![];
+    // Only the names of the generics, without any bounds.
+    let mut ty_generics = vec![];
+    // Tokens not related to the generics e.g. the `where` token and definition.
+    let mut rest = vec![];
+    // The current level of `<`.
+    let mut nesting = 0;
+    let mut toks = input.into_iter();
+    // If we are at the beginning of a generic parameter.
+    let mut at_start = true;
+    let mut skip_until_comma = false;
+    while let Some(tt) = toks.next() {
+        if nesting == 1 && matches!(&tt, TokenTree::Punct(p) if p.as_char() == '>') {
+            // Found the end of the generics.
+            break;
+        } else if nesting >= 1 {
+            decl_generics.push(tt.clone());
+        }
+        match tt.clone() {
+            TokenTree::Punct(p) if p.as_char() == '<' => {
+                if nesting >= 1 && !skip_until_comma {
+                    // This is inside of the generics and part of some bound.
+                    impl_generics.push(tt);
+                }
+                nesting += 1;
+            }
+            TokenTree::Punct(p) if p.as_char() == '>' => {
+                // This is a parsing error, so we just end it here.
+                if nesting == 0 {
+                    break;
+                } else {
+                    nesting -= 1;
+                    if nesting >= 1 && !skip_until_comma {
+                        // We are still inside of the generics and part of some bound.
+                        impl_generics.push(tt);
+                    }
+                }
+            }
+            TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' => {
+                if nesting == 1 {
+                    impl_generics.push(tt.clone());
+                    impl_generics.push(tt);
+                    skip_until_comma = false;
+                }
+            }
+            _ if !skip_until_comma => {
+                match nesting {
+                    // If we haven't entered the generics yet, we still want to keep these tokens.
+                    0 => rest.push(tt),
+                    1 => {
+                        // Here depending on the token, it might be a generic variable name.
+                        match tt.clone() {
+                            TokenTree::Ident(i) if at_start && i.to_string() == "const" => {
+                                let Some(name) = toks.next() else {
+                                    // Parsing error.
+                                    break;
+                                };
+                                impl_generics.push(tt);
+                                impl_generics.push(name.clone());
+                                ty_generics.push(name.clone());
+                                decl_generics.push(name);
+                                at_start = false;
+                            }
+                            TokenTree::Ident(_) if at_start => {
+                                impl_generics.push(tt.clone());
+                                ty_generics.push(tt);
+                                at_start = false;
+                            }
+                            TokenTree::Punct(p) if p.as_char() == ',' => {
+                                impl_generics.push(tt.clone());
+                                ty_generics.push(tt);
+                                at_start = true;
+                            }
+                            // Lifetimes begin with `'`.
+                            TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
+                                impl_generics.push(tt.clone());
+                                ty_generics.push(tt);
+                            }
+                            // Generics can have default values, we skip these.
+                            TokenTree::Punct(p) if p.as_char() == '=' => {
+                                skip_until_comma = true;
+                            }
+                            _ => impl_generics.push(tt),
+                        }
+                    }
+                    _ => impl_generics.push(tt),
+                }
+            }
+            _ => {}
+        }
+    }
+    rest.extend(toks);
+    (
+        Generics {
+            impl_generics,
+            decl_generics,
+            ty_generics,
+        },
+        rest,
+    )
+}
diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
new file mode 100644
index 000000000000..0a2761cc793c
--- /dev/null
+++ b/rust/pin-init/internal/src/lib.rs
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+/// Used to specify the pinning information of the fields of a struct.
+///
+/// This is somewhat similar in purpose as
+/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
+/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
+/// field you want to structurally pin.
+///
+/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
+/// then `#[pin]` directs the type of initializer that is required.
+///
+/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
+/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
+/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
+///
+/// # Examples
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use std::{sync::Mutex, process::Command};
+/// # use kernel::macros::pin_data;
+/// #[pin_data]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+/// }
+/// ```
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use std::{sync::Mutex, process::Command};
+/// # use core::pin::Pin;
+/// # pub struct Info;
+/// # mod bindings {
+/// #     pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
+/// # }
+/// use kernel::macros::{pin_data, pinned_drop};
+///
+/// #[pin_data(PinnedDrop)]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+///     raw_info: *mut Info,
+/// }
+///
+/// #[pinned_drop]
+/// impl PinnedDrop for DriverData {
+///     fn drop(self: Pin<&mut Self>) {
+///         unsafe { bindings::destroy_info(self.raw_info) };
+///     }
+/// }
+/// # fn main() {}
+/// ```
+///
+/// [`pin_init!`]: ../kernel/macro.pin_init.html
+//  ^ cannot use direct link, since `kernel` is not a dependency of `macros`.
+#[proc_macro_attribute]
+pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
+    pin_data::pin_data(inner, item)
+}
+
+/// Used to implement `PinnedDrop` safely.
+///
+/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
+///
+/// # Examples
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use macros::{pin_data, pinned_drop};
+/// # use std::{sync::Mutex, process::Command};
+/// # use core::pin::Pin;
+/// # mod bindings {
+/// #     pub struct Info;
+/// #     pub unsafe fn destroy_info(_ptr: *mut Info) {}
+/// # }
+/// #[pin_data(PinnedDrop)]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+///     raw_info: *mut bindings::Info,
+/// }
+///
+/// #[pinned_drop]
+/// impl PinnedDrop for DriverData {
+///     fn drop(self: Pin<&mut Self>) {
+///         unsafe { bindings::destroy_info(self.raw_info) };
+///     }
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
+    pinned_drop::pinned_drop(args, input)
+}
+
+/// Derives the [`Zeroable`] trait for the given struct.
+///
+/// This can only be used for structs where every field implements the [`Zeroable`] trait.
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::macros::Zeroable;
+///
+/// #[derive(Zeroable)]
+/// pub struct DriverData {
+///     id: i64,
+///     buf_ptr: *mut u8,
+///     len: usize,
+/// }
+/// ```
+#[proc_macro_derive(Zeroable)]
+pub fn derive_zeroable(input: TokenStream) -> TokenStream {
+    zeroable::derive(input)
+}
diff --git a/rust/macros/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
similarity index 100%
rename from rust/macros/pin_data.rs
rename to rust/pin-init/internal/src/pin_data.rs
diff --git a/rust/macros/pinned_drop.rs b/rust/pin-init/internal/src/pinned_drop.rs
similarity index 100%
rename from rust/macros/pinned_drop.rs
rename to rust/pin-init/internal/src/pinned_drop.rs
diff --git a/rust/macros/zeroable.rs b/rust/pin-init/internal/src/zeroable.rs
similarity index 100%
rename from rust/macros/zeroable.rs
rename to rust/pin-init/internal/src/zeroable.rs
diff --git a/rust/kernel/init/__internal.rs b/rust/pin-init/src/__internal.rs
similarity index 100%
rename from rust/kernel/init/__internal.rs
rename to rust/pin-init/src/__internal.rs
diff --git a/rust/kernel/init.rs b/rust/pin-init/src/lib.rs
similarity index 100%
rename from rust/kernel/init.rs
rename to rust/pin-init/src/lib.rs
diff --git a/rust/kernel/init/macros.rs b/rust/pin-init/src/macros.rs
similarity index 100%
rename from rust/kernel/init/macros.rs
rename to rust/pin-init/src/macros.rs
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
  2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
  2025-03-04 22:53   ` [PATCH 02/22] rust: move pin-init API into its own directory Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  9:11     ` Andreas Hindborg
  2025-03-05  9:17     ` Fiona Behrens
  2025-03-04 22:53   ` [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate Benno Lossin
                     ` (20 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

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@proton.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



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (2 preceding siblings ...)
  2025-03-04 22:53   ` [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  9:18     ` Fiona Behrens
  2025-03-05  9:34     ` Andreas Hindborg
  2025-03-04 22:53   ` [PATCH 05/22] rust: pin-init: change examples to the user-space version Benno Lossin
                     ` (19 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Move the documentation of proc-macros from pin-init-internal into
pin-init. This is because documentation can only reference types from
dependencies and pin-init-internal cannot have pin-init as a dependency,
as that would be cyclic.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/internal/src/lib.rs | 109 +----------------------------
 rust/pin-init/src/lib.rs          | 111 ++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 106 deletions(-)

diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
index 0a2761cc793c..bf66cbee2531 100644
--- a/rust/pin-init/internal/src/lib.rs
+++ b/rust/pin-init/internal/src/lib.rs
@@ -1,121 +1,18 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-/// Used to specify the pinning information of the fields of a struct.
-///
-/// This is somewhat similar in purpose as
-/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
-/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
-/// field you want to structurally pin.
-///
-/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
-/// then `#[pin]` directs the type of initializer that is required.
-///
-/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
-/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
-/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
-///
-/// # Examples
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use kernel::macros::pin_data;
-/// #[pin_data]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-/// }
-/// ```
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # pub struct Info;
-/// # mod bindings {
-/// #     pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
-/// # }
-/// use kernel::macros::{pin_data, pinned_drop};
-///
-/// #[pin_data(PinnedDrop)]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut Info,
-/// }
-///
-/// #[pinned_drop]
-/// impl PinnedDrop for DriverData {
-///     fn drop(self: Pin<&mut Self>) {
-///         unsafe { bindings::destroy_info(self.raw_info) };
-///     }
-/// }
-/// # fn main() {}
-/// ```
-///
-/// [`pin_init!`]: ../kernel/macro.pin_init.html
-//  ^ cannot use direct link, since `kernel` is not a dependency of `macros`.
+#[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
     pin_data::pin_data(inner, item)
 }
 
-/// Used to implement `PinnedDrop` safely.
-///
-/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
-///
-/// # Examples
-///
-/// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use macros::{pin_data, pinned_drop};
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # mod bindings {
-/// #     pub struct Info;
-/// #     pub unsafe fn destroy_info(_ptr: *mut Info) {}
-/// # }
-/// #[pin_data(PinnedDrop)]
-/// struct DriverData {
-///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut bindings::Info,
-/// }
-///
-/// #[pinned_drop]
-/// impl PinnedDrop for DriverData {
-///     fn drop(self: Pin<&mut Self>) {
-///         unsafe { bindings::destroy_info(self.raw_info) };
-///     }
-/// }
-/// ```
+#[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
     pinned_drop::pinned_drop(args, input)
 }
 
-/// Derives the [`Zeroable`] trait for the given struct.
-///
-/// This can only be used for structs where every field implements the [`Zeroable`] trait.
-///
-/// # Examples
-///
-/// ```ignore
-/// use kernel::macros::Zeroable;
-///
-/// #[derive(Zeroable)]
-/// pub struct DriverData {
-///     id: i64,
-///     buf_ptr: *mut u8,
-///     len: usize,
-/// }
-/// ```
+#[allow(missing_docs)]
 #[proc_macro_derive(Zeroable)]
 pub fn derive_zeroable(input: TokenStream) -> TokenStream {
     zeroable::derive(input)
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 0307a08ccee9..df6962460874 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -218,6 +218,117 @@
 #[doc(hidden)]
 pub mod macros;
 
+/// Used to specify the pinning information of the fields of a struct.
+///
+/// This is somewhat similar in purpose as
+/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
+/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
+/// field you want to structurally pin.
+///
+/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
+/// then `#[pin]` directs the type of initializer that is required.
+///
+/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
+/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
+/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
+///
+/// # Examples
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use std::{sync::Mutex, process::Command};
+/// # use kernel::macros::pin_data;
+/// #[pin_data]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+/// }
+/// ```
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use std::{sync::Mutex, process::Command};
+/// # use core::pin::Pin;
+/// # pub struct Info;
+/// # mod bindings {
+/// #     pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
+/// # }
+/// use kernel::macros::{pin_data, pinned_drop};
+///
+/// #[pin_data(PinnedDrop)]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+///     raw_info: *mut Info,
+/// }
+///
+/// #[pinned_drop]
+/// impl PinnedDrop for DriverData {
+///     fn drop(self: Pin<&mut Self>) {
+///         unsafe { bindings::destroy_info(self.raw_info) };
+///     }
+/// }
+/// # fn main() {}
+/// ```
+///
+/// [`pin_init!`]: crate::pin_init
+pub use ::macros::pin_data;
+
+/// Used to implement `PinnedDrop` safely.
+///
+/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
+///
+/// # Examples
+///
+/// ```ignore
+/// # #![feature(lint_reasons)]
+/// # use kernel::prelude::*;
+/// # use macros::{pin_data, pinned_drop};
+/// # use std::{sync::Mutex, process::Command};
+/// # use core::pin::Pin;
+/// # mod bindings {
+/// #     pub struct Info;
+/// #     pub unsafe fn destroy_info(_ptr: *mut Info) {}
+/// # }
+/// #[pin_data(PinnedDrop)]
+/// struct DriverData {
+///     #[pin]
+///     queue: Mutex<KVec<Command>>,
+///     buf: KBox<[u8; 1024 * 1024]>,
+///     raw_info: *mut bindings::Info,
+/// }
+///
+/// #[pinned_drop]
+/// impl PinnedDrop for DriverData {
+///     fn drop(self: Pin<&mut Self>) {
+///         unsafe { bindings::destroy_info(self.raw_info) };
+///     }
+/// }
+/// ```
+pub use ::macros::pinned_drop;
+
+/// Derives the [`Zeroable`] trait for the given struct.
+///
+/// This can only be used for structs where every field implements the [`Zeroable`] trait.
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::macros::Zeroable;
+///
+/// #[derive(Zeroable)]
+/// pub struct DriverData {
+///     id: i64,
+///     buf_ptr: *mut u8,
+///     len: usize,
+/// }
+/// ```
+pub use ::macros::Zeroable;
+
 /// Initialize and pin a type directly on the stack.
 ///
 /// # Examples
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 05/22] rust: pin-init: change examples to the user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (3 preceding siblings ...)
  2025-03-04 22:53   ` [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  9:19     ` Fiona Behrens
  2025-03-05 10:06     ` Andreas Hindborg
  2025-03-04 22:53   ` [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!` Benno Lossin
                     ` (18 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

Replace the examples in the documentation by the ones from the
user-space version and introduce the standalone examples from the
user-space version such as the `CMutex<T>` type.

The `CMutex<T>` example from the pinned-init repository [1] is used in
several documentation examples in the user-space version instead of the
kernel `Mutex<T>` type (as it's not available). In order to split off
the pin-init crate, all examples need to be free of kernel-specific
types.

Link: https://github.com/rust-for-Linux/pinned-init [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/examples/big_struct_in_place.rs |  39 ++
 rust/pin-init/examples/error.rs               |  27 ++
 rust/pin-init/examples/linked_list.rs         | 161 ++++++++
 rust/pin-init/examples/mutex.rs               | 209 ++++++++++
 rust/pin-init/examples/pthread_mutex.rs       | 178 +++++++++
 rust/pin-init/examples/static_init.rs         | 122 ++++++
 rust/pin-init/src/lib.rs                      | 365 +++++++++---------
 7 files changed, 915 insertions(+), 186 deletions(-)
 create mode 100644 rust/pin-init/examples/big_struct_in_place.rs
 create mode 100644 rust/pin-init/examples/error.rs
 create mode 100644 rust/pin-init/examples/linked_list.rs
 create mode 100644 rust/pin-init/examples/mutex.rs
 create mode 100644 rust/pin-init/examples/pthread_mutex.rs
 create mode 100644 rust/pin-init/examples/static_init.rs

diff --git a/rust/pin-init/examples/big_struct_in_place.rs b/rust/pin-init/examples/big_struct_in_place.rs
new file mode 100644
index 000000000000..30d44a334ffd
--- /dev/null
+++ b/rust/pin-init/examples/big_struct_in_place.rs
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+use pin_init::*;
+
+// Struct with size over 1GiB
+#[derive(Debug)]
+pub struct BigStruct {
+    buf: [u8; 1024 * 1024 * 1024],
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+    managed_buf: ManagedBuf,
+}
+
+#[derive(Debug)]
+pub struct ManagedBuf {
+    buf: [u8; 1024 * 1024],
+}
+
+impl ManagedBuf {
+    pub fn new() -> impl Init<Self> {
+        init!(ManagedBuf { buf <- zeroed() })
+    }
+}
+
+fn main() {
+    // we want to initialize the struct in-place, otherwise we would get a stackoverflow
+    let buf: Box<BigStruct> = Box::init(init!(BigStruct {
+        buf <- zeroed(),
+        a: 7,
+        b: 186,
+        c: 7789,
+        d: 34,
+        managed_buf <- ManagedBuf::new(),
+    }))
+    .unwrap();
+    println!("{}", core::mem::size_of_val(&*buf));
+}
diff --git a/rust/pin-init/examples/error.rs b/rust/pin-init/examples/error.rs
new file mode 100644
index 000000000000..e0cc258746ce
--- /dev/null
+++ b/rust/pin-init/examples/error.rs
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+
+use core::convert::Infallible;
+
+#[cfg(feature = "alloc")]
+use std::alloc::AllocError;
+
+#[derive(Debug)]
+pub struct Error;
+
+impl From<Infallible> for Error {
+    fn from(e: Infallible) -> Self {
+        match e {}
+    }
+}
+
+#[cfg(feature = "alloc")]
+impl From<AllocError> for Error {
+    fn from(_: AllocError) -> Self {
+        Self
+    }
+}
+
+#[allow(dead_code)]
+fn main() {}
diff --git a/rust/pin-init/examples/linked_list.rs b/rust/pin-init/examples/linked_list.rs
new file mode 100644
index 000000000000..6d7eb0a0ec0d
--- /dev/null
+++ b/rust/pin-init/examples/linked_list.rs
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#![allow(clippy::undocumented_unsafe_blocks)]
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+
+use core::{
+    cell::Cell,
+    convert::Infallible,
+    marker::PhantomPinned,
+    pin::Pin,
+    ptr::{self, NonNull},
+};
+
+use pin_init::*;
+
+#[expect(unused_attributes)]
+mod error;
+use error::Error;
+
+#[pin_data(PinnedDrop)]
+#[repr(C)]
+#[derive(Debug)]
+pub struct ListHead {
+    next: Link,
+    prev: Link,
+    #[pin]
+    pin: PhantomPinned,
+}
+
+impl ListHead {
+    #[inline]
+    pub fn new() -> impl PinInit<Self, Infallible> {
+        try_pin_init!(&this in Self {
+            next: unsafe { Link::new_unchecked(this) },
+            prev: unsafe { Link::new_unchecked(this) },
+            pin: PhantomPinned,
+        }? Infallible)
+    }
+
+    #[inline]
+    pub fn insert_next(list: &ListHead) -> impl PinInit<Self, Infallible> + '_ {
+        try_pin_init!(&this in Self {
+            prev: list.next.prev().replace(unsafe { Link::new_unchecked(this)}),
+            next: list.next.replace(unsafe { Link::new_unchecked(this)}),
+            pin: PhantomPinned,
+        }? Infallible)
+    }
+
+    #[inline]
+    pub fn insert_prev(list: &ListHead) -> impl PinInit<Self, Infallible> + '_ {
+        try_pin_init!(&this in Self {
+            next: list.prev.next().replace(unsafe { Link::new_unchecked(this)}),
+            prev: list.prev.replace(unsafe { Link::new_unchecked(this)}),
+            pin: PhantomPinned,
+        }? Infallible)
+    }
+
+    #[inline]
+    pub fn next(&self) -> Option<NonNull<Self>> {
+        if ptr::eq(self.next.as_ptr(), self) {
+            None
+        } else {
+            Some(unsafe { NonNull::new_unchecked(self.next.as_ptr() as *mut Self) })
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn size(&self) -> usize {
+        let mut size = 1;
+        let mut cur = self.next.clone();
+        while !ptr::eq(self, cur.cur()) {
+            cur = cur.next().clone();
+            size += 1;
+        }
+        size
+    }
+}
+
+#[pinned_drop]
+impl PinnedDrop for ListHead {
+    //#[inline]
+    fn drop(self: Pin<&mut Self>) {
+        if !ptr::eq(self.next.as_ptr(), &*self) {
+            let next = unsafe { &*self.next.as_ptr() };
+            let prev = unsafe { &*self.prev.as_ptr() };
+            next.prev.set(&self.prev);
+            prev.next.set(&self.next);
+        }
+    }
+}
+
+#[repr(transparent)]
+#[derive(Clone, Debug)]
+struct Link(Cell<NonNull<ListHead>>);
+
+impl Link {
+    /// # Safety
+    ///
+    /// The contents of the pointer should form a consistent circular
+    /// linked list; for example, a "next" link should be pointed back
+    /// by the target `ListHead`'s "prev" link and a "prev" link should be
+    /// pointed back by the target `ListHead`'s "next" link.
+    #[inline]
+    unsafe fn new_unchecked(ptr: NonNull<ListHead>) -> Self {
+        Self(Cell::new(ptr))
+    }
+
+    #[inline]
+    fn next(&self) -> &Link {
+        unsafe { &(*self.0.get().as_ptr()).next }
+    }
+
+    #[inline]
+    fn prev(&self) -> &Link {
+        unsafe { &(*self.0.get().as_ptr()).prev }
+    }
+
+    #[allow(dead_code)]
+    fn cur(&self) -> &ListHead {
+        unsafe { &*self.0.get().as_ptr() }
+    }
+
+    #[inline]
+    fn replace(&self, other: Link) -> Link {
+        unsafe { Link::new_unchecked(self.0.replace(other.0.get())) }
+    }
+
+    #[inline]
+    fn as_ptr(&self) -> *const ListHead {
+        self.0.get().as_ptr()
+    }
+
+    #[inline]
+    fn set(&self, val: &Link) {
+        self.0.set(val.0.get());
+    }
+}
+
+#[allow(dead_code)]
+#[cfg_attr(test, test)]
+fn main() -> Result<(), Error> {
+    let a = Box::pin_init(ListHead::new())?;
+    stack_pin_init!(let b = ListHead::insert_next(&a));
+    stack_pin_init!(let c = ListHead::insert_next(&a));
+    stack_pin_init!(let d = ListHead::insert_next(&b));
+    let e = Box::pin_init(ListHead::insert_next(&b))?;
+    println!("a ({a:p}): {a:?}");
+    println!("b ({b:p}): {b:?}");
+    println!("c ({c:p}): {c:?}");
+    println!("d ({d:p}): {d:?}");
+    println!("e ({e:p}): {e:?}");
+    let mut inspect = &*a;
+    while let Some(next) = inspect.next() {
+        println!("({inspect:p}): {inspect:?}");
+        inspect = unsafe { &*next.as_ptr() };
+        if core::ptr::eq(inspect, &*a) {
+            break;
+        }
+    }
+    Ok(())
+}
diff --git a/rust/pin-init/examples/mutex.rs b/rust/pin-init/examples/mutex.rs
new file mode 100644
index 000000000000..073bb79341d1
--- /dev/null
+++ b/rust/pin-init/examples/mutex.rs
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#![allow(clippy::undocumented_unsafe_blocks)]
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+#![allow(clippy::missing_safety_doc)]
+
+use core::{
+    cell::{Cell, UnsafeCell},
+    marker::PhantomPinned,
+    ops::{Deref, DerefMut},
+    pin::Pin,
+    sync::atomic::{AtomicBool, Ordering},
+};
+use std::{
+    sync::Arc,
+    thread::{self, park, sleep, Builder, Thread},
+    time::Duration,
+};
+
+use pin_init::*;
+#[expect(unused_attributes)]
+#[path = "./linked_list.rs"]
+pub mod linked_list;
+use linked_list::*;
+
+pub struct SpinLock {
+    inner: AtomicBool,
+}
+
+impl SpinLock {
+    #[inline]
+    pub fn acquire(&self) -> SpinLockGuard<'_> {
+        while self
+            .inner
+            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
+            .is_err()
+        {
+            while self.inner.load(Ordering::Relaxed) {
+                thread::yield_now();
+            }
+        }
+        SpinLockGuard(self)
+    }
+
+    #[inline]
+    #[allow(clippy::new_without_default)]
+    pub const fn new() -> Self {
+        Self {
+            inner: AtomicBool::new(false),
+        }
+    }
+}
+
+pub struct SpinLockGuard<'a>(&'a SpinLock);
+
+impl Drop for SpinLockGuard<'_> {
+    #[inline]
+    fn drop(&mut self) {
+        self.0.inner.store(false, Ordering::Release);
+    }
+}
+
+#[pin_data]
+pub struct CMutex<T> {
+    #[pin]
+    wait_list: ListHead,
+    spin_lock: SpinLock,
+    locked: Cell<bool>,
+    #[pin]
+    data: UnsafeCell<T>,
+}
+
+impl<T> CMutex<T> {
+    #[inline]
+    pub fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
+        pin_init!(CMutex {
+            wait_list <- ListHead::new(),
+            spin_lock: SpinLock::new(),
+            locked: Cell::new(false),
+            data <- unsafe {
+                pin_init_from_closure(|slot: *mut UnsafeCell<T>| {
+                    val.__pinned_init(slot.cast::<T>())
+                })
+            },
+        })
+    }
+
+    #[inline]
+    pub fn lock(&self) -> Pin<CMutexGuard<'_, T>> {
+        let mut sguard = self.spin_lock.acquire();
+        if self.locked.get() {
+            stack_pin_init!(let wait_entry = WaitEntry::insert_new(&self.wait_list));
+            // println!("wait list length: {}", self.wait_list.size());
+            while self.locked.get() {
+                drop(sguard);
+                park();
+                sguard = self.spin_lock.acquire();
+            }
+            // This does have an effect, as the ListHead inside wait_entry implements Drop!
+            #[expect(clippy::drop_non_drop)]
+            drop(wait_entry);
+        }
+        self.locked.set(true);
+        unsafe {
+            Pin::new_unchecked(CMutexGuard {
+                mtx: self,
+                _pin: PhantomPinned,
+            })
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn get_data_mut(self: Pin<&mut Self>) -> &mut T {
+        // SAFETY: we have an exclusive reference and thus nobody has access to data.
+        unsafe { &mut *self.data.get() }
+    }
+}
+
+unsafe impl<T: Send> Send for CMutex<T> {}
+unsafe impl<T: Send> Sync for CMutex<T> {}
+
+pub struct CMutexGuard<'a, T> {
+    mtx: &'a CMutex<T>,
+    _pin: PhantomPinned,
+}
+
+impl<T> Drop for CMutexGuard<'_, T> {
+    #[inline]
+    fn drop(&mut self) {
+        let sguard = self.mtx.spin_lock.acquire();
+        self.mtx.locked.set(false);
+        if let Some(list_field) = self.mtx.wait_list.next() {
+            let wait_entry = list_field.as_ptr().cast::<WaitEntry>();
+            unsafe { (*wait_entry).thread.unpark() };
+        }
+        drop(sguard);
+    }
+}
+
+impl<T> Deref for CMutexGuard<'_, T> {
+    type Target = T;
+
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        unsafe { &*self.mtx.data.get() }
+    }
+}
+
+impl<T> DerefMut for CMutexGuard<'_, T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe { &mut *self.mtx.data.get() }
+    }
+}
+
+#[pin_data]
+#[repr(C)]
+struct WaitEntry {
+    #[pin]
+    wait_list: ListHead,
+    thread: Thread,
+}
+
+impl WaitEntry {
+    #[inline]
+    fn insert_new(list: &ListHead) -> impl PinInit<Self> + '_ {
+        pin_init!(Self {
+            thread: thread::current(),
+            wait_list <- ListHead::insert_prev(list),
+        })
+    }
+}
+
+#[cfg(not(any(feature = "std", feature = "alloc")))]
+fn main() {}
+
+#[allow(dead_code)]
+#[cfg_attr(test, test)]
+#[cfg(any(feature = "std", feature = "alloc"))]
+fn main() {
+    let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();
+    let mut handles = vec![];
+    let thread_count = 20;
+    let workload = if cfg!(miri) { 100 } else { 1_000 };
+    for i in 0..thread_count {
+        let mtx = mtx.clone();
+        handles.push(
+            Builder::new()
+                .name(format!("worker #{i}"))
+                .spawn(move || {
+                    for _ in 0..workload {
+                        *mtx.lock() += 1;
+                    }
+                    println!("{i} halfway");
+                    sleep(Duration::from_millis((i as u64) * 10));
+                    for _ in 0..workload {
+                        *mtx.lock() += 1;
+                    }
+                    println!("{i} finished");
+                })
+                .expect("should not fail"),
+        );
+    }
+    for h in handles {
+        h.join().expect("thread panicked");
+    }
+    println!("{:?}", &*mtx.lock());
+    assert_eq!(*mtx.lock(), workload * thread_count * 2);
+}
diff --git a/rust/pin-init/examples/pthread_mutex.rs b/rust/pin-init/examples/pthread_mutex.rs
new file mode 100644
index 000000000000..9164298c44c0
--- /dev/null
+++ b/rust/pin-init/examples/pthread_mutex.rs
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+// inspired by https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs
+#![allow(clippy::undocumented_unsafe_blocks)]
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+#[cfg(not(windows))]
+mod pthread_mtx {
+    #[cfg(feature = "alloc")]
+    use core::alloc::AllocError;
+    use core::{
+        cell::UnsafeCell,
+        marker::PhantomPinned,
+        mem::MaybeUninit,
+        ops::{Deref, DerefMut},
+        pin::Pin,
+    };
+    use pin_init::*;
+    use std::convert::Infallible;
+
+    #[pin_data(PinnedDrop)]
+    pub struct PThreadMutex<T> {
+        #[pin]
+        raw: UnsafeCell<libc::pthread_mutex_t>,
+        data: UnsafeCell<T>,
+        #[pin]
+        pin: PhantomPinned,
+    }
+
+    unsafe impl<T: Send> Send for PThreadMutex<T> {}
+    unsafe impl<T: Send> Sync for PThreadMutex<T> {}
+
+    #[pinned_drop]
+    impl<T> PinnedDrop for PThreadMutex<T> {
+        fn drop(self: Pin<&mut Self>) {
+            unsafe {
+                libc::pthread_mutex_destroy(self.raw.get());
+            }
+        }
+    }
+
+    #[derive(Debug)]
+    pub enum Error {
+        #[expect(dead_code)]
+        IO(std::io::Error),
+        Alloc,
+    }
+
+    impl From<Infallible> for Error {
+        fn from(e: Infallible) -> Self {
+            match e {}
+        }
+    }
+
+    #[cfg(feature = "alloc")]
+    impl From<AllocError> for Error {
+        fn from(_: AllocError) -> Self {
+            Self::Alloc
+        }
+    }
+
+    impl<T> PThreadMutex<T> {
+        pub fn new(data: T) -> impl PinInit<Self, Error> {
+            fn init_raw() -> impl PinInit<UnsafeCell<libc::pthread_mutex_t>, Error> {
+                let init = |slot: *mut UnsafeCell<libc::pthread_mutex_t>| {
+                    // we can cast, because `UnsafeCell` has the same layout as T.
+                    let slot: *mut libc::pthread_mutex_t = slot.cast();
+                    let mut attr = MaybeUninit::uninit();
+                    let attr = attr.as_mut_ptr();
+                    // SAFETY: ptr is valid
+                    let ret = unsafe { libc::pthread_mutexattr_init(attr) };
+                    if ret != 0 {
+                        return Err(Error::IO(std::io::Error::from_raw_os_error(ret)));
+                    }
+                    // SAFETY: attr is initialized
+                    let ret = unsafe {
+                        libc::pthread_mutexattr_settype(attr, libc::PTHREAD_MUTEX_NORMAL)
+                    };
+                    if ret != 0 {
+                        // SAFETY: attr is initialized
+                        unsafe { libc::pthread_mutexattr_destroy(attr) };
+                        return Err(Error::IO(std::io::Error::from_raw_os_error(ret)));
+                    }
+                    // SAFETY: slot is valid
+                    unsafe { slot.write(libc::PTHREAD_MUTEX_INITIALIZER) };
+                    // SAFETY: attr and slot are valid ptrs and attr is initialized
+                    let ret = unsafe { libc::pthread_mutex_init(slot, attr) };
+                    // SAFETY: attr was initialized
+                    unsafe { libc::pthread_mutexattr_destroy(attr) };
+                    if ret != 0 {
+                        return Err(Error::IO(std::io::Error::from_raw_os_error(ret)));
+                    }
+                    Ok(())
+                };
+                // SAFETY: mutex has been initialized
+                unsafe { pin_init_from_closure(init) }
+            }
+            try_pin_init!(Self {
+            data: UnsafeCell::new(data),
+            raw <- init_raw(),
+            pin: PhantomPinned,
+        }? Error)
+        }
+
+        pub fn lock(&self) -> PThreadMutexGuard<'_, T> {
+            // SAFETY: raw is always initialized
+            unsafe { libc::pthread_mutex_lock(self.raw.get()) };
+            PThreadMutexGuard { mtx: self }
+        }
+    }
+
+    pub struct PThreadMutexGuard<'a, T> {
+        mtx: &'a PThreadMutex<T>,
+    }
+
+    impl<T> Drop for PThreadMutexGuard<'_, T> {
+        fn drop(&mut self) {
+            // SAFETY: raw is always initialized
+            unsafe { libc::pthread_mutex_unlock(self.mtx.raw.get()) };
+        }
+    }
+
+    impl<T> Deref for PThreadMutexGuard<'_, T> {
+        type Target = T;
+
+        fn deref(&self) -> &Self::Target {
+            unsafe { &*self.mtx.data.get() }
+        }
+    }
+
+    impl<T> DerefMut for PThreadMutexGuard<'_, T> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            unsafe { &mut *self.mtx.data.get() }
+        }
+    }
+}
+
+#[cfg_attr(test, test)]
+fn main() {
+    #[cfg(all(any(feature = "std", feature = "alloc"), not(windows)))]
+    {
+        use core::pin::Pin;
+        use pin_init::*;
+        use pthread_mtx::*;
+        use std::{
+            sync::Arc,
+            thread::{sleep, Builder},
+            time::Duration,
+        };
+        let mtx: Pin<Arc<PThreadMutex<usize>>> = Arc::try_pin_init(PThreadMutex::new(0)).unwrap();
+        let mut handles = vec![];
+        let thread_count = 20;
+        let workload = 1_000_000;
+        for i in 0..thread_count {
+            let mtx = mtx.clone();
+            handles.push(
+                Builder::new()
+                    .name(format!("worker #{i}"))
+                    .spawn(move || {
+                        for _ in 0..workload {
+                            *mtx.lock() += 1;
+                        }
+                        println!("{i} halfway");
+                        sleep(Duration::from_millis((i as u64) * 10));
+                        for _ in 0..workload {
+                            *mtx.lock() += 1;
+                        }
+                        println!("{i} finished");
+                    })
+                    .expect("should not fail"),
+            );
+        }
+        for h in handles {
+            h.join().expect("thread panicked");
+        }
+        println!("{:?}", &*mtx.lock());
+        assert_eq!(*mtx.lock(), workload * thread_count * 2);
+    }
+}
diff --git a/rust/pin-init/examples/static_init.rs b/rust/pin-init/examples/static_init.rs
new file mode 100644
index 000000000000..3487d761aa26
--- /dev/null
+++ b/rust/pin-init/examples/static_init.rs
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#![allow(clippy::undocumented_unsafe_blocks)]
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+
+use core::{
+    cell::{Cell, UnsafeCell},
+    mem::MaybeUninit,
+    ops,
+    pin::Pin,
+    time::Duration,
+};
+use pin_init::*;
+use std::{
+    sync::Arc,
+    thread::{sleep, Builder},
+};
+
+#[expect(unused_attributes)]
+mod mutex;
+use mutex::*;
+
+pub struct StaticInit<T, I> {
+    cell: UnsafeCell<MaybeUninit<T>>,
+    init: Cell<Option<I>>,
+    lock: SpinLock,
+    present: Cell<bool>,
+}
+
+unsafe impl<T: Sync, I> Sync for StaticInit<T, I> {}
+unsafe impl<T: Send, I> Send for StaticInit<T, I> {}
+
+impl<T, I: PinInit<T>> StaticInit<T, I> {
+    pub const fn new(init: I) -> Self {
+        Self {
+            cell: UnsafeCell::new(MaybeUninit::uninit()),
+            init: Cell::new(Some(init)),
+            lock: SpinLock::new(),
+            present: Cell::new(false),
+        }
+    }
+}
+
+impl<T, I: PinInit<T>> ops::Deref for StaticInit<T, I> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        if self.present.get() {
+            unsafe { (*self.cell.get()).assume_init_ref() }
+        } else {
+            println!("acquire spinlock on static init");
+            let _guard = self.lock.acquire();
+            println!("rechecking present...");
+            std::thread::sleep(std::time::Duration::from_millis(200));
+            if self.present.get() {
+                return unsafe { (*self.cell.get()).assume_init_ref() };
+            }
+            println!("doing init");
+            let ptr = self.cell.get().cast::<T>();
+            match self.init.take() {
+                Some(f) => unsafe { f.__pinned_init(ptr).unwrap() },
+                None => unsafe { core::hint::unreachable_unchecked() },
+            }
+            self.present.set(true);
+            unsafe { (*self.cell.get()).assume_init_ref() }
+        }
+    }
+}
+
+pub struct CountInit;
+
+unsafe impl PinInit<CMutex<usize>> for CountInit {
+    unsafe fn __pinned_init(
+        self,
+        slot: *mut CMutex<usize>,
+    ) -> Result<(), core::convert::Infallible> {
+        let init = CMutex::new(0);
+        std::thread::sleep(std::time::Duration::from_millis(1000));
+        unsafe { init.__pinned_init(slot) }
+    }
+}
+
+pub static COUNT: StaticInit<CMutex<usize>, CountInit> = StaticInit::new(CountInit);
+
+#[cfg(not(any(feature = "std", feature = "alloc")))]
+fn main() {}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+fn main() {
+    let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();
+    let mut handles = vec![];
+    let thread_count = 20;
+    let workload = 1_000;
+    for i in 0..thread_count {
+        let mtx = mtx.clone();
+        handles.push(
+            Builder::new()
+                .name(format!("worker #{i}"))
+                .spawn(move || {
+                    for _ in 0..workload {
+                        *COUNT.lock() += 1;
+                        std::thread::sleep(std::time::Duration::from_millis(10));
+                        *mtx.lock() += 1;
+                        std::thread::sleep(std::time::Duration::from_millis(10));
+                        *COUNT.lock() += 1;
+                    }
+                    println!("{i} halfway");
+                    sleep(Duration::from_millis((i as u64) * 10));
+                    for _ in 0..workload {
+                        std::thread::sleep(std::time::Duration::from_millis(10));
+                        *mtx.lock() += 1;
+                    }
+                    println!("{i} finished");
+                })
+                .expect("should not fail"),
+        );
+    }
+    for h in handles {
+        h.join().expect("thread panicked");
+    }
+    println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock());
+    assert_eq!(*mtx.lock(), workload * thread_count * 2);
+}
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index df6962460874..92027e2f60f5 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -33,19 +33,23 @@
 //!
 //! ```rust,ignore
 //! # #![expect(clippy::disallowed_names)]
-//! use kernel::sync::{new_mutex, Mutex};
+//! # #![feature(allocator_api)]
+//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 //! # use core::pin::Pin;
+//! use pin_init::*;
+//!
 //! #[pin_data]
 //! struct Foo {
 //!     #[pin]
-//!     a: Mutex<usize>,
+//!     a: CMutex<usize>,
 //!     b: u32,
 //! }
 //!
 //! let foo = pin_init!(Foo {
-//!     a <- new_mutex!(42, "Foo::a"),
+//!     a <- CMutex::new(42),
 //!     b: 24,
 //! });
+//! # let _ = Box::pin_init(foo);
 //! ```
 //!
 //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
@@ -53,19 +57,23 @@
 //!
 //! ```rust,ignore
 //! # #![expect(clippy::disallowed_names)]
-//! # use kernel::sync::{new_mutex, Mutex};
-//! # use core::pin::Pin;
+//! # #![feature(allocator_api)]
+//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+//! # use core::{alloc::AllocError, pin::Pin};
+//! # use pin_init::*;
+//! #
 //! # #[pin_data]
 //! # struct Foo {
 //! #     #[pin]
-//! #     a: Mutex<usize>,
+//! #     a: CMutex<usize>,
 //! #     b: u32,
 //! # }
+//! #
 //! # let foo = pin_init!(Foo {
-//! #     a <- new_mutex!(42, "Foo::a"),
+//! #     a <- CMutex::new(42),
 //! #     b: 24,
 //! # });
-//! let foo: Result<Pin<KBox<Foo>>> = KBox::pin_init(foo, GFP_KERNEL);
+//! let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
 //! ```
 //!
 //! For more information see the [`pin_init!`] macro.
@@ -76,28 +84,34 @@
 //! above method only works for types where you can access the fields.
 //!
 //! ```rust,ignore
-//! # use kernel::sync::{new_mutex, Arc, Mutex};
-//! let mtx: Result<Arc<Mutex<usize>>> =
-//!     Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);
+//! # #![feature(allocator_api)]
+//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+//! # use pin_init::*;
+//! # use std::sync::Arc;
+//! # use core::pin::Pin;
+//! let mtx: Result<Pin<Arc<Mutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
 //! ```
 //!
 //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
 //!
 //! ```rust,ignore
-//! # use kernel::{sync::Mutex, new_mutex, init::PinInit, try_pin_init};
+//! # #![feature(allocator_api)]
+//! # use pin_init::*;
+//! # #[path = "../examples/error.rs"] mod error; use error::Error;
+//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 //! #[pin_data]
 //! struct DriverData {
 //!     #[pin]
-//!     status: Mutex<i32>,
-//!     buffer: KBox<[u8; 1_000_000]>,
+//!     status: CMutex<i32>,
+//!     buffer: Box<[u8; 1_000_000]>,
 //! }
 //!
 //! impl DriverData {
 //!     fn new() -> impl PinInit<Self, Error> {
 //!         try_pin_init!(Self {
-//!             status <- new_mutex!(0, "DriverData::status"),
-//!             buffer: KBox::init(kernel::init::zeroed(), GFP_KERNEL)?,
-//!         })
+//!             status <- CMutex::new(0),
+//!             buffer: Box::init(pin_init::zeroed())?,
+//!         }? Error)
 //!     }
 //! }
 //! ```
@@ -117,60 +131,61 @@
 //!   `slot` gets called.
 //!
 //! ```rust,ignore
-//! # #![expect(unreachable_pub, clippy::disallowed_names)]
-//! use kernel::{init, types::Opaque};
-//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
-//! # mod bindings {
-//! #     #![expect(non_camel_case_types)]
-//! #     #![expect(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 }
-//! # }
-//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
-//! # trait FromErrno {
-//! #     fn from_errno(errno: kernel::ffi::c_int) -> Error {
-//! #         // Dummy error that can be constructed outside the `kernel` crate.
-//! #         Error::from(core::fmt::Error)
-//! #     }
-//! # }
-//! # impl FromErrno for Error {}
+//! # #![feature(extern_types)]
+//! use pin_init::*;
+//! use core::{
+//!     ptr::addr_of_mut,
+//!     marker::PhantomPinned,
+//!     cell::UnsafeCell,
+//!     pin::Pin,
+//!     mem::MaybeUninit,
+//! };
+//! mod bindings {
+//!     extern "C" {
+//!         pub type foo;
+//!         pub fn init_foo(ptr: *mut foo);
+//!         pub fn destroy_foo(ptr: *mut foo);
+//!         #[must_use = "you must check the error return code"]
+//!         pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
+//!     }
+//! }
+//!
 //! /// # Invariants
 //! ///
 //! /// `foo` is always initialized
 //! #[pin_data(PinnedDrop)]
 //! pub struct RawFoo {
 //!     #[pin]
-//!     foo: Opaque<bindings::foo>,
-//!     #[pin]
 //!     _p: PhantomPinned,
+//!     #[pin]
+//!     foo: UnsafeCell<MaybeUninit<bindings::foo>>,
 //! }
 //!
 //! impl RawFoo {
-//!     pub fn new(flags: u32) -> impl PinInit<Self, Error> {
+//!     pub fn new(flags: u32) -> impl PinInit<Self, i32> {
 //!         // 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 {
-//!             init::pin_init_from_closure(move |slot: *mut Self| {
+//!             pin_init_from_closure(move |slot: *mut Self| {
 //!                 // `slot` contains uninit memory, avoid creating a reference.
 //!                 let foo = addr_of_mut!((*slot).foo);
+//!                 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
 //!
 //!                 // Initialize the `foo`
-//!                 bindings::init_foo(Opaque::raw_get(foo));
+//!                 bindings::init_foo(foo);
 //!
 //!                 // Try to enable it.
-//!                 let err = bindings::enable_foo(Opaque::raw_get(foo), flags);
+//!                 let err = bindings::enable_foo(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));
+//!                     bindings::destroy_foo(foo);
+//!                     Err(err)
+//!                 } else {
+//!                     // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
+//!                     Ok(())
 //!                 }
-//!
-//!                 // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
-//!                 Ok(())
 //!             })
 //!         }
 //!     }
@@ -180,7 +195,7 @@
 //! 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()) };
+//!         unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };
 //!     }
 //! }
 //! ```
@@ -235,35 +250,39 @@
 /// # Examples
 ///
 /// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use kernel::macros::pin_data;
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// use pin_init::pin_data;
+///
+/// enum Command {
+///     /* ... */
+/// }
+///
 /// #[pin_data]
 /// struct DriverData {
 ///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
+///     queue: CMutex<Vec<Command>>,
+///     buf: Box<[u8; 1024 * 1024]>,
 /// }
 /// ```
 ///
 /// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # pub struct Info;
-/// # mod bindings {
-/// #     pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
-/// # }
-/// use kernel::macros::{pin_data, pinned_drop};
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
+/// use core::pin::Pin;
+/// use pin_init::{pin_data, pinned_drop, PinnedDrop};
+///
+/// enum Command {
+///     /* ... */
+/// }
 ///
 /// #[pin_data(PinnedDrop)]
 /// struct DriverData {
 ///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut Info,
+///     queue: CMutex<Vec<Command>>,
+///     buf: Box<[u8; 1024 * 1024]>,
+///     raw_info: *mut bindings::info,
 /// }
 ///
 /// #[pinned_drop]
@@ -272,7 +291,6 @@
 ///         unsafe { bindings::destroy_info(self.raw_info) };
 ///     }
 /// }
-/// # fn main() {}
 /// ```
 ///
 /// [`pin_init!`]: crate::pin_init
@@ -285,21 +303,22 @@
 /// # Examples
 ///
 /// ```ignore
-/// # #![feature(lint_reasons)]
-/// # use kernel::prelude::*;
-/// # use macros::{pin_data, pinned_drop};
-/// # use std::{sync::Mutex, process::Command};
-/// # use core::pin::Pin;
-/// # mod bindings {
-/// #     pub struct Info;
-/// #     pub unsafe fn destroy_info(_ptr: *mut Info) {}
-/// # }
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
+/// use core::pin::Pin;
+/// use pin_init::{pin_data, pinned_drop, PinnedDrop};
+///
+/// enum Command {
+///     /* ... */
+/// }
+///
 /// #[pin_data(PinnedDrop)]
 /// struct DriverData {
 ///     #[pin]
-///     queue: Mutex<KVec<Command>>,
-///     buf: KBox<[u8; 1024 * 1024]>,
-///     raw_info: *mut bindings::Info,
+///     queue: CMutex<Vec<Command>>,
+///     buf: Box<[u8; 1024 * 1024]>,
+///     raw_info: *mut bindings::info,
 /// }
 ///
 /// #[pinned_drop]
@@ -318,7 +337,7 @@
 /// # Examples
 ///
 /// ```ignore
-/// use kernel::macros::Zeroable;
+/// use pin_init::Zeroable;
 ///
 /// #[derive(Zeroable)]
 /// pub struct DriverData {
@@ -335,12 +354,14 @@
 ///
 /// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex};
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::*;
 /// # use core::pin::Pin;
 /// #[pin_data]
 /// struct Foo {
 ///     #[pin]
-///     a: Mutex<usize>,
+///     a: CMutex<usize>,
 ///     b: Bar,
 /// }
 ///
@@ -350,13 +371,13 @@
 /// }
 ///
 /// stack_pin_init!(let foo = pin_init!(Foo {
-///     a <- new_mutex!(42),
+///     a <- CMutex::new(42),
 ///     b: Bar {
 ///         x: 64,
 ///     },
 /// }));
 /// let foo: Pin<&mut Foo> = foo;
-/// pr_info!("a: {}", &*foo.a.lock());
+/// println!("a: {}", &*foo.a.lock());
 /// ```
 ///
 /// # Syntax
@@ -387,70 +408,56 @@ macro_rules! stack_pin_init {
 ///
 /// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{
-/// #     init,
-/// #     pin_init,
-/// #     stack_try_pin_init,
-/// #     init::*,
-/// #     sync::Mutex,
-/// #     new_mutex,
-/// #     alloc::AllocError,
-/// # };
-/// # use macros::pin_data;
-/// # use core::pin::Pin;
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/error.rs"] mod error; use error::Error;
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::*;
 /// #[pin_data]
 /// struct Foo {
 ///     #[pin]
-///     a: Mutex<usize>,
-///     b: KBox<Bar>,
+///     a: CMutex<usize>,
+///     b: Box<Bar>,
 /// }
 ///
 /// struct Bar {
 ///     x: u32,
 /// }
 ///
-/// stack_try_pin_init!(let foo: Result<Pin<&mut Foo>, AllocError> = pin_init!(Foo {
-///     a <- new_mutex!(42),
-///     b: KBox::new(Bar {
+/// stack_try_pin_init!(let foo: Foo = try_pin_init!(Foo {
+///     a <- CMutex::new(42),
+///     b: Box::try_new(Bar {
 ///         x: 64,
-///     }, GFP_KERNEL)?,
-/// }));
+///     })?,
+/// }? Error));
 /// let foo = foo.unwrap();
-/// pr_info!("a: {}", &*foo.a.lock());
+/// println!("a: {}", &*foo.a.lock());
 /// ```
 ///
 /// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{
-/// #     init,
-/// #     pin_init,
-/// #     stack_try_pin_init,
-/// #     init::*,
-/// #     sync::Mutex,
-/// #     new_mutex,
-/// #     alloc::AllocError,
-/// # };
-/// # use macros::pin_data;
-/// # use core::pin::Pin;
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/error.rs"] mod error; use error::Error;
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::*;
 /// #[pin_data]
 /// struct Foo {
 ///     #[pin]
-///     a: Mutex<usize>,
-///     b: KBox<Bar>,
+///     a: CMutex<usize>,
+///     b: Box<Bar>,
 /// }
 ///
 /// struct Bar {
 ///     x: u32,
 /// }
 ///
-/// stack_try_pin_init!(let foo: Pin<&mut Foo> =? pin_init!(Foo {
-///     a <- new_mutex!(42),
-///     b: KBox::new(Bar {
+/// stack_try_pin_init!(let foo: Foo =? try_pin_init!(Foo {
+///     a <- CMutex::new(42),
+///     b: Box::try_new(Bar {
 ///         x: 64,
-///     }, GFP_KERNEL)?,
-/// }));
-/// pr_info!("a: {}", &*foo.a.lock());
-/// # Ok::<_, AllocError>(())
+///     })?,
+/// }? Error));
+/// println!("a: {}", &*foo.a.lock());
+/// # Ok::<_, Error>(())
 /// ```
 ///
 /// # Syntax
@@ -480,7 +487,7 @@ macro_rules! stack_try_pin_init {
 /// The syntax is almost identical to that of a normal `struct` initializer:
 ///
 /// ```rust,ignore
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
+/// # use pin_init::*;
 /// # use core::pin::Pin;
 /// #[pin_data]
 /// struct Foo {
@@ -503,7 +510,7 @@ macro_rules! stack_try_pin_init {
 ///     },
 /// });
 /// # initializer }
-/// # KBox::pin_init(demo(), GFP_KERNEL).unwrap();
+/// # Box::pin_init(demo()).unwrap();
 /// ```
 ///
 /// Arbitrary Rust expressions can be used to set the value of a variable.
@@ -524,7 +531,7 @@ macro_rules! stack_try_pin_init {
 /// To create an initializer function, simply declare it like this:
 ///
 /// ```rust,ignore
-/// # use kernel::{init, pin_init, init::*};
+/// # use pin_init::*;
 /// # use core::pin::Pin;
 /// # #[pin_data]
 /// # struct Foo {
@@ -551,7 +558,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// ```rust,ignore
 /// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
+/// # use pin_init::*;
 /// # use core::pin::Pin;
 /// # #[pin_data]
 /// # struct Foo {
@@ -572,13 +579,13 @@ macro_rules! stack_try_pin_init {
 /// #         })
 /// #     }
 /// # }
-/// let foo = KBox::pin_init(Foo::new(), GFP_KERNEL);
+/// let foo = Box::pin_init(Foo::new());
 /// ```
 ///
 /// They can also easily embed it into their own `struct`s:
 ///
 /// ```rust,ignore
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
+/// # use pin_init::*;
 /// # use core::pin::Pin;
 /// # #[pin_data]
 /// # struct Foo {
@@ -637,7 +644,7 @@ macro_rules! stack_try_pin_init {
 /// For instance:
 ///
 /// ```rust,ignore
-/// # use kernel::{macros::{Zeroable, pin_data}, pin_init};
+/// # use pin_init::*;
 /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
 /// #[pin_data]
 /// #[derive(Zeroable)]
@@ -700,10 +707,12 @@ macro_rules! pin_init {
 /// # Examples
 ///
 /// ```rust,ignore
-/// use kernel::{init::{self, PinInit}, error::Error};
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/error.rs"] mod error; use error::Error;
+/// use pin_init::*;
 /// #[pin_data]
 /// struct BigBuf {
-///     big: KBox<[u8; 1024 * 1024 * 1024]>,
+///     big: Box<[u8; 1024 * 1024 * 1024]>,
 ///     small: [u8; 1024 * 1024],
 ///     ptr: *mut u8,
 /// }
@@ -711,12 +720,13 @@ macro_rules! pin_init {
 /// impl BigBuf {
 ///     fn new() -> impl PinInit<Self, Error> {
 ///         try_pin_init!(Self {
-///             big: KBox::init(init::zeroed(), GFP_KERNEL)?,
+///             big: Box::init(init::zeroed())?,
 ///             small: [0; 1024 * 1024],
 ///             ptr: core::ptr::null_mut(),
 ///         }? Error)
 ///     }
 /// }
+/// # let _ = Box::pin_init(BigBuf::new());
 /// ```
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
@@ -803,18 +813,20 @@ macro_rules! init {
 /// # Examples
 ///
 /// ```rust,ignore
-/// use kernel::{alloc::KBox, init::{PinInit, zeroed}, error::Error};
+/// # #![feature(allocator_api)]
+/// # use core::alloc::AllocError;
+/// use pin_init::*;
 /// struct BigBuf {
-///     big: KBox<[u8; 1024 * 1024 * 1024]>,
+///     big: Box<[u8; 1024 * 1024 * 1024]>,
 ///     small: [u8; 1024 * 1024],
 /// }
 ///
 /// impl BigBuf {
-///     fn new() -> impl Init<Self, Error> {
+///     fn new() -> impl Init<Self, AllocError> {
 ///         try_init!(Self {
-///             big: KBox::init(zeroed(), GFP_KERNEL)?,
+///             big: Box::init(zeroed())?,
 ///             small: [0; 1024 * 1024],
-///         }? Error)
+///         }? AllocError)
 ///     }
 /// }
 /// ```
@@ -859,7 +871,7 @@ macro_rules! try_init {
 ///
 /// This will succeed:
 /// ```ignore
-/// use kernel::assert_pinned;
+/// use pin_init::assert_pinned;
 /// #[pin_data]
 /// struct MyStruct {
 ///     #[pin]
@@ -870,9 +882,8 @@ macro_rules! try_init {
 /// ```
 ///
 /// This will fail:
-// TODO: replace with `compile_fail` when supported.
-/// ```ignore
-/// use kernel::assert_pinned;
+/// ```compile_fail,ignore
+/// use pin_init::assert_pinned;
 /// #[pin_data]
 /// struct MyStruct {
 ///     some_field: u64,
@@ -885,7 +896,7 @@ macro_rules! try_init {
 /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
 /// only be used when the macro is invoked from a function body.
 /// ```ignore
-/// use kernel::assert_pinned;
+/// use pin_init::assert_pinned;
 /// #[pin_data]
 /// struct Foo<T> {
 ///     #[pin]
@@ -963,35 +974,13 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     /// # Examples
     ///
     /// ```rust,ignore
-    /// # #![expect(clippy::disallowed_names)]
-    /// use kernel::{types::Opaque, init::pin_init_from_closure};
-    /// #[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");
-    ///     }
-    /// }
-    ///
-    /// let foo = pin_init!(Foo {
-    ///     // SAFETY: TODO.
-    ///     raw <- unsafe {
-    ///         Opaque::ffi_init(|s| {
-    ///             init_foo(s);
-    ///         })
-    ///     },
-    /// }).pin_chain(|foo| {
-    ///     foo.setup();
+    /// # #![feature(allocator_api)]
+    /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+    /// # use pin_init::*;
+    /// let mtx_init = CMutex::new(42);
+    /// // Make the initializer print the value.
+    /// let mtx_init = mtx_init.pin_chain(|mtx| {
+    ///     println!("{:?}", mtx.get_data_mut());
     ///     Ok(())
     /// });
     /// ```
@@ -1076,7 +1065,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     ///
     /// ```rust,ignore
     /// # #![expect(clippy::disallowed_names)]
-    /// use kernel::{types::Opaque, init::{self, init_from_closure}};
+    /// use pin_init::{init_from_closure, zeroed};
     /// struct Foo {
     ///     buf: [u8; 1_000_000],
     /// }
@@ -1088,7 +1077,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     /// }
     ///
     /// let foo = init!(Foo {
-    ///     buf <- init::zeroed()
+    ///     buf <- zeroed()
     /// }).chain(|foo| {
     ///     foo.setup();
     ///     Ok(())
@@ -1187,11 +1176,10 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
 /// # Examples
 ///
 /// ```rust,ignore
-/// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn};
-/// let array: KBox<[usize; 1_000]> =
-///     KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?;
+/// # use pin_init::*;
+/// use pin_init::init_array_from_fn;
+/// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap();
 /// assert_eq!(array.len(), 1_000);
-/// # Ok::<(), Error>(())
 /// ```
 pub fn init_array_from_fn<I, const N: usize, T, E>(
     mut make_init: impl FnMut(usize) -> I,
@@ -1232,11 +1220,15 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
 /// # Examples
 ///
 /// ```rust,ignore
-/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
-/// let array: Arc<[Mutex<usize>; 1_000]> =
-///     Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?;
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::*;
+/// # use core::pin::Pin;
+/// use pin_init::pin_init_array_from_fn;
+/// use std::sync::Arc;
+/// let array: Pin<Arc<[CMutex<usize>; 1_000]>> =
+///     Arc::pin_init(pin_init_array_from_fn(|i| CMutex::new(i))).unwrap();
 /// assert_eq!(array.len(), 1_000);
-/// # Ok::<(), Error>(())
 /// ```
 pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
     mut make_init: impl FnMut(usize) -> I,
@@ -1421,19 +1413,20 @@ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Ini
 /// Use [`pinned_drop`] to implement this trait safely:
 ///
 /// ```rust,ignore
-/// # use kernel::sync::Mutex;
-/// use kernel::macros::pinned_drop;
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::*;
 /// use core::pin::Pin;
 /// #[pin_data(PinnedDrop)]
 /// struct Foo {
 ///     #[pin]
-///     mtx: Mutex<usize>,
+///     mtx: CMutex<usize>,
 /// }
 ///
 /// #[pinned_drop]
 /// impl PinnedDrop for Foo {
 ///     fn drop(self: Pin<&mut Self>) {
-///         pr_info!("Foo is being dropped!");
+///         println!("Foo is being dropped!");
 ///     }
 /// }
 /// ```
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!`
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (4 preceding siblings ...)
  2025-03-04 22:53   ` [PATCH 05/22] rust: pin-init: change examples to the user-space version Benno Lossin
@ 2025-03-04 22:53   ` Benno Lossin
  2025-03-05  9:19     ` Fiona Behrens
  2025-03-05 10:12     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init` Benno Lossin
                     ` (17 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:53 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

The `[pin_]init!` macros have the same behavior as the `try_[pin_]init!`
macros, except that they set the error type to `Infallible`.
Instead of calling the primitive `__init_internal!` with the correct
parameters, the same can thus be achieved by calling `try_[pin_]init!`.
Since this makes it more clear what their behavior is, simplify the
implementations of `[pin_]init!`.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/lib.rs | 26 ++++++--------------------
 1 file changed, 6 insertions(+), 20 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 92027e2f60f5..4c492efeb5cd 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -676,16 +676,9 @@ macro_rules! pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::__init_internal!(
-            @this($($this)?),
-            @typ($t $(::<$($generics),*>)?),
-            @fields($($fields)*),
-            @error(::core::convert::Infallible),
-            @data(PinData, use_data),
-            @has_data(HasPinData, __pin_data),
-            @construct_closure(pin_init_from_closure),
-            @munch_fields($($fields)*),
-        )
+        $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
+            $($fields)*
+        }? ::core::convert::Infallible)
     };
 }
 
@@ -784,16 +777,9 @@ macro_rules! init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::__init_internal!(
-            @this($($this)?),
-            @typ($t $(::<$($generics),*>)?),
-            @fields($($fields)*),
-            @error(::core::convert::Infallible),
-            @data(InitData, /*no use_data*/),
-            @has_data(HasInitData, __init_data),
-            @construct_closure(init_from_closure),
-            @munch_fields($($fields)*),
-        )
+        $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
+            $($fields)*
+        }? ::core::convert::Infallible)
     }
 }
 
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init`
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (5 preceding siblings ...)
  2025-03-04 22:53   ` [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!` Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:21     ` Fiona Behrens
  2025-03-05 10:29     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate Benno Lossin
                     ` (16 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Move the ability to just write `try_pin_init!(Foo { a <- a_init })`
(note the missing `? Error` at the end) into the kernel crate.
Remove this notation from the pin-init crate, since the default when no
error is specified is the kernel-internal `Error` type. Instead add two
macros in the kernel crate that serve this default and are used instead
of the ones from `pin-init`.

This is done, because the `Error` type that is used as the default is
from the kernel crate and it thus prevents making the pin-init crate
standalone.

In order to not cause a build error due to a name overlap, the macros in
the pin-init crate are renamed, but this change is reverted in a future
commit when it is a standalone crate.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/init.rs      | 113 +++++++++++++++++++++++++++++++++++++++
 rust/kernel/prelude.rs   |   3 +-
 rust/pin-init/src/lib.rs |  55 +++++--------------
 3 files changed, 128 insertions(+), 43 deletions(-)

diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 322dfd9ec347..d80eccf29100 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -133,3 +133,116 @@
 //!     }
 //! }
 //! ```
+
+/// 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::{init::zeroed, error::Error};
+/// 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(zeroed(), GFP_KERNEL)?,
+///             small: [0; 1024 * 1024],
+///         }? Error)
+///     }
+/// }
+/// ```
+///
+/// [`Infallible`]: core::convert::Infallible
+/// [`init!`]: crate::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)*
+    }) => {
+        $crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+            $($fields)*
+        }? $crate::error::Error)
+    };
+    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
+        $($fields:tt)*
+    }? $err:ty) => {
+        $crate::_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::{init::zeroed, error::Error};
+/// #[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(zeroed(), GFP_KERNEL)?,
+///             small: [0; 1024 * 1024],
+///             ptr: core::ptr::null_mut(),
+///         }? Error)
+///     }
+/// }
+/// ```
+///
+/// [`Infallible`]: core::convert::Infallible
+/// [`pin_init!`]: crate::pin_init
+/// [`Error`]: crate::error::Error
+#[macro_export]
+macro_rules! try_pin_init {
+    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
+        $($fields:tt)*
+    }) => {
+        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+            $($fields)*
+        }? $crate::error::Error)
+    };
+    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
+        $($fields:tt)*
+    }? $err:ty) => {
+        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+            $($fields)*
+        }? $err)
+    };
+}
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index dde2e0649790..4123d478c351 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -28,7 +28,8 @@
 pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
 pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
 
-pub use super::{init, pin_init, try_init, try_pin_init};
+pub use super::{init, pin_init};
+pub use super::{try_init, try_pin_init};
 
 pub use super::static_assert;
 
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 4c492efeb5cd..1308b7af7ec9 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -481,7 +481,7 @@ macro_rules! stack_try_pin_init {
 
 /// Construct an in-place, pinned initializer for `struct`s.
 ///
-/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
+/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
 /// [`try_pin_init!`].
 ///
 /// The syntax is almost identical to that of a normal `struct` initializer:
@@ -676,7 +676,7 @@ macro_rules! pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
+        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
             $($fields)*
         }? ::core::convert::Infallible)
     };
@@ -692,9 +692,7 @@ macro_rules! pin_init {
 /// 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`
+/// The syntax is identical to [`pin_init!`] with the following exception: you must append `? $type`
 /// after the `struct` initializer to specify the error type you want to use.
 ///
 /// # Examples
@@ -724,21 +722,7 @@ macro_rules! pin_init {
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
 #[macro_export]
-macro_rules! try_pin_init {
-    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
-        $($fields:tt)*
-    }) => {
-        $crate::__init_internal!(
-            @this($($this)?),
-            @typ($t $(::<$($generics),*>)? ),
-            @fields($($fields)*),
-            @error($crate::error::Error),
-            @data(PinData, use_data),
-            @has_data(HasPinData, __pin_data),
-            @construct_closure(pin_init_from_closure),
-            @munch_fields($($fields)*),
-        )
-    };
+macro_rules! _try_pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
@@ -752,12 +736,12 @@ macro_rules! try_pin_init {
             @construct_closure(pin_init_from_closure),
             @munch_fields($($fields)*),
         )
-    };
+    }
 }
 
 /// Construct an in-place initializer for `struct`s.
 ///
-/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
+/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
 /// [`try_init!`].
 ///
 /// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
@@ -777,7 +761,7 @@ macro_rules! init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
+        $crate::_try_init!($(&$this in)? $t $(::<$($generics),*>)? {
             $($fields)*
         }? ::core::convert::Infallible)
     }
@@ -785,11 +769,11 @@ macro_rules! init {
 
 /// Construct an in-place fallible initializer for `struct`s.
 ///
-/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
+/// If the initialization can complete without error (or [`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 syntax is identical to [`try_pin_init!`]. You need to specify a custom error
+/// via `? $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.
@@ -816,24 +800,11 @@ macro_rules! init {
 ///     }
 /// }
 /// ```
+/// [`try_pin_init!`]: crate::try_pin_init
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
 #[macro_export]
-macro_rules! try_init {
-    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
-        $($fields:tt)*
-    }) => {
-        $crate::__init_internal!(
-            @this($($this)?),
-            @typ($t $(::<$($generics),*>)?),
-            @fields($($fields)*),
-            @error($crate::error::Error),
-            @data(InitData, /*no use_data*/),
-            @has_data(HasInitData, __init_data),
-            @construct_closure(init_from_closure),
-            @munch_fields($($fields)*),
-        )
-    };
+macro_rules! _try_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
@@ -847,7 +818,7 @@ macro_rules! try_init {
             @construct_closure(init_from_closure),
             @munch_fields($($fields)*),
         )
-    };
+    }
 }
 
 /// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (6 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init` Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:23     ` Fiona Behrens
  2025-03-05 11:18     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` " Benno Lossin
                     ` (15 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross
  Cc: rust-for-linux, linux-kernel

In order to make pin-init a standalone crate, move kernel-specific code
directly into the kernel crate. This includes the `InPlaceInit<T>`
trait, its implementations and the implementations of `InPlaceWrite` for
`Arc` and `UniqueArc`. All of these use the kernel's error type which
will become unavailable in pin-init.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/alloc/kbox.rs |   3 +-
 rust/kernel/init.rs       |  55 +++++++++++++++++
 rust/kernel/prelude.rs    |   3 +-
 rust/kernel/sync/arc.rs   |  65 +++++++++++++++++++-
 rust/pin-init/src/lib.rs  | 125 ++------------------------------------
 5 files changed, 127 insertions(+), 124 deletions(-)

diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index cb4ebea3b074..39a3ea7542da 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -15,7 +15,8 @@
 use core::ptr::NonNull;
 use core::result::Result;
 
-use crate::init::{InPlaceInit, InPlaceWrite, Init, PinInit};
+use crate::init::{InPlaceWrite, Init, PinInit};
+use crate::init_ext::InPlaceInit;
 use crate::types::ForeignOwnable;
 
 /// The kernel's [`Box`] type -- a heap allocation for a single value of type `T`.
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index d80eccf29100..d8eb6d7873b7 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -134,6 +134,61 @@
 //! }
 //! ```
 
+use crate::{
+    alloc::{AllocError, Flags},
+    error::{self, Error},
+    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
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 4123d478c351..6b9e068b3710 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -37,6 +37,7 @@
 
 pub use super::{str::CStr, ThisModule};
 
-pub use super::init::{InPlaceInit, InPlaceWrite, Init, PinInit};
+pub use super::init::{InPlaceWrite, Init, PinInit};
+pub use super::init_ext::InPlaceInit;
 
 pub use super::current;
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 3cefda7a4372..31c26b692c6d 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -19,7 +19,8 @@
 use crate::{
     alloc::{AllocError, Flags, KBox},
     bindings,
-    init::{self, InPlaceInit, Init, PinInit},
+    init::{self, InPlaceWrite, Init, PinInit},
+    init_ext::InPlaceInit,
     try_init,
     types::{ForeignOwnable, Opaque},
 };
@@ -202,6 +203,26 @@ unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
 // the reference count reaches zero and `T` is dropped.
 unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
 
+impl<T> InPlaceInit<T> for Arc<T> {
+    type PinnedSelf = Self;
+
+    #[inline]
+    fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+    where
+        E: From<AllocError>,
+    {
+        UniqueArc::try_pin_init(init, flags).map(|u| u.into())
+    }
+
+    #[inline]
+    fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+    where
+        E: From<AllocError>,
+    {
+        UniqueArc::try_init(init, flags).map(|u| u.into())
+    }
+}
+
 impl<T> Arc<T> {
     /// Constructs a new reference counted instance of `T`.
     pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
@@ -659,6 +680,48 @@ pub struct UniqueArc<T: ?Sized> {
     inner: Arc<T>,
 }
 
+impl<T> InPlaceInit<T> for UniqueArc<T> {
+    type PinnedSelf = Pin<Self>;
+
+    #[inline]
+    fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+    where
+        E: From<AllocError>,
+    {
+        UniqueArc::new_uninit(flags)?.write_pin_init(init)
+    }
+
+    #[inline]
+    fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+    where
+        E: From<AllocError>,
+    {
+        UniqueArc::new_uninit(flags)?.write_init(init)
+    }
+}
+
+impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
+    type Initialized = UniqueArc<T>;
+
+    fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
+        let slot = self.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid.
+        unsafe { init.__init(slot)? };
+        // SAFETY: All fields have been initialized.
+        Ok(unsafe { self.assume_init() })
+    }
+
+    fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
+        let slot = self.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid and will not be moved, because we pin it later.
+        unsafe { init.__pinned_init(slot)? };
+        // SAFETY: All fields have been initialized.
+        Ok(unsafe { self.assume_init() }.into())
+    }
+}
+
 impl<T> UniqueArc<T> {
     /// Tries to allocate a new [`UniqueArc`] instance.
     pub fn new(value: T, flags: Flags) -> Result<Self, AllocError> {
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 1308b7af7ec9..49e31228c14a 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -10,7 +10,7 @@
 //! To initialize a `struct` with an in-place constructor you will need two things:
 //! - an in-place constructor,
 //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
-//!   [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
+//!   [`KBox<T>`] or any other smart pointer that supports this library).
 //!
 //! To get an in-place constructor there are generally three options:
 //! - directly creating an in-place constructor using the [`pin_init!`] macro,
@@ -212,10 +212,7 @@
 //! [`pin_init!`]: crate::pin_init!
 
 use crate::{
-    alloc::{AllocError, Flags, KBox},
-    error::{self, Error},
-    sync::Arc,
-    sync::UniqueArc,
+    alloc::KBox,
     types::{Opaque, ScopeGuard},
 };
 use core::{
@@ -891,8 +888,7 @@ macro_rules! assert_pinned {
 /// A pin-initializer for the type `T`.
 ///
 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use
-/// the [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc<T>`] on this.
+/// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]).
 ///
 /// Also see the [module description](self).
 ///
@@ -910,7 +906,6 @@ macro_rules! assert_pinned {
 /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
 ///
 /// [`Arc<T>`]: crate::sync::Arc
-/// [`Arc::pin_init`]: crate::sync::Arc::pin_init
 #[must_use = "An initializer must be used in order to create its value."]
 pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     /// Initializes `slot`.
@@ -976,8 +971,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 /// An initializer for `T`.
 ///
 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use
-/// the [`InPlaceInit::init`] function of a smart pointer like [`Arc<T>`] on this. Because
+/// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because
 /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
 ///
 /// Also see the [module description](self).
@@ -1238,95 +1232,6 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
     }
 }
 
-/// 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)
-    }
-}
-
-impl<T> InPlaceInit<T> for Arc<T> {
-    type PinnedSelf = Self;
-
-    #[inline]
-    fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
-    where
-        E: From<AllocError>,
-    {
-        UniqueArc::try_pin_init(init, flags).map(|u| u.into())
-    }
-
-    #[inline]
-    fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
-    where
-        E: From<AllocError>,
-    {
-        UniqueArc::try_init(init, flags).map(|u| u.into())
-    }
-}
-
-impl<T> InPlaceInit<T> for UniqueArc<T> {
-    type PinnedSelf = Pin<Self>;
-
-    #[inline]
-    fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
-    where
-        E: From<AllocError>,
-    {
-        UniqueArc::new_uninit(flags)?.write_pin_init(init)
-    }
-
-    #[inline]
-    fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
-    where
-        E: From<AllocError>,
-    {
-        UniqueArc::new_uninit(flags)?.write_init(init)
-    }
-}
-
 /// Smart pointer containing uninitialized memory and that can write a value.
 pub trait InPlaceWrite<T> {
     /// The type `Self` turns into when the contents are initialized.
@@ -1343,28 +1248,6 @@ pub trait InPlaceWrite<T> {
     fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>;
 }
 
-impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
-    type Initialized = UniqueArc<T>;
-
-    fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
-        let slot = self.as_mut_ptr();
-        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
-        // slot is valid.
-        unsafe { init.__init(slot)? };
-        // SAFETY: All fields have been initialized.
-        Ok(unsafe { self.assume_init() })
-    }
-
-    fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
-        let slot = self.as_mut_ptr();
-        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
-        // slot is valid and will not be moved, because we pin it later.
-        unsafe { init.__pinned_init(slot)? };
-        // SAFETY: All fields have been initialized.
-        Ok(unsafe { self.assume_init() }.into())
-    }
-}
-
 /// Trait facilitating pinned destruction.
 ///
 /// Use [`pinned_drop`] to implement this trait safely:
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (7 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:24     ` Fiona Behrens
  2025-03-05 11:26     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>` Benno Lossin
                     ` (14 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross
  Cc: rust-for-linux, linux-kernel

In order to make pin-init a standalone crate, move kernel-specific code
directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
of the kernel, move their `Zeroable` implementation into the kernel
crate.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/alloc/kbox.rs | 8 +++++++-
 rust/kernel/types.rs      | 5 ++++-
 rust/pin-init/src/lib.rs  | 8 +-------
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 39a3ea7542da..9861433559dc 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -15,7 +15,7 @@
 use core::ptr::NonNull;
 use core::result::Result;
 
-use crate::init::{InPlaceWrite, Init, PinInit};
+use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
 use crate::init_ext::InPlaceInit;
 use crate::types::ForeignOwnable;
 
@@ -100,6 +100,12 @@
 /// ```
 pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
 
+// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
+//
+// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
+// is no problem with a VTABLE pointer being null.
+unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
+
 // SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`.
 unsafe impl<T, A> Send for Box<T, A>
 where
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 2bbaab83b9d6..9f75bd3866e8 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -2,7 +2,7 @@
 
 //! Kernel types.
 
-use crate::init::{self, PinInit};
+use crate::init::{self, PinInit, Zeroable};
 use core::{
     cell::UnsafeCell,
     marker::{PhantomData, PhantomPinned},
@@ -309,6 +309,9 @@ pub struct Opaque<T> {
     _pin: PhantomPinned,
 }
 
+// SAFETY: `Opaque<T>` allows the inner value to be any bit pattern, including all zeros.
+unsafe impl<T> Zeroable for Opaque<T> {}
+
 impl<T> Opaque<T> {
     /// Creates a new opaque value.
     pub const fn new(value: T) -> Self {
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 49e31228c14a..5fd8fa7c2ce9 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -211,10 +211,7 @@
 //! [`pin_data`]: ::macros::pin_data
 //! [`pin_init!`]: crate::pin_init!
 
-use crate::{
-    alloc::KBox,
-    types::{Opaque, ScopeGuard},
-};
+use crate::{alloc::KBox, types::ScopeGuard};
 use core::{
     cell::UnsafeCell,
     convert::Infallible,
@@ -1342,8 +1339,6 @@ macro_rules! impl_zeroable {
 
     // SAFETY: Type is allowed to take any value, including all zeros.
     {<T>} MaybeUninit<T>,
-    // SAFETY: Type is allowed to take any value, including all zeros.
-    {<T>} Opaque<T>,
 
     // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
     {<T: ?Sized + Zeroable>} UnsafeCell<T>,
@@ -1358,7 +1353,6 @@ macro_rules! impl_zeroable {
     //
     // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant.
     {<T: ?Sized>} Option<NonNull<T>>,
-    {<T: ?Sized>} Option<KBox<T>>,
 
     // SAFETY: `null` pointer is valid.
     //
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>`
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (8 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` " Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:25     ` Fiona Behrens
  2025-03-05 11:30     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 11/22] rust: pin-init: fix documentation links Benno Lossin
                     ` (13 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross
  Cc: rust-for-linux, linux-kernel

When making pin-init its own crate, `Zeroable` will no longer be defined
by the kernel crate and thus implementing it for `Option<Box<T, A>>` is
no longer possible due to the orphan rule.
For this reason introduce a new `ZeroableOption` trait that circumvents
this problem.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/alloc/kbox.rs |  4 ++--
 rust/pin-init/src/lib.rs  | 11 +++++++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 9861433559dc..07150c038e3f 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -15,7 +15,7 @@
 use core::ptr::NonNull;
 use core::result::Result;
 
-use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
+use crate::init::{InPlaceWrite, Init, PinInit, ZeroableOption};
 use crate::init_ext::InPlaceInit;
 use crate::types::ForeignOwnable;
 
@@ -104,7 +104,7 @@
 //
 // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
 // is no problem with a VTABLE pointer being null.
-unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
+unsafe impl<T: ?Sized, A: Allocator> ZeroableOption for Box<T, A> {}
 
 // SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`.
 unsafe impl<T, A> Send for Box<T, A>
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 5fd8fa7c2ce9..fd2c4fdd0ca4 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1297,6 +1297,17 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
 /// ```
 pub unsafe trait Zeroable {}
 
+/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
+/// `None` to that location.
+///
+/// # Safety
+///
+/// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.
+pub unsafe trait ZeroableOption {}
+
+// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
+unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
+
 /// Create a new zeroed T.
 ///
 /// The returned initializer will write `0x00` to every byte of the given `slot`.
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 11/22] rust: pin-init: fix documentation links
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (9 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>` Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:26     ` Fiona Behrens
  2025-03-05 11:37     ` Andreas Hindborg
  2025-03-04 22:54   ` [PATCH 12/22] rust: pin-init: remove kernel-crate dependency Benno Lossin
                     ` (12 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Before switching to compile the `pin-init` crate directly, change
any links that would be invalid to links that are valid both before and
after the switch.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/kernel/sync/condvar.rs     |  2 +-
 rust/pin-init/src/__internal.rs |  4 ++--
 rust/pin-init/src/lib.rs        | 19 +++++++++++--------
 3 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 7df565038d7d..5aa7fa7c7002 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -37,7 +37,7 @@ macro_rules! new_condvar {
 /// spuriously.
 ///
 /// Instances of [`CondVar`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_condvar`] macros.
+/// instances is with the [`pin_init`](crate::pin_init!) and [`new_condvar`] macros.
 ///
 /// # Examples
 ///
diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 74329cc3262c..0db800819681 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -135,7 +135,7 @@ unsafe fn __init_data() -> Self::InitData {
 ///
 /// If `self.is_init` is true, then `self.value` is initialized.
 ///
-/// [`stack_pin_init`]: kernel::stack_pin_init
+/// [`stack_pin_init`]: crate::stack_pin_init
 pub struct StackInit<T> {
     value: MaybeUninit<T>,
     is_init: bool,
@@ -156,7 +156,7 @@ impl<T> StackInit<T> {
     /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this
     /// primitive.
     ///
-    /// [`stack_pin_init`]: kernel::stack_pin_init
+    /// [`stack_pin_init`]: crate::stack_pin_init
     #[inline]
     pub fn uninit() -> Self {
         Self {
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index fd2c4fdd0ca4..4e1c57a358c2 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -10,7 +10,7 @@
 //! To initialize a `struct` with an in-place constructor you will need two things:
 //! - an in-place constructor,
 //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
-//!   [`KBox<T>`] or any other smart pointer that supports this library).
+//!   [`Box<T>`] or any other smart pointer that supports this library).
 //!
 //! To get an in-place constructor there are generally three options:
 //! - directly creating an in-place constructor using the [`pin_init!`] macro,
@@ -204,7 +204,8 @@
 //! [structurally pinned fields]:
 //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
 //! [stack]: crate::stack_pin_init
-//! [`Arc<T>`]: crate::sync::Arc
+//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
+//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
 //! [`impl PinInit<Foo>`]: PinInit
 //! [`impl PinInit<T, E>`]: PinInit
 //! [`impl Init<T, E>`]: Init
@@ -661,7 +662,7 @@ macro_rules! stack_try_pin_init {
 /// });
 /// ```
 ///
-/// [`try_pin_init!`]: kernel::try_pin_init
+/// [`try_pin_init!`]: crate::try_pin_init
 /// [`NonNull<Self>`]: core::ptr::NonNull
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
@@ -885,7 +886,7 @@ macro_rules! assert_pinned {
 /// A pin-initializer for the type `T`.
 ///
 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]).
+/// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]).
 ///
 /// Also see the [module description](self).
 ///
@@ -902,7 +903,8 @@ macro_rules! assert_pinned {
 ///     - `slot` is not partially initialized.
 /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
 ///
-/// [`Arc<T>`]: crate::sync::Arc
+/// [`Arc<T>`]: ../kernel/sync/struct.Arc.html
+/// [`Box<T>`]: ../kernel/sync/struct.KBox.html
 #[must_use = "An initializer must be used in order to create its value."]
 pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     /// Initializes `slot`.
@@ -968,7 +970,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 /// An initializer for `T`.
 ///
 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because
+/// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because
 /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
 ///
 /// Also see the [module description](self).
@@ -992,7 +994,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 /// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
 /// move the pointee after initialization.
 ///
-/// [`Arc<T>`]: crate::sync::Arc
+/// [`Arc<T>`]: ../kernel/sync/struct.Arc.html
+/// [`Box<T>`]: ../kernel/sync/struct.KBox.html
 #[must_use = "An initializer must be used in order to create its value."]
 pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     /// Initializes `slot`.
@@ -1272,7 +1275,7 @@ pub trait InPlaceWrite<T> {
 ///
 /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
 ///
-/// [`pinned_drop`]: kernel::macros::pinned_drop
+/// [`pinned_drop`]: crate::macros::pinned_drop
 pub unsafe trait PinnedDrop: __internal::HasPinData {
     /// Executes the pinned destructor of this type.
     ///
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 12/22] rust: pin-init: remove kernel-crate dependency
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (10 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 11/22] rust: pin-init: fix documentation links Benno Lossin
@ 2025-03-04 22:54   ` Benno Lossin
  2025-03-05  9:27     ` Fiona Behrens
  2025-03-05 11:49     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called Benno Lossin
                     ` (11 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:54 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

In order to make pin-init a standalone crate, remove dependencies on
kernel-specific code such as `ScopeGuard` and `KBox`.

`ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
and can easily be replaced by a primitive construct.

`KBox` is only used for type variance of unsized types and can also
easily be replaced.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/__internal.rs |  2 +-
 rust/pin-init/src/lib.rs        | 41 +++++++++++----------------------
 2 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 0db800819681..74086365a18a 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -105,7 +105,7 @@ fn make_closure<F, O, E>(self, f: F) -> F
     }
 }
 
-pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>);
+pub struct AllData<T: ?Sized>(Invariant<T>);
 
 impl<T: ?Sized> Clone for AllData<T> {
     fn clone(&self) -> Self {
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 4e1c57a358c2..29c0920d1bfe 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -212,7 +212,6 @@
 //! [`pin_data`]: ::macros::pin_data
 //! [`pin_init!`]: crate::pin_init!
 
-use crate::{alloc::KBox, types::ScopeGuard};
 use core::{
     cell::UnsafeCell,
     convert::Infallible,
@@ -944,7 +943,7 @@ fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
 }
 
 /// An initializer returned by [`PinInit::pin_chain`].
-pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>);
+pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
 
 // SAFETY: The `__pinned_init` function is implemented such that it
 // - returns `Ok(())` on successful initialization,
@@ -1043,7 +1042,7 @@ fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
 }
 
 /// An initializer returned by [`Init::chain`].
-pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>);
+pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
 
 // SAFETY: The `__init` function is implemented such that it
 // - returns `Ok(())` on successful initialization,
@@ -1140,25 +1139,19 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
 {
     let init = move |slot: *mut [T; N]| {
         let slot = slot.cast::<T>();
-        // Counts the number of initialized elements and when dropped drops that many elements from
-        // `slot`.
-        let mut init_count = ScopeGuard::new_with_data(0, |i| {
-            // We now free every element that has been initialized before.
-            // SAFETY: The loop initialized exactly the values from 0..i and since we
-            // return `Err` below, the caller will consider the memory at `slot` as
-            // uninitialized.
-            unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
-        });
         for i in 0..N {
             let init = make_init(i);
             // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
             let ptr = unsafe { slot.add(i) };
             // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
             // requirements.
-            unsafe { init.__init(ptr) }?;
-            *init_count += 1;
+            if let Err(e) = unsafe { init.__init(ptr) } {
+                // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
+                // `Err` below, `slot` will be considered uninitialized memory.
+                unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
+                return Err(e);
+            }
         }
-        init_count.dismiss();
         Ok(())
     };
     // SAFETY: The initializer above initializes every element of the array. On failure it drops
@@ -1189,25 +1182,19 @@ pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
 {
     let init = move |slot: *mut [T; N]| {
         let slot = slot.cast::<T>();
-        // Counts the number of initialized elements and when dropped drops that many elements from
-        // `slot`.
-        let mut init_count = ScopeGuard::new_with_data(0, |i| {
-            // We now free every element that has been initialized before.
-            // SAFETY: The loop initialized exactly the values from 0..i and since we
-            // return `Err` below, the caller will consider the memory at `slot` as
-            // uninitialized.
-            unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
-        });
         for i in 0..N {
             let init = make_init(i);
             // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
             let ptr = unsafe { slot.add(i) };
             // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
             // requirements.
-            unsafe { init.__pinned_init(ptr) }?;
-            *init_count += 1;
+            if let Err(e) = unsafe { init.__pinned_init(ptr) } {
+                // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
+                // `Err` below, `slot` will be considered uninitialized memory.
+                unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
+                return Err(e);
+            }
         }
-        init_count.dismiss();
         Ok(())
     };
     // SAFETY: The initializer above initializes every element of the array. On failure it drops
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (11 preceding siblings ...)
  2025-03-04 22:54   ` [PATCH 12/22] rust: pin-init: remove kernel-crate dependency Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05  9:28     ` Fiona Behrens
  2025-03-05 11:52     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 14/22] rust: add pin-init crate build infrastructure Benno Lossin
                     ` (10 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Change the paste macro path from `::kernel::macros::paste!` to use
`$crate::init::macros::paste!` instead, which links to
`::macros::paste!`. This is because the pin-init crate will be a
dependency of the kernel, so it itself cannot have the kernel as a
dependency.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/macros.rs | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs
index 1fd146a83241..c45ad6af5ca0 100644
--- a/rust/pin-init/src/macros.rs
+++ b/rust/pin-init/src/macros.rs
@@ -498,6 +498,8 @@
 //! };
 //! ```
 
+pub use ::macros::paste;
+
 /// Creates a `unsafe impl<...> PinnedDrop for $type` block.
 ///
 /// See [`PinnedDrop`] for more information.
@@ -1134,7 +1136,7 @@ macro_rules! __init_internal {
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            ::kernel::macros::paste!($t::$get_data())
+            $crate::init::macros::paste!($t::$get_data())
         };
         // Ensure that `data` really is of type `$data` and help with type inference:
         let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
@@ -1215,7 +1217,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        ::kernel::macros::paste! {
+        $crate::init::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
@@ -1246,7 +1248,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        ::kernel::macros::paste! {
+        $crate::init::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
@@ -1278,7 +1280,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        ::kernel::macros::paste! {
+        $crate::init::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
@@ -1315,7 +1317,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            ::kernel::macros::paste!(
+            $crate::init::macros::paste!(
                 ::core::ptr::write($slot, $t {
                     $($acc)*
                     ..zeroed
@@ -1339,7 +1341,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            ::kernel::macros::paste!(
+            $crate::init::macros::paste!(
                 ::core::ptr::write($slot, $t {
                     $($acc)*
                 });
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (12 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05 11:59     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 15/22] rust: make pin-init its own crate Benno Lossin
                     ` (9 subsequent siblings)
  23 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier
  Cc: linux-kernel, rust-for-linux, linux-kbuild

From: Miguel Ojeda <ojeda@kernel.org>

Add infrastructure for moving the initialization API to its own crate.
Covers all make targets such as `rust-analyzer` and `rustdoc`. The tests
of pin-init are not added to `rusttest`, as they are already tested in
the user-space repository [1].

Link: https://github.com/Rust-for-Linux/pin-init [1]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Co-developed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/Makefile                      | 75 +++++++++++++++++++++++-------
 rust/pin-init/internal/src/_lib.rs |  3 ++
 rust/pin-init/internal/src/lib.rs  |  4 ++
 rust/pin-init/src/_lib.rs          |  5 ++
 scripts/Makefile.build             |  2 +-
 scripts/generate_rust_analyzer.py  | 17 ++++++-
 6 files changed, 86 insertions(+), 20 deletions(-)
 create mode 100644 rust/pin-init/internal/src/_lib.rs
 create mode 100644 rust/pin-init/src/_lib.rs

diff --git a/rust/Makefile b/rust/Makefile
index ea3849eb78f6..90310f0620eb 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_RUST) += helpers/helpers.o
 CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
 
 always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
-obj-$(CONFIG_RUST) += bindings.o kernel.o
+obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o
 always-$(CONFIG_RUST) += exports_helpers_generated.h \
     exports_bindings_generated.h exports_kernel_generated.h
 
@@ -41,7 +41,10 @@ ifdef CONFIG_RUST
 libmacros_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name macros --crate-type proc-macro - </dev/null)
 libmacros_extension := $(patsubst libmacros.%,%,$(libmacros_name))
 
-always-$(CONFIG_RUST) += $(libmacros_name)
+libpin_init_internal_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name pin_init_internal --crate-type proc-macro - </dev/null)
+libpin_init_internal_extension := $(patsubst libpin_init_internal.%,%,$(libpin_init_internal_name))
+
+always-$(CONFIG_RUST) += $(libmacros_name) $(libpin_init_internal_name)
 
 # `$(rust_flags)` is passed in case the user added `--sysroot`.
 rustc_sysroot := $(shell MAKEFLAGS= $(RUSTC) $(rust_flags) --print sysroot)
@@ -80,7 +83,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
 # command-like flags to solve the issue. Meanwhile, we use the non-custom case
 # and then retouch the generated files.
 rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \
-    rustdoc-kernel
+    rustdoc-kernel rustdoc-pin_init
 	$(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.files/
 	$(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/static.files/
 	$(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \
@@ -110,11 +113,24 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
 rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
 	+$(call if_changed,rustdoc)
 
-rustdoc-kernel: private rustc_target_flags = --extern ffi \
+rustdoc-pin_init_internal: private rustdoc_host = yes
+rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \
+    --extern proc_macro --crate-type proc-macro
+rustdoc-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
+	+$(call if_changed,rustdoc)
+
+rustdoc-pin_init: private rustdoc_host = yes
+rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \
+    --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\"
+rustdoc-pin_init: $(src)/pin-init/src/_lib.rs rustdoc-pin_init_internal \
+    rustdoc-macros FORCE
+	+$(call if_changed,rustdoc)
+
+rustdoc-kernel: private rustc_target_flags = --extern ffi --extern pin_init \
     --extern build_error --extern macros \
     --extern bindings --extern uapi
 rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-ffi rustdoc-macros \
-    rustdoc-compiler_builtins $(obj)/$(libmacros_name) \
+    rustdoc-pin_init rustdoc-compiler_builtins $(obj)/$(libmacros_name) \
     $(obj)/bindings.o FORCE
 	+$(call if_changed,rustdoc)
 
@@ -139,12 +155,24 @@ rusttestlib-macros: private rustc_test_library_proc = yes
 rusttestlib-macros: $(src)/macros/lib.rs FORCE
 	+$(call if_changed,rustc_test_library)
 
+rusttestlib-pin_init_internal: private rustc_target_flags = --cfg kernel \
+    --extern proc_macro
+rusttestlib-pin_init_internal: private rustc_test_library_proc = yes
+rusttestlib-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
+	+$(call if_changed,rustc_test_library)
+
+rusttestlib-pin_init: private rustc_target_flags = --extern pin_init_internal \
+    --extern macros --cfg kernel
+rusttestlib-pin_init: $(src)/pin-init/src/_lib.rs rusttestlib-macros \
+    rusttestlib-pin_init_internal $(obj)/$(libpin_init_internal_name) FORCE
+	+$(call if_changed,rustc_test_library)
+
 rusttestlib-kernel: private rustc_target_flags = --extern ffi \
-    --extern build_error --extern macros \
+    --extern build_error --extern macros --extern pin_init \
     --extern bindings --extern uapi
-rusttestlib-kernel: $(src)/kernel/lib.rs \
-    rusttestlib-bindings rusttestlib-uapi rusttestlib-build_error \
-    $(obj)/$(libmacros_name) $(obj)/bindings.o FORCE
+rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \
+    rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \
+    $(obj)/bindings.o FORCE
 	+$(call if_changed,rustc_test_library)
 
 rusttestlib-bindings: private rustc_target_flags = --extern ffi
@@ -172,8 +200,8 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
 	mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
 	OBJTREE=$(abspath $(objtree)) \
 	$(RUSTDOC) --test $(rust_flags) \
-		-L$(objtree)/$(obj) --extern ffi --extern kernel \
-		--extern build_error --extern macros \
+		-L$(objtree)/$(obj) --extern ffi --extern pin_init \
+		--extern kernel --extern build_error --extern macros \
 		--extern bindings --extern uapi \
 		--no-run --crate-name kernel -Zunstable-options \
 		--sysroot=/dev/null \
@@ -203,18 +231,18 @@ quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T  $<
 rusttest: rusttest-macros rusttest-kernel
 
 rusttest-macros: private rustc_target_flags = --extern proc_macro \
-	--extern macros --extern kernel
+	--extern macros --extern kernel --extern pin_init
 rusttest-macros: private rustdoc_test_target_flags = --crate-type proc-macro
 rusttest-macros: $(src)/macros/lib.rs \
-    rusttestlib-macros rusttestlib-kernel FORCE
+    rusttestlib-macros rusttestlib-kernel rusttestlib-pin_init FORCE
 	+$(call if_changed,rustc_test)
 	+$(call if_changed,rustdoc_test)
 
-rusttest-kernel: private rustc_target_flags = --extern ffi \
+rusttest-kernel: private rustc_target_flags = --extern ffi --extern pin_init \
     --extern build_error --extern macros --extern bindings --extern uapi
 rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-ffi rusttestlib-kernel \
     rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
-    rusttestlib-uapi FORCE
+    rusttestlib-uapi rusttestlib-pin_init FORCE
 	+$(call if_changed,rustc_test)
 
 ifdef CONFIG_CC_IS_CLANG
@@ -361,7 +389,7 @@ $(obj)/exports_kernel_generated.h: $(obj)/kernel.o FORCE
 
 quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
       cmd_rustc_procmacro = \
-	$(RUSTC_OR_CLIPPY) $(rust_common_flags) \
+	$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
 		-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
 		-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
 		--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
@@ -372,6 +400,10 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
 $(obj)/$(libmacros_name): $(src)/macros/lib.rs FORCE
 	+$(call if_changed_dep,rustc_procmacro)
 
+$(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel
+$(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/_lib.rs FORCE
+	+$(call if_changed_dep,rustc_procmacro)
+
 quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
       cmd_rustc_library = \
 	OBJTREE=$(abspath $(objtree)) \
@@ -451,6 +483,13 @@ $(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*'
 $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
 	+$(call if_changed_rule,rustc_library)
 
+$(obj)/pin_init.o: private skip_gendwarfksyms = 1
+$(obj)/pin_init.o: private rustc_target_flags = --extern pin_init_internal \
+    --extern macros --cfg kernel
+$(obj)/pin_init.o: $(src)/pin-init/src/_lib.rs $(obj)/compiler_builtins.o \
+    $(obj)/$(libpin_init_internal_name) $(obj)/$(libmacros_name) FORCE
+	+$(call if_changed_rule,rustc_library)
+
 $(obj)/build_error.o: private skip_gendwarfksyms = 1
 $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE
 	+$(call if_changed_rule,rustc_library)
@@ -473,9 +512,9 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \
     $(obj)/uapi/uapi_generated.rs FORCE
 	+$(call if_changed_rule,rustc_library)
 
-$(obj)/kernel.o: private rustc_target_flags = --extern ffi \
+$(obj)/kernel.o: private rustc_target_flags = --extern ffi --extern pin_init \
     --extern build_error --extern macros --extern bindings --extern uapi
-$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
+$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o $(obj)/pin_init.o \
     $(obj)/$(libmacros_name) $(obj)/bindings.o $(obj)/uapi.o FORCE
 	+$(call if_changed_rule,rustc_library)
 
diff --git a/rust/pin-init/internal/src/_lib.rs b/rust/pin-init/internal/src/_lib.rs
new file mode 100644
index 000000000000..0874cf04e4cb
--- /dev/null
+++ b/rust/pin-init/internal/src/_lib.rs
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+//! Will be removed in a future commit, only exists to prevent compilation errors.
diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
index bf66cbee2531..3146da5cc47c 100644
--- a/rust/pin-init/internal/src/lib.rs
+++ b/rust/pin-init/internal/src/lib.rs
@@ -1,5 +1,9 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
+// When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
+// and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
+// touched by Kconfig when the version string from the compiler changes.
+
 #[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
diff --git a/rust/pin-init/src/_lib.rs b/rust/pin-init/src/_lib.rs
new file mode 100644
index 000000000000..e0918fd8e9e7
--- /dev/null
+++ b/rust/pin-init/src/_lib.rs
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+//! Will be removed in a future commit, only exists to prevent compilation errors.
+
+#![no_std]
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 993708d11874..08b6380933f5 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -237,7 +237,7 @@ rust_common_cmd = \
 	-Zallow-features=$(rust_allowed_features) \
 	-Zcrate-attr=no_std \
 	-Zcrate-attr='feature($(rust_allowed_features))' \
-	-Zunstable-options --extern kernel \
+	-Zunstable-options --extern pin_init --extern kernel \
 	--crate-type rlib -L $(objtree)/rust/ \
 	--crate-name $(basename $(notdir $@)) \
 	--sysroot=/dev/null \
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index aa8ea1a4dbe5..a44a4475d11f 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -93,10 +93,25 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
     )
     crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
 
+    append_crate(
+        "pin_init_internal",
+        srctree / "rust" / "pin-init" / "internal" / "src" / "_lib.rs",
+        [],
+        cfg=["kernel"],
+        is_proc_macro=True,
+    )
+
+    append_crate(
+        "pin_init",
+        srctree / "rust" / "pin-init" / "src" / "_lib.rs",
+        ["core", "pin_init_internal", "macros"],
+        cfg=["kernel"],
+    )
+
     append_crate(
         "kernel",
         srctree / "rust" / "kernel" / "lib.rs",
-        ["core", "macros", "build_error", "bindings"],
+        ["core", "macros", "build_error", "bindings", "pin_init"],
         cfg=cfg,
     )
     crates[-1]["source"] = {
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 15/22] rust: make pin-init its own crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (13 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 14/22] rust: add pin-init crate build infrastructure Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05  9:29     ` Fiona Behrens
  2025-03-05 12:12     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version Benno Lossin
                     ` (8 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman,
	Rafael J. Wysocki, Peter Zijlstra, Ingo Molnar, Will Deacon,
	Waiman Long
  Cc: linux-kernel, rust-for-linux, linux-block

Rename relative paths inside of the crate to still refer to the same
items, also rename paths inside of the kernel crate and adjust the build
system to build the crate.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/Makefile                             |  12 +--
 rust/kernel/alloc/kbox.rs                 |   4 +-
 rust/kernel/block/mq/tag_set.rs           |   5 +-
 rust/kernel/driver.rs                     |   6 +-
 rust/kernel/init.rs                       |  22 +++--
 rust/kernel/lib.rs                        |  10 +-
 rust/kernel/list.rs                       |   2 +-
 rust/kernel/prelude.rs                    |   8 +-
 rust/kernel/sync/arc.rs                   |   7 +-
 rust/kernel/sync/condvar.rs               |   4 +-
 rust/kernel/sync/lock.rs                  |   4 +-
 rust/kernel/sync/lock/mutex.rs            |   2 +-
 rust/kernel/sync/lock/spinlock.rs         |   2 +-
 rust/kernel/types.rs                      |  10 +-
 rust/macros/helpers.rs                    |   4 +-
 rust/macros/lib.rs                        |  11 +--
 rust/macros/module.rs                     |   2 +-
 rust/macros/quote.rs                      |   1 +
 rust/pin-init/internal/src/_lib.rs        |   3 -
 rust/pin-init/internal/src/helpers.rs     |   2 +
 rust/pin-init/internal/src/lib.rs         |  16 ++++
 rust/pin-init/internal/src/pin_data.rs    |   4 +-
 rust/pin-init/internal/src/pinned_drop.rs |   4 +-
 rust/pin-init/internal/src/zeroable.rs    |   8 +-
 rust/pin-init/src/_lib.rs                 |   5 -
 rust/pin-init/src/lib.rs                  |  46 +++++----
 rust/pin-init/src/macros.rs               | 111 +++++++++++-----------
 scripts/generate_rust_analyzer.py         |   4 +-
 28 files changed, 166 insertions(+), 153 deletions(-)
 delete mode 100644 rust/pin-init/internal/src/_lib.rs
 delete mode 100644 rust/pin-init/src/_lib.rs

diff --git a/rust/Makefile b/rust/Makefile
index 90310f0620eb..e761a8cc3bd5 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -116,13 +116,13 @@ rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
 rustdoc-pin_init_internal: private rustdoc_host = yes
 rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \
     --extern proc_macro --crate-type proc-macro
-rustdoc-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
+rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs FORCE
 	+$(call if_changed,rustdoc)
 
 rustdoc-pin_init: private rustdoc_host = yes
 rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \
     --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\"
-rustdoc-pin_init: $(src)/pin-init/src/_lib.rs rustdoc-pin_init_internal \
+rustdoc-pin_init: $(src)/pin-init/src/lib.rs rustdoc-pin_init_internal \
     rustdoc-macros FORCE
 	+$(call if_changed,rustdoc)
 
@@ -158,12 +158,12 @@ rusttestlib-macros: $(src)/macros/lib.rs FORCE
 rusttestlib-pin_init_internal: private rustc_target_flags = --cfg kernel \
     --extern proc_macro
 rusttestlib-pin_init_internal: private rustc_test_library_proc = yes
-rusttestlib-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
+rusttestlib-pin_init_internal: $(src)/pin-init/internal/src/lib.rs FORCE
 	+$(call if_changed,rustc_test_library)
 
 rusttestlib-pin_init: private rustc_target_flags = --extern pin_init_internal \
     --extern macros --cfg kernel
-rusttestlib-pin_init: $(src)/pin-init/src/_lib.rs rusttestlib-macros \
+rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \
     rusttestlib-pin_init_internal $(obj)/$(libpin_init_internal_name) FORCE
 	+$(call if_changed,rustc_test_library)
 
@@ -401,7 +401,7 @@ $(obj)/$(libmacros_name): $(src)/macros/lib.rs FORCE
 	+$(call if_changed_dep,rustc_procmacro)
 
 $(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel
-$(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/_lib.rs FORCE
+$(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs FORCE
 	+$(call if_changed_dep,rustc_procmacro)
 
 quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
@@ -486,7 +486,7 @@ $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
 $(obj)/pin_init.o: private skip_gendwarfksyms = 1
 $(obj)/pin_init.o: private rustc_target_flags = --extern pin_init_internal \
     --extern macros --cfg kernel
-$(obj)/pin_init.o: $(src)/pin-init/src/_lib.rs $(obj)/compiler_builtins.o \
+$(obj)/pin_init.o: $(src)/pin-init/src/lib.rs $(obj)/compiler_builtins.o \
     $(obj)/$(libpin_init_internal_name) $(obj)/$(libmacros_name) FORCE
 	+$(call if_changed_rule,rustc_library)
 
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 07150c038e3f..e6200cd1d06d 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -15,9 +15,9 @@
 use core::ptr::NonNull;
 use core::result::Result;
 
-use crate::init::{InPlaceWrite, Init, PinInit, ZeroableOption};
-use crate::init_ext::InPlaceInit;
+use crate::init::InPlaceInit;
 use crate::types::ForeignOwnable;
+use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
 
 /// The kernel's [`Box`] type -- a heap allocation for a single value of type `T`.
 ///
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index 00ddcc71dfa2..bcf4214ad149 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -10,12 +10,11 @@
     bindings,
     block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations},
     error,
-    prelude::PinInit,
-    try_pin_init,
+    prelude::try_pin_init,
     types::Opaque,
 };
 use core::{convert::TryInto, marker::PhantomData};
-use macros::{pin_data, pinned_drop};
+use pin_init::{pin_data, pinned_drop, PinInit};
 
 /// A wrapper for the C `struct blk_mq_tag_set`.
 ///
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index 2a16d5e64e6c..ec9166cedfa7 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -6,9 +6,9 @@
 //! register using the [`Registration`] class.
 
 use crate::error::{Error, Result};
-use crate::{device, init::PinInit, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
+use crate::{device, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
 use core::pin::Pin;
-use macros::{pin_data, pinned_drop};
+use pin_init::{pin_data, pinned_drop, PinInit};
 
 /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
 /// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
@@ -114,7 +114,7 @@ struct DriverModule {
         impl $crate::InPlaceModule for DriverModule {
             fn init(
                 module: &'static $crate::ThisModule
-            ) -> impl $crate::init::PinInit<Self, $crate::error::Error> {
+            ) -> impl ::pin_init::PinInit<Self, $crate::error::Error> {
                 $crate::try_pin_init!(Self {
                     _driver <- $crate::driver::Registration::new(
                         <Self as $crate::ModuleMetadata>::NAME,
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index d8eb6d7873b7..32d6e4167650 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -23,7 +23,7 @@
 //!
 //! [`Opaque<T>`]: crate::types::Opaque
 //! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init
-//! [`pin_init!`]: crate::pin_init
+//! [`pin_init!`]: pin_init::pin_init
 //!
 //! # Examples
 //!
@@ -137,8 +137,8 @@
 use crate::{
     alloc::{AllocError, Flags},
     error::{self, Error},
-    init::{init_from_closure, pin_init_from_closure, Init, PinInit},
 };
+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 {
@@ -205,7 +205,8 @@ fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
 /// # Examples
 ///
 /// ```rust
-/// use kernel::{init::zeroed, error::Error};
+/// use kernel::error::Error;
+/// use pin_init::zeroed;
 /// struct BigBuf {
 ///     big: KBox<[u8; 1024 * 1024 * 1024]>,
 ///     small: [u8; 1024 * 1024],
@@ -222,7 +223,7 @@ fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
 /// ```
 ///
 /// [`Infallible`]: core::convert::Infallible
-/// [`init!`]: crate::init!
+/// [`init!`]: pin_init::init
 /// [`try_pin_init!`]: crate::try_pin_init!
 /// [`Error`]: crate::error::Error
 #[macro_export]
@@ -230,14 +231,14 @@ macro_rules! try_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+        ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
             $($fields)*
         }? $crate::error::Error)
     };
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
-        $crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+        ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
             $($fields)*
         }? $err)
     };
@@ -262,7 +263,8 @@ macro_rules! try_init {
 ///
 /// ```rust
 /// # #![feature(new_uninit)]
-/// use kernel::{init::zeroed, error::Error};
+/// use kernel::error::Error;
+/// use pin_init::zeroed;
 /// #[pin_data]
 /// struct BigBuf {
 ///     big: KBox<[u8; 1024 * 1024 * 1024]>,
@@ -282,21 +284,21 @@ macro_rules! try_init {
 /// ```
 ///
 /// [`Infallible`]: core::convert::Infallible
-/// [`pin_init!`]: crate::pin_init
+/// [`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)*
     }) => {
-        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+        ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
             $($fields)*
         }? $crate::error::Error)
     };
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
-        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+        ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
             $($fields)*
         }? $err)
     };
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index e3933f3dfc0b..c92497c7c655 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -50,11 +50,7 @@
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
 pub mod firmware;
 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;
@@ -116,11 +112,11 @@ pub trait InPlaceModule: Sync + Send {
     /// Creates an initialiser for the module.
     ///
     /// It is called when the module is loaded.
-    fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error>;
+    fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error>;
 }
 
 impl<T: Module> InPlaceModule for T {
-    fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
+    fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error> {
         let initer = move |slot: *mut Self| {
             let m = <Self as Module>::init(module)?;
 
@@ -130,7 +126,7 @@ fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
         };
 
         // SAFETY: On success, `initer` always fully initialises an instance of `Self`.
-        unsafe { init::pin_init_from_closure(initer) }
+        unsafe { pin_init::pin_init_from_closure(initer) }
     }
 }
 
diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
index fb93330f4af4..717e98e71f65 100644
--- a/rust/kernel/list.rs
+++ b/rust/kernel/list.rs
@@ -4,12 +4,12 @@
 
 //! A linked list implementation.
 
-use crate::init::PinInit;
 use crate::sync::ArcBorrow;
 use crate::types::Opaque;
 use core::iter::{DoubleEndedIterator, FusedIterator};
 use core::marker::PhantomData;
 use core::ptr;
+use pin_init::PinInit;
 
 mod impl_list_item_mod;
 pub use self::impl_list_item_mod::{
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 6b9e068b3710..7f55c13ed859 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -17,7 +17,9 @@
 pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
 
 #[doc(no_inline)]
-pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};
+pub use macros::{module, vtable};
+
+pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
 
 pub use super::{build_assert, build_error};
 
@@ -28,7 +30,6 @@
 pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
 pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
 
-pub use super::{init, pin_init};
 pub use super::{try_init, try_pin_init};
 
 pub use super::static_assert;
@@ -37,7 +38,6 @@
 
 pub use super::{str::CStr, ThisModule};
 
-pub use super::init::{InPlaceWrite, Init, PinInit};
-pub use super::init_ext::InPlaceInit;
+pub use super::init::InPlaceInit;
 
 pub use super::current;
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 31c26b692c6d..c64eac8b4235 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -19,8 +19,7 @@
 use crate::{
     alloc::{AllocError, Flags, KBox},
     bindings,
-    init::{self, InPlaceWrite, Init, PinInit},
-    init_ext::InPlaceInit,
+    init::InPlaceInit,
     try_init,
     types::{ForeignOwnable, Opaque},
 };
@@ -33,7 +32,7 @@
     pin::Pin,
     ptr::NonNull,
 };
-use macros::pin_data;
+use pin_init::{self, pin_data, InPlaceWrite, Init, PinInit};
 
 mod std_vendor;
 
@@ -738,7 +737,7 @@ pub fn new_uninit(flags: Flags) -> Result<UniqueArc<MaybeUninit<T>>, AllocError>
             try_init!(ArcInner {
                 // SAFETY: There are no safety requirements for this FFI call.
                 refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
-                data <- init::uninit::<T, AllocError>(),
+                data <- pin_init::uninit::<T, AllocError>(),
             }? AllocError),
             flags,
         )?;
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 5aa7fa7c7002..c2535db9e0f8 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -8,8 +8,6 @@
 use super::{lock::Backend, lock::Guard, LockClassKey};
 use crate::{
     ffi::{c_int, c_long},
-    init::PinInit,
-    pin_init,
     str::CStr,
     task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE},
     time::Jiffies,
@@ -17,7 +15,7 @@
 };
 use core::marker::PhantomPinned;
 use core::ptr;
-use macros::pin_data;
+use pin_init::{pin_data, pin_init, PinInit};
 
 /// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class.
 #[macro_export]
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index eb80048e0110..7f611b59ac57 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -7,13 +7,11 @@
 
 use super::LockClassKey;
 use crate::{
-    init::PinInit,
-    pin_init,
     str::CStr,
     types::{NotThreadSafe, Opaque, ScopeGuard},
 };
 use core::{cell::UnsafeCell, marker::PhantomPinned};
-use macros::pin_data;
+use pin_init::{pin_data, pin_init, PinInit};
 
 pub mod mutex;
 pub mod spinlock;
diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs
index 70cadbc2e8e2..581cee7ab842 100644
--- a/rust/kernel/sync/lock/mutex.rs
+++ b/rust/kernel/sync/lock/mutex.rs
@@ -26,7 +26,7 @@ macro_rules! new_mutex {
 /// Since it may block, [`Mutex`] needs to be used with care in atomic contexts.
 ///
 /// Instances of [`Mutex`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_mutex`] macros.
+/// instances is with the [`pin_init`](pin_init::pin_init) and [`new_mutex`] macros.
 ///
 /// # Examples
 ///
diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs
index ab2f8d075311..d7be38ccbdc7 100644
--- a/rust/kernel/sync/lock/spinlock.rs
+++ b/rust/kernel/sync/lock/spinlock.rs
@@ -24,7 +24,7 @@ macro_rules! new_spinlock {
 /// unlocked, at which point another CPU will be allowed to make progress.
 ///
 /// Instances of [`SpinLock`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_spinlock`] macros.
+/// instances is with the [`pin_init`](pin_init::pin_init) and [`new_spinlock`] macros.
 ///
 /// # Examples
 ///
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 9f75bd3866e8..a19828a5c206 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -2,7 +2,6 @@
 
 //! Kernel types.
 
-use crate::init::{self, PinInit, Zeroable};
 use core::{
     cell::UnsafeCell,
     marker::{PhantomData, PhantomPinned},
@@ -10,6 +9,7 @@
     ops::{Deref, DerefMut},
     ptr::NonNull,
 };
+use pin_init::{PinInit, Zeroable};
 
 /// Used to transfer ownership to and from foreign (non-Rust) languages.
 ///
@@ -336,7 +336,7 @@ pub fn pin_init(slot: impl PinInit<T>) -> impl PinInit<Self> {
             //   - `ptr` is a valid pointer to uninitialized memory,
             //   - `slot` is not accessed on error; the call is infallible,
             //   - `slot` is pinned in memory.
-            let _ = unsafe { init::PinInit::<T>::__pinned_init(slot, ptr) };
+            let _ = unsafe { PinInit::<T>::__pinned_init(slot, ptr) };
         })
     }
 
@@ -352,7 +352,7 @@ pub fn ffi_init(init_func: impl FnOnce(*mut T)) -> impl PinInit<Self> {
         // SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully
         // initialize the `T`.
         unsafe {
-            init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {
+            pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {
                 init_func(Self::raw_get(slot));
                 Ok(())
             })
@@ -372,7 +372,9 @@ pub fn try_ffi_init<E>(
     ) -> impl PinInit<Self, E> {
         // SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully
         // initialize the `T`.
-        unsafe { init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot))) }
+        unsafe {
+            pin_init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot)))
+        }
     }
 
     /// Returns a raw pointer to the opaque data.
diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs
index 8e07703fcc16..b2bdd4d8c958 100644
--- a/rust/macros/helpers.rs
+++ b/rust/macros/helpers.rs
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
-use proc_macro::{token_stream, Group, TokenStream, TokenTree};
+use proc_macro::{token_stream, Group, TokenTree};
 
 pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
     if let Some(TokenTree::Ident(ident)) = it.next() {
@@ -69,5 +69,3 @@ pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
         panic!("Expected end");
     }
 }
-
-include!("../pin-init/internal/src/helpers.rs");
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 7ff82c82ce0c..8e116e266524 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -2,23 +2,20 @@
 
 //! Crate for all kernel procedural macros.
 
+#![feature(lint_reasons)]
+
 // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
 // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
 // touched by Kconfig when the version string from the compiler changes.
 
 #[macro_use]
+#[expect(unused_macros)]
 mod quote;
 mod concat_idents;
 mod helpers;
 mod module;
 mod paste;
-#[path = "../pin-init/internal/src/pin_data.rs"]
-mod pin_data;
-#[path = "../pin-init/internal/src/pinned_drop.rs"]
-mod pinned_drop;
 mod vtable;
-#[path = "../pin-init/internal/src/zeroable.rs"]
-mod zeroable;
 
 use proc_macro::TokenStream;
 
@@ -374,5 +371,3 @@ pub fn paste(input: TokenStream) -> TokenStream {
     paste::expand(&mut tokens);
     tokens.into_iter().collect()
 }
-
-include!("../pin-init/internal/src/lib.rs");
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index cdf94f4982df..bdd94c79b0d4 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -236,7 +236,7 @@ impl kernel::ModuleMetadata for {type_} {{
             mod __module_init {{
                 mod __module_init {{
                     use super::super::{type_};
-                    use kernel::init::PinInit;
+                    use pin_init::PinInit;
 
                     /// The \"Rust loadable module\" mark.
                     //
diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs
index 33a199e4f176..11d241b85ac3 100644
--- a/rust/macros/quote.rs
+++ b/rust/macros/quote.rs
@@ -2,6 +2,7 @@
 
 use proc_macro::{TokenStream, TokenTree};
 
+#[allow(dead_code)]
 pub(crate) trait ToTokens {
     fn to_tokens(&self, tokens: &mut TokenStream);
 }
diff --git a/rust/pin-init/internal/src/_lib.rs b/rust/pin-init/internal/src/_lib.rs
deleted file mode 100644
index 0874cf04e4cb..000000000000
--- a/rust/pin-init/internal/src/_lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-//! Will be removed in a future commit, only exists to prevent compilation errors.
diff --git a/rust/pin-init/internal/src/helpers.rs b/rust/pin-init/internal/src/helpers.rs
index 2f4fc75c014e..78521ba19d0b 100644
--- a/rust/pin-init/internal/src/helpers.rs
+++ b/rust/pin-init/internal/src/helpers.rs
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
+use proc_macro::{TokenStream, TokenTree};
+
 /// Parsed generics.
 ///
 /// See the field documentation for an explanation what each of the fields represents.
diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
index 3146da5cc47c..c201b8a53915 100644
--- a/rust/pin-init/internal/src/lib.rs
+++ b/rust/pin-init/internal/src/lib.rs
@@ -4,6 +4,22 @@
 // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
 // touched by Kconfig when the version string from the compiler changes.
 
+//! `pin-init` proc macros.
+
+#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
+
+use proc_macro::TokenStream;
+
+#[cfg(kernel)]
+#[path = "../../../macros/quote.rs"]
+#[macro_use]
+mod quote;
+
+mod helpers;
+mod pin_data;
+mod pinned_drop;
+mod zeroable;
+
 #[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index 1d4a3547c684..9b974498f4a8 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -5,7 +5,7 @@
 
 pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream {
     // This proc-macro only does some pre-parsing and then delegates the actual parsing to
-    // `kernel::__pin_data!`.
+    // `pin_init::__pin_data!`.
 
     let (
         Generics {
@@ -71,7 +71,7 @@ pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream {
         .collect::<Vec<_>>();
     // This should be the body of the struct `{...}`.
     let last = rest.pop();
-    let mut quoted = quote!(::kernel::__pin_data! {
+    let mut quoted = quote!(::pin_init::__pin_data! {
         parse_input:
         @args(#args),
         @sig(#(#rest)*),
diff --git a/rust/pin-init/internal/src/pinned_drop.rs b/rust/pin-init/internal/src/pinned_drop.rs
index 88fb72b20660..386f52f73c06 100644
--- a/rust/pin-init/internal/src/pinned_drop.rs
+++ b/rust/pin-init/internal/src/pinned_drop.rs
@@ -35,11 +35,11 @@ pub(crate) fn pinned_drop(_args: TokenStream, input: TokenStream) -> TokenStream
     let idx = pinned_drop_idx
         .unwrap_or_else(|| panic!("Expected an `impl` block implementing `PinnedDrop`."));
     // Fully qualify the `PinnedDrop`, as to avoid any tampering.
-    toks.splice(idx..idx, quote!(::kernel::init::));
+    toks.splice(idx..idx, quote!(::pin_init::));
     // Take the `{}` body and call the declarative macro.
     if let Some(TokenTree::Group(last)) = toks.pop() {
         let last = last.stream();
-        quote!(::kernel::__pinned_drop! {
+        quote!(::pin_init::__pinned_drop! {
             @impl_sig(#(#toks)*),
             @impl_body(#last),
         })
diff --git a/rust/pin-init/internal/src/zeroable.rs b/rust/pin-init/internal/src/zeroable.rs
index cfee2cec18d5..0cf6732f27dc 100644
--- a/rust/pin-init/internal/src/zeroable.rs
+++ b/rust/pin-init/internal/src/zeroable.rs
@@ -27,7 +27,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
             // If we find a `,`, then we have finished a generic/constant/lifetime parameter.
             TokenTree::Punct(p) if nested == 0 && p.as_char() == ',' => {
                 if in_generic && !inserted {
-                    new_impl_generics.extend(quote! { : ::kernel::init::Zeroable });
+                    new_impl_generics.extend(quote! { : ::pin_init::Zeroable });
                 }
                 in_generic = true;
                 inserted = false;
@@ -41,7 +41,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
             TokenTree::Punct(p) if nested == 0 && p.as_char() == ':' => {
                 new_impl_generics.push(tt);
                 if in_generic {
-                    new_impl_generics.extend(quote! { ::kernel::init::Zeroable + });
+                    new_impl_generics.extend(quote! { ::pin_init::Zeroable + });
                     inserted = true;
                 }
             }
@@ -59,10 +59,10 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
     }
     assert_eq!(nested, 0);
     if in_generic && !inserted {
-        new_impl_generics.extend(quote! { : ::kernel::init::Zeroable });
+        new_impl_generics.extend(quote! { : ::pin_init::Zeroable });
     }
     quote! {
-        ::kernel::__derive_zeroable!(
+        ::pin_init::__derive_zeroable!(
             parse_input:
                 @sig(#(#rest)*),
                 @impl_generics(#(#new_impl_generics)*),
diff --git a/rust/pin-init/src/_lib.rs b/rust/pin-init/src/_lib.rs
deleted file mode 100644
index e0918fd8e9e7..000000000000
--- a/rust/pin-init/src/_lib.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-//! Will be removed in a future commit, only exists to prevent compilation errors.
-
-#![no_std]
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 29c0920d1bfe..55d8953620f0 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -209,9 +209,21 @@
 //! [`impl PinInit<Foo>`]: PinInit
 //! [`impl PinInit<T, E>`]: PinInit
 //! [`impl Init<T, E>`]: Init
-//! [`pin_data`]: ::macros::pin_data
+//! [`pin_data`]: crate::pin_data
 //! [`pin_init!`]: crate::pin_init!
 
+#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
+#![cfg_attr(
+    all(
+        any(feature = "alloc", feature = "std"),
+        not(RUSTC_NEW_UNINIT_IS_STABLE)
+    ),
+    feature(new_uninit)
+)]
+#![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "alloc", feature(allocator_api))]
+
 use core::{
     cell::UnsafeCell,
     convert::Infallible,
@@ -288,7 +300,7 @@
 /// ```
 ///
 /// [`pin_init!`]: crate::pin_init
-pub use ::macros::pin_data;
+pub use ::pin_init_internal::pin_data;
 
 /// Used to implement `PinnedDrop` safely.
 ///
@@ -322,7 +334,7 @@
 ///     }
 /// }
 /// ```
-pub use ::macros::pinned_drop;
+pub use ::pin_init_internal::pinned_drop;
 
 /// Derives the [`Zeroable`] trait for the given struct.
 ///
@@ -340,7 +352,7 @@
 ///     len: usize,
 /// }
 /// ```
-pub use ::macros::Zeroable;
+pub use ::pin_init_internal::Zeroable;
 
 /// Initialize and pin a type directly on the stack.
 ///
@@ -385,8 +397,8 @@
 macro_rules! stack_pin_init {
     (let $var:ident $(: $t:ty)? = $val:expr) => {
         let val = $val;
-        let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
-        let mut $var = match $crate::init::__internal::StackInit::init($var, val) {
+        let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
+        let mut $var = match $crate::__internal::StackInit::init($var, val) {
             Ok(res) => res,
             Err(x) => {
                 let x: ::core::convert::Infallible = x;
@@ -463,13 +475,13 @@ macro_rules! stack_pin_init {
 macro_rules! stack_try_pin_init {
     (let $var:ident $(: $t:ty)? = $val:expr) => {
         let val = $val;
-        let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
-        let mut $var = $crate::init::__internal::StackInit::init($var, val);
+        let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
+        let mut $var = $crate::__internal::StackInit::init($var, val);
     };
     (let $var:ident $(: $t:ty)? =? $val:expr) => {
         let val = $val;
-        let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
-        let mut $var = $crate::init::__internal::StackInit::init($var, val)?;
+        let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
+        let mut $var = $crate::__internal::StackInit::init($var, val)?;
     };
 }
 
@@ -670,7 +682,7 @@ macro_rules! pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
+        $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
             $($fields)*
         }? ::core::convert::Infallible)
     };
@@ -716,7 +728,7 @@ macro_rules! pin_init {
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
 #[macro_export]
-macro_rules! _try_pin_init {
+macro_rules! try_pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
@@ -755,7 +767,7 @@ macro_rules! init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }) => {
-        $crate::_try_init!($(&$this in)? $t $(::<$($generics),*>)? {
+        $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
             $($fields)*
         }? ::core::convert::Infallible)
     }
@@ -798,7 +810,7 @@ macro_rules! init {
 // For a detailed example of how this macro works, see the module documentation of the hidden
 // module `__internal` inside of `init/__internal.rs`.
 #[macro_export]
-macro_rules! _try_init {
+macro_rules! try_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
         $($fields:tt)*
     }? $err:ty) => {
@@ -868,8 +880,8 @@ macro_rules! assert_pinned {
     ($ty:ty, $field:ident, $field_ty:ty, inline) => {
         let _ = move |ptr: *mut $field_ty| {
             // SAFETY: This code is unreachable.
-            let data = unsafe { <$ty as $crate::init::__internal::HasPinData>::__pin_data() };
-            let init = $crate::init::__internal::AlwaysFail::<$field_ty>::new();
+            let data = unsafe { <$ty as $crate::__internal::HasPinData>::__pin_data() };
+            let init = $crate::__internal::AlwaysFail::<$field_ty>::new();
             // SAFETY: This code is unreachable.
             unsafe { data.$field(ptr, init) }.ok();
         };
@@ -1262,7 +1274,7 @@ pub trait InPlaceWrite<T> {
 ///
 /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
 ///
-/// [`pinned_drop`]: crate::macros::pinned_drop
+/// [`pinned_drop`]: crate::pinned_drop
 pub unsafe trait PinnedDrop: __internal::HasPinData {
     /// Executes the pinned destructor of this type.
     ///
diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs
index c45ad6af5ca0..d41c4f198c42 100644
--- a/rust/pin-init/src/macros.rs
+++ b/rust/pin-init/src/macros.rs
@@ -19,7 +19,7 @@
 //! We will look at the following example:
 //!
 //! ```rust,ignore
-//! # use kernel::init::*;
+//! # use pin_init::*;
 //! # use core::pin::Pin;
 //! #[pin_data]
 //! #[repr(C)]
@@ -75,7 +75,7 @@
 //! Here is the definition of `Bar` from our example:
 //!
 //! ```rust,ignore
-//! # use kernel::init::*;
+//! # use pin_init::*;
 //! #[pin_data]
 //! #[repr(C)]
 //! struct Bar<T> {
@@ -121,22 +121,22 @@
 //!             self,
 //!             slot: *mut T,
 //!             // Since `t` is `#[pin]`, this is `PinInit`.
-//!             init: impl ::kernel::init::PinInit<T, E>,
+//!             init: impl ::pin_init::PinInit<T, E>,
 //!         ) -> ::core::result::Result<(), E> {
-//!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
+//!             unsafe { ::pin_init::PinInit::__pinned_init(init, slot) }
 //!         }
 //!         pub unsafe fn x<E>(
 //!             self,
 //!             slot: *mut usize,
 //!             // Since `x` is not `#[pin]`, this is `Init`.
-//!             init: impl ::kernel::init::Init<usize, E>,
+//!             init: impl ::pin_init::Init<usize, E>,
 //!         ) -> ::core::result::Result<(), E> {
-//!             unsafe { ::kernel::init::Init::__init(init, slot) }
+//!             unsafe { ::pin_init::Init::__init(init, slot) }
 //!         }
 //!     }
 //!     // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
 //!     // that we constructed above.
-//!     unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> {
+//!     unsafe impl<T> ::pin_init::__internal::HasPinData for Bar<T> {
 //!         type PinData = __ThePinData<T>;
 //!         unsafe fn __pin_data() -> Self::PinData {
 //!             __ThePinData {
@@ -147,7 +147,7 @@
 //!     // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
 //!     // struct. This is important to ensure that no user can implement a rogue `__pin_data`
 //!     // function without using `unsafe`.
-//!     unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> {
+//!     unsafe impl<T> ::pin_init::__internal::PinData for __ThePinData<T> {
 //!         type Datee = Bar<T>;
 //!     }
 //!     // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
@@ -191,7 +191,7 @@
 //!     #[expect(non_camel_case_types)]
 //!     trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
 //!     impl<
-//!         T: ::kernel::init::PinnedDrop,
+//!         T: ::pin_init::PinnedDrop,
 //!     > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
 //!     impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
 //! };
@@ -227,11 +227,11 @@
 //!             // - we `use` the `HasPinData` trait in the block, it is only available in that
 //!             //   scope.
 //!             let data = unsafe {
-//!                 use ::kernel::init::__internal::HasPinData;
+//!                 use ::pin_init::__internal::HasPinData;
 //!                 Self::__pin_data()
 //!             };
 //!             // Ensure that `data` really is of type `PinData` and help with type inference:
-//!             let init = ::kernel::init::__internal::PinData::make_closure::<
+//!             let init = ::pin_init::__internal::PinData::make_closure::<
 //!                 _,
 //!                 __InitOk,
 //!                 ::core::convert::Infallible,
@@ -262,7 +262,7 @@
 //!                     }
 //!                     // We again create a `DropGuard`.
 //!                     let __x_guard = unsafe {
-//!                         ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
+//!                         ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
 //!                     };
 //!                     // Since initialization has successfully completed, we can now forget
 //!                     // the guards. This is not `mem::forget`, since we only have
@@ -303,7 +303,7 @@
 //!             };
 //!             // Construct the initializer.
 //!             let init = unsafe {
-//!                 ::kernel::init::pin_init_from_closure::<
+//!                 ::pin_init::pin_init_from_closure::<
 //!                     _,
 //!                     ::core::convert::Infallible,
 //!                 >(init)
@@ -350,19 +350,19 @@
 //!         unsafe fn b<E>(
 //!             self,
 //!             slot: *mut Bar<u32>,
-//!             init: impl ::kernel::init::PinInit<Bar<u32>, E>,
+//!             init: impl ::pin_init::PinInit<Bar<u32>, E>,
 //!         ) -> ::core::result::Result<(), E> {
-//!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
+//!             unsafe { ::pin_init::PinInit::__pinned_init(init, slot) }
 //!         }
 //!         unsafe fn a<E>(
 //!             self,
 //!             slot: *mut usize,
-//!             init: impl ::kernel::init::Init<usize, E>,
+//!             init: impl ::pin_init::Init<usize, E>,
 //!         ) -> ::core::result::Result<(), E> {
-//!             unsafe { ::kernel::init::Init::__init(init, slot) }
+//!             unsafe { ::pin_init::Init::__init(init, slot) }
 //!         }
 //!     }
-//!     unsafe impl ::kernel::init::__internal::HasPinData for Foo {
+//!     unsafe impl ::pin_init::__internal::HasPinData for Foo {
 //!         type PinData = __ThePinData;
 //!         unsafe fn __pin_data() -> Self::PinData {
 //!             __ThePinData {
@@ -370,7 +370,7 @@
 //!             }
 //!         }
 //!     }
-//!     unsafe impl ::kernel::init::__internal::PinData for __ThePinData {
+//!     unsafe impl ::pin_init::__internal::PinData for __ThePinData {
 //!         type Datee = Foo;
 //!     }
 //!     #[allow(dead_code)]
@@ -394,8 +394,8 @@
 //!             let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
 //!             // Create the unsafe token that proves that we are inside of a destructor, this
 //!             // type is only allowed to be created in a destructor.
-//!             let token = unsafe { ::kernel::init::__internal::OnlyCallFromDrop::new() };
-//!             ::kernel::init::PinnedDrop::drop(pinned, token);
+//!             let token = unsafe { ::pin_init::__internal::OnlyCallFromDrop::new() };
+//!             ::pin_init::PinnedDrop::drop(pinned, token);
 //!         }
 //!     }
 //! };
@@ -421,8 +421,8 @@
 //!
 //! ```rust,ignore
 //! // `unsafe`, full path and the token parameter are added, everything else stays the same.
-//! unsafe impl ::kernel::init::PinnedDrop for Foo {
-//!     fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
+//! unsafe impl ::pin_init::PinnedDrop for Foo {
+//!     fn drop(self: Pin<&mut Self>, _: ::pin_init::__internal::OnlyCallFromDrop) {
 //!         pr_info!("{self:p} is getting dropped.");
 //!     }
 //! }
@@ -448,10 +448,10 @@
 //! let initializer = {
 //!     struct __InitOk;
 //!     let data = unsafe {
-//!         use ::kernel::init::__internal::HasPinData;
+//!         use ::pin_init::__internal::HasPinData;
 //!         Foo::__pin_data()
 //!     };
-//!     let init = ::kernel::init::__internal::PinData::make_closure::<
+//!     let init = ::pin_init::__internal::PinData::make_closure::<
 //!         _,
 //!         __InitOk,
 //!         ::core::convert::Infallible,
@@ -462,12 +462,12 @@
 //!                 unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
 //!             }
 //!             let __a_guard = unsafe {
-//!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
+//!                 ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
 //!             };
 //!             let init = Bar::new(36);
 //!             unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
 //!             let __b_guard = unsafe {
-//!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
+//!                 ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
 //!             };
 //!             ::core::mem::forget(__b_guard);
 //!             ::core::mem::forget(__a_guard);
@@ -492,13 +492,16 @@
 //!         init(slot).map(|__InitOk| ())
 //!     };
 //!     let init = unsafe {
-//!         ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
+//!         ::pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
 //!     };
 //!     init
 //! };
 //! ```
 
+#[cfg(kernel)]
 pub use ::macros::paste;
+#[cfg(not(kernel))]
+pub use ::paste::paste;
 
 /// Creates a `unsafe impl<...> PinnedDrop for $type` block.
 ///
@@ -519,7 +522,7 @@ fn drop($($sig:tt)*) {
         unsafe $($impl_sig)* {
             // Inherit all attributes and the type/ident tokens for the signature.
             $(#[$($attr)*])*
-            fn drop($($sig)*, _: $crate::init::__internal::OnlyCallFromDrop) {
+            fn drop($($sig)*, _: $crate::__internal::OnlyCallFromDrop) {
                 $($inner)*
             }
         }
@@ -865,7 +868,7 @@ impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
             // SAFETY: We have added the correct projection functions above to `__ThePinData` and
             // we also use the least restrictive generics possible.
             unsafe impl<$($impl_generics)*>
-                $crate::init::__internal::HasPinData for $name<$($ty_generics)*>
+                $crate::__internal::HasPinData for $name<$($ty_generics)*>
             where $($whr)*
             {
                 type PinData = __ThePinData<$($ty_generics)*>;
@@ -877,7 +880,7 @@ unsafe fn __pin_data() -> Self::PinData {
 
             // SAFETY: TODO.
             unsafe impl<$($impl_generics)*>
-                $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*>
+                $crate::__internal::PinData for __ThePinData<$($ty_generics)*>
             where $($whr)*
             {
                 type Datee = $name<$($ty_generics)*>;
@@ -936,7 +939,7 @@ impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
         // `PinnedDrop` as the parameter to `#[pin_data]`.
         #[expect(non_camel_case_types)]
         trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
-        impl<T: $crate::init::PinnedDrop>
+        impl<T: $crate::PinnedDrop>
             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
         impl<$($impl_generics)*>
             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*>
@@ -959,8 +962,8 @@ fn drop(&mut self) {
                 let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
                 // SAFETY: Since this is a drop function, we can create this token to call the
                 // pinned destructor of this type.
-                let token = unsafe { $crate::init::__internal::OnlyCallFromDrop::new() };
-                $crate::init::PinnedDrop::drop(pinned, token);
+                let token = unsafe { $crate::__internal::OnlyCallFromDrop::new() };
+                $crate::PinnedDrop::drop(pinned, token);
             }
         }
     };
@@ -1000,10 +1003,10 @@ impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
                 $pvis unsafe fn $p_field<E>(
                     self,
                     slot: *mut $p_type,
-                    init: impl $crate::init::PinInit<$p_type, E>,
+                    init: impl $crate::PinInit<$p_type, E>,
                 ) -> ::core::result::Result<(), E> {
                     // SAFETY: TODO.
-                    unsafe { $crate::init::PinInit::__pinned_init(init, slot) }
+                    unsafe { $crate::PinInit::__pinned_init(init, slot) }
                 }
             )*
             $(
@@ -1011,10 +1014,10 @@ impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
                 $fvis unsafe fn $field<E>(
                     self,
                     slot: *mut $type,
-                    init: impl $crate::init::Init<$type, E>,
+                    init: impl $crate::Init<$type, E>,
                 ) -> ::core::result::Result<(), E> {
                     // SAFETY: TODO.
-                    unsafe { $crate::init::Init::__init(init, slot) }
+                    unsafe { $crate::Init::__init(init, slot) }
                 }
             )*
         }
@@ -1131,15 +1134,15 @@ macro_rules! __init_internal {
         //
         // SAFETY: TODO.
         let data = unsafe {
-            use $crate::init::__internal::$has_data;
+            use $crate::__internal::$has_data;
             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            $crate::init::macros::paste!($t::$get_data())
+            $crate::macros::paste!($t::$get_data())
         };
         // Ensure that `data` really is of type `$data` and help with type inference:
-        let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
+        let init = $crate::__internal::$data::make_closure::<_, __InitOk, $err>(
             data,
             move |slot| {
                 {
@@ -1149,7 +1152,7 @@ macro_rules! __init_internal {
                     // error when fields are missing (since they will be zeroed). We also have to
                     // check that the type actually implements `Zeroable`.
                     $({
-                        fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
+                        fn assert_zeroable<T: $crate::Zeroable>(_: *mut T) {}
                         // Ensure that the struct is indeed `Zeroable`.
                         assert_zeroable(slot);
                         // SAFETY: The type implements `Zeroable` by the check above.
@@ -1186,7 +1189,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
             init(slot).map(|__InitOk| ())
         };
         // SAFETY: TODO.
-        let init = unsafe { $crate::init::$construct_closure::<_, $err>(init) };
+        let init = unsafe { $crate::$construct_closure::<_, $err>(init) };
         init
     }};
     (init_slot($($use_data:ident)?):
@@ -1217,10 +1220,10 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        $crate::init::macros::paste! {
+        $crate::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
-                $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
+                $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
             };
 
             $crate::__init_internal!(init_slot($use_data):
@@ -1243,15 +1246,15 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
         // return when an error/panic occurs.
-        unsafe { $crate::init::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
+        unsafe { $crate::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
         // Create the drop guard:
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        $crate::init::macros::paste! {
+        $crate::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
-                $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
+                $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
             };
 
             $crate::__init_internal!(init_slot():
@@ -1280,10 +1283,10 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
         //
         // We rely on macro hygiene to make it impossible for users to access this local variable.
         // We use `paste!` to create new hygiene for `$field`.
-        $crate::init::macros::paste! {
+        $crate::macros::paste! {
             // SAFETY: We forget the guard later when initialization has succeeded.
             let [< __ $field _guard >] = unsafe {
-                $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
+                $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
             };
 
             $crate::__init_internal!(init_slot($($use_data)?):
@@ -1317,7 +1320,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            $crate::init::macros::paste!(
+            $crate::macros::paste!(
                 ::core::ptr::write($slot, $t {
                     $($acc)*
                     ..zeroed
@@ -1341,7 +1344,7 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
             // information that is associated to already parsed fragments, so a path fragment
             // cannot be used in this position. Doing the retokenization results in valid rust
             // code.
-            $crate::init::macros::paste!(
+            $crate::macros::paste!(
                 ::core::ptr::write($slot, $t {
                     $($acc)*
                 });
@@ -1396,12 +1399,12 @@ macro_rules! __derive_zeroable {
     ) => {
         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
         #[automatically_derived]
-        unsafe impl<$($impl_generics)*> $crate::init::Zeroable for $name<$($ty_generics)*>
+        unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
         where
             $($($whr)*)?
         {}
         const _: () = {
-            fn assert_zeroable<T: ?::core::marker::Sized + $crate::init::Zeroable>() {}
+            fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {}
             fn ensure_zeroable<$($impl_generics)*>()
                 where $($($whr)*)?
             {
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index a44a4475d11f..54228e87e577 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -95,7 +95,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
 
     append_crate(
         "pin_init_internal",
-        srctree / "rust" / "pin-init" / "internal" / "src" / "_lib.rs",
+        srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
         [],
         cfg=["kernel"],
         is_proc_macro=True,
@@ -103,7 +103,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
 
     append_crate(
         "pin_init",
-        srctree / "rust" / "pin-init" / "src" / "_lib.rs",
+        srctree / "rust" / "pin-init" / "src" / "lib.rs",
         ["core", "pin_init_internal", "macros"],
         cfg=["kernel"],
     )
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (14 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 15/22] rust: make pin-init its own crate Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05  9:32     ` Fiona Behrens
  2025-03-05 12:22     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 17/22] rust: pin-init: synchronize documentation with " Benno Lossin
                     ` (7 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

To synchronize the kernel's version of pin-init with the user-space
version, introduce support for `std` and `alloc`. While the kernel uses
neither, the user-space version has to support both. Thus include the
required `#[cfg]`s and additional code.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/__internal.rs |  27 ++++++
 rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
 rust/pin-init/src/lib.rs        |  17 ++--
 3 files changed, 196 insertions(+), 6 deletions(-)
 create mode 100644 rust/pin-init/src/alloc.rs

diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 74086365a18a..27d4a8619c04 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
     }
 }
 
+#[test]
+fn stack_init_reuse() {
+    use ::std::{borrow::ToOwned, println, string::String};
+    use core::pin::pin;
+
+    #[derive(Debug)]
+    struct Foo {
+        a: usize,
+        b: String,
+    }
+    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
+    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
+        slot.as_mut().init(crate::init!(Foo {
+            a: 42,
+            b: "Hello".to_owned(),
+        }));
+    let value = value.unwrap();
+    println!("{value:?}");
+    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
+        slot.as_mut().init(crate::init!(Foo {
+            a: 24,
+            b: "world!".to_owned(),
+        }));
+    let value = value.unwrap();
+    println!("{value:?}");
+}
+
 /// When a value of this type is dropped, it drops a `T`.
 ///
 /// Can be forgotten to prevent the drop.
diff --git a/rust/pin-init/src/alloc.rs b/rust/pin-init/src/alloc.rs
new file mode 100644
index 000000000000..e16baa3b434e
--- /dev/null
+++ b/rust/pin-init/src/alloc.rs
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+use alloc::{boxed::Box, sync::Arc};
+#[cfg(feature = "alloc")]
+use core::alloc::AllocError;
+use core::{mem::MaybeUninit, pin::Pin};
+#[cfg(feature = "std")]
+use std::sync::Arc;
+
+#[cfg(not(feature = "alloc"))]
+type AllocError = core::convert::Infallible;
+
+use crate::{
+    init_from_closure, pin_init_from_closure, InPlaceWrite, Init, PinInit, ZeroableOption,
+};
+
+pub extern crate alloc;
+
+// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
+//
+// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
+// is no problem with a VTABLE pointer being null.
+unsafe impl<T: ?Sized> ZeroableOption for Box<T> {}
+
+/// Smart pointer that can initialize memory in-place.
+pub trait InPlaceInit<T>: Sized {
+    /// 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>) -> Result<Pin<Self>, 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(init: impl PinInit<T>) -> Result<Pin<Self>, AllocError> {
+        // SAFETY: We delegate to `init` and only change the error type.
+        let init = unsafe {
+            pin_init_from_closure(|slot| match init.__pinned_init(slot) {
+                Ok(()) => Ok(()),
+                Err(i) => match i {},
+            })
+        };
+        Self::try_pin_init(init)
+    }
+
+    /// Use the given initializer to in-place initialize a `T`.
+    fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
+    where
+        E: From<AllocError>;
+
+    /// Use the given initializer to in-place initialize a `T`.
+    fn init(init: impl Init<T>) -> Result<Self, AllocError> {
+        // SAFETY: We delegate to `init` and only change the error type.
+        let init = unsafe {
+            init_from_closure(|slot| match init.__init(slot) {
+                Ok(()) => Ok(()),
+                Err(i) => match i {},
+            })
+        };
+        Self::try_init(init)
+    }
+}
+
+#[cfg(feature = "alloc")]
+macro_rules! try_new_uninit {
+    ($type:ident) => {
+        $type::try_new_uninit()?
+    };
+}
+#[cfg(all(feature = "std", not(feature = "alloc")))]
+macro_rules! try_new_uninit {
+    ($type:ident) => {
+        $type::new_uninit()
+    };
+}
+
+impl<T> InPlaceInit<T> for Box<T> {
+    #[inline]
+    fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
+    where
+        E: From<AllocError>,
+    {
+        try_new_uninit!(Box).write_pin_init(init)
+    }
+
+    #[inline]
+    fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
+    where
+        E: From<AllocError>,
+    {
+        try_new_uninit!(Box).write_init(init)
+    }
+}
+
+impl<T> InPlaceInit<T> for Arc<T> {
+    #[inline]
+    fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
+    where
+        E: From<AllocError>,
+    {
+        let mut this = try_new_uninit!(Arc);
+        let Some(slot) = Arc::get_mut(&mut this) else {
+            // SAFETY: the Arc has just been created and has no external references
+            unsafe { core::hint::unreachable_unchecked() }
+        };
+        let slot = slot.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid and will not be moved, because we pin it later.
+        unsafe { init.__pinned_init(slot)? };
+        // SAFETY: All fields have been initialized and this is the only `Arc` to that data.
+        Ok(unsafe { Pin::new_unchecked(this.assume_init()) })
+    }
+
+    #[inline]
+    fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
+    where
+        E: From<AllocError>,
+    {
+        let mut this = try_new_uninit!(Arc);
+        let Some(slot) = Arc::get_mut(&mut this) else {
+            // SAFETY: the Arc has just been created and has no external references
+            unsafe { core::hint::unreachable_unchecked() }
+        };
+        let slot = slot.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid.
+        unsafe { init.__init(slot)? };
+        // SAFETY: All fields have been initialized.
+        Ok(unsafe { this.assume_init() })
+    }
+}
+
+impl<T> InPlaceWrite<T> for Box<MaybeUninit<T>> {
+    type Initialized = Box<T>;
+
+    fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
+        let slot = self.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid.
+        unsafe { init.__init(slot)? };
+        // SAFETY: All fields have been initialized.
+        Ok(unsafe { self.assume_init() })
+    }
+
+    fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
+        let slot = self.as_mut_ptr();
+        // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+        // slot is valid and will not be moved, because we pin it later.
+        unsafe { init.__pinned_init(slot)? };
+        // SAFETY: All fields have been initialized.
+        Ok(unsafe { self.assume_init() }.into())
+    }
+}
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 55d8953620f0..1fdca35906a0 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -204,8 +204,8 @@
 //! [structurally pinned fields]:
 //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
 //! [stack]: crate::stack_pin_init
-//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
-//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
+//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
+//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
 //! [`impl PinInit<Foo>`]: PinInit
 //! [`impl PinInit<T, E>`]: PinInit
 //! [`impl Init<T, E>`]: Init
@@ -239,6 +239,11 @@
 #[doc(hidden)]
 pub mod macros;
 
+#[cfg(any(feature = "std", feature = "alloc"))]
+mod alloc;
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub use alloc::InPlaceInit;
+
 /// Used to specify the pinning information of the fields of a struct.
 ///
 /// This is somewhat similar in purpose as
@@ -914,8 +919,8 @@ macro_rules! assert_pinned {
 ///     - `slot` is not partially initialized.
 /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
 ///
-/// [`Arc<T>`]: ../kernel/sync/struct.Arc.html
-/// [`Box<T>`]: ../kernel/sync/struct.KBox.html
+/// [`Arc<T>`]: alloc::alloc::sync::Arc
+/// [`Box<T>`]: alloc::alloc::boxed::Box
 #[must_use = "An initializer must be used in order to create its value."]
 pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     /// Initializes `slot`.
@@ -1005,8 +1010,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 /// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
 /// move the pointee after initialization.
 ///
-/// [`Arc<T>`]: ../kernel/sync/struct.Arc.html
-/// [`Box<T>`]: ../kernel/sync/struct.KBox.html
+/// [`Arc<T>`]: alloc::alloc::sync::Arc
+/// [`Box<T>`]: alloc::alloc::boxed::Box
 #[must_use = "An initializer must be used in order to create its value."]
 pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     /// Initializes `slot`.
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 17/22] rust: pin-init: synchronize documentation with the user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (15 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05  9:33     ` Fiona Behrens
  2025-03-05 12:52     ` Andreas Hindborg
  2025-03-04 22:55   ` [PATCH 18/22] rust: pin-init: internal: synchronize with " Benno Lossin
                     ` (6 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Synchronize documentation and examples with the user-space version.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/__internal.rs |   8 +-
 rust/pin-init/src/lib.rs        | 143 +++++++++++++++++++++++---------
 rust/pin-init/src/macros.rs     |  20 ++---
 3 files changed, 116 insertions(+), 55 deletions(-)

diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 27d4a8619c04..5336d659685d 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -1,11 +1,9 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! This module contains API-internal items for pin-init.
+//! This module contains library internal items.
 //!
-//! These items must not be used outside of
-//! - `kernel/init.rs`
-//! - `macros/pin_data.rs`
-//! - `macros/pinned_drop.rs`
+//! These items must not be used outside of this crate and the pin-init-internal crate located at
+//! `../internal`.
 
 use super::*;
 
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 1fdca35906a0..fb64cddd1a72 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1,10 +1,37 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! API to safely and fallibly initialize pinned `struct`s using in-place constructors.
+//! Library to safely and fallibly initialize pinned `struct`s using in-place constructors.
+//!
+//! [Pinning][pinning] is Rust's way of ensuring data does not move.
 //!
 //! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
 //! overflow.
 //!
+//! This library's main use-case is in [Rust-for-Linux]. Although this version can be used
+//! standalone.
+//!
+//! There are cases when you want to in-place initialize a struct. For example when it is very big
+//! and moving it from the stack is not an option, because it is bigger than the stack itself.
+//! Another reason would be that you need the address of the object to initialize it. This stands
+//! in direct conflict with Rust's normal process of first initializing an object and then moving
+//! it into it's final memory location. For more information, see
+//! <https://rust-for-linux.com/the-safe-pinned-initialization-problem>.
+//!
+//! This library allows you to do in-place initialization safely.
+//!
+//! ## Nightly Needed for `alloc` feature
+//!
+//! This library requires the [`allocator_api` unstable feature] when the `alloc` feature is
+//! enabled and thus this feature can only be used with a nightly compiler. When enabling the
+//! `alloc` feature, the user will be required to activate `allocator_api` as well.
+//!
+//! [`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html
+//!
+//! The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.
+//! However, using the crate on stable compilers is possible by disabling `alloc`. In practice this
+//! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
+//! mode.
+//!
 //! # Overview
 //!
 //! To initialize a `struct` with an in-place constructor you will need two things:
@@ -17,12 +44,17 @@
 //! - a custom function/macro returning an in-place constructor provided by someone else,
 //! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
 //!
-//! Aside from pinned initialization, this API also supports in-place construction without pinning,
-//! the macros/types/functions are generally named like the pinned variants without the `pin`
-//! prefix.
+//! Aside from pinned initialization, this library also supports in-place construction without
+//! pinning, the macros/types/functions are generally named like the pinned variants without the
+//! `pin_` prefix.
 //!
 //! # Examples
 //!
+//! Throughout the examples we will often make use of the `CMutex` type which can be found in
+//! `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
+//! the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
+//! requires it to be pinned to be locked and thus is a prime candidate for using this library.
+//!
 //! ## Using the [`pin_init!`] macro
 //!
 //! If you want to use [`PinInit`], then you will have to annotate your `struct` with
@@ -36,7 +68,7 @@
 //! # #![feature(allocator_api)]
 //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 //! # use core::pin::Pin;
-//! use pin_init::*;
+//! use pin_init::{pin_data, pin_init, InPlaceInit};
 //!
 //! #[pin_data]
 //! struct Foo {
@@ -80,8 +112,8 @@
 //!
 //! ## Using a custom function/macro that returns an initializer
 //!
-//! Many types from the kernel supply a function/macro that returns an initializer, because the
-//! above method only works for types where you can access the fields.
+//! Many types that use this library supply a function/macro that returns an initializer, because
+//! the above method only works for types where you can access the fields.
 //!
 //! ```rust,ignore
 //! # #![feature(allocator_api)]
@@ -89,7 +121,7 @@
 //! # use pin_init::*;
 //! # use std::sync::Arc;
 //! # use core::pin::Pin;
-//! let mtx: Result<Pin<Arc<Mutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
+//! let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
 //! ```
 //!
 //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
@@ -132,7 +164,7 @@
 //!
 //! ```rust,ignore
 //! # #![feature(extern_types)]
-//! use pin_init::*;
+//! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
 //! use core::{
 //!     ptr::addr_of_mut,
 //!     marker::PhantomPinned,
@@ -141,8 +173,11 @@
 //!     mem::MaybeUninit,
 //! };
 //! mod bindings {
+//!     #[repr(C)]
+//!     pub struct foo {
+//!         /* fields from C ... */
+//!     }
 //!     extern "C" {
-//!         pub type foo;
 //!         pub fn init_foo(ptr: *mut foo);
 //!         pub fn destroy_foo(ptr: *mut foo);
 //!         #[must_use = "you must check the error return code"]
@@ -200,17 +235,20 @@
 //! }
 //! ```
 //!
+//! 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`]: https://rust.docs.kernel.org/kernel/sync/index.html
 //! [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
 //! [stack]: crate::stack_pin_init
 //! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
 //! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
-//! [`impl PinInit<Foo>`]: PinInit
-//! [`impl PinInit<T, E>`]: PinInit
-//! [`impl Init<T, E>`]: Init
-//! [`pin_data`]: crate::pin_data
-//! [`pin_init!`]: crate::pin_init!
+//! [`impl PinInit<Foo>`]: crate::PinInit
+//! [`impl PinInit<T, E>`]: crate::PinInit
+//! [`impl Init<T, E>`]: crate::Init
+//! [Rust-for-Linux]: https://rust-for-linux.com/
 
 #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
 #![cfg_attr(
@@ -396,8 +434,6 @@
 /// A normal `let` binding with optional type annotation. The expression is expected to implement
 /// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
 /// type, then use [`stack_try_pin_init!`].
-///
-/// [`stack_try_pin_init!`]: crate::stack_try_pin_init!
 #[macro_export]
 macro_rules! stack_pin_init {
     (let $var:ident $(: $t:ty)? = $val:expr) => {
@@ -534,10 +570,10 @@ macro_rules! stack_try_pin_init {
 ///
 /// # Init-functions
 ///
-/// When working with this API it is often desired to let others construct your types without
-/// giving access to all fields. This is where you would normally write a plain function `new`
-/// that would return a new instance of your type. With this API that is also possible.
-/// However, there are a few extra things to keep in mind.
+/// When working with this library it is often desired to let others construct your types without
+/// giving access to all fields. This is where you would normally write a plain function `new` that
+/// would return a new instance of your type. With this library that is also possible. However,
+/// there are a few extra things to keep in mind.
 ///
 /// To create an initializer function, simply declare it like this:
 ///
@@ -666,22 +702,22 @@ macro_rules! stack_try_pin_init {
 ///     #[pin]
 ///     pin: PhantomPinned,
 /// }
-/// pin_init!(&this in Buf {
+///
+/// let init = pin_init!(&this in Buf {
 ///     buf: [0; 64],
 ///     // SAFETY: TODO.
 ///     ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
 ///     pin: PhantomPinned,
 /// });
-/// pin_init!(Buf {
+/// let init = pin_init!(Buf {
 ///     buf: [1; 64],
 ///     ..Zeroable::zeroed()
 /// });
 /// ```
 ///
-/// [`try_pin_init!`]: crate::try_pin_init
 /// [`NonNull<Self>`]: core::ptr::NonNull
 // For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+// module `macros` inside of `macros.rs`.
 #[macro_export]
 macro_rules! pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -711,7 +747,8 @@ macro_rules! pin_init {
 /// ```rust,ignore
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/error.rs"] mod error; use error::Error;
-/// use pin_init::*;
+/// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};
+///
 /// #[pin_data]
 /// struct BigBuf {
 ///     big: Box<[u8; 1024 * 1024 * 1024]>,
@@ -722,7 +759,7 @@ macro_rules! pin_init {
 /// impl BigBuf {
 ///     fn new() -> impl PinInit<Self, Error> {
 ///         try_pin_init!(Self {
-///             big: Box::init(init::zeroed())?,
+///             big: Box::init(zeroed())?,
 ///             small: [0; 1024 * 1024],
 ///             ptr: core::ptr::null_mut(),
 ///         }? Error)
@@ -731,7 +768,7 @@ macro_rules! pin_init {
 /// # let _ = Box::pin_init(BigBuf::new());
 /// ```
 // For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+// module `macros` inside of `macros.rs`.
 #[macro_export]
 macro_rules! try_pin_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -764,9 +801,30 @@ macro_rules! try_pin_init {
 /// This initializer is for initializing data in-place that might later be moved. If you want to
 /// pin-initialize, use [`pin_init!`].
 ///
-/// [`try_init!`]: crate::try_init!
+/// # Examples
+///
+/// ```rust
+/// # #![feature(allocator_api)]
+/// # #[path = "../examples/error.rs"] mod error; use error::Error;
+/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
+/// # use pin_init::InPlaceInit;
+/// use pin_init::{init, Init, zeroed};
+///
+/// struct BigBuf {
+///     small: [u8; 1024 * 1024],
+/// }
+///
+/// impl BigBuf {
+///     fn new() -> impl Init<Self> {
+///         init!(Self {
+///             small <- zeroed(),
+///         })
+///     }
+/// }
+/// # let _ = Box::init(BigBuf::new());
+/// ```
 // For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+// module `macros` inside of `macros.rs`.
 #[macro_export]
 macro_rules! init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -796,7 +854,9 @@ macro_rules! init {
 /// ```rust,ignore
 /// # #![feature(allocator_api)]
 /// # use core::alloc::AllocError;
-/// use pin_init::*;
+/// # use pin_init::InPlaceInit;
+/// use pin_init::{try_init, Init, zeroed};
+///
 /// struct BigBuf {
 ///     big: Box<[u8; 1024 * 1024 * 1024]>,
 ///     small: [u8; 1024 * 1024],
@@ -810,10 +870,10 @@ macro_rules! init {
 ///         }? AllocError)
 ///     }
 /// }
+/// # let _ = Box::init(BigBuf::new());
 /// ```
-/// [`try_pin_init!`]: crate::try_pin_init
 // For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+// module `macros` inside of `macros.rs`.
 #[macro_export]
 macro_rules! try_init {
     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -839,7 +899,8 @@ macro_rules! try_init {
 ///
 /// This will succeed:
 /// ```ignore
-/// use pin_init::assert_pinned;
+/// use pin_init::{pin_data, assert_pinned};
+///
 /// #[pin_data]
 /// struct MyStruct {
 ///     #[pin]
@@ -851,7 +912,8 @@ macro_rules! try_init {
 ///
 /// This will fail:
 /// ```compile_fail,ignore
-/// use pin_init::assert_pinned;
+/// use pin_init::{pin_data, assert_pinned};
+///
 /// #[pin_data]
 /// struct MyStruct {
 ///     some_field: u64,
@@ -864,7 +926,9 @@ macro_rules! try_init {
 /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
 /// only be used when the macro is invoked from a function body.
 /// ```ignore
-/// use pin_init::assert_pinned;
+/// # use core::pin::Pin;
+/// use pin_init::{pin_data, assert_pinned};
+///
 /// #[pin_data]
 /// struct Foo<T> {
 ///     #[pin]
@@ -1032,14 +1096,15 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     ///
     /// ```rust,ignore
     /// # #![expect(clippy::disallowed_names)]
-    /// use pin_init::{init_from_closure, zeroed};
+    /// use pin_init::{init, zeroed, Init};
+    ///
     /// struct Foo {
     ///     buf: [u8; 1_000_000],
     /// }
     ///
     /// impl Foo {
     ///     fn setup(&mut self) {
-    ///         pr_info!("Setting up foo");
+    ///         println!("Setting up foo");
     ///     }
     /// }
     ///
@@ -1278,8 +1343,6 @@ pub trait InPlaceWrite<T> {
 /// # Safety
 ///
 /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
-///
-/// [`pinned_drop`]: crate::pinned_drop
 pub unsafe trait PinnedDrop: __internal::HasPinData {
     /// Executes the pinned destructor of this type.
     ///
diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs
index d41c4f198c42..361623324d5c 100644
--- a/rust/pin-init/src/macros.rs
+++ b/rust/pin-init/src/macros.rs
@@ -1,8 +1,8 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
 //! This module provides the macros that actually implement the proc-macros `pin_data` and
-//! `pinned_drop`. It also contains `__init_internal` the implementation of the `{try_}{pin_}init!`
-//! macros.
+//! `pinned_drop`. It also contains `__init_internal`, the implementation of the
+//! `{try_}{pin_}init!` macros.
 //!
 //! These macros should never be called directly, since they expect their input to be
 //! in a certain format which is internal. If used incorrectly, these macros can lead to UB even in
@@ -11,16 +11,17 @@
 //! This architecture has been chosen because the kernel does not yet have access to `syn` which
 //! would make matters a lot easier for implementing these as proc-macros.
 //!
+//! Since this library and the kernel implementation should diverge as little as possible, the same
+//! approach has been taken here.
+//!
 //! # Macro expansion example
 //!
 //! This section is intended for readers trying to understand the macros in this module and the
-//! `pin_init!` macros from `init.rs`.
+//! `[try_][pin_]init!` macros from `lib.rs`.
 //!
 //! We will look at the following example:
 //!
 //! ```rust,ignore
-//! # use pin_init::*;
-//! # use core::pin::Pin;
 //! #[pin_data]
 //! #[repr(C)]
 //! struct Bar<T> {
@@ -45,7 +46,7 @@
 //! #[pinned_drop]
 //! impl PinnedDrop for Foo {
 //!     fn drop(self: Pin<&mut Self>) {
-//!         pr_info!("{self:p} is getting dropped.");
+//!         println!("{self:p} is getting dropped.");
 //!     }
 //! }
 //!
@@ -75,7 +76,6 @@
 //! Here is the definition of `Bar` from our example:
 //!
 //! ```rust,ignore
-//! # use pin_init::*;
 //! #[pin_data]
 //! #[repr(C)]
 //! struct Bar<T> {
@@ -251,7 +251,7 @@
 //!                     // is an error later. This `DropGuard` will drop the field when it gets
 //!                     // dropped and has not yet been forgotten.
 //!                     let __t_guard = unsafe {
-//!                         ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
+//!                         ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
 //!                     };
 //!                     // Expansion of `x: 0,`:
 //!                     // Since this can be an arbitrary expression we cannot place it inside
@@ -412,7 +412,7 @@
 //! #[pinned_drop]
 //! impl PinnedDrop for Foo {
 //!     fn drop(self: Pin<&mut Self>) {
-//!         pr_info!("{self:p} is getting dropped.");
+//!         println!("{self:p} is getting dropped.");
 //!     }
 //! }
 //! ```
@@ -423,7 +423,7 @@
 //! // `unsafe`, full path and the token parameter are added, everything else stays the same.
 //! unsafe impl ::pin_init::PinnedDrop for Foo {
 //!     fn drop(self: Pin<&mut Self>, _: ::pin_init::__internal::OnlyCallFromDrop) {
-//!         pr_info!("{self:p} is getting dropped.");
+//!         println!("{self:p} is getting dropped.");
 //!     }
 //! }
 //! ```
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 18/22] rust: pin-init: internal: synchronize with user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (16 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 17/22] rust: pin-init: synchronize documentation with " Benno Lossin
@ 2025-03-04 22:55   ` Benno Lossin
  2025-03-05 12:56     ` Andreas Hindborg
  2025-03-04 22:56   ` [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the " Benno Lossin
                     ` (5 subsequent siblings)
  23 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:55 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

This commit synchronizes with the user-space version that uses the
quote crate [1] instead of a custom `quote!` macro.
The imports in the different version are achieved using `cfg` on the
kernel config value. This is always set in the kernel and never set in
the user-space version.

Since the quote crate requires the proc_macro2 crate, imports also need
to be adjusted and `.into()` calls have to be inserted.

Link: https://crates.io/crates/quote [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/internal/src/helpers.rs     |  3 +++
 rust/pin-init/internal/src/lib.rs         | 16 +++++++++++++---
 rust/pin-init/internal/src/pin_data.rs    |  3 +++
 rust/pin-init/internal/src/pinned_drop.rs |  3 +++
 rust/pin-init/internal/src/zeroable.rs    |  3 +++
 5 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/rust/pin-init/internal/src/helpers.rs b/rust/pin-init/internal/src/helpers.rs
index 78521ba19d0b..236f989a50f2 100644
--- a/rust/pin-init/internal/src/helpers.rs
+++ b/rust/pin-init/internal/src/helpers.rs
@@ -1,5 +1,8 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
+#[cfg(not(kernel))]
+use proc_macro2 as proc_macro;
+
 use proc_macro::{TokenStream, TokenTree};
 
 /// Parsed generics.
diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
index c201b8a53915..30e145f80bc0 100644
--- a/rust/pin-init/internal/src/lib.rs
+++ b/rust/pin-init/internal/src/lib.rs
@@ -7,6 +7,13 @@
 //! `pin-init` proc macros.
 
 #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
+// Allow `.into()` to convert
+// - `proc_macro2::TokenStream` into `proc_macro::TokenStream` in the user-space version.
+// - `proc_macro::TokenStream` into `proc_macro::TokenStream` in the kernel version.
+//   Clippy warns on this conversion, but it's required by the user-space version.
+//
+// Remove once we have `proc_macro2` in the kernel.
+#![allow(clippy::useless_conversion)]
 
 use proc_macro::TokenStream;
 
@@ -14,6 +21,9 @@
 #[path = "../../../macros/quote.rs"]
 #[macro_use]
 mod quote;
+#[cfg(not(kernel))]
+#[macro_use]
+extern crate quote;
 
 mod helpers;
 mod pin_data;
@@ -23,17 +33,17 @@
 #[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
-    pin_data::pin_data(inner, item)
+    pin_data::pin_data(inner.into(), item.into()).into()
 }
 
 #[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
-    pinned_drop::pinned_drop(args, input)
+    pinned_drop::pinned_drop(args.into(), input.into()).into()
 }
 
 #[allow(missing_docs)]
 #[proc_macro_derive(Zeroable)]
 pub fn derive_zeroable(input: TokenStream) -> TokenStream {
-    zeroable::derive(input)
+    zeroable::derive(input.into()).into()
 }
diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index 9b974498f4a8..87d4a7eb1d35 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -1,5 +1,8 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
+#[cfg(not(kernel))]
+use proc_macro2 as proc_macro;
+
 use crate::helpers::{parse_generics, Generics};
 use proc_macro::{Group, Punct, Spacing, TokenStream, TokenTree};
 
diff --git a/rust/pin-init/internal/src/pinned_drop.rs b/rust/pin-init/internal/src/pinned_drop.rs
index 386f52f73c06..c824dd8b436d 100644
--- a/rust/pin-init/internal/src/pinned_drop.rs
+++ b/rust/pin-init/internal/src/pinned_drop.rs
@@ -1,5 +1,8 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
+#[cfg(not(kernel))]
+use proc_macro2 as proc_macro;
+
 use proc_macro::{TokenStream, TokenTree};
 
 pub(crate) fn pinned_drop(_args: TokenStream, input: TokenStream) -> TokenStream {
diff --git a/rust/pin-init/internal/src/zeroable.rs b/rust/pin-init/internal/src/zeroable.rs
index 0cf6732f27dc..acc94008c152 100644
--- a/rust/pin-init/internal/src/zeroable.rs
+++ b/rust/pin-init/internal/src/zeroable.rs
@@ -1,5 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#[cfg(not(kernel))]
+use proc_macro2 as proc_macro;
+
 use crate::helpers::{parse_generics, Generics};
 use proc_macro::{TokenStream, TokenTree};
 
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (17 preceding siblings ...)
  2025-03-04 22:55   ` [PATCH 18/22] rust: pin-init: internal: synchronize with " Benno Lossin
@ 2025-03-04 22:56   ` Benno Lossin
  2025-03-05 12:57     ` Andreas Hindborg
  2025-03-04 22:56   ` [PATCH 20/22] rust: pin-init: add miscellaneous files from " Benno Lossin
                     ` (4 subsequent siblings)
  23 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:56 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

Last differences between the kernel version and the user-space version
are removed here.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/internal/src/lib.rs | 5 ++---
 rust/pin-init/src/__internal.rs   | 2 +-
 rust/pin-init/src/lib.rs          | 2 --
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
index 30e145f80bc0..babe5e878550 100644
--- a/rust/pin-init/internal/src/lib.rs
+++ b/rust/pin-init/internal/src/lib.rs
@@ -14,6 +14,8 @@
 //
 // Remove once we have `proc_macro2` in the kernel.
 #![allow(clippy::useless_conversion)]
+// Documentation is done in the pin-init crate instead.
+#![allow(missing_docs)]
 
 use proc_macro::TokenStream;
 
@@ -30,19 +32,16 @@
 mod pinned_drop;
 mod zeroable;
 
-#[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
     pin_data::pin_data(inner.into(), item.into()).into()
 }
 
-#[allow(missing_docs)]
 #[proc_macro_attribute]
 pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
     pinned_drop::pinned_drop(args.into(), input.into()).into()
 }
 
-#[allow(missing_docs)]
 #[proc_macro_derive(Zeroable)]
 pub fn derive_zeroable(input: TokenStream) -> TokenStream {
     zeroable::derive(input.into()).into()
diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 5336d659685d..6b258502a9d7 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -11,7 +11,7 @@
 ///
 /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
 /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns
-pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
+pub(crate) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
 
 /// Module-internal type implementing `PinInit` and `Init`.
 ///
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index fb64cddd1a72..3d57760a3cee 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -341,8 +341,6 @@
 ///     }
 /// }
 /// ```
-///
-/// [`pin_init!`]: crate::pin_init
 pub use ::pin_init_internal::pin_data;
 
 /// Used to implement `PinnedDrop` safely.
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 20/22] rust: pin-init: add miscellaneous files from the user-space version
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (18 preceding siblings ...)
  2025-03-04 22:56   ` [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the " Benno Lossin
@ 2025-03-04 22:56   ` Benno Lossin
  2025-03-05  9:35     ` Fiona Behrens
  2025-03-05 13:04     ` Andreas Hindborg
  2025-03-04 22:56   ` [PATCH 21/22] rust: pin-init: re-enable doctests Benno Lossin
                     ` (3 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:56 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

Add readme and contribution guidelines of the user-space version of
pin-init.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/CONTRIBUTING.md |  72 +++++++++++
 rust/pin-init/README.md       | 228 ++++++++++++++++++++++++++++++++++
 2 files changed, 300 insertions(+)
 create mode 100644 rust/pin-init/CONTRIBUTING.md
 create mode 100644 rust/pin-init/README.md

diff --git a/rust/pin-init/CONTRIBUTING.md b/rust/pin-init/CONTRIBUTING.md
new file mode 100644
index 000000000000..16c899a7ae0b
--- /dev/null
+++ b/rust/pin-init/CONTRIBUTING.md
@@ -0,0 +1,72 @@
+# Contributing to `pin-init`
+
+Thanks for showing interest in contributing to `pin-init`! This document outlines the guidelines for
+contributing to `pin-init`.
+
+All contributions are double-licensed under Apache 2.0 and MIT. You can find the respective licenses
+in the `LICENSE-APACHE` and `LICENSE-MIT` files.
+
+## Non-Code Contributions
+
+### Bug Reports
+
+For any type of bug report, please submit an issue using the bug report issue template.
+
+If the issue is a soundness issue, please privately report it as a security vulnerability via the
+GitHub web interface.
+
+### Feature Requests
+
+If you have any feature requests, please submit an issue using the feature request issue template.
+
+### Questions and Getting Help
+
+You can ask questions in the Discussions page of the GitHub repository. If you're encountering
+problems or just have questions related to `pin-init` in the Linux kernel, you can also ask your
+questions in the [Rust-for-Linux Zulip](https://rust-for-linux.zulipchat.com/) or see
+<https://rust-for-linux.com/contact>.
+
+## Contributing Code
+
+### Linux Kernel
+
+`pin-init` is used by the Linux kernel and all commits are synchronized to it. For this reason, the
+same requirements for commits apply to `pin-init`. See [the kernel's documentation] for details. The
+rest of this document will also cover some of the rules listed there and additional ones.
+
+[the kernel's documentation]: https://docs.kernel.org/process/submitting-patches.html
+
+Contributions to `pin-init` ideally go through the [GitHub repository], because that repository runs
+a CI with lots of tests not present in the kernel. However, patches are also accepted (though not
+preferred). Do note that there are some files that are only present in the GitHub repository such as
+tests, licenses and cargo related files. Making changes to them can only happen via GitHub.
+
+[GitHub repository]: https://github.com/Rust-for-Linux/pin-init
+
+### Commit Style
+
+Everything must compile without errors or warnings and all tests must pass after **every commit**.
+This is important for bisection and also required by the kernel.
+
+Each commit should be a single, logically cohesive change. Of course it's best to keep the changes
+small and digestible, but logically linked changes should be made in the same commit. For example,
+when fixing typos, create a single commit that fixes all of them instead of one commit per typo.
+
+Commits must have a meaningful commit title. Commits with changes to files in the `internal`
+directory should have a title prefixed with `internal:`. The commit message should explain the
+change and its rationale. You also have to add your `Signed-off-by` tag, see [Developer's
+Certificate of Origin]. This has to be done for both mailing list submissions as well as GitHub
+submissions.
+
+[Developer's Certificate of Origin]: https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin
+
+Any changes made to public APIs must be documented not only in the commit message, but also in the
+`CHANGELOG.md` file. This is especially important for breaking changes, as those warrant a major
+version bump.
+
+If you make changes to the top-level crate documentation, you also need to update the `README.md`
+via `cargo rdme`.
+
+Some of these rules can be ignored if the change is done solely to files that are not present in the
+kernel version of this library. Those files are documented in the `sync-kernel.sh` script at the
+very bottom in the `--exclude` flag given to the `git am` command.
diff --git a/rust/pin-init/README.md b/rust/pin-init/README.md
new file mode 100644
index 000000000000..c68fffba540f
--- /dev/null
+++ b/rust/pin-init/README.md
@@ -0,0 +1,228 @@
+[![Crates.io](https://img.shields.io/crates/v/pin-init.svg)](https://crates.io/crates/pin-init)
+[![Documentation](https://docs.rs/pin-init/badge.svg)](https://docs.rs/pin-init/)
+[![Dependency status](https://deps.rs/repo/github/Rust-for-Linux/pin-init/status.svg)](https://deps.rs/repo/github/Rust-for-Linux/pin-init)
+![License](https://img.shields.io/crates/l/pin-init)
+[![Toolchain](https://img.shields.io/badge/toolchain-nightly-red)](#nightly-only)
+![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml)
+# Pinned-init
+
+<!-- cargo-rdme start -->
+
+Library to safely and fallibly initialize pinned `struct`s using in-place constructors.
+
+[Pinning][pinning] is Rust's way of ensuring data does not move.
+
+It also allows in-place initialization of big `struct`s that would otherwise produce a stack
+overflow.
+
+This library's main use-case is in [Rust-for-Linux]. Although this version can be used
+standalone.
+
+There are cases when you want to in-place initialize a struct. For example when it is very big
+and moving it from the stack is not an option, because it is bigger than the stack itself.
+Another reason would be that you need the address of the object to initialize it. This stands
+in direct conflict with Rust's normal process of first initializing an object and then moving
+it into it's final memory location. For more information, see
+<https://rust-for-linux.com/the-safe-pinned-initialization-problem>.
+
+This library allows you to do in-place initialization safely.
+
+### Nightly Needed for `alloc` feature
+
+This library requires the [`allocator_api` unstable feature] when the `alloc` feature is
+enabled and thus this feature can only be used with a nightly compiler. When enabling the
+`alloc` feature, the user will be required to activate `allocator_api` as well.
+
+[`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html
+
+The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.
+However, using the crate on stable compilers is possible by disabling `alloc`. In practice this
+will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
+mode.
+
+## Overview
+
+To initialize a `struct` with an in-place constructor you will need two things:
+- an in-place constructor,
+- a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
+  [`Box<T>`] or any other smart pointer that supports this library).
+
+To get an in-place constructor there are generally three options:
+- directly creating an in-place constructor using the [`pin_init!`] macro,
+- a custom function/macro returning an in-place constructor provided by someone else,
+- using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
+
+Aside from pinned initialization, this library also supports in-place construction without
+pinning, the macros/types/functions are generally named like the pinned variants without the
+`pin_` prefix.
+
+## Examples
+
+Throughout the examples we will often make use of the `CMutex` type which can be found in
+`../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
+the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
+requires it to be pinned to be locked and thus is a prime candidate for using this library.
+
+### Using the [`pin_init!`] macro
+
+If you want to use [`PinInit`], then you will have to annotate your `struct` with
+`#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
+[structurally pinned fields]. After doing this, you can then create an in-place constructor via
+[`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
+that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
+
+```rust
+use pin_init::{pin_data, pin_init, InPlaceInit};
+
+#[pin_data]
+struct Foo {
+    #[pin]
+    a: CMutex<usize>,
+    b: u32,
+}
+
+let foo = pin_init!(Foo {
+    a <- CMutex::new(42),
+    b: 24,
+});
+```
+
+`foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
+(or just the stack) to actually initialize a `Foo`:
+
+```rust
+let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
+```
+
+For more information see the [`pin_init!`] macro.
+
+### Using a custom function/macro that returns an initializer
+
+Many types that use this library supply a function/macro that returns an initializer, because
+the above method only works for types where you can access the fields.
+
+```rust
+let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
+```
+
+To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
+
+```rust
+#[pin_data]
+struct DriverData {
+    #[pin]
+    status: CMutex<i32>,
+    buffer: Box<[u8; 1_000_000]>,
+}
+
+impl DriverData {
+    fn new() -> impl PinInit<Self, Error> {
+        try_pin_init!(Self {
+            status <- CMutex::new(0),
+            buffer: Box::init(pin_init::zeroed())?,
+        }? Error)
+    }
+}
+```
+
+### Manual creation of an initializer
+
+Often when working with primitives the previous approaches are not sufficient. That is where
+[`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
+[`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
+actually does the initialization in the correct way. Here are the things to look out for
+(we are calling the parameter to the closure `slot`):
+- when the closure returns `Ok(())`, then it has completed the initialization successfully, so
+  `slot` now contains a valid bit pattern for the type `T`,
+- when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
+  you need to take care to clean up anything if your initialization fails mid-way,
+- you may assume that `slot` will stay pinned even after the closure returns until `drop` of
+  `slot` gets called.
+
+```rust
+use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
+use core::{
+    ptr::addr_of_mut,
+    marker::PhantomPinned,
+    cell::UnsafeCell,
+    pin::Pin,
+    mem::MaybeUninit,
+};
+mod bindings {
+    #[repr(C)]
+    pub struct foo {
+        /* fields from C ... */
+    }
+    extern "C" {
+        pub fn init_foo(ptr: *mut foo);
+        pub fn destroy_foo(ptr: *mut foo);
+        #[must_use = "you must check the error return code"]
+        pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
+    }
+}
+
+/// # Invariants
+///
+/// `foo` is always initialized
+#[pin_data(PinnedDrop)]
+pub struct RawFoo {
+    #[pin]
+    _p: PhantomPinned,
+    #[pin]
+    foo: UnsafeCell<MaybeUninit<bindings::foo>>,
+}
+
+impl RawFoo {
+    pub fn new(flags: u32) -> impl PinInit<Self, i32> {
+        // 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_from_closure(move |slot: *mut Self| {
+                // `slot` contains uninit memory, avoid creating a reference.
+                let foo = addr_of_mut!((*slot).foo);
+                let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
+
+                // Initialize the `foo`
+                bindings::init_foo(foo);
+
+                // Try to enable it.
+                let err = bindings::enable_foo(foo, flags);
+                if err != 0 {
+                    // Enabling has failed, first clean up the foo and then return the error.
+                    bindings::destroy_foo(foo);
+                    Err(err)
+                } else {
+                    // 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().cast::<bindings::foo>()) };
+    }
+}
+```
+
+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`]: https://rust.docs.kernel.org/kernel/sync/index.html
+[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
+[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html
+[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
+[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
+[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
+[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
+[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html
+[Rust-for-Linux]: https://rust-for-linux.com/
+
+<!-- cargo-rdme end -->
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 21/22] rust: pin-init: re-enable doctests
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (19 preceding siblings ...)
  2025-03-04 22:56   ` [PATCH 20/22] rust: pin-init: add miscellaneous files from " Benno Lossin
@ 2025-03-04 22:56   ` Benno Lossin
  2025-03-05  9:35     ` Fiona Behrens
  2025-03-05 13:05     ` Andreas Hindborg
  2025-03-04 22:56   ` [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate Benno Lossin
                     ` (2 subsequent siblings)
  23 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:56 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel

The pin-init crate is now compiled in a standalone fashion, so revert
the earlier commit that disabled the doctests in pin-init in order to
avoid build errors while transitioning the crate into a standalone
version.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 rust/pin-init/src/lib.rs | 54 ++++++++++++++++++++--------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 3d57760a3cee..cb015b118283 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -63,7 +63,7 @@
 //! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
 //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
 //!
-//! ```rust,ignore
+//! ```rust
 //! # #![expect(clippy::disallowed_names)]
 //! # #![feature(allocator_api)]
 //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
@@ -87,7 +87,7 @@
 //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
 //! (or just the stack) to actually initialize a `Foo`:
 //!
-//! ```rust,ignore
+//! ```rust
 //! # #![expect(clippy::disallowed_names)]
 //! # #![feature(allocator_api)]
 //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
@@ -115,7 +115,7 @@
 //! Many types that use this library supply a function/macro that returns an initializer, because
 //! the above method only works for types where you can access the fields.
 //!
-//! ```rust,ignore
+//! ```rust
 //! # #![feature(allocator_api)]
 //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 //! # use pin_init::*;
@@ -126,7 +126,7 @@
 //!
 //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
 //!
-//! ```rust,ignore
+//! ```rust
 //! # #![feature(allocator_api)]
 //! # use pin_init::*;
 //! # #[path = "../examples/error.rs"] mod error; use error::Error;
@@ -162,7 +162,7 @@
 //! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
 //!   `slot` gets called.
 //!
-//! ```rust,ignore
+//! ```rust
 //! # #![feature(extern_types)]
 //! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
 //! use core::{
@@ -298,7 +298,7 @@
 ///
 /// # Examples
 ///
-/// ```ignore
+/// ```
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 /// use pin_init::pin_data;
@@ -315,7 +315,7 @@
 /// }
 /// ```
 ///
-/// ```ignore
+/// ```
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
@@ -349,7 +349,7 @@
 ///
 /// # Examples
 ///
-/// ```ignore
+/// ```
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
@@ -383,7 +383,7 @@
 ///
 /// # Examples
 ///
-/// ```ignore
+/// ```
 /// use pin_init::Zeroable;
 ///
 /// #[derive(Zeroable)]
@@ -399,7 +399,7 @@
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![expect(clippy::disallowed_names)]
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
@@ -451,7 +451,7 @@ macro_rules! stack_pin_init {
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![expect(clippy::disallowed_names)]
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/error.rs"] mod error; use error::Error;
@@ -478,7 +478,7 @@ macro_rules! stack_pin_init {
 /// println!("a: {}", &*foo.a.lock());
 /// ```
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![expect(clippy::disallowed_names)]
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/error.rs"] mod error; use error::Error;
@@ -531,7 +531,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// The syntax is almost identical to that of a normal `struct` initializer:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # use pin_init::*;
 /// # use core::pin::Pin;
 /// #[pin_data]
@@ -575,7 +575,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// To create an initializer function, simply declare it like this:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # use pin_init::*;
 /// # use core::pin::Pin;
 /// # #[pin_data]
@@ -601,7 +601,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// Users of `Foo` can now create it like this:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![expect(clippy::disallowed_names)]
 /// # use pin_init::*;
 /// # use core::pin::Pin;
@@ -629,7 +629,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// They can also easily embed it into their own `struct`s:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # use pin_init::*;
 /// # use core::pin::Pin;
 /// # #[pin_data]
@@ -688,7 +688,7 @@ macro_rules! stack_try_pin_init {
 ///
 /// For instance:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # use pin_init::*;
 /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
 /// #[pin_data]
@@ -742,7 +742,7 @@ macro_rules! pin_init {
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/error.rs"] mod error; use error::Error;
 /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};
@@ -849,7 +849,7 @@ macro_rules! init {
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![feature(allocator_api)]
 /// # use core::alloc::AllocError;
 /// # use pin_init::InPlaceInit;
@@ -896,7 +896,7 @@ macro_rules! try_init {
 /// # Example
 ///
 /// This will succeed:
-/// ```ignore
+/// ```
 /// use pin_init::{pin_data, assert_pinned};
 ///
 /// #[pin_data]
@@ -909,7 +909,7 @@ macro_rules! try_init {
 /// ```
 ///
 /// This will fail:
-/// ```compile_fail,ignore
+/// ```compile_fail
 /// use pin_init::{pin_data, assert_pinned};
 ///
 /// #[pin_data]
@@ -923,7 +923,7 @@ macro_rules! try_init {
 /// Some uses of the macro may trigger the `can't use generic parameters from outer item` error. To
 /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
 /// only be used when the macro is invoked from a function body.
-/// ```ignore
+/// ```
 /// # use core::pin::Pin;
 /// use pin_init::{pin_data, assert_pinned};
 ///
@@ -1002,7 +1002,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     ///
     /// # Examples
     ///
-    /// ```rust,ignore
+    /// ```rust
     /// # #![feature(allocator_api)]
     /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
     /// # use pin_init::*;
@@ -1092,7 +1092,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
     ///
     /// # Examples
     ///
-    /// ```rust,ignore
+    /// ```rust
     /// # #![expect(clippy::disallowed_names)]
     /// use pin_init::{init, zeroed, Init};
     ///
@@ -1205,7 +1205,7 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # use pin_init::*;
 /// use pin_init::init_array_from_fn;
 /// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap();
@@ -1243,7 +1243,7 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
 ///
 /// # Examples
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 /// # use pin_init::*;
@@ -1319,7 +1319,7 @@ pub trait InPlaceWrite<T> {
 ///
 /// Use [`pinned_drop`] to implement this trait safely:
 ///
-/// ```rust,ignore
+/// ```rust
 /// # #![feature(allocator_api)]
 /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
 /// # use pin_init::*;
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (20 preceding siblings ...)
  2025-03-04 22:56   ` [PATCH 21/22] rust: pin-init: re-enable doctests Benno Lossin
@ 2025-03-04 22:56   ` Benno Lossin
  2025-03-05  0:17     ` Jarkko Sakkinen
  2025-03-04 23:12   ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
  2025-03-05 13:56   ` Andreas Hindborg
  23 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 22:56 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich
  Cc: linux-kernel, rust-for-linux

Add maintainers entry for the `pin-init` crate.

This crate is already being maintained by me, but until now there
existed two different versions: the version inside of the kernel tree
and a user-space version at [1]. The previous patches synchronized these
two versions to reduce the maintenance burden. In order to keep them
synchronized from now on, separate the maintenance from other Rust code.

Link: https://github.com/Rust-for-Linux/pin-init [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
 MAINTAINERS | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..ced7fac4dbbe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20735,6 +20735,19 @@ S:	Maintained
 F:	rust/kernel/alloc.rs
 F:	rust/kernel/alloc/
 
+RUST [PIN-INIT]
+M:	Benno Lossin <benno.lossin@proton.me>
+L:	rust-for-linux@vger.kernel.org
+S:	Maintained
+W:	https://rust-for-linux.com/pin-init
+B:	https://github.com/Rust-for-Linux/pin-init/issues
+C:	zulip://rust-for-linux.zulipchat.com
+P:	rust/pin-init/CONTRIBUTING.md
+T:	git https://github.com/Rust-for-Linux/linux.git pin-init-next
+F:	rust/kernel/init.rs
+F:	rust/pin-init/
+K:	\bpin-init\b|pin_init\b|PinInit
+
 RXRPC SOCKETS (AF_RXRPC)
 M:	David Howells <dhowells@redhat.com>
 M:	Marc Dionne <marc.dionne@auristor.com>
-- 
2.47.2



^ permalink raw reply related	[flat|nested] 103+ messages in thread

* Re: [PATCH 00/22] make pin-init into a standalone crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (21 preceding siblings ...)
  2025-03-04 22:56   ` [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate Benno Lossin
@ 2025-03-04 23:12   ` Benno Lossin
  2025-03-05 13:56   ` Andreas Hindborg
  23 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-04 23:12 UTC (permalink / raw)
  To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux

On Tue Mar 4, 2025 at 11:52 PM CET, Benno Lossin wrote:
> This patch series extracts the pin-init API from the kernel crate and
> turns it into a standalone crate used by the kernel crate. The reasoning
> for this change is that the maintenance burden for me is too great
> maintaining two (more and more) diverging versions of the same library.
> At [1] you can find the user-space version of the pin-init library as a
> Rust crate.
>
> The reason for the difference between the two versions is that the
> kernel does not use the `std` and `alloc` standard libraries as almost
> every other user-space Rust crate does. This not only prevents the
> kernel version from implementing features for the `Arc` type from
> `alloc`, but also from any `std` types appearing in the documentation.
> Additionally, the documentation text is different in several places as
> it explicitly mentions the kernel's `Opaque<T>` type.
>
> There are also minor changes in code that occurred due to the same
> reason as the documentation changes or due to the non-optimal setup for
> synchronizing changes between the two versions (the process it fully
> manual, as no diffs can be ported between the two). For example, the
> `try_[pin_]init!` macros in the kernel default to the kernel's own
> `Error` type. The user-space version does not have such defaulting
> behavior.
>
> Since there are other projects outside of the kernel that have begun
> using pin-init, the only sensible solution to this problem is to
> synchronize both versions and then develop them simultaneously, ensuring
> perpetual diff-compatibility. I have even had people contribute code on
> github.
>
> Additionally, I want to do some big changes to the pin-init library
> internals. For example, porting the proc-macros over to `syn`. We will
> probably get support for this later this year in the kernel and I want
> to be ready to be able to make that switch as soon as possible. This is
> because non-syn proc-macros are just pure hell and the current
> implementation is a frankenstein-monster of a mix of declarative macros
> and proc-macros that I'd rather replace by using `syn`. I already wrote
> the code for that transition and will be submitting an RFC based on this
> series shortly.

RFC: https://lore.kernel.org/rust-for-linux/20250304225536.2033853-1-benno.lossin@proton.me/

The RFC has been generated from the same changes to the user-space
version, you can find the associated PR here:
https://github.com/Rust-for-Linux/pin-init/pull/31

It is much much more convenient to let a script handle the changes and
then verify them later compared with making the changes to both
versions, double checking again and again.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate
  2025-03-04 22:56   ` [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate Benno Lossin
@ 2025-03-05  0:17     ` Jarkko Sakkinen
  2025-03-05  0:43       ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Jarkko Sakkinen @ 2025-03-05  0:17 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

On Tue, Mar 04, 2025 at 10:56:27PM +0000, Benno Lossin wrote:
> Add maintainers entry for the `pin-init` crate.
> 
> This crate is already being maintained by me, but until now there
> existed two different versions: the version inside of the kernel tree
> and a user-space version at [1]. The previous patches synchronized these
> two versions to reduce the maintenance burden. In order to keep them
> synchronized from now on, separate the maintenance from other Rust code.
> 
> Link: https://github.com/Rust-for-Linux/pin-init [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  MAINTAINERS | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8e0736dc2ee0..ced7fac4dbbe 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20735,6 +20735,19 @@ S:	Maintained
>  F:	rust/kernel/alloc.rs
>  F:	rust/kernel/alloc/
>  
> +RUST [PIN-INIT]

In some subsystems the order is exactly the opposite. E.g.,

ASIX PHY DRIVER [RUST]

> +M:	Benno Lossin <benno.lossin@proton.me>
> +L:	rust-for-linux@vger.kernel.org
> +S:	Maintained
> +W:	https://rust-for-linux.com/pin-init
> +B:	https://github.com/Rust-for-Linux/pin-init/issues
> +C:	zulip://rust-for-linux.zulipchat.com
> +P:	rust/pin-init/CONTRIBUTING.md
> +T:	git https://github.com/Rust-for-Linux/linux.git pin-init-next
> +F:	rust/kernel/init.rs
> +F:	rust/pin-init/
> +K:	\bpin-init\b|pin_init\b|PinInit
> +
>  RXRPC SOCKETS (AF_RXRPC)
>  M:	David Howells <dhowells@redhat.com>
>  M:	Marc Dionne <marc.dionne@auristor.com>
> -- 
> 2.47.2
> 
> 
> 

BR, Jarkko

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate
  2025-03-05  0:17     ` Jarkko Sakkinen
@ 2025-03-05  0:43       ` Benno Lossin
  2025-03-05  5:14         ` Jarkko Sakkinen
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05  0:43 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

On Wed Mar 5, 2025 at 1:17 AM CET, Jarkko Sakkinen wrote:
> On Tue, Mar 04, 2025 at 10:56:27PM +0000, Benno Lossin wrote:
>> Add maintainers entry for the `pin-init` crate.
>>
>> This crate is already being maintained by me, but until now there
>> existed two different versions: the version inside of the kernel tree
>> and a user-space version at [1]. The previous patches synchronized these
>> two versions to reduce the maintenance burden. In order to keep them
>> synchronized from now on, separate the maintenance from other Rust code.
>>
>> Link: https://github.com/Rust-for-Linux/pin-init [1]
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  MAINTAINERS | 13 +++++++++++++
>>  1 file changed, 13 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 8e0736dc2ee0..ced7fac4dbbe 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -20735,6 +20735,19 @@ S:	Maintained
>>  F:	rust/kernel/alloc.rs
>>  F:	rust/kernel/alloc/
>>
>> +RUST [PIN-INIT]
>
> In some subsystems the order is exactly the opposite. E.g.,
>
> ASIX PHY DRIVER [RUST]

I think that `RUST [PIN-INIT]` makes sense in this case, since it is a
core Rust library. In the example you gave above, the `ASIX PHY DRIVER`
subsystem already exists, so it makes sense to have a rustified version.
With pin-init, there is no C counterpart. So IMO the only other
alternative would be just `PIN-INIT`.

---
Cheers,
Benno

>> +M:	Benno Lossin <benno.lossin@proton.me>
>> +L:	rust-for-linux@vger.kernel.org
>> +S:	Maintained
>> +W:	https://rust-for-linux.com/pin-init
>> +B:	https://github.com/Rust-for-Linux/pin-init/issues
>> +C:	zulip://rust-for-linux.zulipchat.com
>> +P:	rust/pin-init/CONTRIBUTING.md
>> +T:	git https://github.com/Rust-for-Linux/linux.git pin-init-next
>> +F:	rust/kernel/init.rs
>> +F:	rust/pin-init/
>> +K:	\bpin-init\b|pin_init\b|PinInit
>> +
>>  RXRPC SOCKETS (AF_RXRPC)
>>  M:	David Howells <dhowells@redhat.com>
>>  M:	Marc Dionne <marc.dionne@auristor.com>
>> --
>> 2.47.2
>>
>>
>>
>
> BR, Jarkko



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate
  2025-03-05  0:43       ` Benno Lossin
@ 2025-03-05  5:14         ` Jarkko Sakkinen
  0 siblings, 0 replies; 103+ messages in thread
From: Jarkko Sakkinen @ 2025-03-05  5:14 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

On Wed, Mar 05, 2025 at 12:43:18AM +0000, Benno Lossin wrote:
> On Wed Mar 5, 2025 at 1:17 AM CET, Jarkko Sakkinen wrote:
> > On Tue, Mar 04, 2025 at 10:56:27PM +0000, Benno Lossin wrote:
> >> Add maintainers entry for the `pin-init` crate.
> >>
> >> This crate is already being maintained by me, but until now there
> >> existed two different versions: the version inside of the kernel tree
> >> and a user-space version at [1]. The previous patches synchronized these
> >> two versions to reduce the maintenance burden. In order to keep them
> >> synchronized from now on, separate the maintenance from other Rust code.
> >>
> >> Link: https://github.com/Rust-for-Linux/pin-init [1]
> >> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> >> ---
> >>  MAINTAINERS | 13 +++++++++++++
> >>  1 file changed, 13 insertions(+)
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 8e0736dc2ee0..ced7fac4dbbe 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -20735,6 +20735,19 @@ S:	Maintained
> >>  F:	rust/kernel/alloc.rs
> >>  F:	rust/kernel/alloc/
> >>
> >> +RUST [PIN-INIT]
> >
> > In some subsystems the order is exactly the opposite. E.g.,
> >
> > ASIX PHY DRIVER [RUST]
> 
> I think that `RUST [PIN-INIT]` makes sense in this case, since it is a
> core Rust library. In the example you gave above, the `ASIX PHY DRIVER`
> subsystem already exists, so it makes sense to have a rustified version.
> With pin-init, there is no C counterpart. So IMO the only other
> alternative would be just `PIN-INIT`.

Right, got it, thanks.

BR, Jarkko

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
@ 2025-03-05  8:51     ` Andreas Hindborg
  2025-03-05 12:53       ` Benno Lossin
  2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05  8:51 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> This is the first commit in a series that splits off the pin-init crate
> from the kernel crate.

I recently learned that using imperative mode in the commit message is
preferred [1]. You might want to consider that for next spin.

>
> The build system cannot handle doctests in the kernel crate in files
> outside of `rust/kernel/`. Since subsequent commits will move files out
> of that directory, but will still compile them as part of the kernel
> crate, ignore all doctests in the to-be-moved files.
>
> The tests will be re-enabled later when the separation into its own
> crate has been completed, since then the doctests of that new crate will
> be handled as normal host doctests.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>


Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg


[1] https://docs.kernel.org/process/submitting-patches.html


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 02/22] rust: move pin-init API into its own directory
  2025-03-04 22:53   ` [PATCH 02/22] rust: move pin-init API into its own directory Benno Lossin
@ 2025-03-05  9:03     ` Andreas Hindborg
  2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05  9:03 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> In preparation of splitting off the pin-init crate from the kernel
> crate, move all pin-init API code (including proc-macros) into
> `rust/pin-init`.
>
> Moved modules have their import path adjusted via the `#[path = "..."]`
> attribute. This allows the files to still be imported in the kernel
> crate even though the files are in different directories.
>
> Code that is moved out of files (but the file itself stays where it is)
> is imported via the `include!` macro. This also allows the code to be
> moved while still being part of the kernel crate.
>
> Note that this commit moves the generics parsing code out of the GPL-2.0
> file `rust/macros/helpers.rs` into the Apache-2.0 OR MIT file
> `rust/pin_init/internal/src/helpers.rs`. I am the sole author of that
> code and it already is available with that license at [1].
> The same is true for the entry-points of the proc-macros `pin_data`,
> `pinned_drop` and `derive_zeroable` in `rust/macros/lib.rs` that are
> moved to `rust/pin_data/internal/src/lib.rs`. Although there are some
> smaller patches that fix the doctests.
>
> Link: https://github.com/Rust-for-Linux/pinned-init [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there
  2025-03-04 22:53   ` [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there Benno Lossin
@ 2025-03-05  9:11     ` Andreas Hindborg
  2025-03-05 11:03       ` Benno Lossin
  2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05  9:11 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> 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 patch **moves** very few lines. The additions to init.rs seem
either copied or new additions.


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
  2025-03-05  8:51     ` Andreas Hindborg
@ 2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:17 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> This is the first commit in a series that splits off the pin-init crate
> from the kernel crate.
>
> The build system cannot handle doctests in the kernel crate in files
> outside of `rust/kernel/`. Since subsequent commits will move files out
> of that directory, but will still compile them as part of the kernel
> crate, ignore all doctests in the to-be-moved files.
>
> The tests will be re-enabled later when the separation into its own
> crate has been completed, since then the doctests of that new crate will
> be handled as normal host doctests.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 02/22] rust: move pin-init API into its own directory
  2025-03-04 22:53   ` [PATCH 02/22] rust: move pin-init API into its own directory Benno Lossin
  2025-03-05  9:03     ` Andreas Hindborg
@ 2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:17 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

Benno Lossin <benno.lossin@proton.me> writes:

> In preparation of splitting off the pin-init crate from the kernel
> crate, move all pin-init API code (including proc-macros) into
> `rust/pin-init`.
>
> Moved modules have their import path adjusted via the `#[path = "..."]`
> attribute. This allows the files to still be imported in the kernel
> crate even though the files are in different directories.
>
> Code that is moved out of files (but the file itself stays where it is)
> is imported via the `include!` macro. This also allows the code to be
> moved while still being part of the kernel crate.
>
> Note that this commit moves the generics parsing code out of the GPL-2.0
> file `rust/macros/helpers.rs` into the Apache-2.0 OR MIT file
> `rust/pin_init/internal/src/helpers.rs`. I am the sole author of that
> code and it already is available with that license at [1].
> The same is true for the entry-points of the proc-macros `pin_data`,
> `pinned_drop` and `derive_zeroable` in `rust/macros/lib.rs` that are
> moved to `rust/pin_data/internal/src/lib.rs`. Although there are some
> smaller patches that fix the doctests.
>
> Link: https://github.com/Rust-for-Linux/pinned-init [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there
  2025-03-04 22:53   ` [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there Benno Lossin
  2025-03-05  9:11     ` Andreas Hindborg
@ 2025-03-05  9:17     ` Fiona Behrens
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:17 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

Benno Lossin <benno.lossin@proton.me> writes:

> 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@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate
  2025-03-04 22:53   ` [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate Benno Lossin
@ 2025-03-05  9:18     ` Fiona Behrens
  2025-03-05  9:34     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:18 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> Move the documentation of proc-macros from pin-init-internal into
> pin-init. This is because documentation can only reference types from
> dependencies and pin-init-internal cannot have pin-init as a dependency,
> as that would be cyclic.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 05/22] rust: pin-init: change examples to the user-space version
  2025-03-04 22:53   ` [PATCH 05/22] rust: pin-init: change examples to the user-space version Benno Lossin
@ 2025-03-05  9:19     ` Fiona Behrens
  2025-03-05 10:06     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:19 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

Benno Lossin <benno.lossin@proton.me> writes:

> Replace the examples in the documentation by the ones from the
> user-space version and introduce the standalone examples from the
> user-space version such as the `CMutex<T>` type.
>
> The `CMutex<T>` example from the pinned-init repository [1] is used in
> several documentation examples in the user-space version instead of the
> kernel `Mutex<T>` type (as it's not available). In order to split off
> the pin-init crate, all examples need to be free of kernel-specific
> types.
>
> Link: https://github.com/rust-for-Linux/pinned-init [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!`
  2025-03-04 22:53   ` [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!` Benno Lossin
@ 2025-03-05  9:19     ` Fiona Behrens
  2025-03-05 10:12     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:19 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> The `[pin_]init!` macros have the same behavior as the `try_[pin_]init!`
> macros, except that they set the error type to `Infallible`.
> Instead of calling the primitive `__init_internal!` with the correct
> parameters, the same can thus be achieved by calling `try_[pin_]init!`.
> Since this makes it more clear what their behavior is, simplify the
> implementations of `[pin_]init!`.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init`
  2025-03-04 22:54   ` [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init` Benno Lossin
@ 2025-03-05  9:21     ` Fiona Behrens
  2025-03-05 10:29     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:21 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> Move the ability to just write `try_pin_init!(Foo { a <- a_init })`
> (note the missing `? Error` at the end) into the kernel crate.
> Remove this notation from the pin-init crate, since the default when no
> error is specified is the kernel-internal `Error` type. Instead add two
> macros in the kernel crate that serve this default and are used instead
> of the ones from `pin-init`.
>
> This is done, because the `Error` type that is used as the default is
> from the kernel crate and it thus prevents making the pin-init crate
> standalone.
>
> In order to not cause a build error due to a name overlap, the macros in
> the pin-init crate are renamed, but this change is reverted in a future
> commit when it is a standalone crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-04 22:54   ` [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate Benno Lossin
@ 2025-03-05  9:23     ` Fiona Behrens
  2025-03-05 11:18     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:23 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, move kernel-specific code
> directly into the kernel crate. This includes the `InPlaceInit<T>`
> trait, its implementations and the implementations of `InPlaceWrite` for
> `Arc` and `UniqueArc`. All of these use the kernel's error type which
> will become unavailable in pin-init.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-04 22:54   ` [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` " Benno Lossin
@ 2025-03-05  9:24     ` Fiona Behrens
  2025-03-05 11:26     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:24 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, move kernel-specific code
> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
> of the kernel, move their `Zeroable` implementation into the kernel
> crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>`
  2025-03-04 22:54   ` [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>` Benno Lossin
@ 2025-03-05  9:25     ` Fiona Behrens
  2025-03-05 11:30     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:25 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> When making pin-init its own crate, `Zeroable` will no longer be defined
> by the kernel crate and thus implementing it for `Option<Box<T, A>>` is
> no longer possible due to the orphan rule.
> For this reason introduce a new `ZeroableOption` trait that circumvents
> this problem.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

> ---
>  rust/kernel/alloc/kbox.rs |  4 ++--
>  rust/pin-init/src/lib.rs  | 11 +++++++++++
>  2 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> index 9861433559dc..07150c038e3f 100644
> --- a/rust/kernel/alloc/kbox.rs
> +++ b/rust/kernel/alloc/kbox.rs
> @@ -15,7 +15,7 @@
>  use core::ptr::NonNull;
>  use core::result::Result;
>  
> -use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
> +use crate::init::{InPlaceWrite, Init, PinInit, ZeroableOption};
>  use crate::init_ext::InPlaceInit;
>  use crate::types::ForeignOwnable;
>  
> @@ -104,7 +104,7 @@
>  //
>  // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
>  // is no problem with a VTABLE pointer being null.
> -unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
> +unsafe impl<T: ?Sized, A: Allocator> ZeroableOption for Box<T, A> {}
>  
>  // SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`.
>  unsafe impl<T, A> Send for Box<T, A>
> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
> index 5fd8fa7c2ce9..fd2c4fdd0ca4 100644
> --- a/rust/pin-init/src/lib.rs
> +++ b/rust/pin-init/src/lib.rs
> @@ -1297,6 +1297,17 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
>  /// ```
>  pub unsafe trait Zeroable {}
>  
> +/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
> +/// `None` to that location.
> +///
> +/// # Safety
> +///
> +/// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.

is sound does sound a bit vague, but also don't have ideas.

Thanks
Fiona

> +pub unsafe trait ZeroableOption {}
> +
> +// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
> +unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
> +
>  /// Create a new zeroed T.
>  ///
>  /// The returned initializer will write `0x00` to every byte of the given `slot`.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 11/22] rust: pin-init: fix documentation links
  2025-03-04 22:54   ` [PATCH 11/22] rust: pin-init: fix documentation links Benno Lossin
@ 2025-03-05  9:26     ` Fiona Behrens
  2025-03-05 11:37     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:26 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> Before switching to compile the `pin-init` crate directly, change
> any links that would be invalid to links that are valid both before and
> after the switch.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 12/22] rust: pin-init: remove kernel-crate dependency
  2025-03-04 22:54   ` [PATCH 12/22] rust: pin-init: remove kernel-crate dependency Benno Lossin
@ 2025-03-05  9:27     ` Fiona Behrens
  2025-03-05 11:49     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:27 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, remove dependencies on
> kernel-specific code such as `ScopeGuard` and `KBox`.
>
> `ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
> and can easily be replaced by a primitive construct.
>
> `KBox` is only used for type variance of unsized types and can also
> easily be replaced.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called
  2025-03-04 22:55   ` [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called Benno Lossin
@ 2025-03-05  9:28     ` Fiona Behrens
  2025-03-05 11:52     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:28 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> Change the paste macro path from `::kernel::macros::paste!` to use
> `$crate::init::macros::paste!` instead, which links to
> `::macros::paste!`. This is because the pin-init crate will be a
> dependency of the kernel, so it itself cannot have the kernel as a
> dependency.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 15/22] rust: make pin-init its own crate
  2025-03-04 22:55   ` [PATCH 15/22] rust: make pin-init its own crate Benno Lossin
@ 2025-03-05  9:29     ` Fiona Behrens
  2025-03-05 12:12     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:29 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Greg Kroah-Hartman, Rafael J. Wysocki,
	Peter Zijlstra, Ingo Molnar, Will Deacon, Waiman Long,
	linux-kernel, rust-for-linux, linux-block

Benno Lossin <benno.lossin@proton.me> writes:

> Rename relative paths inside of the crate to still refer to the same
> items, also rename paths inside of the kernel crate and adjust the build
> system to build the crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-04 22:55   ` [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version Benno Lossin
@ 2025-03-05  9:32     ` Fiona Behrens
  2025-03-05 12:22     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:32 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

Benno Lossin <benno.lossin@proton.me> writes:

> To synchronize the kernel's version of pin-init with the user-space
> version, introduce support for `std` and `alloc`. While the kernel uses
> neither, the user-space version has to support both. Thus include the
> required `#[cfg]`s and additional code.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 17/22] rust: pin-init: synchronize documentation with the user-space version
  2025-03-04 22:55   ` [PATCH 17/22] rust: pin-init: synchronize documentation with " Benno Lossin
@ 2025-03-05  9:33     ` Fiona Behrens
  2025-03-05 12:52     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:33 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> Synchronize documentation and examples with the user-space version.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate
  2025-03-04 22:53   ` [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate Benno Lossin
  2025-03-05  9:18     ` Fiona Behrens
@ 2025-03-05  9:34     ` Andreas Hindborg
  2025-03-05 11:05       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05  9:34 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Move the documentation of proc-macros from pin-init-internal into
> pin-init. This is because documentation can only reference types from
> dependencies and pin-init-internal cannot have pin-init as a dependency,
> as that would be cyclic.

`pin_data` et. al. is now re-exported both in `kernel::prelude` and
`kernel::init`, but I guess that is fine?

When you say "can only reference types", do you mean via links in the text?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 20/22] rust: pin-init: add miscellaneous files from the user-space version
  2025-03-04 22:56   ` [PATCH 20/22] rust: pin-init: add miscellaneous files from " Benno Lossin
@ 2025-03-05  9:35     ` Fiona Behrens
  2025-03-05 13:04     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:35 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, linux-kernel, rust-for-linux

Benno Lossin <benno.lossin@proton.me> writes:

> Add readme and contribution guidelines of the user-space version of
> pin-init.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 21/22] rust: pin-init: re-enable doctests
  2025-03-04 22:56   ` [PATCH 21/22] rust: pin-init: re-enable doctests Benno Lossin
@ 2025-03-05  9:35     ` Fiona Behrens
  2025-03-05 13:05     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Fiona Behrens @ 2025-03-05  9:35 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

Benno Lossin <benno.lossin@proton.me> writes:

> The pin-init crate is now compiled in a standalone fashion, so revert
> the earlier commit that disabled the doctests in pin-init in order to
> avoid build errors while transitioning the crate into a standalone
> version.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 05/22] rust: pin-init: change examples to the user-space version
  2025-03-04 22:53   ` [PATCH 05/22] rust: pin-init: change examples to the user-space version Benno Lossin
  2025-03-05  9:19     ` Fiona Behrens
@ 2025-03-05 10:06     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 10:06 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> Replace the examples in the documentation by the ones from the
> user-space version and introduce the standalone examples from the
> user-space version such as the `CMutex<T>` type.
>
> The `CMutex<T>` example from the pinned-init repository [1] is used in
> several documentation examples in the user-space version instead of the
> kernel `Mutex<T>` type (as it's not available). In order to split off
> the pin-init crate, all examples need to be free of kernel-specific
> types.
>
> Link: https://github.com/rust-for-Linux/pinned-init [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/pin-init/examples/big_struct_in_place.rs |  39 ++
>  rust/pin-init/examples/error.rs               |  27 ++
>  rust/pin-init/examples/linked_list.rs         | 161 ++++++++
>  rust/pin-init/examples/mutex.rs               | 209 ++++++++++
>  rust/pin-init/examples/pthread_mutex.rs       | 178 +++++++++
>  rust/pin-init/examples/static_init.rs         | 122 ++++++

Do I need to review all these data structures and algorithms?

[...]

> @@ -76,28 +84,34 @@
>  //! above method only works for types where you can access the fields.
>  //!
>  //! ```rust,ignore
> -//! # use kernel::sync::{new_mutex, Arc, Mutex};
> -//! let mtx: Result<Arc<Mutex<usize>>> =
> -//!     Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);
> +//! # #![feature(allocator_api)]
> +//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
> +//! # use pin_init::*;
> +//! # use std::sync::Arc;
> +//! # use core::pin::Pin;
> +//! let mtx: Result<Pin<Arc<Mutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
>  //! ```

Should this be `CMutex<_>` on the lhs?


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!`
  2025-03-04 22:53   ` [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!` Benno Lossin
  2025-03-05  9:19     ` Fiona Behrens
@ 2025-03-05 10:12     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 10:12 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> The `[pin_]init!` macros have the same behavior as the `try_[pin_]init!`
> macros, except that they set the error type to `Infallible`.
> Instead of calling the primitive `__init_internal!` with the correct
> parameters, the same can thus be achieved by calling `try_[pin_]init!`.
> Since this makes it more clear what their behavior is, simplify the
> implementations of `[pin_]init!`.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init`
  2025-03-04 22:54   ` [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init` Benno Lossin
  2025-03-05  9:21     ` Fiona Behrens
@ 2025-03-05 10:29     ` Andreas Hindborg
  2025-03-05 10:47       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 10:29 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Move the ability to just write `try_pin_init!(Foo { a <- a_init })`
> (note the missing `? Error` at the end) into the kernel crate.
> Remove this notation from the pin-init crate, since the default when no
> error is specified is the kernel-internal `Error` type. Instead add two
> macros in the kernel crate that serve this default and are used instead
> of the ones from `pin-init`.
>
> This is done, because the `Error` type that is used as the default is
> from the kernel crate and it thus prevents making the pin-init crate
> standalone.
>
> In order to not cause a build error due to a name overlap, the macros in
> the pin-init crate are renamed, but this change is reverted in a future
> commit when it is a standalone crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

[...]

> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
> index dde2e0649790..4123d478c351 100644
> --- a/rust/kernel/prelude.rs
> +++ b/rust/kernel/prelude.rs
> @@ -28,7 +28,8 @@
>  pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
>  pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
>
> -pub use super::{init, pin_init, try_init, try_pin_init};
> +pub use super::{init, pin_init};
> +pub use super::{try_init, try_pin_init};

Are you trying out a new scheme here - a balance between normalized and
line-by-line use declarations? 😆


Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init`
  2025-03-05 10:29     ` Andreas Hindborg
@ 2025-03-05 10:47       ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 10:47 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 11:29 AM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> Move the ability to just write `try_pin_init!(Foo { a <- a_init })`
>> (note the missing `? Error` at the end) into the kernel crate.
>> Remove this notation from the pin-init crate, since the default when no
>> error is specified is the kernel-internal `Error` type. Instead add two
>> macros in the kernel crate that serve this default and are used instead
>> of the ones from `pin-init`.
>>
>> This is done, because the `Error` type that is used as the default is
>> from the kernel crate and it thus prevents making the pin-init crate
>> standalone.
>>
>> In order to not cause a build error due to a name overlap, the macros in
>> the pin-init crate are renamed, but this change is reverted in a future
>> commit when it is a standalone crate.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>
> [...]
>
>> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
>> index dde2e0649790..4123d478c351 100644
>> --- a/rust/kernel/prelude.rs
>> +++ b/rust/kernel/prelude.rs
>> @@ -28,7 +28,8 @@
>>  pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
>>  pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
>>
>> -pub use super::{init, pin_init, try_init, try_pin_init};
>> +pub use super::{init, pin_init};
>> +pub use super::{try_init, try_pin_init};
>
> Are you trying out a new scheme here - a balance between normalized and
> line-by-line use declarations? 😆

Uh no, not intentionally at least. This is an artifact of moving the
changes between the different patches, the "rust: make pin-init its own
crate" commit removes the line with `init` and `pin_init`, but keeps the
one with the `try_` versions. That is because those two will continue to
live in the `kernel` crate.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there
  2025-03-05  9:11     ` Andreas Hindborg
@ 2025-03-05 11:03       ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 11:03 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

On Wed Mar 5, 2025 at 10:11 AM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> 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 patch **moves** very few lines. The additions to init.rs seem
> either copied or new additions.

Yes git's `--color-moved` only shows a few moved lines, but all
documentation lines that are removed from `rust/pin-init/src/lib.rs` are
added into `init.rs`. The example is "new", as it is copied from the
user-space version [1]. I can update the commit message with more
information. 

[1]: https://github.com/Rust-for-Linux/pin-init/blob/main/src/lib.rs#L160

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate
  2025-03-05  9:34     ` Andreas Hindborg
@ 2025-03-05 11:05       ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 11:05 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 10:34 AM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> Move the documentation of proc-macros from pin-init-internal into
>> pin-init. This is because documentation can only reference types from
>> dependencies and pin-init-internal cannot have pin-init as a dependency,
>> as that would be cyclic.
>
> `pin_data` et. al. is now re-exported both in `kernel::prelude` and
> `kernel::init`, but I guess that is fine?

Yes, that is fine, later the imports will be resolved such that the
prelude re-exports the macros from the pin-init crate (so the docs
should also be rendered there).

> When you say "can only reference types", do you mean via links in the text?

Yes, I mean the doc-links, e.g. [`Zeroable`].

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-04 22:54   ` [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate Benno Lossin
  2025-03-05  9:23     ` Fiona Behrens
@ 2025-03-05 11:18     ` Andreas Hindborg
  2025-03-05 12:06       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:18 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, move kernel-specific code
> directly into the kernel crate. This includes the `InPlaceInit<T>`
> trait, its implementations and the implementations of `InPlaceWrite` for
> `Arc` and `UniqueArc`. All of these use the kernel's error type which
> will become unavailable in pin-init.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/kernel/alloc/kbox.rs |   3 +-
>  rust/kernel/init.rs       |  55 +++++++++++++++++
>  rust/kernel/prelude.rs    |   3 +-
>  rust/kernel/sync/arc.rs   |  65 +++++++++++++++++++-
>  rust/pin-init/src/lib.rs  | 125 ++------------------------------------
>  5 files changed, 127 insertions(+), 124 deletions(-)
>

[...]

> --- a/rust/pin-init/src/lib.rs
> +++ b/rust/pin-init/src/lib.rs
> @@ -10,7 +10,7 @@
>  //! To initialize a `struct` with an in-place constructor you will need two things:
>  //! - an in-place constructor,
>  //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
> -//!   [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
> +//!   [`KBox<T>`] or any other smart pointer that supports this library).

Would you not want to remove references to `KBox` here as well? Even
though you don't have to move the impl, I don't imagine `KBox` exist in
user space?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-04 22:54   ` [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` " Benno Lossin
  2025-03-05  9:24     ` Fiona Behrens
@ 2025-03-05 11:26     ` Andreas Hindborg
  2025-03-05 12:05       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:26 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, move kernel-specific code
> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
> of the kernel, move their `Zeroable` implementation into the kernel
> crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/kernel/alloc/kbox.rs | 8 +++++++-
>  rust/kernel/types.rs      | 5 ++++-
>  rust/pin-init/src/lib.rs  | 8 +-------
>  3 files changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> index 39a3ea7542da..9861433559dc 100644
> --- a/rust/kernel/alloc/kbox.rs
> +++ b/rust/kernel/alloc/kbox.rs
> @@ -15,7 +15,7 @@
>  use core::ptr::NonNull;
>  use core::result::Result;
>
> -use crate::init::{InPlaceWrite, Init, PinInit};
> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
>  use crate::init_ext::InPlaceInit;
>  use crate::types::ForeignOwnable;
>
> @@ -100,6 +100,12 @@
>  /// ```
>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
>
> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
> +//
> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
> +// is no problem with a VTABLE pointer being null.
> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}

Could you elaborate the statement related to vtable pointers? How does
that come into play for `Option<Box<_>>`? Is it for fat pointers to
trait objects?

Otherwise LGTM.


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>`
  2025-03-04 22:54   ` [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>` Benno Lossin
  2025-03-05  9:25     ` Fiona Behrens
@ 2025-03-05 11:30     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:30 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> When making pin-init its own crate, `Zeroable` will no longer be defined
> by the kernel crate and thus implementing it for `Option<Box<T, A>>` is
> no longer possible due to the orphan rule.
> For this reason introduce a new `ZeroableOption` trait that circumvents
> this problem.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 11/22] rust: pin-init: fix documentation links
  2025-03-04 22:54   ` [PATCH 11/22] rust: pin-init: fix documentation links Benno Lossin
  2025-03-05  9:26     ` Fiona Behrens
@ 2025-03-05 11:37     ` Andreas Hindborg
  2025-03-05 11:49       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:37 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Before switching to compile the `pin-init` crate directly, change
> any links that would be invalid to links that are valid both before and
> after the switch.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/kernel/sync/condvar.rs     |  2 +-
>  rust/pin-init/src/__internal.rs |  4 ++--
>  rust/pin-init/src/lib.rs        | 19 +++++++++++--------
>  3 files changed, 14 insertions(+), 11 deletions(-)
>
> diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
> index 7df565038d7d..5aa7fa7c7002 100644
> --- a/rust/kernel/sync/condvar.rs
> +++ b/rust/kernel/sync/condvar.rs

[...]

> @@ -204,7 +204,8 @@
>  //! [structurally pinned fields]:
>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>  //! [stack]: crate::stack_pin_init
> -//! [`Arc<T>`]: crate::sync::Arc
> +//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
> +//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>  //! [`impl PinInit<Foo>`]: PinInit
>  //! [`impl PinInit<T, E>`]: PinInit
>  //! [`impl Init<T, E>`]: Init

Won't this diff from the user space implementation?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 11/22] rust: pin-init: fix documentation links
  2025-03-05 11:37     ` Andreas Hindborg
@ 2025-03-05 11:49       ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 11:49 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 12:37 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> Before switching to compile the `pin-init` crate directly, change
>> any links that would be invalid to links that are valid both before and
>> after the switch.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  rust/kernel/sync/condvar.rs     |  2 +-
>>  rust/pin-init/src/__internal.rs |  4 ++--
>>  rust/pin-init/src/lib.rs        | 19 +++++++++++--------
>>  3 files changed, 14 insertions(+), 11 deletions(-)
>>
>> diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
>> index 7df565038d7d..5aa7fa7c7002 100644
>> --- a/rust/kernel/sync/condvar.rs
>> +++ b/rust/kernel/sync/condvar.rs
>
> [...]
>
>> @@ -204,7 +204,8 @@
>>  //! [structurally pinned fields]:
>>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>>  //! [stack]: crate::stack_pin_init
>> -//! [`Arc<T>`]: crate::sync::Arc
>> +//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
>> +//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>>  //! [`impl PinInit<Foo>`]: PinInit
>>  //! [`impl PinInit<T, E>`]: PinInit
>>  //! [`impl Init<T, E>`]: Init
>
> Won't this diff from the user space implementation?

It's only an intermediate state, it will be changed again in "rust:
pin-init: add `std` and `alloc` support from the user-space version".

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 12/22] rust: pin-init: remove kernel-crate dependency
  2025-03-04 22:54   ` [PATCH 12/22] rust: pin-init: remove kernel-crate dependency Benno Lossin
  2025-03-05  9:27     ` Fiona Behrens
@ 2025-03-05 11:49     ` Andreas Hindborg
  2025-03-05 12:00       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:49 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> In order to make pin-init a standalone crate, remove dependencies on
> kernel-specific code such as `ScopeGuard` and `KBox`.
>
> `ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
> and can easily be replaced by a primitive construct.
>
> `KBox` is only used for type variance of unsized types and can also
> easily be replaced.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>

> ---
>  rust/pin-init/src/__internal.rs |  2 +-
>  rust/pin-init/src/lib.rs        | 41 +++++++++++----------------------
>  2 files changed, 15 insertions(+), 28 deletions(-)
>
> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
> index 0db800819681..74086365a18a 100644
> --- a/rust/pin-init/src/__internal.rs
> +++ b/rust/pin-init/src/__internal.rs
> @@ -105,7 +105,7 @@ fn make_closure<F, O, E>(self, f: F) -> F
>      }
>  }
>
> -pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>);
> +pub struct AllData<T: ?Sized>(Invariant<T>);

Off topic, trying to learn something: You define `Invariant<T>` like so:

  pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;

Consulting the variance table at [1], could you define it as

  pub(super) type Invariant<T> = PhantomData<*mut T>;

or is there another reason for using `fn`?


Best regards,
Andreas Hindborg


[1] https://doc.rust-lang.org/nomicon/subtyping.html#variance



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called
  2025-03-04 22:55   ` [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called Benno Lossin
  2025-03-05  9:28     ` Fiona Behrens
@ 2025-03-05 11:52     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:52 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Change the paste macro path from `::kernel::macros::paste!` to use
> `$crate::init::macros::paste!` instead, which links to
> `::macros::paste!`. This is because the pin-init crate will be a
> dependency of the kernel, so it itself cannot have the kernel as a
> dependency.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-04 22:55   ` [PATCH 14/22] rust: add pin-init crate build infrastructure Benno Lossin
@ 2025-03-05 11:59     ` Andreas Hindborg
  2025-03-05 12:10       ` Benno Lossin
  2025-03-05 12:47       ` Miguel Ojeda
  0 siblings, 2 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 11:59 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

"Benno Lossin" <benno.lossin@proton.me> writes:

> From: Miguel Ojeda <ojeda@kernel.org>
>
> Add infrastructure for moving the initialization API to its own crate.
> Covers all make targets such as `rust-analyzer` and `rustdoc`. The tests
> of pin-init are not added to `rusttest`, as they are already tested in
> the user-space repository [1].

If it's not too much hassle, why not add them in the kernel as well? I
would rather not have to go fetch the user space repo from github, in
the event that I ever need to patch pin-init.


>
> Link: https://github.com/Rust-for-Linux/pin-init [1]
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> Co-developed-by: Benno Lossin <benno.lossin@proton.me>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/Makefile                      | 75 +++++++++++++++++++++++-------
>  rust/pin-init/internal/src/_lib.rs |  3 ++
>  rust/pin-init/internal/src/lib.rs  |  4 ++
>  rust/pin-init/src/_lib.rs          |  5 ++
>  scripts/Makefile.build             |  2 +-
>  scripts/generate_rust_analyzer.py  | 17 ++++++-
>  6 files changed, 86 insertions(+), 20 deletions(-)
>  create mode 100644 rust/pin-init/internal/src/_lib.rs
>  create mode 100644 rust/pin-init/src/_lib.rs
>
> diff --git a/rust/Makefile b/rust/Makefile
> index ea3849eb78f6..90310f0620eb 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile

[...]

> @@ -110,11 +113,24 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
>  rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
>  	+$(call if_changed,rustdoc)
>
> -rustdoc-kernel: private rustc_target_flags = --extern ffi \
> +rustdoc-pin_init_internal: private rustdoc_host = yes
> +rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \
> +    --extern proc_macro --crate-type proc-macro
> +rustdoc-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
> +	+$(call if_changed,rustdoc)
> +
> +rustdoc-pin_init: private rustdoc_host = yes
> +rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \
> +    --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\"
> +rustdoc-pin_init: $(src)/pin-init/src/_lib.rs rustdoc-pin_init_internal \
> +    rustdoc-macros FORCE
> +	+$(call if_changed,rustdoc)

Is it possible to do some code sharing here, such that when we add a
crate, it's just a matter of putting the path/name on a list somewhere?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 12/22] rust: pin-init: remove kernel-crate dependency
  2025-03-05 11:49     ` Andreas Hindborg
@ 2025-03-05 12:00       ` Benno Lossin
  2025-03-05 12:27         ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:00 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 12:49 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> In order to make pin-init a standalone crate, remove dependencies on
>> kernel-specific code such as `ScopeGuard` and `KBox`.
>>
>> `ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
>> and can easily be replaced by a primitive construct.
>>
>> `KBox` is only used for type variance of unsized types and can also
>> easily be replaced.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>
> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
>
>> ---
>>  rust/pin-init/src/__internal.rs |  2 +-
>>  rust/pin-init/src/lib.rs        | 41 +++++++++++----------------------
>>  2 files changed, 15 insertions(+), 28 deletions(-)
>>
>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>> index 0db800819681..74086365a18a 100644
>> --- a/rust/pin-init/src/__internal.rs
>> +++ b/rust/pin-init/src/__internal.rs
>> @@ -105,7 +105,7 @@ fn make_closure<F, O, E>(self, f: F) -> F
>>      }
>>  }
>>
>> -pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>);
>> +pub struct AllData<T: ?Sized>(Invariant<T>);
>
> Off topic, trying to learn something: You define `Invariant<T>` like so:
>
>   pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
>
> Consulting the variance table at [1], could you define it as
>
>   pub(super) type Invariant<T> = PhantomData<*mut T>;
>
> or is there another reason for using `fn`?

Yes! There is another reason: `Send` and `Sync`, my `Invariant` type
will always be `Send` and `Sync`, but `PhantomData<*mut T>` is always
`!Send` and `!Sync`.
One could argue that an `Invariant<T>` type should impl `Send`/`Sync`
if and only if `T` does, but for my usage it doesn't matter. If you do
need to use that, you could use `PhantomData<(fn(*mut T) -> *mut T, T)>`

---
Cheers,
Benno

>
>
> Best regards,
> Andreas Hindborg
>
>
> [1] https://doc.rust-lang.org/nomicon/subtyping.html#variance


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-05 11:26     ` Andreas Hindborg
@ 2025-03-05 12:05       ` Benno Lossin
  2025-03-05 12:11         ` Alice Ryhl
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:05 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

On Wed Mar 5, 2025 at 12:26 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> In order to make pin-init a standalone crate, move kernel-specific code
>> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
>> of the kernel, move their `Zeroable` implementation into the kernel
>> crate.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  rust/kernel/alloc/kbox.rs | 8 +++++++-
>>  rust/kernel/types.rs      | 5 ++++-
>>  rust/pin-init/src/lib.rs  | 8 +-------
>>  3 files changed, 12 insertions(+), 9 deletions(-)
>>
>> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
>> index 39a3ea7542da..9861433559dc 100644
>> --- a/rust/kernel/alloc/kbox.rs
>> +++ b/rust/kernel/alloc/kbox.rs
>> @@ -15,7 +15,7 @@
>>  use core::ptr::NonNull;
>>  use core::result::Result;
>>
>> -use crate::init::{InPlaceWrite, Init, PinInit};
>> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
>>  use crate::init_ext::InPlaceInit;
>>  use crate::types::ForeignOwnable;
>>
>> @@ -100,6 +100,12 @@
>>  /// ```
>>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
>>
>> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
>> +//
>> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
>> +// is no problem with a VTABLE pointer being null.
>> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
>
> Could you elaborate the statement related to vtable pointers? How does
> that come into play for `Option<Box<_>>`? Is it for fat pointers to
> trait objects?

Yes it is for fat pointers, if you have a `x: *mut dyn Trait`, then you
aren't allowed to write all zeroes to `x`, because the VTABLE pointer
(that is part of the fat pointer) is not allowed to be null.

Now for `Option<Box<_>>`, this doesn't matter, as there if the normal
pointer part of the fat pointer is all zeroes, then the VTABLE pointer
part is considered padding bytes, as it's the `None` variant.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-05 11:18     ` Andreas Hindborg
@ 2025-03-05 12:06       ` Benno Lossin
  2025-03-05 12:28         ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:06 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

On Wed Mar 5, 2025 at 12:18 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> In order to make pin-init a standalone crate, move kernel-specific code
>> directly into the kernel crate. This includes the `InPlaceInit<T>`
>> trait, its implementations and the implementations of `InPlaceWrite` for
>> `Arc` and `UniqueArc`. All of these use the kernel's error type which
>> will become unavailable in pin-init.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  rust/kernel/alloc/kbox.rs |   3 +-
>>  rust/kernel/init.rs       |  55 +++++++++++++++++
>>  rust/kernel/prelude.rs    |   3 +-
>>  rust/kernel/sync/arc.rs   |  65 +++++++++++++++++++-
>>  rust/pin-init/src/lib.rs  | 125 ++------------------------------------
>>  5 files changed, 127 insertions(+), 124 deletions(-)
>>
>
> [...]
>
>> --- a/rust/pin-init/src/lib.rs
>> +++ b/rust/pin-init/src/lib.rs
>> @@ -10,7 +10,7 @@
>>  //! To initialize a `struct` with an in-place constructor you will need two things:
>>  //! - an in-place constructor,
>>  //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
>> -//!   [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
>> +//!   [`KBox<T>`] or any other smart pointer that supports this library).
>
> Would you not want to remove references to `KBox` here as well? Even
> though you don't have to move the impl, I don't imagine `KBox` exist in
> user space?

Yes, this is done in "rust: pin-init: fix documentation links".

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 11:59     ` Andreas Hindborg
@ 2025-03-05 12:10       ` Benno Lossin
  2025-03-05 12:31         ` Andreas Hindborg
  2025-03-05 12:47       ` Miguel Ojeda
  1 sibling, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:10 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

On Wed Mar 5, 2025 at 12:59 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> From: Miguel Ojeda <ojeda@kernel.org>
>>
>> Add infrastructure for moving the initialization API to its own crate.
>> Covers all make targets such as `rust-analyzer` and `rustdoc`. The tests
>> of pin-init are not added to `rusttest`, as they are already tested in
>> the user-space repository [1].
>
> If it's not too much hassle, why not add them in the kernel as well? I
> would rather not have to go fetch the user space repo from github, in
> the event that I ever need to patch pin-init.

I tried to add them, but encountered a lot of problems. Maybe the new
build system can help with that. But if you insist, I can try to get
them to work again in a different series now.

The tests run every day in the GitHub CI and any changes that go through
the pin-init-next tree will also be tested there before I submit any
PRs.

>> Link: https://github.com/Rust-for-Linux/pin-init [1]
>> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
>> Co-developed-by: Benno Lossin <benno.lossin@proton.me>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  rust/Makefile                      | 75 +++++++++++++++++++++++-------
>>  rust/pin-init/internal/src/_lib.rs |  3 ++
>>  rust/pin-init/internal/src/lib.rs  |  4 ++
>>  rust/pin-init/src/_lib.rs          |  5 ++
>>  scripts/Makefile.build             |  2 +-
>>  scripts/generate_rust_analyzer.py  | 17 ++++++-
>>  6 files changed, 86 insertions(+), 20 deletions(-)
>>  create mode 100644 rust/pin-init/internal/src/_lib.rs
>>  create mode 100644 rust/pin-init/src/_lib.rs
>>
>> diff --git a/rust/Makefile b/rust/Makefile
>> index ea3849eb78f6..90310f0620eb 100644
>> --- a/rust/Makefile
>> +++ b/rust/Makefile
>
> [...]
>
>> @@ -110,11 +113,24 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
>>  rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
>>  	+$(call if_changed,rustdoc)
>>
>> -rustdoc-kernel: private rustc_target_flags = --extern ffi \
>> +rustdoc-pin_init_internal: private rustdoc_host = yes
>> +rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \
>> +    --extern proc_macro --crate-type proc-macro
>> +rustdoc-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
>> +	+$(call if_changed,rustdoc)
>> +
>> +rustdoc-pin_init: private rustdoc_host = yes
>> +rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \
>> +    --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\"
>> +rustdoc-pin_init: $(src)/pin-init/src/_lib.rs rustdoc-pin_init_internal \
>> +    rustdoc-macros FORCE
>> +	+$(call if_changed,rustdoc)
>
> Is it possible to do some code sharing here, such that when we add a
> crate, it's just a matter of putting the path/name on a list somewhere?

Miguel informed me that this Makefile won't exist in the new build
system, so I'd rather not do that.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-05 12:05       ` Benno Lossin
@ 2025-03-05 12:11         ` Alice Ryhl
  2025-03-05 12:17           ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Alice Ryhl @ 2025-03-05 12:11 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Andreas Hindborg, Danilo Krummrich, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Trevor Gross,
	rust-for-linux, linux-kernel

On Wed, Mar 5, 2025 at 1:05 PM Benno Lossin <benno.lossin@proton.me> wrote:
>
> On Wed Mar 5, 2025 at 12:26 PM CET, Andreas Hindborg wrote:
> > "Benno Lossin" <benno.lossin@proton.me> writes:
> >
> >> In order to make pin-init a standalone crate, move kernel-specific code
> >> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
> >> of the kernel, move their `Zeroable` implementation into the kernel
> >> crate.
> >>
> >> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> >> ---
> >>  rust/kernel/alloc/kbox.rs | 8 +++++++-
> >>  rust/kernel/types.rs      | 5 ++++-
> >>  rust/pin-init/src/lib.rs  | 8 +-------
> >>  3 files changed, 12 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> >> index 39a3ea7542da..9861433559dc 100644
> >> --- a/rust/kernel/alloc/kbox.rs
> >> +++ b/rust/kernel/alloc/kbox.rs
> >> @@ -15,7 +15,7 @@
> >>  use core::ptr::NonNull;
> >>  use core::result::Result;
> >>
> >> -use crate::init::{InPlaceWrite, Init, PinInit};
> >> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
> >>  use crate::init_ext::InPlaceInit;
> >>  use crate::types::ForeignOwnable;
> >>
> >> @@ -100,6 +100,12 @@
> >>  /// ```
> >>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
> >>
> >> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
> >> +//
> >> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
> >> +// is no problem with a VTABLE pointer being null.
> >> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
> >
> > Could you elaborate the statement related to vtable pointers? How does
> > that come into play for `Option<Box<_>>`? Is it for fat pointers to
> > trait objects?
>
> Yes it is for fat pointers, if you have a `x: *mut dyn Trait`, then you
> aren't allowed to write all zeroes to `x`, because the VTABLE pointer
> (that is part of the fat pointer) is not allowed to be null.
>
> Now for `Option<Box<_>>`, this doesn't matter, as there if the normal
> pointer part of the fat pointer is all zeroes, then the VTABLE pointer
> part is considered padding bytes, as it's the `None` variant.

The standard library only guarantees that all zeros is valid for
Option<Box<T,A>> when T:Sized and A=Global.
https://doc.rust-lang.org/stable/std/option/index.html#representation

Alice

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 15/22] rust: make pin-init its own crate
  2025-03-04 22:55   ` [PATCH 15/22] rust: make pin-init its own crate Benno Lossin
  2025-03-05  9:29     ` Fiona Behrens
@ 2025-03-05 12:12     ` Andreas Hindborg
  2025-03-05 13:40       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:12 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Greg Kroah-Hartman, Rafael J. Wysocki, Peter Zijlstra,
	Ingo Molnar, Will Deacon, Waiman Long, linux-kernel,
	rust-for-linux, linux-block

"Benno Lossin" <benno.lossin@proton.me> writes:

> Rename relative paths inside of the crate to still refer to the same
> items, also rename paths inside of the kernel crate and adjust the build
> system to build the crate.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---

[...]

> diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
> index 7ff82c82ce0c..8e116e266524 100644
> --- a/rust/macros/lib.rs
> +++ b/rust/macros/lib.rs
> @@ -2,23 +2,20 @@
>
>  //! Crate for all kernel procedural macros.
>
> +#![feature(lint_reasons)]

Commit message should probably say something about this.

> +
>  // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
>  // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
>  // touched by Kconfig when the version string from the compiler changes.
>
>  #[macro_use]
> +#[expect(unused_macros)]
>  mod quote;
>  mod concat_idents;
>  mod helpers;
>  mod module;
>  mod paste;
> -#[path = "../pin-init/internal/src/pin_data.rs"]
> -mod pin_data;
> -#[path = "../pin-init/internal/src/pinned_drop.rs"]
> -mod pinned_drop;
>  mod vtable;
> -#[path = "../pin-init/internal/src/zeroable.rs"]
> -mod zeroable;
>
>  use proc_macro::TokenStream;
>
> @@ -374,5 +371,3 @@ pub fn paste(input: TokenStream) -> TokenStream {
>      paste::expand(&mut tokens);
>      tokens.into_iter().collect()
>  }
> -
> -include!("../pin-init/internal/src/lib.rs");
> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
> index cdf94f4982df..bdd94c79b0d4 100644
> --- a/rust/macros/module.rs
> +++ b/rust/macros/module.rs
> @@ -236,7 +236,7 @@ impl kernel::ModuleMetadata for {type_} {{
>              mod __module_init {{
>                  mod __module_init {{
>                      use super::super::{type_};
> -                    use kernel::init::PinInit;
> +                    use pin_init::PinInit;
>
>                      /// The \"Rust loadable module\" mark.
>                      //
> diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs
> index 33a199e4f176..11d241b85ac3 100644
> --- a/rust/macros/quote.rs
> +++ b/rust/macros/quote.rs
> @@ -2,6 +2,7 @@
>
>  use proc_macro::{TokenStream, TokenTree};
>
> +#[allow(dead_code)]

#[expect(dead_code)] ?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-05 12:11         ` Alice Ryhl
@ 2025-03-05 12:17           ` Benno Lossin
  2025-03-05 12:49             ` Alice Ryhl
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:17 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Andreas Hindborg, Danilo Krummrich, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Trevor Gross,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 1:11 PM CET, Alice Ryhl wrote:
> On Wed, Mar 5, 2025 at 1:05 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>
>> On Wed Mar 5, 2025 at 12:26 PM CET, Andreas Hindborg wrote:
>> > "Benno Lossin" <benno.lossin@proton.me> writes:
>> >
>> >> In order to make pin-init a standalone crate, move kernel-specific code
>> >> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
>> >> of the kernel, move their `Zeroable` implementation into the kernel
>> >> crate.
>> >>
>> >> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> >> ---
>> >>  rust/kernel/alloc/kbox.rs | 8 +++++++-
>> >>  rust/kernel/types.rs      | 5 ++++-
>> >>  rust/pin-init/src/lib.rs  | 8 +-------
>> >>  3 files changed, 12 insertions(+), 9 deletions(-)
>> >>
>> >> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
>> >> index 39a3ea7542da..9861433559dc 100644
>> >> --- a/rust/kernel/alloc/kbox.rs
>> >> +++ b/rust/kernel/alloc/kbox.rs
>> >> @@ -15,7 +15,7 @@
>> >>  use core::ptr::NonNull;
>> >>  use core::result::Result;
>> >>
>> >> -use crate::init::{InPlaceWrite, Init, PinInit};
>> >> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
>> >>  use crate::init_ext::InPlaceInit;
>> >>  use crate::types::ForeignOwnable;
>> >>
>> >> @@ -100,6 +100,12 @@
>> >>  /// ```
>> >>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
>> >>
>> >> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
>> >> +//
>> >> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
>> >> +// is no problem with a VTABLE pointer being null.
>> >> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
>> >
>> > Could you elaborate the statement related to vtable pointers? How does
>> > that come into play for `Option<Box<_>>`? Is it for fat pointers to
>> > trait objects?
>>
>> Yes it is for fat pointers, if you have a `x: *mut dyn Trait`, then you
>> aren't allowed to write all zeroes to `x`, because the VTABLE pointer
>> (that is part of the fat pointer) is not allowed to be null.
>>
>> Now for `Option<Box<_>>`, this doesn't matter, as there if the normal
>> pointer part of the fat pointer is all zeroes, then the VTABLE pointer
>> part is considered padding bytes, as it's the `None` variant.
>
> The standard library only guarantees that all zeros is valid for
> Option<Box<T,A>> when T:Sized and A=Global.
> https://doc.rust-lang.org/stable/std/option/index.html#representation

Oh! That's a problem then... I'll remove that then (and I can also get
rid of the `ZeroableOption` trait).

We should also backport (& fix it in mainline), I'll submit a patch
shortly.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-04 22:55   ` [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version Benno Lossin
  2025-03-05  9:32     ` Fiona Behrens
@ 2025-03-05 12:22     ` Andreas Hindborg
  2025-03-05 13:55       ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:22 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> To synchronize the kernel's version of pin-init with the user-space
> version, introduce support for `std` and `alloc`. While the kernel uses
> neither, the user-space version has to support both. Thus include the
> required `#[cfg]`s and additional code.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
>  rust/pin-init/src/__internal.rs |  27 ++++++
>  rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
>  rust/pin-init/src/lib.rs        |  17 ++--
>  3 files changed, 196 insertions(+), 6 deletions(-)
>  create mode 100644 rust/pin-init/src/alloc.rs
>
> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
> index 74086365a18a..27d4a8619c04 100644
> --- a/rust/pin-init/src/__internal.rs
> +++ b/rust/pin-init/src/__internal.rs
> @@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
>      }
>  }
>
> +#[test]

I think the kunit support we have in the pipeline will pick this up?

> +fn stack_init_reuse() {
> +    use ::std::{borrow::ToOwned, println, string::String};
> +    use core::pin::pin;
> +
> +    #[derive(Debug)]
> +    struct Foo {
> +        a: usize,
> +        b: String,
> +    }
> +    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
> +        slot.as_mut().init(crate::init!(Foo {
> +            a: 42,
> +            b: "Hello".to_owned(),
> +        }));
> +    let value = value.unwrap();
> +    println!("{value:?}");
> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
> +        slot.as_mut().init(crate::init!(Foo {
> +            a: 24,
> +            b: "world!".to_owned(),
> +        }));
> +    let value = value.unwrap();
> +    println!("{value:?}");
> +}
> +

[...]

> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
> index 55d8953620f0..1fdca35906a0 100644
> --- a/rust/pin-init/src/lib.rs
> +++ b/rust/pin-init/src/lib.rs
> @@ -204,8 +204,8 @@
>  //! [structurally pinned fields]:
>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>  //! [stack]: crate::stack_pin_init
> -//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
> -//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
> +//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
> +//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html

Now these will render incorrect in the kernel docs, right?

>  //! [`impl PinInit<Foo>`]: PinInit
>  //! [`impl PinInit<T, E>`]: PinInit
>  //! [`impl Init<T, E>`]: Init
> @@ -239,6 +239,11 @@
>  #[doc(hidden)]
>  pub mod macros;
>
> +#[cfg(any(feature = "std", feature = "alloc"))]
> +mod alloc;
> +#[cfg(any(feature = "std", feature = "alloc"))]
> +pub use alloc::InPlaceInit;

Do we really need to have this entire file sitting dead in the kernel
tree? If you are not building the user space version from the kernel
sources, I don't think we need it here. Even when you want to sync
between the two repositories, it should be easy to handle an entire file
being not present on one side.


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 12/22] rust: pin-init: remove kernel-crate dependency
  2025-03-05 12:00       ` Benno Lossin
@ 2025-03-05 12:27         ` Andreas Hindborg
  0 siblings, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:27 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 12:49 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> In order to make pin-init a standalone crate, remove dependencies on
>>> kernel-specific code such as `ScopeGuard` and `KBox`.
>>>
>>> `ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
>>> and can easily be replaced by a primitive construct.
>>>
>>> `KBox` is only used for type variance of unsized types and can also
>>> easily be replaced.
>>>
>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>
>> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
>>
>>> ---
>>>  rust/pin-init/src/__internal.rs |  2 +-
>>>  rust/pin-init/src/lib.rs        | 41 +++++++++++----------------------
>>>  2 files changed, 15 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>>> index 0db800819681..74086365a18a 100644
>>> --- a/rust/pin-init/src/__internal.rs
>>> +++ b/rust/pin-init/src/__internal.rs
>>> @@ -105,7 +105,7 @@ fn make_closure<F, O, E>(self, f: F) -> F
>>>      }
>>>  }
>>>
>>> -pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>);
>>> +pub struct AllData<T: ?Sized>(Invariant<T>);
>>
>> Off topic, trying to learn something: You define `Invariant<T>` like so:
>>
>>   pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
>>
>> Consulting the variance table at [1], could you define it as
>>
>>   pub(super) type Invariant<T> = PhantomData<*mut T>;
>>
>> or is there another reason for using `fn`?
>
> Yes! There is another reason: `Send` and `Sync`, my `Invariant` type
> will always be `Send` and `Sync`, but `PhantomData<*mut T>` is always
> `!Send` and `!Sync`.
> One could argue that an `Invariant<T>` type should impl `Send`/`Sync`
> if and only if `T` does, but for my usage it doesn't matter. If you do
> need to use that, you could use `PhantomData<(fn(*mut T) -> *mut T, T)>`

Awesome, thanks for explaining.

Could you add this info to the docstring for `Invariant<T>`?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-05 12:06       ` Benno Lossin
@ 2025-03-05 12:28         ` Andreas Hindborg
  2025-03-05 12:37           ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:28 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 12:18 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> In order to make pin-init a standalone crate, move kernel-specific code
>>> directly into the kernel crate. This includes the `InPlaceInit<T>`
>>> trait, its implementations and the implementations of `InPlaceWrite` for
>>> `Arc` and `UniqueArc`. All of these use the kernel's error type which
>>> will become unavailable in pin-init.
>>>
>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>> ---
>>>  rust/kernel/alloc/kbox.rs |   3 +-
>>>  rust/kernel/init.rs       |  55 +++++++++++++++++
>>>  rust/kernel/prelude.rs    |   3 +-
>>>  rust/kernel/sync/arc.rs   |  65 +++++++++++++++++++-
>>>  rust/pin-init/src/lib.rs  | 125 ++------------------------------------
>>>  5 files changed, 127 insertions(+), 124 deletions(-)
>>>
>>
>> [...]
>>
>>> --- a/rust/pin-init/src/lib.rs
>>> +++ b/rust/pin-init/src/lib.rs
>>> @@ -10,7 +10,7 @@
>>>  //! To initialize a `struct` with an in-place constructor you will need two things:
>>>  //! - an in-place constructor,
>>>  //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
>>> -//!   [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
>>> +//!   [`KBox<T>`] or any other smart pointer that supports this library).
>>
>> Would you not want to remove references to `KBox` here as well? Even
>> though you don't have to move the impl, I don't imagine `KBox` exist in
>> user space?
>
> Yes, this is done in "rust: pin-init: fix documentation links".

Yea, maybe I should have read the entire thing before firing off emails.


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 12:10       ` Benno Lossin
@ 2025-03-05 12:31         ` Andreas Hindborg
  2025-03-05 12:50           ` Miguel Ojeda
  0 siblings, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:31 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 12:59 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> From: Miguel Ojeda <ojeda@kernel.org>
>>>
>>> Add infrastructure for moving the initialization API to its own crate.
>>> Covers all make targets such as `rust-analyzer` and `rustdoc`. The tests
>>> of pin-init are not added to `rusttest`, as they are already tested in
>>> the user-space repository [1].
>>
>> If it's not too much hassle, why not add them in the kernel as well? I
>> would rather not have to go fetch the user space repo from github, in
>> the event that I ever need to patch pin-init.
>
> I tried to add them, but encountered a lot of problems. Maybe the new
> build system can help with that. But if you insist, I can try to get
> them to work again in a different series now.
>
> The tests run every day in the GitHub CI and any changes that go through
> the pin-init-next tree will also be tested there before I submit any
> PRs.

I _really_ think that the ability to run the tests should be present in
the kernel repository. But I also do not want to block this series on it,
if it is something that will be easier to achieve with the build system
overhaul that is in the pipeline.

>
>>> Link: https://github.com/Rust-for-Linux/pin-init [1]
>>> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
>>> Co-developed-by: Benno Lossin <benno.lossin@proton.me>
>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>> ---
>>>  rust/Makefile                      | 75 +++++++++++++++++++++++-------
>>>  rust/pin-init/internal/src/_lib.rs |  3 ++
>>>  rust/pin-init/internal/src/lib.rs  |  4 ++
>>>  rust/pin-init/src/_lib.rs          |  5 ++
>>>  scripts/Makefile.build             |  2 +-
>>>  scripts/generate_rust_analyzer.py  | 17 ++++++-
>>>  6 files changed, 86 insertions(+), 20 deletions(-)
>>>  create mode 100644 rust/pin-init/internal/src/_lib.rs
>>>  create mode 100644 rust/pin-init/src/_lib.rs
>>>
>>> diff --git a/rust/Makefile b/rust/Makefile
>>> index ea3849eb78f6..90310f0620eb 100644
>>> --- a/rust/Makefile
>>> +++ b/rust/Makefile
>>
>> [...]
>>
>>> @@ -110,11 +113,24 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
>>>  rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
>>>  	+$(call if_changed,rustdoc)
>>>
>>> -rustdoc-kernel: private rustc_target_flags = --extern ffi \
>>> +rustdoc-pin_init_internal: private rustdoc_host = yes
>>> +rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \
>>> +    --extern proc_macro --crate-type proc-macro
>>> +rustdoc-pin_init_internal: $(src)/pin-init/internal/src/_lib.rs FORCE
>>> +	+$(call if_changed,rustdoc)
>>> +
>>> +rustdoc-pin_init: private rustdoc_host = yes
>>> +rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \
>>> +    --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\"
>>> +rustdoc-pin_init: $(src)/pin-init/src/_lib.rs rustdoc-pin_init_internal \
>>> +    rustdoc-macros FORCE
>>> +	+$(call if_changed,rustdoc)
>>
>> Is it possible to do some code sharing here, such that when we add a
>> crate, it's just a matter of putting the path/name on a list somewhere?
>
> Miguel informed me that this Makefile won't exist in the new build
> system, so I'd rather not do that.

OK, cool.


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
  2025-03-05 12:28         ` Andreas Hindborg
@ 2025-03-05 12:37           ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:37 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Danilo Krummrich, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, rust-for-linux,
	linux-kernel

On Wed Mar 5, 2025 at 1:28 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> On Wed Mar 5, 2025 at 12:18 PM CET, Andreas Hindborg wrote:
>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>
>>>> In order to make pin-init a standalone crate, move kernel-specific code
>>>> directly into the kernel crate. This includes the `InPlaceInit<T>`
>>>> trait, its implementations and the implementations of `InPlaceWrite` for
>>>> `Arc` and `UniqueArc`. All of these use the kernel's error type which
>>>> will become unavailable in pin-init.
>>>>
>>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>>> ---
>>>>  rust/kernel/alloc/kbox.rs |   3 +-
>>>>  rust/kernel/init.rs       |  55 +++++++++++++++++
>>>>  rust/kernel/prelude.rs    |   3 +-
>>>>  rust/kernel/sync/arc.rs   |  65 +++++++++++++++++++-
>>>>  rust/pin-init/src/lib.rs  | 125 ++------------------------------------
>>>>  5 files changed, 127 insertions(+), 124 deletions(-)
>>>>
>>>
>>> [...]
>>>
>>>> --- a/rust/pin-init/src/lib.rs
>>>> +++ b/rust/pin-init/src/lib.rs
>>>> @@ -10,7 +10,7 @@
>>>>  //! To initialize a `struct` with an in-place constructor you will need two things:
>>>>  //! - an in-place constructor,
>>>>  //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
>>>> -//!   [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
>>>> +//!   [`KBox<T>`] or any other smart pointer that supports this library).
>>>
>>> Would you not want to remove references to `KBox` here as well? Even
>>> though you don't have to move the impl, I don't imagine `KBox` exist in
>>> user space?
>>
>> Yes, this is done in "rust: pin-init: fix documentation links".
>
> Yea, maybe I should have read the entire thing before firing off emails.

No worries, happens to me as well :)

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 11:59     ` Andreas Hindborg
  2025-03-05 12:10       ` Benno Lossin
@ 2025-03-05 12:47       ` Miguel Ojeda
  1 sibling, 0 replies; 103+ messages in thread
From: Miguel Ojeda @ 2025-03-05 12:47 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

On Wed, Mar 5, 2025 at 12:59 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> If it's not too much hassle, why not add them in the kernel as well? I
> would rather not have to go fetch the user space repo from github, in
> the event that I ever need to patch pin-init.

If you need to patch it, then you should generally do so upstream --
this is supposed to be a vendored/sync'd library.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-05 12:17           ` Benno Lossin
@ 2025-03-05 12:49             ` Alice Ryhl
  2025-03-05 12:51               ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Alice Ryhl @ 2025-03-05 12:49 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Andreas Hindborg, Danilo Krummrich, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Trevor Gross,
	rust-for-linux, linux-kernel

On Wed, Mar 5, 2025 at 1:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>
> On Wed Mar 5, 2025 at 1:11 PM CET, Alice Ryhl wrote:
> > On Wed, Mar 5, 2025 at 1:05 PM Benno Lossin <benno.lossin@proton.me> wrote:
> >>
> >> On Wed Mar 5, 2025 at 12:26 PM CET, Andreas Hindborg wrote:
> >> > "Benno Lossin" <benno.lossin@proton.me> writes:
> >> >
> >> >> In order to make pin-init a standalone crate, move kernel-specific code
> >> >> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
> >> >> of the kernel, move their `Zeroable` implementation into the kernel
> >> >> crate.
> >> >>
> >> >> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> >> >> ---
> >> >>  rust/kernel/alloc/kbox.rs | 8 +++++++-
> >> >>  rust/kernel/types.rs      | 5 ++++-
> >> >>  rust/pin-init/src/lib.rs  | 8 +-------
> >> >>  3 files changed, 12 insertions(+), 9 deletions(-)
> >> >>
> >> >> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> >> >> index 39a3ea7542da..9861433559dc 100644
> >> >> --- a/rust/kernel/alloc/kbox.rs
> >> >> +++ b/rust/kernel/alloc/kbox.rs
> >> >> @@ -15,7 +15,7 @@
> >> >>  use core::ptr::NonNull;
> >> >>  use core::result::Result;
> >> >>
> >> >> -use crate::init::{InPlaceWrite, Init, PinInit};
> >> >> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
> >> >>  use crate::init_ext::InPlaceInit;
> >> >>  use crate::types::ForeignOwnable;
> >> >>
> >> >> @@ -100,6 +100,12 @@
> >> >>  /// ```
> >> >>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
> >> >>
> >> >> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
> >> >> +//
> >> >> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
> >> >> +// is no problem with a VTABLE pointer being null.
> >> >> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
> >> >
> >> > Could you elaborate the statement related to vtable pointers? How does
> >> > that come into play for `Option<Box<_>>`? Is it for fat pointers to
> >> > trait objects?
> >>
> >> Yes it is for fat pointers, if you have a `x: *mut dyn Trait`, then you
> >> aren't allowed to write all zeroes to `x`, because the VTABLE pointer
> >> (that is part of the fat pointer) is not allowed to be null.
> >>
> >> Now for `Option<Box<_>>`, this doesn't matter, as there if the normal
> >> pointer part of the fat pointer is all zeroes, then the VTABLE pointer
> >> part is considered padding bytes, as it's the `None` variant.
> >
> > The standard library only guarantees that all zeros is valid for
> > Option<Box<T,A>> when T:Sized and A=Global.
> > https://doc.rust-lang.org/stable/std/option/index.html#representation
>
> Oh! That's a problem then... I'll remove that then (and I can also get
> rid of the `ZeroableOption` trait).

Don't you still need it for KBox?

Alice

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 12:31         ` Andreas Hindborg
@ 2025-03-05 12:50           ` Miguel Ojeda
  2025-03-05 13:00             ` Benno Lossin
  2025-03-05 14:19             ` Andreas Hindborg
  0 siblings, 2 replies; 103+ messages in thread
From: Miguel Ojeda @ 2025-03-05 12:50 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

On Wed, Mar 5, 2025 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> I _really_ think that the ability to run the tests should be present in
> the kernel repository. But I also do not want to block this series on it,
> if it is something that will be easier to achieve with the build system
> overhaul that is in the pipeline.

No, that is not the plan. Even with the new build system, this is
supposed to be developed upstream as far as I understand, so you will
need to run them there anyway.

Unless there is a reason we could catch more bugs here, that is.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` into the kernel crate
  2025-03-05 12:49             ` Alice Ryhl
@ 2025-03-05 12:51               ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:51 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Andreas Hindborg, Danilo Krummrich, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Trevor Gross,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 1:49 PM CET, Alice Ryhl wrote:
> On Wed, Mar 5, 2025 at 1:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>
>> On Wed Mar 5, 2025 at 1:11 PM CET, Alice Ryhl wrote:
>> > On Wed, Mar 5, 2025 at 1:05 PM Benno Lossin <benno.lossin@proton.me> wrote:
>> >>
>> >> On Wed Mar 5, 2025 at 12:26 PM CET, Andreas Hindborg wrote:
>> >> > "Benno Lossin" <benno.lossin@proton.me> writes:
>> >> >
>> >> >> In order to make pin-init a standalone crate, move kernel-specific code
>> >> >> directly into the kernel crate. Since `Opaque<T>` and `KBox<T>` are part
>> >> >> of the kernel, move their `Zeroable` implementation into the kernel
>> >> >> crate.
>> >> >>
>> >> >> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> >> >> ---
>> >> >>  rust/kernel/alloc/kbox.rs | 8 +++++++-
>> >> >>  rust/kernel/types.rs      | 5 ++++-
>> >> >>  rust/pin-init/src/lib.rs  | 8 +-------
>> >> >>  3 files changed, 12 insertions(+), 9 deletions(-)
>> >> >>
>> >> >> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
>> >> >> index 39a3ea7542da..9861433559dc 100644
>> >> >> --- a/rust/kernel/alloc/kbox.rs
>> >> >> +++ b/rust/kernel/alloc/kbox.rs
>> >> >> @@ -15,7 +15,7 @@
>> >> >>  use core::ptr::NonNull;
>> >> >>  use core::result::Result;
>> >> >>
>> >> >> -use crate::init::{InPlaceWrite, Init, PinInit};
>> >> >> +use crate::init::{InPlaceWrite, Init, PinInit, Zeroable};
>> >> >>  use crate::init_ext::InPlaceInit;
>> >> >>  use crate::types::ForeignOwnable;
>> >> >>
>> >> >> @@ -100,6 +100,12 @@
>> >> >>  /// ```
>> >> >>  pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
>> >> >>
>> >> >> +// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
>> >> >> +//
>> >> >> +// In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant and there
>> >> >> +// is no problem with a VTABLE pointer being null.
>> >> >> +unsafe impl<T: ?Sized, A: Allocator> Zeroable for Option<Box<T, A>> {}
>> >> >
>> >> > Could you elaborate the statement related to vtable pointers? How does
>> >> > that come into play for `Option<Box<_>>`? Is it for fat pointers to
>> >> > trait objects?
>> >>
>> >> Yes it is for fat pointers, if you have a `x: *mut dyn Trait`, then you
>> >> aren't allowed to write all zeroes to `x`, because the VTABLE pointer
>> >> (that is part of the fat pointer) is not allowed to be null.
>> >>
>> >> Now for `Option<Box<_>>`, this doesn't matter, as there if the normal
>> >> pointer part of the fat pointer is all zeroes, then the VTABLE pointer
>> >> part is considered padding bytes, as it's the `None` variant.
>> >
>> > The standard library only guarantees that all zeros is valid for
>> > Option<Box<T,A>> when T:Sized and A=Global.
>> > https://doc.rust-lang.org/stable/std/option/index.html#representation
>>
>> Oh! That's a problem then... I'll remove that then (and I can also get
>> rid of the `ZeroableOption` trait).
>
> Don't you still need it for KBox?

Yes that's correct, when I wrote the above, I was under the impression
that I had to remove the `Zeroable` impl for `KBox` completely, but that
is not the case. I can still keep the one for `T: Sized` (since it's
transparently wrapping `NonNull<T>`).

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 17/22] rust: pin-init: synchronize documentation with the user-space version
  2025-03-04 22:55   ` [PATCH 17/22] rust: pin-init: synchronize documentation with " Benno Lossin
  2025-03-05  9:33     ` Fiona Behrens
@ 2025-03-05 12:52     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:52 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Synchronize documentation and examples with the user-space version.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-05  8:51     ` Andreas Hindborg
@ 2025-03-05 12:53       ` Benno Lossin
  2025-03-05 13:00         ` Miguel Ojeda
  2025-03-05 14:09         ` Andreas Hindborg
  0 siblings, 2 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 12:53 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 9:51 AM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> This is the first commit in a series that splits off the pin-init crate
>> from the kernel crate.
>
> I recently learned that using imperative mode in the commit message is
> preferred [1]. You might want to consider that for next spin.

Thanks for pointing that out, any suggestions for this concrete case? I
wasn't able to come up with an imperative statement.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 18/22] rust: pin-init: internal: synchronize with user-space version
  2025-03-04 22:55   ` [PATCH 18/22] rust: pin-init: internal: synchronize with " Benno Lossin
@ 2025-03-05 12:56     ` Andreas Hindborg
  0 siblings, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:56 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> This commit synchronizes with the user-space version that uses the
> quote crate [1] instead of a custom `quote!` macro.
> The imports in the different version are achieved using `cfg` on the
> kernel config value. This is always set in the kernel and never set in
> the user-space version.
>
> Since the quote crate requires the proc_macro2 crate, imports also need
> to be adjusted and `.into()` calls have to be inserted.
>
> Link: https://crates.io/crates/quote [1]
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the user-space version
  2025-03-04 22:56   ` [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the " Benno Lossin
@ 2025-03-05 12:57     ` Andreas Hindborg
  0 siblings, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 12:57 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> Last differences between the kernel version and the user-space version
> are removed here.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-05 12:53       ` Benno Lossin
@ 2025-03-05 13:00         ` Miguel Ojeda
  2025-03-05 14:09         ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Miguel Ojeda @ 2025-03-05 13:00 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Andreas Hindborg, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed, Mar 5, 2025 at 1:53 PM Benno Lossin <benno.lossin@proton.me> wrote:
>
> Thanks for pointing that out, any suggestions for this concrete case? I
> wasn't able to come up with an imperative statement.

Normally I follow a "Context, Why, (thus) What, Alternatives, Future"
format or similar.

The imperative is meant for the "What" part, i.e. the actual change
you are performing, which you already do in "..., ignore all doctests
...", so that looks fine to me.

You could just remove the first line, or perhaps move it and reword it
with ", in order to..." after the "ignore" sentence.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 12:50           ` Miguel Ojeda
@ 2025-03-05 13:00             ` Benno Lossin
  2025-03-05 14:19             ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 13:00 UTC (permalink / raw)
  To: Miguel Ojeda, Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

On Wed Mar 5, 2025 at 1:50 PM CET, Miguel Ojeda wrote:
> On Wed, Mar 5, 2025 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> I _really_ think that the ability to run the tests should be present in
>> the kernel repository. But I also do not want to block this series on it,
>> if it is something that will be easier to achieve with the build system
>> overhaul that is in the pipeline.
>
> No, that is not the plan. Even with the new build system, this is
> supposed to be developed upstream as far as I understand, so you will
> need to run them there anyway.

Yes, the plan is that development will happen on GitHub. I will of
course continue to take patches via the list, but I would prefer if
people make changes via GitHub PRs, since those run the CI (which also
includes a lot more tests that I haven't vendored here).

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 20/22] rust: pin-init: add miscellaneous files from the user-space version
  2025-03-04 22:56   ` [PATCH 20/22] rust: pin-init: add miscellaneous files from " Benno Lossin
  2025-03-05  9:35     ` Fiona Behrens
@ 2025-03-05 13:04     ` Andreas Hindborg
  2025-03-05 13:37       ` Miguel Ojeda
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 13:04 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> Add readme and contribution guidelines of the user-space version of
> pin-init.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

While we don't _need_ to carry this, I don't mind. I think it is
different than the dead code in an earlier patch.

But really, if you are already going to sync changes with automated
tools, it should be simple enough to have a list of file that are
excluded from user space to kernel syncs.


Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 21/22] rust: pin-init: re-enable doctests
  2025-03-04 22:56   ` [PATCH 21/22] rust: pin-init: re-enable doctests Benno Lossin
  2025-03-05  9:35     ` Fiona Behrens
@ 2025-03-05 13:05     ` Andreas Hindborg
  1 sibling, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 13:05 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> The pin-init crate is now compiled in a standalone fashion, so revert
> the earlier commit that disabled the doctests in pin-init in order to
> avoid build errors while transitioning the crate into a standalone
> version.
>
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>

I really would prefer if I could run those tests with kernel
infrastructure.

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 20/22] rust: pin-init: add miscellaneous files from the user-space version
  2025-03-05 13:04     ` Andreas Hindborg
@ 2025-03-05 13:37       ` Miguel Ojeda
  2025-03-05 13:58         ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Miguel Ojeda @ 2025-03-05 13:37 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

On Wed, Mar 5, 2025 at 2:08 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> But really, if you are already going to sync changes with automated
> tools, it should be simple enough to have a list of file that are
> excluded from user space to kernel syncs.

As far as I understand, Benno already excludes some files -- so extra
files could also be excluded easily.

Not sure about these though, e.g. they could help someone realize they
need to contribute/develop it elsewhere. On the other hand, we could
have a custom one in the kernel instead, explaining just that.

Up to Benno!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 15/22] rust: make pin-init its own crate
  2025-03-05 12:12     ` Andreas Hindborg
@ 2025-03-05 13:40       ` Benno Lossin
  2025-03-05 14:20         ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 13:40 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Greg Kroah-Hartman, Rafael J. Wysocki, Peter Zijlstra,
	Ingo Molnar, Will Deacon, Waiman Long, linux-kernel,
	rust-for-linux, linux-block

On Wed Mar 5, 2025 at 1:12 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> Rename relative paths inside of the crate to still refer to the same
>> items, also rename paths inside of the kernel crate and adjust the build
>> system to build the crate.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>
> [...]
>
>> diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
>> index 7ff82c82ce0c..8e116e266524 100644
>> --- a/rust/macros/lib.rs
>> +++ b/rust/macros/lib.rs
>> @@ -2,23 +2,20 @@
>>
>>  //! Crate for all kernel procedural macros.
>>
>> +#![feature(lint_reasons)]
>
> Commit message should probably say something about this.

Done.

>> +
>>  // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
>>  // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
>>  // touched by Kconfig when the version string from the compiler changes.
>>
>>  #[macro_use]
>> +#[expect(unused_macros)]
>>  mod quote;
>>  mod concat_idents;
>>  mod helpers;
>>  mod module;
>>  mod paste;
>> -#[path = "../pin-init/internal/src/pin_data.rs"]
>> -mod pin_data;
>> -#[path = "../pin-init/internal/src/pinned_drop.rs"]
>> -mod pinned_drop;
>>  mod vtable;
>> -#[path = "../pin-init/internal/src/zeroable.rs"]
>> -mod zeroable;
>>
>>  use proc_macro::TokenStream;
>>
>> @@ -374,5 +371,3 @@ pub fn paste(input: TokenStream) -> TokenStream {
>>      paste::expand(&mut tokens);
>>      tokens.into_iter().collect()
>>  }
>> -
>> -include!("../pin-init/internal/src/lib.rs");
>> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
>> index cdf94f4982df..bdd94c79b0d4 100644
>> --- a/rust/macros/module.rs
>> +++ b/rust/macros/module.rs
>> @@ -236,7 +236,7 @@ impl kernel::ModuleMetadata for {type_} {{
>>              mod __module_init {{
>>                  mod __module_init {{
>>                      use super::super::{type_};
>> -                    use kernel::init::PinInit;
>> +                    use pin_init::PinInit;
>>
>>                      /// The \"Rust loadable module\" mark.
>>                      //
>> diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs
>> index 33a199e4f176..11d241b85ac3 100644
>> --- a/rust/macros/quote.rs
>> +++ b/rust/macros/quote.rs
>> @@ -2,6 +2,7 @@
>>
>>  use proc_macro::{TokenStream, TokenTree};
>>
>> +#[allow(dead_code)]
>
> #[expect(dead_code)] ?

`expect` can't be used here, since `quote.rs` is imported in
`pin-init/internal/src/lib.rs` and used in that crate. But it is unused
in the `macros` crate, hence we need to allow it.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-05 12:22     ` Andreas Hindborg
@ 2025-03-05 13:55       ` Benno Lossin
  2025-03-05 14:29         ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 13:55 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

On Wed Mar 5, 2025 at 1:22 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> To synchronize the kernel's version of pin-init with the user-space
>> version, introduce support for `std` and `alloc`. While the kernel uses
>> neither, the user-space version has to support both. Thus include the
>> required `#[cfg]`s and additional code.
>>
>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>> ---
>>  rust/pin-init/src/__internal.rs |  27 ++++++
>>  rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
>>  rust/pin-init/src/lib.rs        |  17 ++--
>>  3 files changed, 196 insertions(+), 6 deletions(-)
>>  create mode 100644 rust/pin-init/src/alloc.rs
>>
>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>> index 74086365a18a..27d4a8619c04 100644
>> --- a/rust/pin-init/src/__internal.rs
>> +++ b/rust/pin-init/src/__internal.rs
>> @@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
>>      }
>>  }
>>
>> +#[test]
>
> I think the kunit support we have in the pipeline will pick this up?

Is that support also enabled for crates outside of the `kernel` crate?
I would argue it shouldn't and then this isn't a problem.

>> +fn stack_init_reuse() {
>> +    use ::std::{borrow::ToOwned, println, string::String};
>> +    use core::pin::pin;
>> +
>> +    #[derive(Debug)]
>> +    struct Foo {
>> +        a: usize,
>> +        b: String,
>> +    }
>> +    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>> +        slot.as_mut().init(crate::init!(Foo {
>> +            a: 42,
>> +            b: "Hello".to_owned(),
>> +        }));
>> +    let value = value.unwrap();
>> +    println!("{value:?}");
>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>> +        slot.as_mut().init(crate::init!(Foo {
>> +            a: 24,
>> +            b: "world!".to_owned(),
>> +        }));
>> +    let value = value.unwrap();
>> +    println!("{value:?}");
>> +}
>> +
>
> [...]
>
>> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
>> index 55d8953620f0..1fdca35906a0 100644
>> --- a/rust/pin-init/src/lib.rs
>> +++ b/rust/pin-init/src/lib.rs
>> @@ -204,8 +204,8 @@
>>  //! [structurally pinned fields]:
>>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>>  //! [stack]: crate::stack_pin_init
>> -//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
>> -//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>> +//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
>> +//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
>
> Now these will render incorrect in the kernel docs, right?

What do you mean by that? The link will resolve to the std versions of
`Arc` and `Box`. But that is also what this crate will support, as it
doesn't know about the kernel's own alloc.

>>  //! [`impl PinInit<Foo>`]: PinInit
>>  //! [`impl PinInit<T, E>`]: PinInit
>>  //! [`impl Init<T, E>`]: Init
>> @@ -239,6 +239,11 @@
>>  #[doc(hidden)]
>>  pub mod macros;
>>
>> +#[cfg(any(feature = "std", feature = "alloc"))]
>> +mod alloc;
>> +#[cfg(any(feature = "std", feature = "alloc"))]
>> +pub use alloc::InPlaceInit;
>
> Do we really need to have this entire file sitting dead in the kernel
> tree? If you are not building the user space version from the kernel
> sources, I don't think we need it here. Even when you want to sync
> between the two repositories, it should be easy to handle an entire file
> being not present on one side.

I do have a script that does the commit porting, you can find it at [1].
So I could easily add that file there. However, I think it also is
important that it's easy to remember which files are synchronized and
which files aren't. At the moment it's very simple, the synchronized
files are:
- README.md
- CONTRIBUTING.md
- src/*
- internal/src/*
- examples/*

If I introduce special cases for files in src, I fear that I might get
confused at some point, making a change that shouldn't be done etc.

I understand your worry about the dead file, but at the same time, I
think it's vital to keep the pattern of synchronized files as simple as
possible.

[1]: https://github.com/Rust-for-Linux/pin-init/commit/7eda8fda7cb48883511db4b5f4fff8d574eef25a

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 00/22] make pin-init into a standalone crate
  2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
                     ` (22 preceding siblings ...)
  2025-03-04 23:12   ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
@ 2025-03-05 13:56   ` Andreas Hindborg
  2025-03-05 14:03     ` Benno Lossin
  23 siblings, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 13:56 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

Hi Benno,

"Benno Lossin" <benno.lossin@proton.me> writes:

> This patch series extracts the pin-init API from the kernel crate and
> turns it into a standalone crate used by the kernel crate. The reasoning
> for this change is that the maintenance burden for me is too great
> maintaining two (more and more) diverging versions of the same library.
> At [1] you can find the user-space version of the pin-init library as a
> Rust crate.

[...]


Tested-by: Andreas Hindborg <a.hindborg@kernel.org>


Tested with downstream rnull driver. The driver is 71 patches on top of
this series. It required a handful of trivial changes to patches that
touch pin_init, but everything seems to be working just fine.

Reviewing this series made my head spin. It must have taken a
significant effort to compose the series. Thank you for making that
effort!


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 20/22] rust: pin-init: add miscellaneous files from the user-space version
  2025-03-05 13:37       ` Miguel Ojeda
@ 2025-03-05 13:58         ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 13:58 UTC (permalink / raw)
  To: Miguel Ojeda, Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

On Wed Mar 5, 2025 at 2:37 PM CET, Miguel Ojeda wrote:
> On Wed, Mar 5, 2025 at 2:08 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> But really, if you are already going to sync changes with automated
>> tools, it should be simple enough to have a list of file that are
>> excluded from user space to kernel syncs.
>
> As far as I understand, Benno already excludes some files -- so extra
> files could also be excluded easily.
>
> Not sure about these though, e.g. they could help someone realize they
> need to contribute/develop it elsewhere. On the other hand, we could
> have a custom one in the kernel instead, explaining just that.

CONTRIBUTING.md is also referenced by the MAINTAINERS entry in the `P:`
field. For README.md, I don't mind removing it, as that still keeps the
rules of which files should be synchronized simple (see the other
thread). But I agree with Miguel that it is beneficial to keep in order
to show that it is a vendored library.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 00/22] make pin-init into a standalone crate
  2025-03-05 13:56   ` Andreas Hindborg
@ 2025-03-05 14:03     ` Benno Lossin
  2025-03-05 14:36       ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 14:03 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

On Wed Mar 5, 2025 at 2:56 PM CET, Andreas Hindborg wrote:
> Hi Benno,
>
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> This patch series extracts the pin-init API from the kernel crate and
>> turns it into a standalone crate used by the kernel crate. The reasoning
>> for this change is that the maintenance burden for me is too great
>> maintaining two (more and more) diverging versions of the same library.
>> At [1] you can find the user-space version of the pin-init library as a
>> Rust crate.
>
> [...]
>
>
> Tested-by: Andreas Hindborg <a.hindborg@kernel.org>

Thanks a lot for the quick reviews and testing!

> Tested with downstream rnull driver. The driver is 71 patches on top of
> this series. It required a handful of trivial changes to patches that
> touch pin_init, but everything seems to be working just fine.

Do you still have those trivial changes around? I would like to know
what kind of changes you had to do. Was it just import adjustments or
did you also need other changes?

If you find the time, I would greatly appreciate if also you put your
rnvme driver on top and test with that.

> Reviewing this series made my head spin. It must have taken a
> significant effort to compose the series. Thank you for making that
> effort!

Yeah it wasn't easy to get the two versions on the same page again. The
hardest part was to split the changes into self-contained patches and
also to ensure nothing breaks between them.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-05 12:53       ` Benno Lossin
  2025-03-05 13:00         ` Miguel Ojeda
@ 2025-03-05 14:09         ` Andreas Hindborg
  2025-03-05 14:31           ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 14:09 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 9:51 AM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> This is the first commit in a series that splits off the pin-init crate
>>> from the kernel crate.
>>
>> I recently learned that using imperative mode in the commit message is
>> preferred [1]. You might want to consider that for next spin.
>
> Thanks for pointing that out, any suggestions for this concrete case? I
> wasn't able to come up with an imperative statement.

I would drop the first paragraph entirely, since the subject is 01/22
and the cover letter provides plenty of context.

  The build system cannot handle doctests in the kernel crate in files
  outside of `rust/kernel/`. Subsequent commits will move files out
  of that directory, but will still compile them as part of the kernel
  crate. Thus, ignore all doctests in the to-be-moved files.

  Leave tests disabled until they are separated into their
  own crate and they stop causing breakage.

Not sure if it is better? More robot for sure 🤖

This part from the original is not correct:?

  since then the doctests of that new crate will be handled as normal
  host doctests.

The build system will not run those tests when they are not in the
kernel crate?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 12:50           ` Miguel Ojeda
  2025-03-05 13:00             ` Benno Lossin
@ 2025-03-05 14:19             ` Andreas Hindborg
  2025-03-05 14:34               ` Benno Lossin
  1 sibling, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 14:19 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

"Miguel Ojeda" <miguel.ojeda.sandonis@gmail.com> writes:

> On Wed, Mar 5, 2025 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> I _really_ think that the ability to run the tests should be present in
>> the kernel repository. But I also do not want to block this series on it,
>> if it is something that will be easier to achieve with the build system
>> overhaul that is in the pipeline.
>
> No, that is not the plan. Even with the new build system, this is
> supposed to be developed upstream as far as I understand, so you will
> need to run them there anyway.
>
> Unless there is a reason we could catch more bugs here, that is.

I guess it would be no different than `syn`. But I think it is a shame
that we move something that people could contribute to via the kernel
development flow - out of the kernel development flow.

Ultimately I guess this is for the maintainer to decide, and I don't
have to like the decision.


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 15/22] rust: make pin-init its own crate
  2025-03-05 13:40       ` Benno Lossin
@ 2025-03-05 14:20         ` Andreas Hindborg
  0 siblings, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 14:20 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Greg Kroah-Hartman, Rafael J. Wysocki, Peter Zijlstra,
	Ingo Molnar, Will Deacon, Waiman Long, linux-kernel,
	rust-for-linux, linux-block

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 1:12 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> Rename relative paths inside of the crate to still refer to the same
>>> items, also rename paths inside of the kernel crate and adjust the build
>>> system to build the crate.
>>>
>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>> ---
>>
>> [...]
>>
>>> diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
>>> index 7ff82c82ce0c..8e116e266524 100644
>>> --- a/rust/macros/lib.rs
>>> +++ b/rust/macros/lib.rs
>>> @@ -2,23 +2,20 @@
>>>
>>>  //! Crate for all kernel procedural macros.
>>>
>>> +#![feature(lint_reasons)]
>>
>> Commit message should probably say something about this.
>
> Done.
>
>>> +
>>>  // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
>>>  // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
>>>  // touched by Kconfig when the version string from the compiler changes.
>>>
>>>  #[macro_use]
>>> +#[expect(unused_macros)]
>>>  mod quote;
>>>  mod concat_idents;
>>>  mod helpers;
>>>  mod module;
>>>  mod paste;
>>> -#[path = "../pin-init/internal/src/pin_data.rs"]
>>> -mod pin_data;
>>> -#[path = "../pin-init/internal/src/pinned_drop.rs"]
>>> -mod pinned_drop;
>>>  mod vtable;
>>> -#[path = "../pin-init/internal/src/zeroable.rs"]
>>> -mod zeroable;
>>>
>>>  use proc_macro::TokenStream;
>>>
>>> @@ -374,5 +371,3 @@ pub fn paste(input: TokenStream) -> TokenStream {
>>>      paste::expand(&mut tokens);
>>>      tokens.into_iter().collect()
>>>  }
>>> -
>>> -include!("../pin-init/internal/src/lib.rs");
>>> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
>>> index cdf94f4982df..bdd94c79b0d4 100644
>>> --- a/rust/macros/module.rs
>>> +++ b/rust/macros/module.rs
>>> @@ -236,7 +236,7 @@ impl kernel::ModuleMetadata for {type_} {{
>>>              mod __module_init {{
>>>                  mod __module_init {{
>>>                      use super::super::{type_};
>>> -                    use kernel::init::PinInit;
>>> +                    use pin_init::PinInit;
>>>
>>>                      /// The \"Rust loadable module\" mark.
>>>                      //
>>> diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs
>>> index 33a199e4f176..11d241b85ac3 100644
>>> --- a/rust/macros/quote.rs
>>> +++ b/rust/macros/quote.rs
>>> @@ -2,6 +2,7 @@
>>>
>>>  use proc_macro::{TokenStream, TokenTree};
>>>
>>> +#[allow(dead_code)]
>>
>> #[expect(dead_code)] ?
>
> `expect` can't be used here, since `quote.rs` is imported in
> `pin-init/internal/src/lib.rs` and used in that crate. But it is unused
> in the `macros` crate, hence we need to allow it.

Got it 👍


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-05 13:55       ` Benno Lossin
@ 2025-03-05 14:29         ` Andreas Hindborg
  2025-03-05 15:05           ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 14:29 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 1:22 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> To synchronize the kernel's version of pin-init with the user-space
>>> version, introduce support for `std` and `alloc`. While the kernel uses
>>> neither, the user-space version has to support both. Thus include the
>>> required `#[cfg]`s and additional code.
>>>
>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>> ---
>>>  rust/pin-init/src/__internal.rs |  27 ++++++
>>>  rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
>>>  rust/pin-init/src/lib.rs        |  17 ++--
>>>  3 files changed, 196 insertions(+), 6 deletions(-)
>>>  create mode 100644 rust/pin-init/src/alloc.rs
>>>
>>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>>> index 74086365a18a..27d4a8619c04 100644
>>> --- a/rust/pin-init/src/__internal.rs
>>> +++ b/rust/pin-init/src/__internal.rs
>>> @@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
>>>      }
>>>  }
>>>
>>> +#[test]
>>
>> I think the kunit support we have in the pipeline will pick this up?
>
> Is that support also enabled for crates outside of the `kernel` crate?
> I would argue it shouldn't and then this isn't a problem.

Re conversation about moving pin_init out of the kernel, we should
distinguish between vendored crates and crates that is part of the
kernel. This one is now vendored and tests are not meant to be run by
the kernel build system and infrastructure. Other crates will be
different, living in the kernel.

>
>>> +fn stack_init_reuse() {
>>> +    use ::std::{borrow::ToOwned, println, string::String};
>>> +    use core::pin::pin;
>>> +
>>> +    #[derive(Debug)]
>>> +    struct Foo {
>>> +        a: usize,
>>> +        b: String,
>>> +    }
>>> +    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>> +        slot.as_mut().init(crate::init!(Foo {
>>> +            a: 42,
>>> +            b: "Hello".to_owned(),
>>> +        }));
>>> +    let value = value.unwrap();
>>> +    println!("{value:?}");
>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>> +        slot.as_mut().init(crate::init!(Foo {
>>> +            a: 24,
>>> +            b: "world!".to_owned(),
>>> +        }));
>>> +    let value = value.unwrap();
>>> +    println!("{value:?}");
>>> +}
>>> +
>>
>> [...]
>>
>>> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
>>> index 55d8953620f0..1fdca35906a0 100644
>>> --- a/rust/pin-init/src/lib.rs
>>> +++ b/rust/pin-init/src/lib.rs
>>> @@ -204,8 +204,8 @@
>>>  //! [structurally pinned fields]:
>>>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>>>  //! [stack]: crate::stack_pin_init
>>> -//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
>>> -//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>>> +//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
>>> +//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
>>
>> Now these will render incorrect in the kernel docs, right?
>
> What do you mean by that? The link will resolve to the std versions of
> `Arc` and `Box`. But that is also what this crate will support, as it
> doesn't know about the kernel's own alloc.

I mean that if I render the kernel documentation, go to `pin_init` and
click the `Arc<T>` link, I end up in `std`. But I am in the kernel, so
not what I would expect.

But I guess there is no easy solution? Being a kernel developer, I would
prefer a kernel first approach. Can't have it all, I guess.

>
>>>  //! [`impl PinInit<Foo>`]: PinInit
>>>  //! [`impl PinInit<T, E>`]: PinInit
>>>  //! [`impl Init<T, E>`]: Init
>>> @@ -239,6 +239,11 @@
>>>  #[doc(hidden)]
>>>  pub mod macros;
>>>
>>> +#[cfg(any(feature = "std", feature = "alloc"))]
>>> +mod alloc;
>>> +#[cfg(any(feature = "std", feature = "alloc"))]
>>> +pub use alloc::InPlaceInit;
>>
>> Do we really need to have this entire file sitting dead in the kernel
>> tree? If you are not building the user space version from the kernel
>> sources, I don't think we need it here. Even when you want to sync
>> between the two repositories, it should be easy to handle an entire file
>> being not present on one side.
>
> I do have a script that does the commit porting, you can find it at [1].
> So I could easily add that file there. However, I think it also is
> important that it's easy to remember which files are synchronized and
> which files aren't. At the moment it's very simple, the synchronized
> files are:
> - README.md
> - CONTRIBUTING.md
> - src/*
> - internal/src/*
> - examples/*
>
> If I introduce special cases for files in src, I fear that I might get
> confused at some point, making a change that shouldn't be done etc.
>
> I understand your worry about the dead file, but at the same time, I
> think it's vital to keep the pattern of synchronized files as simple as
> possible.

I don't agree about this one - but I am not the one that has to do the
work. I would prefer we don't keep dead user space code in the kernel
tree, and I would ask that you consider if you can find a solution for
that which works for you. If not, I will live with the dead code.


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 01/22] rust: init: disable doctests
  2025-03-05 14:09         ` Andreas Hindborg
@ 2025-03-05 14:31           ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 14:31 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux, linux-kernel

On Wed Mar 5, 2025 at 3:09 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> On Wed Mar 5, 2025 at 9:51 AM CET, Andreas Hindborg wrote:
>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>
>>>> This is the first commit in a series that splits off the pin-init crate
>>>> from the kernel crate.
>>>
>>> I recently learned that using imperative mode in the commit message is
>>> preferred [1]. You might want to consider that for next spin.
>>
>> Thanks for pointing that out, any suggestions for this concrete case? I
>> wasn't able to come up with an imperative statement.
>
> I would drop the first paragraph entirely, since the subject is 01/22
> and the cover letter provides plenty of context.

Done.

>   The build system cannot handle doctests in the kernel crate in files
>   outside of `rust/kernel/`. Subsequent commits will move files out
>   of that directory, but will still compile them as part of the kernel
>   crate. Thus, ignore all doctests in the to-be-moved files.
>
>   Leave tests disabled until they are separated into their
>   own crate and they stop causing breakage.
>
> Not sure if it is better? More robot for sure 🤖

Thanks!

>
> This part from the original is not correct:?
>
>   since then the doctests of that new crate will be handled as normal
>   host doctests.
>
> The build system will not run those tests when they are not in the
> kernel crate?

Yes, that sentence was from an old version when I tried to get them to
work. Removed it in next version.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 14/22] rust: add pin-init crate build infrastructure
  2025-03-05 14:19             ` Andreas Hindborg
@ 2025-03-05 14:34               ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 14:34 UTC (permalink / raw)
  To: Andreas Hindborg, Miguel Ojeda
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Masahiro Yamada, Nathan Chancellor, Nicolas Schier, linux-kernel,
	rust-for-linux, linux-kbuild

On Wed Mar 5, 2025 at 3:19 PM CET, Andreas Hindborg wrote:
> "Miguel Ojeda" <miguel.ojeda.sandonis@gmail.com> writes:
>
>> On Wed, Mar 5, 2025 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>>
>>> I _really_ think that the ability to run the tests should be present in
>>> the kernel repository. But I also do not want to block this series on it,
>>> if it is something that will be easier to achieve with the build system
>>> overhaul that is in the pipeline.
>>
>> No, that is not the plan. Even with the new build system, this is
>> supposed to be developed upstream as far as I understand, so you will
>> need to run them there anyway.
>>
>> Unless there is a reason we could catch more bugs here, that is.
>
> I guess it would be no different than `syn`. But I think it is a shame
> that we move something that people could contribute to via the kernel
> development flow - out of the kernel development flow.

You *can* send patches via the list, I will pick them up and run them
through the GitHub CI.

Patches that arrive via GitHub will also go through the list and people
can add their tags there.

Also I don't think that pin-init will receive a lot of contributions in
the first place. I do have a lot of changes planned for when we get
`syn`, but other than that, I don't think it will change a lot in the
future.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 00/22] make pin-init into a standalone crate
  2025-03-05 14:03     ` Benno Lossin
@ 2025-03-05 14:36       ` Andreas Hindborg
  2025-03-05 14:47         ` Benno Lossin
  0 siblings, 1 reply; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 14:36 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 2:56 PM CET, Andreas Hindborg wrote:
>> Hi Benno,
>>
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>
>>> This patch series extracts the pin-init API from the kernel crate and
>>> turns it into a standalone crate used by the kernel crate. The reasoning
>>> for this change is that the maintenance burden for me is too great
>>> maintaining two (more and more) diverging versions of the same library.
>>> At [1] you can find the user-space version of the pin-init library as a
>>> Rust crate.
>>
>> [...]
>>
>>
>> Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
>
> Thanks a lot for the quick reviews and testing!
>
>> Tested with downstream rnull driver. The driver is 71 patches on top of
>> this series. It required a handful of trivial changes to patches that
>> touch pin_init, but everything seems to be working just fine.
>
> Do you still have those trivial changes around? I would like to know
> what kind of changes you had to do. Was it just import adjustments or
> did you also need other changes?

I pushed my branch to [1]. I folded most of the changes before I got
lazy and put a commit on top, so you have to do a range-diff with
v6.14-rc1..rnull-v6.14-rc1.
>
> If you find the time, I would greatly appreciate if also you put your
> rnvme driver on top and test with that.

I can do that, but I have a few work items to tend to first and I go on
PTO next week.

>
>> Reviewing this series made my head spin. It must have taken a
>> significant effort to compose the series. Thank you for making that
>> effort!
>
> Yeah it wasn't easy to get the two versions on the same page again. The
> hardest part was to split the changes into self-contained patches and
> also to ensure nothing breaks between them.

I checked every commit - nothing broken for me. Very impressive 😎


Best regards,
Andreas Hindborg


[1] https://github.com/metaspace/linux pin-init-rnull-v6.14


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 00/22] make pin-init into a standalone crate
  2025-03-05 14:36       ` Andreas Hindborg
@ 2025-03-05 14:47         ` Benno Lossin
  0 siblings, 0 replies; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 14:47 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

On Wed Mar 5, 2025 at 3:36 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>
>> On Wed Mar 5, 2025 at 2:56 PM CET, Andreas Hindborg wrote:
>>> Hi Benno,
>>>
>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>
>>>> This patch series extracts the pin-init API from the kernel crate and
>>>> turns it into a standalone crate used by the kernel crate. The reasoning
>>>> for this change is that the maintenance burden for me is too great
>>>> maintaining two (more and more) diverging versions of the same library.
>>>> At [1] you can find the user-space version of the pin-init library as a
>>>> Rust crate.
>>>
>>> [...]
>>>
>>>
>>> Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
>>
>> Thanks a lot for the quick reviews and testing!
>>
>>> Tested with downstream rnull driver. The driver is 71 patches on top of
>>> this series. It required a handful of trivial changes to patches that
>>> touch pin_init, but everything seems to be working just fine.
>>
>> Do you still have those trivial changes around? I would like to know
>> what kind of changes you had to do. Was it just import adjustments or
>> did you also need other changes?
>
> I pushed my branch to [1]. I folded most of the changes before I got
> lazy and put a commit on top, so you have to do a range-diff with
> v6.14-rc1..rnull-v6.14-rc1.

Thanks! Those changes are what I expected.

>> If you find the time, I would greatly appreciate if also you put your
>> rnvme driver on top and test with that.
>
> I can do that, but I have a few work items to tend to first and I go on
> PTO next week.

No worries, I think I will have to spin a new version anyways.

>>> Reviewing this series made my head spin. It must have taken a
>>> significant effort to compose the series. Thank you for making that
>>> effort!
>>
>> Yeah it wasn't easy to get the two versions on the same page again. The
>> hardest part was to split the changes into self-contained patches and
>> also to ensure nothing breaks between them.
>
> I checked every commit - nothing broken for me. Very impressive 😎

Thanks!

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-05 14:29         ` Andreas Hindborg
@ 2025-03-05 15:05           ` Benno Lossin
  2025-03-05 17:27             ` Andreas Hindborg
  0 siblings, 1 reply; 103+ messages in thread
From: Benno Lossin @ 2025-03-05 15:05 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

On Wed Mar 5, 2025 at 3:29 PM CET, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>> On Wed Mar 5, 2025 at 1:22 PM CET, Andreas Hindborg wrote:
>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>> To synchronize the kernel's version of pin-init with the user-space
>>>> version, introduce support for `std` and `alloc`. While the kernel uses
>>>> neither, the user-space version has to support both. Thus include the
>>>> required `#[cfg]`s and additional code.
>>>>
>>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>>> ---
>>>>  rust/pin-init/src/__internal.rs |  27 ++++++
>>>>  rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
>>>>  rust/pin-init/src/lib.rs        |  17 ++--
>>>>  3 files changed, 196 insertions(+), 6 deletions(-)
>>>>  create mode 100644 rust/pin-init/src/alloc.rs
>>>>
>>>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>>>> index 74086365a18a..27d4a8619c04 100644
>>>> --- a/rust/pin-init/src/__internal.rs
>>>> +++ b/rust/pin-init/src/__internal.rs
>>>> @@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
>>>>      }
>>>>  }
>>>>
>>>> +#[test]
>>>
>>> I think the kunit support we have in the pipeline will pick this up?
>>
>> Is that support also enabled for crates outside of the `kernel` crate?
>> I would argue it shouldn't and then this isn't a problem.
>
> Re conversation about moving pin_init out of the kernel, we should
> distinguish between vendored crates and crates that is part of the
> kernel. This one is now vendored and tests are not meant to be run by
> the kernel build system and infrastructure. Other crates will be
> different, living in the kernel.

Yes, but I wouldn't necessarily call this category "vendored"; e.g. we
could write a crate that is kernel-only, but doesn't actually have any
code that requires kernel infrastructure. How about we call these
kernel-agnostic crates? :)

>>>> +fn stack_init_reuse() {
>>>> +    use ::std::{borrow::ToOwned, println, string::String};
>>>> +    use core::pin::pin;
>>>> +
>>>> +    #[derive(Debug)]
>>>> +    struct Foo {
>>>> +        a: usize,
>>>> +        b: String,
>>>> +    }
>>>> +    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
>>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>>> +        slot.as_mut().init(crate::init!(Foo {
>>>> +            a: 42,
>>>> +            b: "Hello".to_owned(),
>>>> +        }));
>>>> +    let value = value.unwrap();
>>>> +    println!("{value:?}");
>>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>>> +        slot.as_mut().init(crate::init!(Foo {
>>>> +            a: 24,
>>>> +            b: "world!".to_owned(),
>>>> +        }));
>>>> +    let value = value.unwrap();
>>>> +    println!("{value:?}");
>>>> +}
>>>> +
>>>
>>> [...]
>>>
>>>> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
>>>> index 55d8953620f0..1fdca35906a0 100644
>>>> --- a/rust/pin-init/src/lib.rs
>>>> +++ b/rust/pin-init/src/lib.rs
>>>> @@ -204,8 +204,8 @@
>>>>  //! [structurally pinned fields]:
>>>>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>>>>  //! [stack]: crate::stack_pin_init
>>>> -//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
>>>> -//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>>>> +//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
>>>> +//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
>>>
>>> Now these will render incorrect in the kernel docs, right?
>>
>> What do you mean by that? The link will resolve to the std versions of
>> `Arc` and `Box`. But that is also what this crate will support, as it
>> doesn't know about the kernel's own alloc.
>
> I mean that if I render the kernel documentation, go to `pin_init` and
> click the `Arc<T>` link, I end up in `std`. But I am in the kernel, so
> not what I would expect.
>
> But I guess there is no easy solution? Being a kernel developer, I would
> prefer a kernel first approach. Can't have it all, I guess.

I could change the link depending on the `kernel` cfg, so

    #![cfg_attr(kernel, doc = "[`Arc<T>`]: https://rust.docs.kernel.org...")]
    #![cfg_attr(not(kernel), doc = "[`Arc<T>`]: https://doc.rust-lang.org...")]

But if anyone visits the documentation on `docs.rs`, then they will get
the user-space one... What do you think?

>>>>  //! [`impl PinInit<Foo>`]: PinInit
>>>>  //! [`impl PinInit<T, E>`]: PinInit
>>>>  //! [`impl Init<T, E>`]: Init
>>>> @@ -239,6 +239,11 @@
>>>>  #[doc(hidden)]
>>>>  pub mod macros;
>>>>
>>>> +#[cfg(any(feature = "std", feature = "alloc"))]
>>>> +mod alloc;
>>>> +#[cfg(any(feature = "std", feature = "alloc"))]
>>>> +pub use alloc::InPlaceInit;
>>>
>>> Do we really need to have this entire file sitting dead in the kernel
>>> tree? If you are not building the user space version from the kernel
>>> sources, I don't think we need it here. Even when you want to sync
>>> between the two repositories, it should be easy to handle an entire file
>>> being not present on one side.
>>
>> I do have a script that does the commit porting, you can find it at [1].
>> So I could easily add that file there. However, I think it also is
>> important that it's easy to remember which files are synchronized and
>> which files aren't. At the moment it's very simple, the synchronized
>> files are:
>> - README.md
>> - CONTRIBUTING.md
>> - src/*
>> - internal/src/*
>> - examples/*
>>
>> If I introduce special cases for files in src, I fear that I might get
>> confused at some point, making a change that shouldn't be done etc.
>>
>> I understand your worry about the dead file, but at the same time, I
>> think it's vital to keep the pattern of synchronized files as simple as
>> possible.
>
> I don't agree about this one - but I am not the one that has to do the
> work. I would prefer we don't keep dead user space code in the kernel
> tree, and I would ask that you consider if you can find a solution for
> that which works for you. If not, I will live with the dead code.

I will see if I can come up with a solution.

---
Cheers,
Benno


^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version
  2025-03-05 15:05           ` Benno Lossin
@ 2025-03-05 17:27             ` Andreas Hindborg
  0 siblings, 0 replies; 103+ messages in thread
From: Andreas Hindborg @ 2025-03-05 17:27 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel, rust-for-linux

"Benno Lossin" <benno.lossin@proton.me> writes:

> On Wed Mar 5, 2025 at 3:29 PM CET, Andreas Hindborg wrote:
>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>> On Wed Mar 5, 2025 at 1:22 PM CET, Andreas Hindborg wrote:
>>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>>> To synchronize the kernel's version of pin-init with the user-space
>>>>> version, introduce support for `std` and `alloc`. While the kernel uses
>>>>> neither, the user-space version has to support both. Thus include the
>>>>> required `#[cfg]`s and additional code.
>>>>>
>>>>> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
>>>>> ---
>>>>>  rust/pin-init/src/__internal.rs |  27 ++++++
>>>>>  rust/pin-init/src/alloc.rs      | 158 ++++++++++++++++++++++++++++++++
>>>>>  rust/pin-init/src/lib.rs        |  17 ++--
>>>>>  3 files changed, 196 insertions(+), 6 deletions(-)
>>>>>  create mode 100644 rust/pin-init/src/alloc.rs
>>>>>
>>>>> diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
>>>>> index 74086365a18a..27d4a8619c04 100644
>>>>> --- a/rust/pin-init/src/__internal.rs
>>>>> +++ b/rust/pin-init/src/__internal.rs
>>>>> @@ -186,6 +186,33 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
>>>>>      }
>>>>>  }
>>>>>
>>>>> +#[test]
>>>>
>>>> I think the kunit support we have in the pipeline will pick this up?
>>>
>>> Is that support also enabled for crates outside of the `kernel` crate?
>>> I would argue it shouldn't and then this isn't a problem.
>>
>> Re conversation about moving pin_init out of the kernel, we should
>> distinguish between vendored crates and crates that is part of the
>> kernel. This one is now vendored and tests are not meant to be run by
>> the kernel build system and infrastructure. Other crates will be
>> different, living in the kernel.
>
> Yes, but I wouldn't necessarily call this category "vendored"; e.g. we
> could write a crate that is kernel-only, but doesn't actually have any
> code that requires kernel infrastructure. How about we call these
> kernel-agnostic crates? :)

Sounds good to me 👍

>
>>>>> +fn stack_init_reuse() {
>>>>> +    use ::std::{borrow::ToOwned, println, string::String};
>>>>> +    use core::pin::pin;
>>>>> +
>>>>> +    #[derive(Debug)]
>>>>> +    struct Foo {
>>>>> +        a: usize,
>>>>> +        b: String,
>>>>> +    }
>>>>> +    let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
>>>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>>>> +        slot.as_mut().init(crate::init!(Foo {
>>>>> +            a: 42,
>>>>> +            b: "Hello".to_owned(),
>>>>> +        }));
>>>>> +    let value = value.unwrap();
>>>>> +    println!("{value:?}");
>>>>> +    let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
>>>>> +        slot.as_mut().init(crate::init!(Foo {
>>>>> +            a: 24,
>>>>> +            b: "world!".to_owned(),
>>>>> +        }));
>>>>> +    let value = value.unwrap();
>>>>> +    println!("{value:?}");
>>>>> +}
>>>>> +
>>>>
>>>> [...]
>>>>
>>>>> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
>>>>> index 55d8953620f0..1fdca35906a0 100644
>>>>> --- a/rust/pin-init/src/lib.rs
>>>>> +++ b/rust/pin-init/src/lib.rs
>>>>> @@ -204,8 +204,8 @@
>>>>>  //! [structurally pinned fields]:
>>>>>  //!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
>>>>>  //! [stack]: crate::stack_pin_init
>>>>> -//! [`Arc<T>`]: ../kernel/sync/struct.Arc.html
>>>>> -//! [`Box<T>`]: ../kernel/alloc/struct.KBox.html
>>>>> +//! [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
>>>>> +//! [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
>>>>
>>>> Now these will render incorrect in the kernel docs, right?
>>>
>>> What do you mean by that? The link will resolve to the std versions of
>>> `Arc` and `Box`. But that is also what this crate will support, as it
>>> doesn't know about the kernel's own alloc.
>>
>> I mean that if I render the kernel documentation, go to `pin_init` and
>> click the `Arc<T>` link, I end up in `std`. But I am in the kernel, so
>> not what I would expect.
>>
>> But I guess there is no easy solution? Being a kernel developer, I would
>> prefer a kernel first approach. Can't have it all, I guess.
>
> I could change the link depending on the `kernel` cfg, so
>
>     #![cfg_attr(kernel, doc = "[`Arc<T>`]: https://rust.docs.kernel.org..")]
>     #![cfg_attr(not(kernel), doc = "[`Arc<T>`]: https://doc.rust-lang.org...")]
>
> But if anyone visits the documentation on `docs.rs`, then they will get
> the user-space one... What do you think?

That would be nice. I think kernel developers would read the docs via
rust.docs.kernel.org, if they read them online (myself being my only
reference, so not enough sample size).


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 103+ messages in thread

end of thread, other threads:[~2025-03-05 17:27 UTC | newest]

Thread overview: 103+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <xn5HRPkxO91lsoIUAwMnnAvQRCAgmw6nzTZX2DsODS0viAvz_g6B8l3dpYNtcL2jBXySi0DQrVi04b6MY8GbMw==@protonmail.internalid>
2025-03-04 22:52 ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
2025-03-04 22:53   ` [PATCH 01/22] rust: init: disable doctests Benno Lossin
2025-03-05  8:51     ` Andreas Hindborg
2025-03-05 12:53       ` Benno Lossin
2025-03-05 13:00         ` Miguel Ojeda
2025-03-05 14:09         ` Andreas Hindborg
2025-03-05 14:31           ` Benno Lossin
2025-03-05  9:17     ` Fiona Behrens
2025-03-04 22:53   ` [PATCH 02/22] rust: move pin-init API into its own directory Benno Lossin
2025-03-05  9:03     ` Andreas Hindborg
2025-03-05  9:17     ` Fiona Behrens
2025-03-04 22:53   ` [PATCH 03/22] rust: add extensions to the pin-init crate and move relevant documentation there Benno Lossin
2025-03-05  9:11     ` Andreas Hindborg
2025-03-05 11:03       ` Benno Lossin
2025-03-05  9:17     ` Fiona Behrens
2025-03-04 22:53   ` [PATCH 04/22] rust: pin-init: move proc-macro documentation into pin-init crate Benno Lossin
2025-03-05  9:18     ` Fiona Behrens
2025-03-05  9:34     ` Andreas Hindborg
2025-03-05 11:05       ` Benno Lossin
2025-03-04 22:53   ` [PATCH 05/22] rust: pin-init: change examples to the user-space version Benno Lossin
2025-03-05  9:19     ` Fiona Behrens
2025-03-05 10:06     ` Andreas Hindborg
2025-03-04 22:53   ` [PATCH 06/22] rust: pin-init: call `try_[pin_]init!` from `[pin_]init!` instead of `__init_internal!` Benno Lossin
2025-03-05  9:19     ` Fiona Behrens
2025-03-05 10:12     ` Andreas Hindborg
2025-03-04 22:54   ` [PATCH 07/22] rust: pin-init: move the default error behavior of `try_[pin_]init` Benno Lossin
2025-03-05  9:21     ` Fiona Behrens
2025-03-05 10:29     ` Andreas Hindborg
2025-03-05 10:47       ` Benno Lossin
2025-03-04 22:54   ` [PATCH 08/22] rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate Benno Lossin
2025-03-05  9:23     ` Fiona Behrens
2025-03-05 11:18     ` Andreas Hindborg
2025-03-05 12:06       ` Benno Lossin
2025-03-05 12:28         ` Andreas Hindborg
2025-03-05 12:37           ` Benno Lossin
2025-03-04 22:54   ` [PATCH 09/22] rust: pin-init: move impl `Zeroable` for `Opaque` and `Option<KBox<T>>` " Benno Lossin
2025-03-05  9:24     ` Fiona Behrens
2025-03-05 11:26     ` Andreas Hindborg
2025-03-05 12:05       ` Benno Lossin
2025-03-05 12:11         ` Alice Ryhl
2025-03-05 12:17           ` Benno Lossin
2025-03-05 12:49             ` Alice Ryhl
2025-03-05 12:51               ` Benno Lossin
2025-03-04 22:54   ` [PATCH 10/22] rust: add `ZeroableOption` and implement it instead of `Zeroable` for `Option<Box<T, A>>` Benno Lossin
2025-03-05  9:25     ` Fiona Behrens
2025-03-05 11:30     ` Andreas Hindborg
2025-03-04 22:54   ` [PATCH 11/22] rust: pin-init: fix documentation links Benno Lossin
2025-03-05  9:26     ` Fiona Behrens
2025-03-05 11:37     ` Andreas Hindborg
2025-03-05 11:49       ` Benno Lossin
2025-03-04 22:54   ` [PATCH 12/22] rust: pin-init: remove kernel-crate dependency Benno Lossin
2025-03-05  9:27     ` Fiona Behrens
2025-03-05 11:49     ` Andreas Hindborg
2025-03-05 12:00       ` Benno Lossin
2025-03-05 12:27         ` Andreas Hindborg
2025-03-04 22:55   ` [PATCH 13/22] rust: pin-init: change the way the `paste!` macro is called Benno Lossin
2025-03-05  9:28     ` Fiona Behrens
2025-03-05 11:52     ` Andreas Hindborg
2025-03-04 22:55   ` [PATCH 14/22] rust: add pin-init crate build infrastructure Benno Lossin
2025-03-05 11:59     ` Andreas Hindborg
2025-03-05 12:10       ` Benno Lossin
2025-03-05 12:31         ` Andreas Hindborg
2025-03-05 12:50           ` Miguel Ojeda
2025-03-05 13:00             ` Benno Lossin
2025-03-05 14:19             ` Andreas Hindborg
2025-03-05 14:34               ` Benno Lossin
2025-03-05 12:47       ` Miguel Ojeda
2025-03-04 22:55   ` [PATCH 15/22] rust: make pin-init its own crate Benno Lossin
2025-03-05  9:29     ` Fiona Behrens
2025-03-05 12:12     ` Andreas Hindborg
2025-03-05 13:40       ` Benno Lossin
2025-03-05 14:20         ` Andreas Hindborg
2025-03-04 22:55   ` [PATCH 16/22] rust: pin-init: add `std` and `alloc` support from the user-space version Benno Lossin
2025-03-05  9:32     ` Fiona Behrens
2025-03-05 12:22     ` Andreas Hindborg
2025-03-05 13:55       ` Benno Lossin
2025-03-05 14:29         ` Andreas Hindborg
2025-03-05 15:05           ` Benno Lossin
2025-03-05 17:27             ` Andreas Hindborg
2025-03-04 22:55   ` [PATCH 17/22] rust: pin-init: synchronize documentation with " Benno Lossin
2025-03-05  9:33     ` Fiona Behrens
2025-03-05 12:52     ` Andreas Hindborg
2025-03-04 22:55   ` [PATCH 18/22] rust: pin-init: internal: synchronize with " Benno Lossin
2025-03-05 12:56     ` Andreas Hindborg
2025-03-04 22:56   ` [PATCH 19/22] rust: pin-init: miscellaneous synchronization with the " Benno Lossin
2025-03-05 12:57     ` Andreas Hindborg
2025-03-04 22:56   ` [PATCH 20/22] rust: pin-init: add miscellaneous files from " Benno Lossin
2025-03-05  9:35     ` Fiona Behrens
2025-03-05 13:04     ` Andreas Hindborg
2025-03-05 13:37       ` Miguel Ojeda
2025-03-05 13:58         ` Benno Lossin
2025-03-04 22:56   ` [PATCH 21/22] rust: pin-init: re-enable doctests Benno Lossin
2025-03-05  9:35     ` Fiona Behrens
2025-03-05 13:05     ` Andreas Hindborg
2025-03-04 22:56   ` [PATCH 22/22] MAINTAINERS: add entry for the `pin-init` crate Benno Lossin
2025-03-05  0:17     ` Jarkko Sakkinen
2025-03-05  0:43       ` Benno Lossin
2025-03-05  5:14         ` Jarkko Sakkinen
2025-03-04 23:12   ` [PATCH 00/22] make pin-init into a standalone crate Benno Lossin
2025-03-05 13:56   ` Andreas Hindborg
2025-03-05 14:03     ` Benno Lossin
2025-03-05 14:36       ` Andreas Hindborg
2025-03-05 14:47         ` Benno Lossin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).