Skip to content

Commit 86f7dac

Browse files
y86-devojeda
authored andcommitted
rust: add extensions to the pin-init crate and move relevant documentation there
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. Also include an example from the user-space version [1] adapted to the kernel. The new `init.rs` file will also be populated by kernel-specific extensions to the pin-init crate by the next commits. Link: https://github.com/Rust-for-Linux/pin-init/blob/c1417c64c71229f0fd444d75e88f33e3c547c829/src/lib.rs#L161 [1] Signed-off-by: Benno Lossin <[email protected]> Reviewed-by: Fiona Behrens <[email protected]> Tested-by: Andreas Hindborg <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent fbf8fb3 commit 86f7dac

File tree

3 files changed

+138
-14
lines changed

3 files changed

+138
-14
lines changed

rust/kernel/init.rs

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Extensions to the [`pin-init`] crate.
4+
//!
5+
//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
6+
//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
7+
//!
8+
//! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer
9+
//! to its documentation to better understand how to use it. Additionally, there are many examples
10+
//! throughout the kernel, such as the types from the [`sync`] module. And the ones presented
11+
//! below.
12+
//!
13+
//! [`sync`]: crate::sync
14+
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
15+
//! [`pin-init`]: https://rust.docs.kernel.org/pin_init/
16+
//!
17+
//! # [`Opaque<T>`]
18+
//!
19+
//! For the special case where initializing a field is a single FFI-function call that cannot fail,
20+
//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
21+
//! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in
22+
//! combination with [`pin_init!`].
23+
//!
24+
//! [`Opaque<T>`]: crate::types::Opaque
25+
//! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init
26+
//! [`pin_init!`]: crate::pin_init
27+
//!
28+
//! # Examples
29+
//!
30+
//! ## General Examples
31+
//!
32+
//! ```rust,ignore
33+
//! # #![allow(clippy::disallowed_names)]
34+
//! use kernel::types::Opaque;
35+
//! use pin_init::pin_init_from_closure;
36+
//!
37+
//! // assume we have some `raw_foo` type in C:
38+
//! #[repr(C)]
39+
//! struct RawFoo([u8; 16]);
40+
//! extern {
41+
//! fn init_foo(_: *mut RawFoo);
42+
//! }
43+
//!
44+
//! #[pin_data]
45+
//! struct Foo {
46+
//! #[pin]
47+
//! raw: Opaque<RawFoo>,
48+
//! }
49+
//!
50+
//! impl Foo {
51+
//! fn setup(self: Pin<&mut Self>) {
52+
//! pr_info!("Setting up foo");
53+
//! }
54+
//! }
55+
//!
56+
//! let foo = pin_init!(Foo {
57+
//! raw <- unsafe {
58+
//! Opaque::ffi_init(|s| {
59+
//! // note that this cannot fail.
60+
//! init_foo(s);
61+
//! })
62+
//! },
63+
//! }).pin_chain(|foo| {
64+
//! foo.setup();
65+
//! Ok(())
66+
//! });
67+
//! ```
68+
//!
69+
//! ```rust,ignore
70+
//! # #![allow(unreachable_pub, clippy::disallowed_names)]
71+
//! use kernel::{prelude::*, types::Opaque};
72+
//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
73+
//! # mod bindings {
74+
//! # #![allow(non_camel_case_types)]
75+
//! # pub struct foo;
76+
//! # pub unsafe fn init_foo(_ptr: *mut foo) {}
77+
//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}
78+
//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }
79+
//! # }
80+
//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
81+
//! # trait FromErrno {
82+
//! # fn from_errno(errno: core::ffi::c_int) -> Error {
83+
//! # // Dummy error that can be constructed outside the `kernel` crate.
84+
//! # Error::from(core::fmt::Error)
85+
//! # }
86+
//! # }
87+
//! # impl FromErrno for Error {}
88+
//! /// # Invariants
89+
//! ///
90+
//! /// `foo` is always initialized
91+
//! #[pin_data(PinnedDrop)]
92+
//! pub struct RawFoo {
93+
//! #[pin]
94+
//! foo: Opaque<bindings::foo>,
95+
//! #[pin]
96+
//! _p: PhantomPinned,
97+
//! }
98+
//!
99+
//! impl RawFoo {
100+
//! pub fn new(flags: u32) -> impl PinInit<Self, Error> {
101+
//! // SAFETY:
102+
//! // - when the closure returns `Ok(())`, then it has successfully initialized and
103+
//! // enabled `foo`,
104+
//! // - when it returns `Err(e)`, then it has cleaned up before
105+
//! unsafe {
106+
//! pin_init::pin_init_from_closure(move |slot: *mut Self| {
107+
//! // `slot` contains uninit memory, avoid creating a reference.
108+
//! let foo = addr_of_mut!((*slot).foo);
109+
//!
110+
//! // Initialize the `foo`
111+
//! bindings::init_foo(Opaque::raw_get(foo));
112+
//!
113+
//! // Try to enable it.
114+
//! let err = bindings::enable_foo(Opaque::raw_get(foo), flags);
115+
//! if err != 0 {
116+
//! // Enabling has failed, first clean up the foo and then return the error.
117+
//! bindings::destroy_foo(Opaque::raw_get(foo));
118+
//! return Err(Error::from_errno(err));
119+
//! }
120+
//!
121+
//! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
122+
//! Ok(())
123+
//! })
124+
//! }
125+
//! }
126+
//! }
127+
//!
128+
//! #[pinned_drop]
129+
//! impl PinnedDrop for RawFoo {
130+
//! fn drop(self: Pin<&mut Self>) {
131+
//! // SAFETY: Since `foo` is initialized, destroying is safe.
132+
//! unsafe { bindings::destroy_foo(self.foo.get()) };
133+
//! }
134+
//! }
135+
//! ```

rust/kernel/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ pub mod firmware;
5252
pub mod fs;
5353
#[path = "../pin-init/src/lib.rs"]
5454
pub mod init;
55+
// momentarily use the name `init_ext` and set the path manually
56+
#[path = "init.rs"]
57+
pub mod init_ext;
5558
pub mod io;
5659
pub mod ioctl;
5760
pub mod jump_label;

rust/pin-init/src/lib.rs

-14
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
66
//! overflow.
77
//!
8-
//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
9-
//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
10-
//!
118
//! # Overview
129
//!
1310
//! To initialize a `struct` with an in-place constructor you will need two things:
@@ -188,15 +185,6 @@
188185
//! }
189186
//! ```
190187
//!
191-
//! For the special case where initializing a field is a single FFI-function call that cannot fail,
192-
//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
193-
//! [`Opaque`] field by just delegating to the supplied closure. You can use these in combination
194-
//! with [`pin_init!`].
195-
//!
196-
//! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
197-
//! the `kernel` crate. The [`sync`] module is a good starting point.
198-
//!
199-
//! [`sync`]: kernel::sync
200188
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
201189
//! [structurally pinned fields]:
202190
//! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
@@ -205,8 +193,6 @@
205193
//! [`impl PinInit<Foo>`]: PinInit
206194
//! [`impl PinInit<T, E>`]: PinInit
207195
//! [`impl Init<T, E>`]: Init
208-
//! [`Opaque`]: kernel::types::Opaque
209-
//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init
210196
//! [`pin_data`]: ::macros::pin_data
211197
//! [`pin_init!`]: crate::pin_init!
212198

0 commit comments

Comments
 (0)