Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: pin-init: change blanket impls for `[Pin]Init` and add one for `Result<T, E>`

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 ]
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/all/20250529081027.297648-2-lossin@kernel.org
[ Add title prefix `rust: pin-init`. - Benno ]
Signed-off-by: Benno Lossin <lossin@kernel.org>

+33 -9
+7 -5
rust/kernel/block/mq/tag_set.rs
··· 9 9 use crate::{ 10 10 bindings, 11 11 block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations}, 12 - error, 12 + error::{self, Result}, 13 13 prelude::try_pin_init, 14 14 types::Opaque, 15 15 }; ··· 41 41 // SAFETY: `blk_mq_tag_set` only contains integers and pointers, which 42 42 // all are allowed to be 0. 43 43 let tag_set: bindings::blk_mq_tag_set = unsafe { core::mem::zeroed() }; 44 - let tag_set = core::mem::size_of::<RequestDataWrapper>() 44 + let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>() 45 45 .try_into() 46 46 .map(|cmd_size| { 47 47 bindings::blk_mq_tag_set { ··· 56 56 nr_maps: num_maps, 57 57 ..tag_set 58 58 } 59 - }); 59 + }) 60 + .map(Opaque::new) 61 + .map_err(|e| e.into()); 60 62 61 63 try_pin_init!(TagSet { 62 - inner <- PinInit::<_, error::Error>::pin_chain(Opaque::new(tag_set?), |tag_set| { 64 + inner <- tag_set.pin_chain(|tag_set| { 63 65 // SAFETY: we do not move out of `tag_set`. 64 - let tag_set = unsafe { Pin::get_unchecked_mut(tag_set) }; 66 + let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) }; 65 67 // SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`. 66 68 error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())}) 67 69 }),
+26 -4
rust/pin-init/src/lib.rs
··· 1391 1391 } 1392 1392 1393 1393 // SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`. 1394 - unsafe impl<T, E> Init<T, E> for T { 1395 - unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 1394 + unsafe impl<T> Init<T> for T { 1395 + unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> { 1396 1396 // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1397 1397 unsafe { slot.write(self) }; 1398 1398 Ok(()) ··· 1401 1401 1402 1402 // SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of 1403 1403 // `slot`. Additionally, all pinning invariants of `T` are upheld. 1404 - unsafe impl<T, E> PinInit<T, E> for T { 1405 - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 1404 + unsafe impl<T> PinInit<T> for T { 1405 + unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> { 1406 1406 // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1407 1407 unsafe { slot.write(self) }; 1408 + Ok(()) 1409 + } 1410 + } 1411 + 1412 + // SAFETY: when the `__init` function returns with 1413 + // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. 1414 + // - `Err(err)`, slot was not written to. 1415 + unsafe impl<T, E> Init<T, E> for Result<T, E> { 1416 + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 1417 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1418 + unsafe { slot.write(self?) }; 1419 + Ok(()) 1420 + } 1421 + } 1422 + 1423 + // SAFETY: when the `__pinned_init` function returns with 1424 + // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. 1425 + // - `Err(err)`, slot was not written to. 1426 + unsafe impl<T, E> PinInit<T, E> for Result<T, E> { 1427 + unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 1428 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1429 + unsafe { slot.write(self?) }; 1408 1430 Ok(()) 1409 1431 } 1410 1432 }