From: Benno Lossin <lossin@kernel.org>
To: "Andreas Hindborg" <a.hindborg@kernel.org>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Jens Axboe" <axboe@kernel.dk>, "Fiona Behrens" <me@kloenk.dev>,
"Christian Schrefl" <chrisi.schrefl@gmail.com>
Cc: linux-block@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] change blanket impls for `[Pin]Init` and add one for `Result<T, E>`
Date: Thu, 29 May 2025 10:10:24 +0200 [thread overview]
Message-ID: <20250529081027.297648-2-lossin@kernel.org> (raw)
In-Reply-To: <20250529081027.297648-1-lossin@kernel.org>
Remove the error from the blanket implementations `impl<T, E> Init<T, E>
for T` (and also for `PinInit`). Add implementations for `Result<T, E>`.
This allows one to easily construct (un)conditional failing
initializers. It also improves the compatibility with APIs that do not
use pin-init, because users can supply a `Result<T, E>` to a function
taking an `impl PinInit<T, E>`.
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Link: https://github.com/Rust-for-Linux/pin-init/pull/62/commits/58612514b256c6f4a4a0718be25298410e67387a
[ Also fix a compile error in block. - Benno ]
Signed-off-by: Benno Lossin <lossin@kernel.org>
---
This patch is also needed by Danilo for initializing `Devres`
ergonomically.
---
rust/kernel/block/mq/tag_set.rs | 12 +++++++-----
rust/pin-init/src/lib.rs | 30 ++++++++++++++++++++++++++----
2 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index bcf4214ad149..c3cf56d52bee 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -9,7 +9,7 @@
use crate::{
bindings,
block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations},
- error,
+ error::{self, Result},
prelude::try_pin_init,
types::Opaque,
};
@@ -41,7 +41,7 @@ pub fn new(
// SAFETY: `blk_mq_tag_set` only contains integers and pointers, which
// all are allowed to be 0.
let tag_set: bindings::blk_mq_tag_set = unsafe { core::mem::zeroed() };
- let tag_set = core::mem::size_of::<RequestDataWrapper>()
+ let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>()
.try_into()
.map(|cmd_size| {
bindings::blk_mq_tag_set {
@@ -56,12 +56,14 @@ pub fn new(
nr_maps: num_maps,
..tag_set
}
- });
+ })
+ .map(Opaque::new)
+ .map_err(|e| e.into());
try_pin_init!(TagSet {
- inner <- PinInit::<_, error::Error>::pin_chain(Opaque::new(tag_set?), |tag_set| {
+ inner <- tag_set.pin_chain(|tag_set| {
// SAFETY: we do not move out of `tag_set`.
- let tag_set = unsafe { Pin::get_unchecked_mut(tag_set) };
+ let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) };
// SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`.
error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})
}),
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index d1c3ca5cfff4..f4e034497cdd 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1391,8 +1391,8 @@ pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
}
// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`.
-unsafe impl<T, E> Init<T, E> for T {
- unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
+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(())
@@ -1401,14 +1401,36 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
// SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of
// `slot`. Additionally, all pinning invariants of `T` are upheld.
-unsafe impl<T, E> PinInit<T, E> for T {
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
+unsafe impl<T> PinInit<T> for T {
+ unsafe fn __pinned_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: when the `__pinned_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> {
+ // SAFETY: `slot` is valid for writes by the safety requirements of this function.
+ unsafe { slot.write(self?) };
+ Ok(())
+ }
+}
+
/// 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.
--
2.49.0
next parent reply other threads:[~2025-05-29 8:10 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20250529081027.297648-1-lossin@kernel.org>
2025-05-29 8:10 ` Benno Lossin [this message]
2025-05-29 19:11 ` [PATCH 2/2] change blanket impls for `[Pin]Init` and add one for `Result<T, E>` Boqun Feng
2025-05-29 19:54 ` Benno Lossin
2025-06-10 13:44 ` Danilo Krummrich
2025-06-11 21:27 ` Benno Lossin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250529081027.297648-2-lossin@kernel.org \
--to=lossin@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=axboe@kernel.dk \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=chrisi.schrefl@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=me@kloenk.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox