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.

Merge tag 'pin-init-v6.16' of https://github.com/Rust-for-Linux/linux into rust-next

Pull pin-init updates from Benno Lossin:
"Added:

- 'Wrapper<T>' trait for creating pin-initializers for wrapper
structs with a structurally pinned value such as 'UnsafeCell<T>' or
'MaybeUninit<T>'.

- 'MaybeZeroable' derive macro to try to derive 'Zeroable', but not
error if not all fields implement it. This is needed to derive
'Zeroable' for all bindgen-generated structs.

- 'unsafe fn cast_[pin_]init()' functions to unsafely change the
initialized type of an initializer. These are utilized by the
'Wrapper<T>' implementations.

Changed:

- Added support for visibility in 'Zeroable' derive macro.

- Added support for 'union's in 'Zeroable' derive macro.

Upstream dev news:

- The CI has been streamlined & some bugs with it have been fixed. I
also added new workflows to check if the user-space version and the
one in the kernel tree have diverged.

- I also started to use the issues [1] tab to keep track of any
problems or unexpected/unwanted things. This should help folks
report and diagnose issues w.r.t. 'pin-init' better.

[1] https://github.com/rust-for-linux/pin-init/issues"

* tag 'pin-init-v6.16' of https://github.com/Rust-for-Linux/linux:
rust: pin-init: improve documentation for `Zeroable` derive macros
rust: pin-init: fix typos
rust: pin-init: add `MaybeZeroable` derive macro
rust: pin-init: allow `Zeroable` derive macro to also be applied to unions
rust: pin-init: allow `pub` fields in `derive(Zeroable)`
rust: pin-init: Update the structural pinning link in readme.
rust: pin-init: Update Changelog and Readme
rust: pin-init: Implement `Wrapper` for `UnsafePinned` behind feature flag.
rust: pin-init: Add the `Wrapper` trait.
rust: pin-init: add `cast_[pin_]init` functions to change the initialized type
rust: pin-init: examples: use `allow` instead of `expect`
rust: pin-init: examples: conditionally enable `feature(lint_reasons)`
rust: pin-init: internal: skip rustfmt formatting of kernel-only module
rust: pin-init: synchronize README.md

+279 -10
+11 -3
rust/pin-init/README.md
··· 40 40 will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std 41 41 mode. 42 42 43 + ### Nightly needed for `unsafe-pinned` feature 44 + 45 + This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type. 46 + This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735) 47 + and therefore a nightly compiler. Note that this feature is not enabled by default. 48 + 43 49 ## Overview 44 50 45 51 To initialize a `struct` with an in-place constructor you will need two things: ··· 222 216 223 217 [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html 224 218 [pinning]: https://doc.rust-lang.org/std/pin/index.html 225 - [structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field 219 + [structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning 226 220 [stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html 227 - [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html 228 - [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html 229 221 [`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 230 222 [`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 231 223 [`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html 232 224 [Rust-for-Linux]: https://rust-for-linux.com/ 233 225 234 226 <!-- cargo-rdme end --> 227 + 228 + <!-- These links are not picked up by cargo-rdme, since they are behind cfgs... --> 229 + [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html 230 + [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
+1
rust/pin-init/examples/linked_list.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 6 6 7 use core::{ 7 8 cell::Cell,
+1
rust/pin-init/examples/mutex.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 6 #![allow(clippy::missing_safety_doc)] 6 7 7 8 use core::{
+3 -1
rust/pin-init/examples/pthread_mutex.rs
··· 3 3 // inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs> 4 4 #![allow(clippy::undocumented_unsafe_blocks)] 5 5 #![cfg_attr(feature = "alloc", feature(allocator_api))] 6 + #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 7 + 6 8 #[cfg(not(windows))] 7 9 mod pthread_mtx { 8 10 #[cfg(feature = "alloc")] ··· 42 40 43 41 #[derive(Debug)] 44 42 pub enum Error { 45 - #[expect(dead_code)] 43 + #[allow(dead_code)] 46 44 IO(std::io::Error), 47 45 Alloc, 48 46 }
+1
rust/pin-init/examples/static_init.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 6 6 7 use core::{ 7 8 cell::{Cell, UnsafeCell},
+6
rust/pin-init/internal/src/lib.rs
··· 22 22 #[cfg(kernel)] 23 23 #[path = "../../../macros/quote.rs"] 24 24 #[macro_use] 25 + #[cfg_attr(not(kernel), rustfmt::skip)] 25 26 mod quote; 26 27 #[cfg(not(kernel))] 27 28 #[macro_use] ··· 46 45 #[proc_macro_derive(Zeroable)] 47 46 pub fn derive_zeroable(input: TokenStream) -> TokenStream { 48 47 zeroable::derive(input.into()).into() 48 + } 49 + 50 + #[proc_macro_derive(MaybeZeroable)] 51 + pub fn maybe_derive_zeroable(input: TokenStream) -> TokenStream { 52 + zeroable::maybe_derive(input.into()).into() 49 53 }
+26 -1
rust/pin-init/internal/src/zeroable.rs
··· 6 6 use crate::helpers::{parse_generics, Generics}; 7 7 use proc_macro::{TokenStream, TokenTree}; 8 8 9 - pub(crate) fn derive(input: TokenStream) -> TokenStream { 9 + pub(crate) fn parse_zeroable_derive_input( 10 + input: TokenStream, 11 + ) -> ( 12 + Vec<TokenTree>, 13 + Vec<TokenTree>, 14 + Vec<TokenTree>, 15 + Option<TokenTree>, 16 + ) { 10 17 let ( 11 18 Generics { 12 19 impl_generics, ··· 71 64 if in_generic && !inserted { 72 65 new_impl_generics.extend(quote! { : ::pin_init::Zeroable }); 73 66 } 67 + (rest, new_impl_generics, ty_generics, last) 68 + } 69 + 70 + pub(crate) fn derive(input: TokenStream) -> TokenStream { 71 + let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input); 74 72 quote! { 75 73 ::pin_init::__derive_zeroable!( 74 + parse_input: 75 + @sig(#(#rest)*), 76 + @impl_generics(#(#new_impl_generics)*), 77 + @ty_generics(#(#ty_generics)*), 78 + @body(#last), 79 + ); 80 + } 81 + } 82 + 83 + pub(crate) fn maybe_derive(input: TokenStream) -> TokenStream { 84 + let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input); 85 + quote! { 86 + ::pin_init::__maybe_derive_zeroable!( 76 87 parse_input: 77 88 @sig(#(#rest)*), 78 89 @impl_generics(#(#new_impl_generics)*),
+140 -4
rust/pin-init/src/lib.rs
··· 32 32 //! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std 33 33 //! mode. 34 34 //! 35 + //! ## Nightly needed for `unsafe-pinned` feature 36 + //! 37 + //! This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type. 38 + //! This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735) 39 + //! and therefore a nightly compiler. Note that this feature is not enabled by default. 40 + //! 35 41 //! # Overview 36 42 //! 37 43 //! To initialize a `struct` with an in-place constructor you will need two things: ··· 247 241 //! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html 248 242 //! [pinning]: https://doc.rust-lang.org/std/pin/index.html 249 243 //! [structurally pinned fields]: 250 - //! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field 244 + //! https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning 251 245 //! [stack]: crate::stack_pin_init 252 246 #![cfg_attr( 253 247 kernel, ··· 275 269 #![forbid(missing_docs, unsafe_op_in_unsafe_fn)] 276 270 #![cfg_attr(not(feature = "std"), no_std)] 277 271 #![cfg_attr(feature = "alloc", feature(allocator_api))] 272 + #![cfg_attr( 273 + all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED), 274 + feature(unsafe_pinned) 275 + )] 278 276 279 277 use core::{ 280 278 cell::UnsafeCell, ··· 395 385 /// ``` 396 386 pub use ::pin_init_internal::pinned_drop; 397 387 398 - /// Derives the [`Zeroable`] trait for the given struct. 388 + /// Derives the [`Zeroable`] trait for the given `struct` or `union`. 399 389 /// 400 - /// This can only be used for structs where every field implements the [`Zeroable`] trait. 390 + /// This can only be used for `struct`s/`union`s where every field implements the [`Zeroable`] 391 + /// trait. 401 392 /// 402 393 /// # Examples 403 394 /// ··· 407 396 /// 408 397 /// #[derive(Zeroable)] 409 398 /// pub struct DriverData { 410 - /// id: i64, 399 + /// pub(crate) id: i64, 411 400 /// buf_ptr: *mut u8, 412 401 /// len: usize, 413 402 /// } 414 403 /// ``` 404 + /// 405 + /// ``` 406 + /// use pin_init::Zeroable; 407 + /// 408 + /// #[derive(Zeroable)] 409 + /// pub union SignCast { 410 + /// signed: i64, 411 + /// unsigned: u64, 412 + /// } 413 + /// ``` 415 414 pub use ::pin_init_internal::Zeroable; 415 + 416 + /// Derives the [`Zeroable`] trait for the given `struct` or `union` if all fields implement 417 + /// [`Zeroable`]. 418 + /// 419 + /// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field 420 + /// doesn't implement [`Zeroable`]. 421 + /// 422 + /// # Examples 423 + /// 424 + /// ``` 425 + /// use pin_init::MaybeZeroable; 426 + /// 427 + /// // implmements `Zeroable` 428 + /// #[derive(MaybeZeroable)] 429 + /// pub struct DriverData { 430 + /// pub(crate) id: i64, 431 + /// buf_ptr: *mut u8, 432 + /// len: usize, 433 + /// } 434 + /// 435 + /// // does not implmement `Zeroable` 436 + /// #[derive(MaybeZeroable)] 437 + /// pub struct DriverData2 { 438 + /// pub(crate) id: i64, 439 + /// buf_ptr: *mut u8, 440 + /// len: usize, 441 + /// // this field doesn't implement `Zeroable` 442 + /// other_data: &'static i32, 443 + /// } 444 + /// ``` 445 + pub use ::pin_init_internal::MaybeZeroable; 416 446 417 447 /// Initialize and pin a type directly on the stack. 418 448 /// ··· 1268 1216 __internal::InitClosure(f, PhantomData) 1269 1217 } 1270 1218 1219 + /// Changes the to be initialized type. 1220 + /// 1221 + /// # Safety 1222 + /// 1223 + /// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a 1224 + /// pointer must result in a valid `U`. 1225 + #[expect(clippy::let_and_return)] 1226 + pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> { 1227 + // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety 1228 + // requirements. 1229 + let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) }; 1230 + // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a 1231 + // cycle when computing the type returned by this function) 1232 + res 1233 + } 1234 + 1235 + /// Changes the to be initialized type. 1236 + /// 1237 + /// # Safety 1238 + /// 1239 + /// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a 1240 + /// pointer must result in a valid `U`. 1241 + #[expect(clippy::let_and_return)] 1242 + pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> { 1243 + // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety 1244 + // requirements. 1245 + let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) }; 1246 + // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a 1247 + // cycle when computing the type returned by this function) 1248 + res 1249 + } 1250 + 1271 1251 /// An initializer that leaves the memory uninitialized. 1272 1252 /// 1273 1253 /// The initializer is a no-op. The `slot` memory is not changed. ··· 1565 1481 } 1566 1482 1567 1483 impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J); 1484 + 1485 + /// This trait allows creating an instance of `Self` which contains exactly one 1486 + /// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning). 1487 + /// 1488 + /// This is useful when using wrapper `struct`s like [`UnsafeCell`] or with new-type `struct`s. 1489 + /// 1490 + /// # Examples 1491 + /// 1492 + /// ``` 1493 + /// # use core::cell::UnsafeCell; 1494 + /// # use pin_init::{pin_data, pin_init, Wrapper}; 1495 + /// 1496 + /// #[pin_data] 1497 + /// struct Foo {} 1498 + /// 1499 + /// #[pin_data] 1500 + /// struct Bar { 1501 + /// #[pin] 1502 + /// content: UnsafeCell<Foo> 1503 + /// }; 1504 + /// 1505 + /// let foo_initializer = pin_init!(Foo{}); 1506 + /// let initializer = pin_init!(Bar { 1507 + /// content <- UnsafeCell::pin_init(foo_initializer) 1508 + /// }); 1509 + /// ``` 1510 + pub trait Wrapper<T> { 1511 + /// Creates an pin-initializer for a [`Self`] containing `T` from the `value_init` initializer. 1512 + fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>; 1513 + } 1514 + 1515 + impl<T> Wrapper<T> for UnsafeCell<T> { 1516 + fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> { 1517 + // SAFETY: `UnsafeCell<T>` has a compatible layout to `T`. 1518 + unsafe { cast_pin_init(value_init) } 1519 + } 1520 + } 1521 + 1522 + impl<T> Wrapper<T> for MaybeUninit<T> { 1523 + fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> { 1524 + // SAFETY: `MaybeUninit<T>` has a compatible layout to `T`. 1525 + unsafe { cast_pin_init(value_init) } 1526 + } 1527 + } 1528 + 1529 + #[cfg(all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED))] 1530 + impl<T> Wrapper<T> for core::pin::UnsafePinned<T> { 1531 + fn pin_init<E>(init: impl PinInit<T, E>) -> impl PinInit<Self, E> { 1532 + // SAFETY: `UnsafePinned<T>` has a compatible layout to `T`. 1533 + unsafe { cast_pin_init(init) } 1534 + } 1535 + }
+90 -1
rust/pin-init/src/macros.rs
··· 1393 1393 @body({ 1394 1394 $( 1395 1395 $(#[$($field_attr:tt)*])* 1396 - $field:ident : $field_ty:ty 1396 + $field_vis:vis $field:ident : $field_ty:ty 1397 1397 ),* $(,)? 1398 1398 }), 1399 1399 ) => { ··· 1411 1411 $(assert_zeroable::<$field_ty>();)* 1412 1412 } 1413 1413 }; 1414 + }; 1415 + (parse_input: 1416 + @sig( 1417 + $(#[$($struct_attr:tt)*])* 1418 + $vis:vis union $name:ident 1419 + $(where $($whr:tt)*)? 1420 + ), 1421 + @impl_generics($($impl_generics:tt)*), 1422 + @ty_generics($($ty_generics:tt)*), 1423 + @body({ 1424 + $( 1425 + $(#[$($field_attr:tt)*])* 1426 + $field_vis:vis $field:ident : $field_ty:ty 1427 + ),* $(,)? 1428 + }), 1429 + ) => { 1430 + // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero. 1431 + #[automatically_derived] 1432 + unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*> 1433 + where 1434 + $($($whr)*)? 1435 + {} 1436 + const _: () = { 1437 + fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {} 1438 + fn ensure_zeroable<$($impl_generics)*>() 1439 + where $($($whr)*)? 1440 + { 1441 + $(assert_zeroable::<$field_ty>();)* 1442 + } 1443 + }; 1444 + }; 1445 + } 1446 + 1447 + #[doc(hidden)] 1448 + #[macro_export] 1449 + macro_rules! __maybe_derive_zeroable { 1450 + (parse_input: 1451 + @sig( 1452 + $(#[$($struct_attr:tt)*])* 1453 + $vis:vis struct $name:ident 1454 + $(where $($whr:tt)*)? 1455 + ), 1456 + @impl_generics($($impl_generics:tt)*), 1457 + @ty_generics($($ty_generics:tt)*), 1458 + @body({ 1459 + $( 1460 + $(#[$($field_attr:tt)*])* 1461 + $field_vis:vis $field:ident : $field_ty:ty 1462 + ),* $(,)? 1463 + }), 1464 + ) => { 1465 + // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero. 1466 + #[automatically_derived] 1467 + unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*> 1468 + where 1469 + $( 1470 + // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds` 1471 + // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>. 1472 + $field_ty: for<'__dummy> $crate::Zeroable, 1473 + )* 1474 + $($($whr)*)? 1475 + {} 1476 + }; 1477 + (parse_input: 1478 + @sig( 1479 + $(#[$($struct_attr:tt)*])* 1480 + $vis:vis union $name:ident 1481 + $(where $($whr:tt)*)? 1482 + ), 1483 + @impl_generics($($impl_generics:tt)*), 1484 + @ty_generics($($ty_generics:tt)*), 1485 + @body({ 1486 + $( 1487 + $(#[$($field_attr:tt)*])* 1488 + $field_vis:vis $field:ident : $field_ty:ty 1489 + ),* $(,)? 1490 + }), 1491 + ) => { 1492 + // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero. 1493 + #[automatically_derived] 1494 + unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*> 1495 + where 1496 + $( 1497 + // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds` 1498 + // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>. 1499 + $field_ty: for<'__dummy> $crate::Zeroable, 1500 + )* 1501 + $($($whr)*)? 1502 + {} 1414 1503 }; 1415 1504 }