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: add miscellaneous files from the user-space version

Add readme and contribution guidelines of the user-space version of
pin-init.

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250308110339.2997091-21-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Benno Lossin and committed by
Miguel Ojeda
2e5f4f3c a9fa3a9c

+300
+72
rust/pin-init/CONTRIBUTING.md
··· 1 + # Contributing to `pin-init` 2 + 3 + Thanks for showing interest in contributing to `pin-init`! This document outlines the guidelines for 4 + contributing to `pin-init`. 5 + 6 + All contributions are double-licensed under Apache 2.0 and MIT. You can find the respective licenses 7 + in the `LICENSE-APACHE` and `LICENSE-MIT` files. 8 + 9 + ## Non-Code Contributions 10 + 11 + ### Bug Reports 12 + 13 + For any type of bug report, please submit an issue using the bug report issue template. 14 + 15 + If the issue is a soundness issue, please privately report it as a security vulnerability via the 16 + GitHub web interface. 17 + 18 + ### Feature Requests 19 + 20 + If you have any feature requests, please submit an issue using the feature request issue template. 21 + 22 + ### Questions and Getting Help 23 + 24 + You can ask questions in the Discussions page of the GitHub repository. If you're encountering 25 + problems or just have questions related to `pin-init` in the Linux kernel, you can also ask your 26 + questions in the [Rust-for-Linux Zulip](https://rust-for-linux.zulipchat.com/) or see 27 + <https://rust-for-linux.com/contact>. 28 + 29 + ## Contributing Code 30 + 31 + ### Linux Kernel 32 + 33 + `pin-init` is used by the Linux kernel and all commits are synchronized to it. For this reason, the 34 + same requirements for commits apply to `pin-init`. See [the kernel's documentation] for details. The 35 + rest of this document will also cover some of the rules listed there and additional ones. 36 + 37 + [the kernel's documentation]: https://docs.kernel.org/process/submitting-patches.html 38 + 39 + Contributions to `pin-init` ideally go through the [GitHub repository], because that repository runs 40 + a CI with lots of tests not present in the kernel. However, patches are also accepted (though not 41 + preferred). Do note that there are some files that are only present in the GitHub repository such as 42 + tests, licenses and cargo related files. Making changes to them can only happen via GitHub. 43 + 44 + [GitHub repository]: https://github.com/Rust-for-Linux/pin-init 45 + 46 + ### Commit Style 47 + 48 + Everything must compile without errors or warnings and all tests must pass after **every commit**. 49 + This is important for bisection and also required by the kernel. 50 + 51 + Each commit should be a single, logically cohesive change. Of course it's best to keep the changes 52 + small and digestible, but logically linked changes should be made in the same commit. For example, 53 + when fixing typos, create a single commit that fixes all of them instead of one commit per typo. 54 + 55 + Commits must have a meaningful commit title. Commits with changes to files in the `internal` 56 + directory should have a title prefixed with `internal:`. The commit message should explain the 57 + change and its rationale. You also have to add your `Signed-off-by` tag, see [Developer's 58 + Certificate of Origin]. This has to be done for both mailing list submissions as well as GitHub 59 + submissions. 60 + 61 + [Developer's Certificate of Origin]: https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin 62 + 63 + Any changes made to public APIs must be documented not only in the commit message, but also in the 64 + `CHANGELOG.md` file. This is especially important for breaking changes, as those warrant a major 65 + version bump. 66 + 67 + If you make changes to the top-level crate documentation, you also need to update the `README.md` 68 + via `cargo rdme`. 69 + 70 + Some of these rules can be ignored if the change is done solely to files that are not present in the 71 + kernel version of this library. Those files are documented in the `sync-kernel.sh` script at the 72 + very bottom in the `--exclude` flag given to the `git am` command.
+228
rust/pin-init/README.md
··· 1 + [![Crates.io](https://img.shields.io/crates/v/pin-init.svg)](https://crates.io/crates/pin-init) 2 + [![Documentation](https://docs.rs/pin-init/badge.svg)](https://docs.rs/pin-init/) 3 + [![Dependency status](https://deps.rs/repo/github/Rust-for-Linux/pin-init/status.svg)](https://deps.rs/repo/github/Rust-for-Linux/pin-init) 4 + ![License](https://img.shields.io/crates/l/pin-init) 5 + [![Toolchain](https://img.shields.io/badge/toolchain-nightly-red)](#nightly-only) 6 + ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml) 7 + # `pin-init` 8 + 9 + <!-- cargo-rdme start --> 10 + 11 + Library to safely and fallibly initialize pinned `struct`s using in-place constructors. 12 + 13 + [Pinning][pinning] is Rust's way of ensuring data does not move. 14 + 15 + It also allows in-place initialization of big `struct`s that would otherwise produce a stack 16 + overflow. 17 + 18 + This library's main use-case is in [Rust-for-Linux]. Although this version can be used 19 + standalone. 20 + 21 + There are cases when you want to in-place initialize a struct. For example when it is very big 22 + and moving it from the stack is not an option, because it is bigger than the stack itself. 23 + Another reason would be that you need the address of the object to initialize it. This stands 24 + in direct conflict with Rust's normal process of first initializing an object and then moving 25 + it into it's final memory location. For more information, see 26 + <https://rust-for-linux.com/the-safe-pinned-initialization-problem>. 27 + 28 + This library allows you to do in-place initialization safely. 29 + 30 + ### Nightly Needed for `alloc` feature 31 + 32 + This library requires the [`allocator_api` unstable feature] when the `alloc` feature is 33 + enabled and thus this feature can only be used with a nightly compiler. When enabling the 34 + `alloc` feature, the user will be required to activate `allocator_api` as well. 35 + 36 + [`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html 37 + 38 + The feature is enabled by default, thus by default `pin-init` will require a nightly compiler. 39 + However, using the crate on stable compilers is possible by disabling `alloc`. In practice this 40 + will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std 41 + mode. 42 + 43 + ## Overview 44 + 45 + To initialize a `struct` with an in-place constructor you will need two things: 46 + - an in-place constructor, 47 + - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`], 48 + [`Box<T>`] or any other smart pointer that supports this library). 49 + 50 + To get an in-place constructor there are generally three options: 51 + - directly creating an in-place constructor using the [`pin_init!`] macro, 52 + - a custom function/macro returning an in-place constructor provided by someone else, 53 + - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer. 54 + 55 + Aside from pinned initialization, this library also supports in-place construction without 56 + pinning, the macros/types/functions are generally named like the pinned variants without the 57 + `pin_` prefix. 58 + 59 + ## Examples 60 + 61 + Throughout the examples we will often make use of the `CMutex` type which can be found in 62 + `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from 63 + the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list 64 + requires it to be pinned to be locked and thus is a prime candidate for using this library. 65 + 66 + ### Using the [`pin_init!`] macro 67 + 68 + If you want to use [`PinInit`], then you will have to annotate your `struct` with 69 + `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for 70 + [structurally pinned fields]. After doing this, you can then create an in-place constructor via 71 + [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is 72 + that you need to write `<-` instead of `:` for fields that you want to initialize in-place. 73 + 74 + ```rust 75 + use pin_init::{pin_data, pin_init, InPlaceInit}; 76 + 77 + #[pin_data] 78 + struct Foo { 79 + #[pin] 80 + a: CMutex<usize>, 81 + b: u32, 82 + } 83 + 84 + let foo = pin_init!(Foo { 85 + a <- CMutex::new(42), 86 + b: 24, 87 + }); 88 + ``` 89 + 90 + `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like 91 + (or just the stack) to actually initialize a `Foo`: 92 + 93 + ```rust 94 + let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo); 95 + ``` 96 + 97 + For more information see the [`pin_init!`] macro. 98 + 99 + ### Using a custom function/macro that returns an initializer 100 + 101 + Many types that use this library supply a function/macro that returns an initializer, because 102 + the above method only works for types where you can access the fields. 103 + 104 + ```rust 105 + let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42)); 106 + ``` 107 + 108 + To declare an init macro/function you just return an [`impl PinInit<T, E>`]: 109 + 110 + ```rust 111 + #[pin_data] 112 + struct DriverData { 113 + #[pin] 114 + status: CMutex<i32>, 115 + buffer: Box<[u8; 1_000_000]>, 116 + } 117 + 118 + impl DriverData { 119 + fn new() -> impl PinInit<Self, Error> { 120 + try_pin_init!(Self { 121 + status <- CMutex::new(0), 122 + buffer: Box::init(pin_init::zeroed())?, 123 + }? Error) 124 + } 125 + } 126 + ``` 127 + 128 + ### Manual creation of an initializer 129 + 130 + Often when working with primitives the previous approaches are not sufficient. That is where 131 + [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a 132 + [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure 133 + actually does the initialization in the correct way. Here are the things to look out for 134 + (we are calling the parameter to the closure `slot`): 135 + - when the closure returns `Ok(())`, then it has completed the initialization successfully, so 136 + `slot` now contains a valid bit pattern for the type `T`, 137 + - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so 138 + you need to take care to clean up anything if your initialization fails mid-way, 139 + - you may assume that `slot` will stay pinned even after the closure returns until `drop` of 140 + `slot` gets called. 141 + 142 + ```rust 143 + use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure}; 144 + use core::{ 145 + ptr::addr_of_mut, 146 + marker::PhantomPinned, 147 + cell::UnsafeCell, 148 + pin::Pin, 149 + mem::MaybeUninit, 150 + }; 151 + mod bindings { 152 + #[repr(C)] 153 + pub struct foo { 154 + /* fields from C ... */ 155 + } 156 + extern "C" { 157 + pub fn init_foo(ptr: *mut foo); 158 + pub fn destroy_foo(ptr: *mut foo); 159 + #[must_use = "you must check the error return code"] 160 + pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32; 161 + } 162 + } 163 + 164 + /// # Invariants 165 + /// 166 + /// `foo` is always initialized 167 + #[pin_data(PinnedDrop)] 168 + pub struct RawFoo { 169 + #[pin] 170 + _p: PhantomPinned, 171 + #[pin] 172 + foo: UnsafeCell<MaybeUninit<bindings::foo>>, 173 + } 174 + 175 + impl RawFoo { 176 + pub fn new(flags: u32) -> impl PinInit<Self, i32> { 177 + // SAFETY: 178 + // - when the closure returns `Ok(())`, then it has successfully initialized and 179 + // enabled `foo`, 180 + // - when it returns `Err(e)`, then it has cleaned up before 181 + unsafe { 182 + pin_init_from_closure(move |slot: *mut Self| { 183 + // `slot` contains uninit memory, avoid creating a reference. 184 + let foo = addr_of_mut!((*slot).foo); 185 + let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>(); 186 + 187 + // Initialize the `foo` 188 + bindings::init_foo(foo); 189 + 190 + // Try to enable it. 191 + let err = bindings::enable_foo(foo, flags); 192 + if err != 0 { 193 + // Enabling has failed, first clean up the foo and then return the error. 194 + bindings::destroy_foo(foo); 195 + Err(err) 196 + } else { 197 + // All fields of `RawFoo` have been initialized, since `_p` is a ZST. 198 + Ok(()) 199 + } 200 + }) 201 + } 202 + } 203 + } 204 + 205 + #[pinned_drop] 206 + impl PinnedDrop for RawFoo { 207 + fn drop(self: Pin<&mut Self>) { 208 + // SAFETY: Since `foo` is initialized, destroying is safe. 209 + unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) }; 210 + } 211 + } 212 + ``` 213 + 214 + For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside 215 + the `kernel` crate. The [`sync`] module is a good starting point. 216 + 217 + [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html 218 + [pinning]: https://doc.rust-lang.org/std/pin/index.html 219 + [structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field 220 + [stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html 221 + [`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html 222 + [`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html 223 + [`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 224 + [`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 225 + [`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html 226 + [Rust-for-Linux]: https://rust-for-linux.com/ 227 + 228 + <!-- cargo-rdme end -->