Rust for Linux List
 help / color / mirror / Atom feed
* [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init`
@ 2026-07-29 15:38 Gary Guo
  2026-07-29 15:38 ` [PATCH v2 1/5] rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation Gary Guo
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

Currently we have `PinInit::__pinned_init` and `Init::__init` which has
slightly different safety requirement but are required to do the same
thing. Instead of having to duplicate impl everywhere, it's simpler to just
use `Init` as a marker trait that cancels out the pinning requirement on
`PinInit::__pinned_init`. This also simplifies code (and shorten the symbol
name) so `__init` can always be used.

However, there are multiple users currently using `__pinned_init`. This is
not designed to be public API; however `pin_init` failed to provide a
public API alternative so it is still being used. Add `ptr_init` and
`ptr_try_init` methods and convert users to use them instead. `__init`
users can use these as well due to the super-trait relationship.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
Changes in v2:
- Add a public API for `__init` and convert users.
- Remove the part about multiple cycles. Danilo suggests me to take the
  entirety in single cycle as this doesn't conflict with other branches.
- Link to v1: https://patch.msgid.link/20260722-merge-init-v1-0-d4594de76538@garyguo.net

---
Gary Guo (5):
      rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation
      rust: pin-init: merge `__pinned_init` and `__init`
      rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`
      rust: treewide: replace `__pinned_init` with `ptr_[try_]init`
      rust: pin-init: remove `__pinned_init` method for `cfg(kernel)`

 drivers/gpu/nova-core/gsp/cmdq.rs     |   4 +-
 rust/kernel/alloc/kbox.rs             |   8 +-
 rust/kernel/dma.rs                    |  10 +-
 rust/kernel/drm/device.rs             |   2 +-
 rust/kernel/drm/gpuvm/va.rs           |   2 +-
 rust/kernel/drm/gpuvm/vm_bo.rs        |   2 +-
 rust/kernel/init.rs                   |   6 +-
 rust/kernel/pwm.rs                    |   2 +-
 rust/kernel/sync/arc.rs               |   8 +-
 rust/kernel/types.rs                  |   8 +-
 rust/macros/module.rs                 |   2 +-
 rust/pin-init/examples/mutex.rs       |   6 +-
 rust/pin-init/examples/static_init.rs |  10 +-
 rust/pin-init/src/__internal.rs       |   8 +-
 rust/pin-init/src/alloc.rs            |   6 +-
 rust/pin-init/src/lib.rs              | 177 +++++++++++++++++-----------------
 16 files changed, 128 insertions(+), 133 deletions(-)
---
base-commit: 6d0795b507fb1db2e6aefe533d949db3a4abf4c6
change-id: 20260722-merge-init-3ed98519ec7f

Best regards,
--  
Gary Guo <gary@garyguo.net>


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

* [PATCH v2 1/5] rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
@ 2026-07-29 15:38 ` Gary Guo
  2026-07-29 15:38 ` [PATCH v2 2/5] rust: pin-init: merge `__pinned_init` and `__init` Gary Guo
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

`UnsafeCell` is able to obtain the extension trait via `Wrapper`.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/examples/mutex.rs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/rust/pin-init/examples/mutex.rs b/rust/pin-init/examples/mutex.rs
index 882f3e23f5dd..e8d4dbb664fe 100644
--- a/rust/pin-init/examples/mutex.rs
+++ b/rust/pin-init/examples/mutex.rs
@@ -79,11 +79,7 @@ pub fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
             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>())
-                })
-            },
+            data <- UnsafeCell::pin_init(val),
         })
     }
 

-- 
2.54.0


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

* [PATCH v2 2/5] rust: pin-init: merge `__pinned_init` and `__init`
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
  2026-07-29 15:38 ` [PATCH v2 1/5] rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation Gary Guo
@ 2026-07-29 15:38 ` Gary Guo
  2026-07-29 15:38 ` [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init` Gary Guo
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

These functions have the same requirements and are also required to execute
the same code. Prevent duplication by merging them to the single function
and document the additional relaxation of `Init::__init` on both the merged
function and the safety requirement of `Init`.

The existing `__pinned_init` function is deprecated and kept for
compatibility for existing users. For `cfg(kernel)`, it is soft-deprecated
for now and will be removed when all users are migrated.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/examples/static_init.rs |   9 +--
 rust/pin-init/src/__internal.rs       |   8 +-
 rust/pin-init/src/alloc.rs            |   6 +-
 rust/pin-init/src/lib.rs              | 146 +++++++++++++---------------------
 4 files changed, 67 insertions(+), 102 deletions(-)

diff --git a/rust/pin-init/examples/static_init.rs b/rust/pin-init/examples/static_init.rs
index 58cd4241b78c..8e71556ffe85 100644
--- a/rust/pin-init/examples/static_init.rs
+++ b/rust/pin-init/examples/static_init.rs
@@ -59,7 +59,7 @@ fn deref(&self) -> &Self::Target {
             println!("doing init");
             let ptr = self.cell.get().cast::<T>();
             match self.init.take() {
-                Some(f) => unsafe { f.__pinned_init(ptr).unwrap() },
+                Some(f) => unsafe { f.__init(ptr).unwrap() },
                 None => unsafe { core::hint::unreachable_unchecked() },
             }
             self.present.set(true);
@@ -71,13 +71,10 @@ fn deref(&self) -> &Self::Target {
 pub struct CountInit;
 
 unsafe impl PinInit<CMutex<usize>> for CountInit {
-    unsafe fn __pinned_init(
-        self,
-        slot: *mut CMutex<usize>,
-    ) -> Result<(), core::convert::Infallible> {
+    unsafe fn __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) }
+        unsafe { init.__init(slot) }
     }
 }
 
diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 56dc655e323e..ae9a0e68cd75 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -181,7 +181,7 @@ pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mu
             unsafe { this.value.assume_init_drop() };
         }
         // SAFETY: The memory slot is valid and this type ensures that it will stay pinned.
-        unsafe { init.__pinned_init(this.value.as_mut_ptr())? };
+        unsafe { init.__init(this.value.as_mut_ptr())? };
         // INVARIANT: `this.value` is initialized above.
         this.is_init = true;
         // SAFETY: The slot is now pinned, since we will never give access to `&mut T`.
@@ -289,7 +289,7 @@ pub fn init<E>(self, init: impl PinInit<T, E>) -> Result<DropGuard<Pinned, T>, E
         // - when `Err` is returned, we also propagate the error without touching `ptr`;
         //   also `self` is consumed so it cannot be touched further.
         // - the drop guard will not hand out `&mut` (only `Pin<&mut T>`).
-        unsafe { init.__pinned_init(self.ptr)? };
+        unsafe { init.__init(self.ptr)? };
 
         // SAFETY:
         // - `self.ptr` is valid, properly aligned and pinned per type invariant.
@@ -396,9 +396,9 @@ fn default() -> Self {
     }
 }
 
-// SAFETY: `__pinned_init` always fails, which is always okay.
+// SAFETY: `__init` always fails, which is always okay.
 unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> {
-    unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> {
+    unsafe fn __init(self, _slot: *mut T) -> Result<(), ()> {
         Err(())
     }
 }
diff --git a/rust/pin-init/src/alloc.rs b/rust/pin-init/src/alloc.rs
index 5017f57442d8..641f4c7ce890 100644
--- a/rust/pin-init/src/alloc.rs
+++ b/rust/pin-init/src/alloc.rs
@@ -38,7 +38,7 @@ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
     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) {
+            pin_init_from_closure(|slot| match init.__init(slot) {
                 Ok(()) => Ok(()),
                 Err(i) => match i {},
             })
@@ -109,7 +109,7 @@ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
         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)? };
+        unsafe { init.__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()) })
     }
@@ -149,7 +149,7 @@ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Ini
         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)? };
+        unsafe { init.__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 f4ccb0e87200..fde53473763f 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -889,7 +889,7 @@ macro_rules! assert_pinned {
 /// When implementing this trait you will need to take great care. Also there are probably very few
 /// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible.
 ///
-/// The [`PinInit::__pinned_init`] function:
+/// The [`PinInit::__init`] function:
 /// - returns `Ok(())` if it initialized every field of `slot`,
 /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
 ///     - `slot` can be deallocated without UB occurring,
@@ -909,6 +909,20 @@ macro_rules! assert_pinned {
 #[cfg_attr(not(kernel), doc = "[`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 {
+    /// Alias of [`PinInit::__init`].
+    ///
+    /// New code should use `__init` instead.
+    ///
+    /// # Safety
+    ///
+    /// Same as `__init`.
+    #[inline(always)]
+    #[cfg_attr(not(kernel), deprecated = "use `__init` instead")]
+    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
+        // SAFETY: Per safety requirement.
+        unsafe { self.__init(slot) }
+    }
+
     /// Initializes `slot`.
     ///
     /// # Safety
@@ -917,7 +931,8 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
     ///   deallocate.
     /// - `slot` will not move until it is dropped, i.e. it will be pinned.
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
+    ///   If `Self: Init<T, E>`, this requirement is cancelled and it may be moved.
+    unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
 
     /// First initializes the value using `self` then calls the function `f` with the initialized
     /// value.
@@ -948,7 +963,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::PhantomInvariant<(E, T)>);
 
-// SAFETY: The `__pinned_init` function is implemented such that it
+// SAFETY: The `__init` function is implemented such that it
 // - returns `Ok(())` on successful initialization,
 // - returns `Err(err)` on error and in this case `slot` will be dropped.
 // - considers `slot` pinned.
@@ -957,8 +972,8 @@ unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
     I: PinInit<T, E>,
     F: FnOnce(Pin<&mut T>) -> Result<(), E>,
 {
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
-        // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
+    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
+        // SAFETY: All requirements fulfilled since this function is `__init`.
         let slot = unsafe { __internal::Slot::<__internal::Pinned, _>::new(slot) };
         let mut guard = slot.init(self.0)?;
         (self.1)(guard.let_binding())?;
@@ -980,19 +995,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 /// When implementing this trait you will need to take great care. Also there are probably very few
 /// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible.
 ///
-/// The [`Init::__init`] function:
-/// - returns `Ok(())` if it initialized every field of `slot`,
-/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
-///     - `slot` can be deallocated without UB occurring,
-///     - `slot` does not need to be dropped,
-///     - `slot` is not partially initialized.
-/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
-///
-/// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same
-/// code as `__init`.
-///
-/// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
-/// move the pointee after initialization.
+/// The [`PinInit::__init`] function must work without the pinning requirement; the caller is
+/// allowed to move the pointee after initialization.
 ///
 #[cfg_attr(
     kernel,
@@ -1006,15 +1010,6 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 #[cfg_attr(not(kernel), doc = "[`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`.
-    ///
-    /// # Safety
-    ///
-    /// - `slot` is a valid pointer to uninitialized memory.
-    /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
-    ///   deallocate.
-    unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
-
     /// First initializes the value using `self` then calls the function `f` with the initialized
     /// value.
     ///
@@ -1053,10 +1048,18 @@ 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::PhantomInvariant<(E, T)>);
 
+// SAFETY: The `__init` function does not rely on the pinning requirement.
+unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
+where
+    I: Init<T, E>,
+    F: FnOnce(&mut T) -> Result<(), E>,
+{
+}
+
 // SAFETY: The `__init` function is implemented such that it
 // - returns `Ok(())` on successful initialization,
 // - returns `Err(err)` on error and in this case `slot` will be dropped.
-unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
+unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
 where
     I: Init<T, E>,
     F: FnOnce(&mut T) -> Result<(), E>,
@@ -1071,44 +1074,28 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
     }
 }
 
-// SAFETY: `__pinned_init` behaves exactly the same as `__init`.
-unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
-where
-    I: Init<T, E>,
-    F: FnOnce(&mut T) -> Result<(), E>,
-{
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
-        // SAFETY: `__init` has less strict requirements compared to `__pinned_init`.
-        unsafe { self.__init(slot) }
-    }
-}
-
 /// Implement `PinInit` and `Init` for closures.
 ///
 /// It is unsafe to create this type, since the closure needs to fulfill the same safety
-/// requirement as the `__pinned_init`/`__init` functions.
+/// requirement as the `__init` functions.
 struct InitClosure<F, T: ?Sized>(F, __internal::PhantomInvariant<T>);
 
-// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__init` invariants.
-unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T>
-where
-    F: FnOnce(*mut T) -> Result<(), E>,
+// SAFETY: When constructing via `init_from_closure`, the `__init` function does not rely on the
+// pinning requirement. When constructing via `pin_init_from_closure`, the opaque type prevents this
+// implementation from being visible.
+unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T> where
+    F: FnOnce(*mut T) -> Result<(), E>
 {
-    #[inline]
-    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
-        (self.0)(slot)
-    }
 }
 
 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__pinned_init` invariants.
+// `__init` invariants.
 unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T>
 where
     F: FnOnce(*mut T) -> Result<(), E>,
 {
     #[inline]
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
+    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
         (self.0)(slot)
     }
 }
@@ -1160,7 +1147,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> {
     // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
     // requirements.
-    unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) }
+    unsafe { pin_init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) }
 }
 
 /// Changes the to be initialized type.
@@ -1195,7 +1182,7 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
     F: FnMut(usize) -> I,
     I: PinInit<T, E>,
 {
-    unsafe fn __pinned_init(mut self, slot: *mut [T; N]) -> Result<(), E> {
+    unsafe fn __init(mut self, slot: *mut [T; N]) -> Result<(), E> {
         /// # Invariants
         ///
         /// - `ptr[..num_init]` contains initialized elements of type `T`
@@ -1237,7 +1224,7 @@ fn drop(&mut self) {
             // - If `Err` is touched, the subslot is not touched further, the guard will drop
             //   previously initialized elements only.
             // - `slot` is pinned so is the subslot.
-            unsafe { init.__pinned_init(&raw mut (*slot)[i]) }?;
+            unsafe { init.__init(&raw mut (*slot)[i]) }?;
         }
 
         // Dismiss the drop guard now that all elements are initialized.
@@ -1246,18 +1233,13 @@ fn drop(&mut self) {
     }
 }
 
-// SAFETY: Follows the `PinInit` impl. `__init` executes the same code as `__pinned_init`.
+// SAFETY: `I: Init` cancels out the pinning requirement on subslots, which is the only place in the
+// `__init` function that relies on `slot` being pinned.
 unsafe impl<T, F, I, E, const N: usize> Init<[T; N], E> for ArrayInit<T, F>
 where
     F: FnMut(usize) -> I,
     I: Init<T, E>,
 {
-    #[inline(always)]
-    unsafe fn __init(self, slot: *mut [T; N]) -> Result<(), E> {
-        // SAFETY: `I: Init` cancels out the pinning requirement on subslots. The other safety
-        // requirements follow that of `__init`.
-        unsafe { self.__pinned_init(slot) }
-    }
 }
 
 /// Initializes an array by initializing each element via the provided initializer.
@@ -1336,13 +1318,13 @@ pub fn pin_init_scope<T, E, F, I>(make_init: F) -> impl PinInit<T, E>
 {
     // SAFETY:
     // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized,
-    // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__pinned_init`.
-    // - The safety requirements of `init.__pinned_init` are fulfilled, since it's being called
-    //   from an initializer.
+    // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__init`.
+    // - The safety requirements of `init.__init` are fulfilled, since it's being called from an
+    //   initializer.
     unsafe {
         pin_init_from_closure(move |slot: *mut T| -> Result<(), E> {
             let init = make_init()?;
-            init.__pinned_init(slot)
+            init.__init(slot)
         })
     }
 }
@@ -1390,41 +1372,27 @@ pub fn init_scope<T, E, F, I>(make_init: F) -> impl Init<T, E>
     }
 }
 
-// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`.
-unsafe impl<T> Init<T> for T {
-    unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
-        // SAFETY: `slot` is valid for writes by the safety requirements of this function.
-        unsafe { slot.write(self) };
-        Ok(())
-    }
-}
+// SAFETY: The `__init` function does not rely on slot being pinned after it returns.
+unsafe impl<T> Init<T> for T {}
 
-// SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of
+// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of
 // `slot`. Additionally, all pinning invariants of `T` are upheld.
 unsafe impl<T> PinInit<T> for T {
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> {
+    unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
         // SAFETY: `slot` is valid for writes by the safety requirements of this function.
         unsafe { slot.write(self) };
         Ok(())
     }
 }
 
-// SAFETY: when the `__init` function returns with
-// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
-// - `Err(err)`, slot was not written to.
-unsafe impl<T, E> Init<T, E> for Result<T, E> {
-    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
-        // SAFETY: `slot` is valid for writes by the safety requirements of this function.
-        unsafe { slot.write(self?) };
-        Ok(())
-    }
-}
+// SAFETY: The `__init` function does not rely on slot being pinned after it returns.
+unsafe impl<T, E> Init<T, E> for Result<T, E> {}
 
-// SAFETY: when the `__pinned_init` function returns with
+// SAFETY: when the `__init` function returns with
 // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
 // - `Err(err)`, slot was not written to.
 unsafe impl<T, E> PinInit<T, E> for Result<T, E> {
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
+    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: `slot` is valid for writes by the safety requirements of this function.
         unsafe { slot.write(self?) };
         Ok(())
@@ -1467,7 +1435,7 @@ fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initial
         //
         // The `'static` borrow guarantees the data will not be
         // moved/invalidated until it gets dropped (which is never).
-        unsafe { init.__pinned_init(slot)? };
+        unsafe { init.__init(slot)? };
 
         // SAFETY: The above call initialized the memory.
         Ok(Pin::static_mut(unsafe { self.assume_init_mut() }))

-- 
2.54.0


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

* [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
  2026-07-29 15:38 ` [PATCH v2 1/5] rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation Gary Guo
  2026-07-29 15:38 ` [PATCH v2 2/5] rust: pin-init: merge `__pinned_init` and `__init` Gary Guo
@ 2026-07-29 15:38 ` Gary Guo
  2026-08-05 10:22   ` Benno Lossin
  2026-07-29 15:38 ` [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init` Gary Guo
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

The `__init` method is not designed to be a public API (existence of "__"
is a hint for this); but currently there is no other API that allows raw
initialization on pointers. Add `ptr_init` and `ptr_try_init` and recommend
people to use this instead if raw pointer initialization is needed.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/examples/static_init.rs |  5 +++--
 rust/pin-init/src/lib.rs              | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/rust/pin-init/examples/static_init.rs b/rust/pin-init/examples/static_init.rs
index 8e71556ffe85..109cceea2eab 100644
--- a/rust/pin-init/examples/static_init.rs
+++ b/rust/pin-init/examples/static_init.rs
@@ -59,7 +59,7 @@ fn deref(&self) -> &Self::Target {
             println!("doing init");
             let ptr = self.cell.get().cast::<T>();
             match self.init.take() {
-                Some(f) => unsafe { f.__init(ptr).unwrap() },
+                Some(f) => unsafe { pin_init::ptr_init(ptr, f) },
                 None => unsafe { core::hint::unreachable_unchecked() },
             }
             self.present.set(true);
@@ -74,7 +74,8 @@ unsafe impl PinInit<CMutex<usize>> for CountInit {
     unsafe fn __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.__init(slot) }
+        unsafe { pin_init::ptr_init(slot, init) };
+        Ok(())
     }
 }
 
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index fde53473763f..78a67ef54f4e 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -917,7 +917,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     ///
     /// Same as `__init`.
     #[inline(always)]
-    #[cfg_attr(not(kernel), deprecated = "use `__init` instead")]
+    #[cfg_attr(not(kernel), deprecated = "use `ptr_try_init` instead")]
     unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: Per safety requirement.
         unsafe { self.__init(slot) }
@@ -925,6 +925,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 
     /// Initializes `slot`.
     ///
+    /// It is not recommended to call this directly. Use [`ptr_init`] or [`ptr_try_init`].
+    ///
     /// # Safety
     ///
     /// - `slot` is a valid pointer to uninitialized memory.
@@ -960,6 +962,34 @@ fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
     }
 }
 
+/// Initializes `slot` with an initializer.
+///
+/// # Safety
+///
+/// - `slot` is a valid pointer to uninitialized memory.
+/// - `slot` will not move until it is dropped, i.e. it will be pinned.
+///   If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
+#[inline(always)]
+pub unsafe fn ptr_init<T>(slot: *mut T, init: impl PinInit<T>) {
+    // SAFETY: Per safety requirement.
+    unsafe { init.__init(slot).unwrap_or_else(|e| match e {}) }
+}
+
+/// Fallibly initializes `slot` with an initializer.
+///
+/// # Safety
+///
+/// - `slot` is a valid pointer to uninitialized memory.
+/// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
+///   deallocate.
+/// - `slot` will not move until it is dropped, i.e. it will be pinned.
+///   If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
+#[inline(always)]
+pub unsafe fn ptr_try_init<T, E>(slot: *mut T, init: impl PinInit<T, E>) -> Result<(), E> {
+    // SAFETY: Per safety requirement.
+    unsafe { init.__init(slot) }
+}
+
 /// An initializer returned by [`PinInit::pin_chain`].
 pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::PhantomInvariant<(E, T)>);
 

-- 
2.54.0


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

* [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init`
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
                   ` (2 preceding siblings ...)
  2026-07-29 15:38 ` [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init` Gary Guo
@ 2026-07-29 15:38 ` Gary Guo
  2026-07-30 14:03   ` Danilo Krummrich
  2026-08-03 12:19   ` Miguel Ojeda
  2026-07-29 15:38 ` [PATCH v2 5/5] rust: pin-init: remove `__pinned_init` method for `cfg(kernel)` Gary Guo
  2026-08-03 13:54 ` [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
  5 siblings, 2 replies; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

The `__init` method is not designed to be a public API (existence of "__"
is a hint for this); replace users with `pin_init::ptr_[try_]init` which
does the same thing.

There are a few users of `__init` which are replaced as well.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 drivers/gpu/nova-core/gsp/cmdq.rs |  4 ++--
 rust/kernel/alloc/kbox.rs         |  8 ++++----
 rust/kernel/dma.rs                | 10 +++++-----
 rust/kernel/drm/device.rs         |  2 +-
 rust/kernel/drm/gpuvm/va.rs       |  2 +-
 rust/kernel/drm/gpuvm/vm_bo.rs    |  2 +-
 rust/kernel/init.rs               |  6 ++++--
 rust/kernel/pwm.rs                |  2 +-
 rust/kernel/sync/arc.rs           |  8 ++++----
 rust/kernel/types.rs              |  8 ++++----
 rust/macros/module.rs             |  2 +-
 11 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 070de0731e95..dbcd06a43350 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -645,8 +645,8 @@ fn send_single_command<M>(&mut self, bar: Bar0<'_>, command: M) -> Result
         // SAFETY: `msg_header` and `cmd` are valid references, and not touched if the initializer
         // fails.
         unsafe {
-            msg_element.__init(core::ptr::from_mut(dst.header))?;
-            command.init().__init(core::ptr::from_mut(cmd))?;
+            pin_init::ptr_try_init(core::ptr::from_mut(dst.header), msg_element)?;
+            pin_init::ptr_try_init(core::ptr::from_mut(cmd), command.init())?;
         }
 
         // Fill the variable-length payload, which may be empty.
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 35d1e015848d..c04c687b9ef3 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -372,13 +372,13 @@ pub fn pin_slice<Func, Item, E>(
             // - `ptr` is a valid pointer to uninitialized memory.
             // - `ptr` is not used if an error is returned.
             // - `ptr` won't be moved until it is dropped, i.e. it is pinned.
-            unsafe { init(i).__pinned_init(ptr)? };
+            unsafe { pin_init::ptr_try_init(ptr, init(i))? };
 
             // SAFETY:
             // - `i + 1 <= len`, hence we don't exceed the capacity, due to the call to
             //   `with_capacity()` above.
             // - The new value at index buffer.len() + 1 is the only element being added here, and
-            //   it has been initialized above by `init(i).__pinned_init(ptr)`.
+            //   it has been initialized above by `ptr_try_init(ptr, i)`.
             unsafe { buffer.inc_len(1) };
         }
 
@@ -463,7 +463,7 @@ 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)? };
+        unsafe { pin_init::ptr_try_init(slot, init)? };
         // SAFETY: All fields have been initialized.
         Ok(unsafe { Box::assume_init(self) })
     }
@@ -473,7 +473,7 @@ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Ini
         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)? };
+        unsafe { pin_init::ptr_try_init(slot, init)? };
         // SAFETY: All fields have been initialized.
         Ok(unsafe { Box::assume_init(self) }.into())
     }
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 200def84fb69..21e4f7b03836 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -449,7 +449,7 @@ pub fn init_at<E>(&mut self, i: usize, init: impl Init<T, E>) -> Result
         // - `T: AsBytes + FromBytes` guarantees all bit patterns are valid, so partial writes on
         //   error cannot leave the element in an invalid state.
         // - The DMA address has not been exposed yet, so there is no concurrent device access.
-        unsafe { init.__init(ptr)? };
+        unsafe { pin_init::ptr_try_init(ptr, init)? };
 
         Ok(())
     }
@@ -791,10 +791,10 @@ pub fn init_with_attrs<E>(
 
         // SAFETY:
         // - `ptr` is valid, properly aligned, and points to exclusively owned memory.
-        // - If `__init` fails, `self` is dropped, which safely frees the underlying `Coherent`'s
-        //   DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop` requirements
-        //   we are bypassing.
-        unsafe { init.__init(ptr)? };
+        // - If `ptr_try_init` fails, `self` is dropped, which safely frees the underlying
+        //   `Coherent`'s DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop`
+        //   requirements we are bypassing.
+        unsafe { pin_init::ptr_try_init(ptr, init)? };
 
         Ok(dmem)
     }
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 477cf771fb10..290f0cd471ce 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -244,7 +244,7 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<S
         // SAFETY:
         // - `raw_data` is a valid pointer to uninitialized memory.
         // - `raw_data` will not move until it is dropped.
-        unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| {
+        unsafe { pin_init::ptr_try_init(raw_data, data) }.inspect_err(|_| {
             // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the
             // refcount must be non-zero.
             unsafe { bindings::drm_dev_put(drm_dev) };
diff --git a/rust/kernel/drm/gpuvm/va.rs b/rust/kernel/drm/gpuvm/va.rs
index 0b09fe44ab39..b61209090c32 100644
--- a/rust/kernel/drm/gpuvm/va.rs
+++ b/rust/kernel/drm/gpuvm/va.rs
@@ -116,7 +116,7 @@ pub fn new(flags: AllocFlags) -> Result<GpuVaAlloc<T>, AllocError> {
     pub(super) fn prepare(mut self, va_data: impl PinInit<T::VaData>) -> *mut bindings::drm_gpuva {
         let va_ptr = MaybeUninit::as_mut_ptr(&mut self.0);
         // SAFETY: The `data` field is pinned.
-        let Ok(()) = unsafe { va_data.__pinned_init(&raw mut (*va_ptr).data) };
+        unsafe { pin_init::ptr_init(&raw mut (*va_ptr).data, va_data) };
         KBox::into_raw(self.0).cast()
     }
 }
diff --git a/rust/kernel/drm/gpuvm/vm_bo.rs b/rust/kernel/drm/gpuvm/vm_bo.rs
index c064ac63897b..cb0662c71087 100644
--- a/rust/kernel/drm/gpuvm/vm_bo.rs
+++ b/rust/kernel/drm/gpuvm/vm_bo.rs
@@ -181,7 +181,7 @@ pub(super) fn new(
         };
         let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
         // SAFETY: `ptr->data` is a valid pinned location.
-        let Ok(()) = unsafe { value.__pinned_init(&raw mut (*raw_ptr).data) };
+        unsafe { pin_init::ptr_init(&raw mut (*raw_ptr).data, value) };
         // INVARIANTS: We just created the vm_bo so it's absent from lists, and the data is valid
         // as we just initialized it.
         Ok(GpuVmBoAlloc(ptr))
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 05a12e869a57..7d2c6bc5dd36 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -158,7 +158,9 @@ fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::Pi
     {
         // 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)))
+            pin_init_from_closure(|slot| {
+                pin_init::ptr_try_init(slot, init).map_err(|e| Error::from(e))
+            })
         };
         Self::try_pin_init(init, flags)
     }
@@ -176,7 +178,7 @@ fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
     {
         // 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)))
+            init_from_closure(|slot| pin_init::ptr_try_init(slot, init).map_err(|e| Error::from(e)))
         };
         Self::try_init(init, flags)
     }
diff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs
index 6c9d667009ef..5affd88b0fe8 100644
--- a/rust/kernel/pwm.rs
+++ b/rust/kernel/pwm.rs
@@ -600,7 +600,7 @@ pub fn new<'a>(
         let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) };
 
         // SAFETY: We construct the `T` object in-place in the allocated private memory.
-        unsafe { data.__pinned_init(drvdata_ptr.cast()) }.inspect_err(|_| {
+        unsafe { pin_init::ptr_try_init(drvdata_ptr.cast(), data) }.inspect_err(|_| {
             // SAFETY: It is safe to call `pwmchip_put()` with a valid pointer obtained
             // from `pwmchip_alloc()`. We will not use pointer after this.
             unsafe { bindings::pwmchip_put(c_chip_ptr) }
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 5ac4961b7cd2..66af7035b824 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -717,7 +717,7 @@ 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)? };
+        unsafe { pin_init::ptr_try_init(slot, init)? };
         // SAFETY: All fields have been initialized.
         Ok(unsafe { self.assume_init() })
     }
@@ -727,7 +727,7 @@ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Ini
         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)? };
+        unsafe { pin_init::ptr_try_init(slot, init)? };
         // SAFETY: All fields have been initialized.
         Ok(unsafe { self.assume_init() }.into())
     }
@@ -795,7 +795,7 @@ pub unsafe fn assume_init(self) -> UniqueArc<T> {
     #[inline]
     pub fn init_with<E>(mut self, init: impl Init<T, E>) -> core::result::Result<UniqueArc<T>, E> {
         // SAFETY: The supplied pointer is valid for initialization.
-        match unsafe { init.__init(self.as_mut_ptr()) } {
+        match unsafe { pin_init::ptr_try_init(self.as_mut_ptr(), init) } {
             // SAFETY: Initialization completed successfully.
             Ok(()) => Ok(unsafe { self.assume_init() }),
             Err(err) => Err(err),
@@ -810,7 +810,7 @@ pub fn pin_init_with<E>(
     ) -> core::result::Result<Pin<UniqueArc<T>>, E> {
         // SAFETY: The supplied pointer is valid for initialization and we will later pin the value
         // to ensure it does not move.
-        match unsafe { init.__pinned_init(self.as_mut_ptr()) } {
+        match unsafe { pin_init::ptr_try_init(self.as_mut_ptr(), init) } {
             // SAFETY: Initialization completed successfully.
             Ok(()) => Ok(unsafe { self.assume_init() }.into()),
             Err(err) => Err(err),
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index ac316fd7b538..46497957d846 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -417,13 +417,13 @@ pub const fn cast_from(this: *const T) -> *const Self {
 
 impl<T> Wrapper<T> for Opaque<T> {
     /// Create an opaque pin-initializer from the given pin-initializer.
-    fn pin_init<E>(slot: impl PinInit<T, E>) -> impl PinInit<Self, E> {
-        Self::try_ffi_init(|ptr: *mut T| {
+    fn pin_init<E>(init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
+        Self::try_ffi_init(|slot: *mut T| {
             // SAFETY:
-            //   - `ptr` is a valid pointer to uninitialized memory,
+            //   - `slot` is a valid pointer to uninitialized memory,
             //   - `slot` is not accessed on error,
             //   - `slot` is pinned in memory.
-            unsafe { PinInit::<T, E>::__pinned_init(slot, ptr) }
+            unsafe { pin_init::ptr_try_init(slot, init) }
         })
     }
 }
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 06c18e207508..1421109f6487 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -621,7 +621,7 @@ unsafe fn __init() -> ::kernel::ffi::c_int {
                     // SAFETY: No data race, since `__MOD` can only be accessed by this module
                     // and there only `__init` and `__exit` access it. These functions are only
                     // called once and `__exit` cannot be called before or during `__init`.
-                    match unsafe { initer.__pinned_init(__MOD.as_mut_ptr()) } {
+                    match unsafe { ::pin_init::ptr_try_init(__MOD.as_mut_ptr(), initer) } {
                         Ok(m) => 0,
                         Err(e) => e.to_errno(),
                     }

-- 
2.54.0


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

* [PATCH v2 5/5] rust: pin-init: remove `__pinned_init` method for `cfg(kernel)`
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
                   ` (3 preceding siblings ...)
  2026-07-29 15:38 ` [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init` Gary Guo
@ 2026-07-29 15:38 ` Gary Guo
  2026-08-03 13:54 ` [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
  5 siblings, 0 replies; 11+ messages in thread
From: Gary Guo @ 2026-07-29 15:38 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel, Gary Guo

Remove `__pinned_init` for kernel configuration, with all users gone.
Still perserve it temporarily as deprecated so other users have time to
move off it.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/lib.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 78a67ef54f4e..16f60dcb8330 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -917,7 +917,8 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     ///
     /// Same as `__init`.
     #[inline(always)]
-    #[cfg_attr(not(kernel), deprecated = "use `ptr_try_init` instead")]
+    #[cfg(not(kernel))]
+    #[deprecated = "use `ptr_try_init` instead"]
     unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: Per safety requirement.
         unsafe { self.__init(slot) }

-- 
2.54.0


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

* Re: [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init`
  2026-07-29 15:38 ` [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init` Gary Guo
@ 2026-07-30 14:03   ` Danilo Krummrich
  2026-08-03 12:19   ` Miguel Ojeda
  1 sibling, 0 replies; 11+ messages in thread
From: Danilo Krummrich @ 2026-07-30 14:03 UTC (permalink / raw)
  To: Gary Guo
  Cc: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan,
	Michal Wilczynski, rust-for-linux, linux-pwm, linux-kernel

On 7/29/26 5:38 PM, Gary Guo wrote:
> The `__init` method is not designed to be a public API (existence of "__"
> is a hint for this); replace users with `pin_init::ptr_[try_]init` which
> does the same thing.
> 
> There are a few users of `__init` which are replaced as well.
> 
> Signed-off-by: Gary Guo <gary@garyguo.net>


Acked-by: Danilo Krummrich <dakr@kernel.org>

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

* Re: [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init`
  2026-07-29 15:38 ` [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init` Gary Guo
  2026-07-30 14:03   ` Danilo Krummrich
@ 2026-08-03 12:19   ` Miguel Ojeda
  1 sibling, 0 replies; 11+ messages in thread
From: Miguel Ojeda @ 2026-08-03 12:19 UTC (permalink / raw)
  To: Gary Guo
  Cc: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski, rust-for-linux, linux-pwm,
	linux-kernel

On Wed, Jul 29, 2026 at 5:39 PM Gary Guo <gary@garyguo.net> wrote:
>
> The `__init` method is not designed to be a public API (existence of "__"
> is a hint for this); replace users with `pin_init::ptr_[try_]init` which
> does the same thing.
>
> There are a few users of `__init` which are replaced as well.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>

Since you asked:

Acked-by: Miguel Ojeda <ojeda@kernel.org>

But I obviously trust you to change this even treewide! :)

Thanks!

Cheers,
Miguel

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

* Re: [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init`
  2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
                   ` (4 preceding siblings ...)
  2026-07-29 15:38 ` [PATCH v2 5/5] rust: pin-init: remove `__pinned_init` method for `cfg(kernel)` Gary Guo
@ 2026-08-03 13:54 ` Gary Guo
  5 siblings, 0 replies; 11+ messages in thread
From: Gary Guo @ 2026-08-03 13:54 UTC (permalink / raw)
  To: Gary Guo, Benno Lossin, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel

On Wed Jul 29, 2026 at 4:38 PM BST, Gary Guo wrote:
> Currently we have `PinInit::__pinned_init` and `Init::__init` which has
> slightly different safety requirement but are required to do the same
> thing. Instead of having to duplicate impl everywhere, it's simpler to just
> use `Init` as a marker trait that cancels out the pinning requirement on
> `PinInit::__pinned_init`. This also simplifies code (and shorten the symbol
> name) so `__init` can always be used.
>
> However, there are multiple users currently using `__pinned_init`. This is
> not designed to be public API; however `pin_init` failed to provide a
> public API alternative so it is still being used. Add `ptr_init` and
> `ptr_try_init` methods and convert users to use them instead. `__init`
> users can use these as well due to the super-trait relationship.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> ---
> Changes in v2:
> - Add a public API for `__init` and convert users.
> - Remove the part about multiple cycles. Danilo suggests me to take the
>   entirety in single cycle as this doesn't conflict with other branches.
> - Link to v1: https://patch.msgid.link/20260722-merge-init-v1-0-d4594de76538@garyguo.net
>
> ---
> Gary Guo (5):
>       rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation

[ Reworded commit message as it's a bit unclear. ]

>       rust: pin-init: merge `__pinned_init` and `__init`
>       rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`
>       rust: treewide: replace `__pinned_init` with `ptr_[try_]init`
>       rust: pin-init: remove `__pinned_init` method for `cfg(kernel)`

Applied to pin-init-next.

Best,
Gary

>
>  drivers/gpu/nova-core/gsp/cmdq.rs     |   4 +-
>  rust/kernel/alloc/kbox.rs             |   8 +-
>  rust/kernel/dma.rs                    |  10 +-
>  rust/kernel/drm/device.rs             |   2 +-
>  rust/kernel/drm/gpuvm/va.rs           |   2 +-
>  rust/kernel/drm/gpuvm/vm_bo.rs        |   2 +-
>  rust/kernel/init.rs                   |   6 +-
>  rust/kernel/pwm.rs                    |   2 +-
>  rust/kernel/sync/arc.rs               |   8 +-
>  rust/kernel/types.rs                  |   8 +-
>  rust/macros/module.rs                 |   2 +-
>  rust/pin-init/examples/mutex.rs       |   6 +-
>  rust/pin-init/examples/static_init.rs |  10 +-
>  rust/pin-init/src/__internal.rs       |   8 +-
>  rust/pin-init/src/alloc.rs            |   6 +-
>  rust/pin-init/src/lib.rs              | 177 +++++++++++++++++-----------------
>  16 files changed, 128 insertions(+), 133 deletions(-)
> ---
> base-commit: 6d0795b507fb1db2e6aefe533d949db3a4abf4c6
> change-id: 20260722-merge-init-3ed98519ec7f
>
> Best regards,
> --  
> Gary Guo <gary@garyguo.net>



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

* Re: [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`
  2026-07-29 15:38 ` [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init` Gary Guo
@ 2026-08-05 10:22   ` Benno Lossin
  2026-08-05 10:56     ` Gary Guo
  0 siblings, 1 reply; 11+ messages in thread
From: Benno Lossin @ 2026-08-05 10:22 UTC (permalink / raw)
  To: Gary Guo, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel

On Wed Jul 29, 2026 at 5:38 PM CEST, Gary Guo wrote:
> The `__init` method is not designed to be a public API (existence of "__"
> is a hint for this); but currently there is no other API that allows raw
> initialization on pointers. Add `ptr_init` and `ptr_try_init` and recommend
> people to use this instead if raw pointer initialization is needed.

How about we call these two functions `raw_init` and `raw_try_init`
respectively? I feel like that conveys the meaning of what they are
doing much better.

With that: Reviewed-by: Benno Lossin <lossin@kernel.org>

Cheers,
Benno

> Signed-off-by: Gary Guo <gary@garyguo.net>
> ---
>  rust/pin-init/examples/static_init.rs |  5 +++--
>  rust/pin-init/src/lib.rs              | 32 +++++++++++++++++++++++++++++++-
>  2 files changed, 34 insertions(+), 3 deletions(-)

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

* Re: [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`
  2026-08-05 10:22   ` Benno Lossin
@ 2026-08-05 10:56     ` Gary Guo
  0 siblings, 0 replies; 11+ messages in thread
From: Gary Guo @ 2026-08-05 10:56 UTC (permalink / raw)
  To: Benno Lossin, Gary Guo, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, Michal Wilczynski
  Cc: rust-for-linux, linux-pwm, linux-kernel

On Wed Aug 5, 2026 at 11:22 AM BST, Benno Lossin wrote:
> On Wed Jul 29, 2026 at 5:38 PM CEST, Gary Guo wrote:
>> The `__init` method is not designed to be a public API (existence of "__"
>> is a hint for this); but currently there is no other API that allows raw
>> initialization on pointers. Add `ptr_init` and `ptr_try_init` and recommend
>> people to use this instead if raw pointer initialization is needed.
>
> How about we call these two functions `raw_init` and `raw_try_init`
> respectively? I feel like that conveys the meaning of what they are
> doing much better.
>
> With that: Reviewed-by: Benno Lossin <lossin@kernel.org>

Hmm, I agree that these names are better.

Given that I've picked these to pin-init-next already, I've amended the tree.
Could you check the changes I made there?

Best,
Gary

>
> Cheers,
> Benno
>
>> Signed-off-by: Gary Guo <gary@garyguo.net>
>> ---
>>  rust/pin-init/examples/static_init.rs |  5 +++--
>>  rust/pin-init/src/lib.rs              | 32 +++++++++++++++++++++++++++++++-
>>  2 files changed, 34 insertions(+), 3 deletions(-)



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

end of thread, other threads:[~2026-08-05 10:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 15:38 [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo
2026-07-29 15:38 ` [PATCH v2 1/5] rust: pin-init: examples: use `Wrapper::pin_init` instead of manual reimplementation Gary Guo
2026-07-29 15:38 ` [PATCH v2 2/5] rust: pin-init: merge `__pinned_init` and `__init` Gary Guo
2026-07-29 15:38 ` [PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init` Gary Guo
2026-08-05 10:22   ` Benno Lossin
2026-08-05 10:56     ` Gary Guo
2026-07-29 15:38 ` [PATCH v2 4/5] rust: treewide: replace `__pinned_init` with `ptr_[try_]init` Gary Guo
2026-07-30 14:03   ` Danilo Krummrich
2026-08-03 12:19   ` Miguel Ojeda
2026-07-29 15:38 ` [PATCH v2 5/5] rust: pin-init: remove `__pinned_init` method for `cfg(kernel)` Gary Guo
2026-08-03 13:54 ` [PATCH v2 0/5] rust: pin-init: merge `__init` and `__pinned_init` Gary Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox