From: Danilo Krummrich <dakr@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
Cc: ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com,
boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
benno.lossin@proton.me, a.hindborg@samsung.com,
akpm@linux-foundation.org, daniel.almeida@collabora.com,
faith.ekstrand@collabora.com, boris.brezillon@collabora.com,
lina@asahilina.net, mcanal@igalia.com, zhiw@nvidia.com,
cjia@nvidia.com, jhubbard@nvidia.com, airlied@redhat.com,
ajanulgu@redhat.com, lyude@redhat.com,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-mm@kvack.org
Subject: Re: [PATCH v5 09/26] rust: alloc: implement kernel `Box`
Date: Wed, 14 Aug 2024 14:22:01 +0200 [thread overview]
Message-ID: <Zryhae9OXD_dqfR8@pollux> (raw)
In-Reply-To: <CAH5fLgiyDtMWKe0db+uvKGPoPRepjiSxddSrBh8jF1N1COpdDg@mail.gmail.com>
On Wed, Aug 14, 2024 at 10:26:10AM +0200, Alice Ryhl wrote:
> On Mon, Aug 12, 2024 at 8:25 PM Danilo Krummrich <dakr@kernel.org> wrote:
> >
> > `Box` provides the simplest way to allocate memory for a generic type
> > with one of the kernel's allocators, e.g. `Kmalloc`, `Vmalloc` or
> > `KVmalloc`.
> >
> > In contrast to Rust's `Box` type, the kernel `Box` type considers the
> > kernel's GFP flags for all appropriate functions, always reports
> > allocation failures through `Result<_, AllocError>` and remains
> > independent from unstable features.
> >
> > Signed-off-by: Danilo Krummrich <dakr@kernel.org>
> > ---
> > rust/kernel/alloc.rs | 6 +
> > rust/kernel/alloc/kbox.rs | 423 ++++++++++++++++++++++++++++++++++++++
> > rust/kernel/prelude.rs | 2 +-
> > 3 files changed, 430 insertions(+), 1 deletion(-)
> > create mode 100644 rust/kernel/alloc/kbox.rs
> >
> > diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
> > index 295107777a12..ed46b69204d0 100644
> > --- a/rust/kernel/alloc.rs
> > +++ b/rust/kernel/alloc.rs
> > @@ -5,6 +5,7 @@
> > #[cfg(not(any(test, testlib)))]
> > pub mod allocator;
> > pub mod box_ext;
> > +pub mod kbox;
> > pub mod vec_ext;
> >
> > #[cfg(any(test, testlib))]
> > @@ -13,6 +14,11 @@
> > #[cfg(any(test, testlib))]
> > pub use self::allocator_test as allocator;
> >
> > +pub use self::kbox::Box;
> > +pub use self::kbox::KBox;
> > +pub use self::kbox::KVBox;
> > +pub use self::kbox::VBox;
> > +
> > /// Indicates an allocation error.
> > #[derive(Copy, Clone, PartialEq, Eq, Debug)]
> > pub struct AllocError;
> > diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> > new file mode 100644
> > index 000000000000..67bdfc0712d2
> > --- /dev/null
> > +++ b/rust/kernel/alloc/kbox.rs
> > @@ -0,0 +1,423 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +//! Implementation of [`Box`].
> > +
> > +use super::{AllocError, Allocator, Flags};
> > +use core::fmt;
> > +use core::marker::PhantomData;
> > +use core::mem::ManuallyDrop;
> > +use core::mem::MaybeUninit;
> > +use core::ops::{Deref, DerefMut};
> > +use core::pin::Pin;
> > +use core::ptr::NonNull;
> > +use core::result::Result;
> > +
> > +use crate::init::{InPlaceInit, Init, PinInit};
> > +use crate::types::ForeignOwnable;
> > +
> > +/// The kernel's [`Box`] type - a heap allocation for a single value of type `T`.
> > +///
> > +/// This is the kernel's version of the Rust stdlib's `Box`. There are a couple of differences,
> > +/// for example no `noalias` attribute is emitted and partially moving out of a `Box` is not
> > +/// supported.
> > +///
> > +/// `Box` works with any of the kernel's allocators, e.g. [`super::allocator::Kmalloc`],
> > +/// [`super::allocator::Vmalloc`] or [`super::allocator::KVmalloc`]. There are aliases for `Box`
> > +/// with these allocators ([`KBox`], [`VBox`], [`KVBox`]).
> > +///
> > +/// When dropping a [`Box`], the value is also dropped and the heap memory is automatically freed.
> > +///
> > +/// # Examples
> > +///
> > +/// ```
> > +/// let b = KBox::<u64>::new(24_u64, GFP_KERNEL)?;
> > +///
> > +/// assert_eq!(*b, 24_u64);
> > +///
> > +/// # Ok::<(), Error>(())
>
> This is a minor nit, but when hiding lines in examples you should
> avoid having the rendered docs have empty lines at the beginning/end.
> There are also several examples of this below with the
> kernel::bindings import.
Makes sense, gonna fix it.
>
> > +/// ```
> > +///
> > +/// ```
> > +/// # use kernel::bindings;
> > +///
> > +/// const SIZE: usize = bindings::KMALLOC_MAX_SIZE as usize + 1;
> > +/// struct Huge([u8; SIZE]);
> > +///
> > +/// assert!(KBox::<Huge>::new_uninit(GFP_KERNEL | __GFP_NOWARN).is_err());
> > +/// ```
> > +///
> > +/// ```
> > +/// # use kernel::bindings;
> > +///
> > +/// const SIZE: usize = bindings::KMALLOC_MAX_SIZE as usize + 1;
> > +/// struct Huge([u8; SIZE]);
> > +///
> > +/// assert!(KVBox::<Huge>::new_uninit(GFP_KERNEL).is_ok());
> > +/// ```
> > +///
> > +/// # Invariants
> > +///
> > +/// The [`Box`]' pointer always properly aligned and either points to memory allocated with `A` or,
> > +/// for zero-sized types, is a dangling pointer.
> > +pub struct Box<T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
>
> I was about to say this needs a PhantomData<T> too, but I guess it
> isn't necessary anymore.
> https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking
>
> > +// SAFETY: `Box` is `Send` if `T` is `Send` because the data referenced by `self.0` is unaliased.
>
> Instead of "unaliased" I would probably just say "because the Box owns a T".
I'm fine with either one, if that's preferred, I'll change it.
>
> > +
> > +// SAFETY: `Box` is `Sync` if `T` is `Sync` because the data referenced by `self.0` is unaliased.
> > +unsafe impl<T, A> Sync for Box<T, A>
> > +where
> > + T: Send + ?Sized,
> > + A: Allocator,
>
> This needs to say `T: Sync` instead of `T: Send`. That matches the std Box.
Good catch, pretty sure `Vec` has the same copy-paste mistake.
>
> > +
> > +impl<T, A> Box<T, A>
> > +where
> > + T: ?Sized,
> > + A: Allocator,
> > +{
> > + /// Creates a new `Box<T, A>` from a raw pointer.
> > + ///
> > + /// # Safety
> > + ///
> > + /// `raw` must point to valid memory, previously be allocated with `A`, and provide at least
> > + /// the size of type `T`. For ZSTs `raw` must be a dangling pointer.
>
> Hmm. I don't love this wording. How about this?
>
> For non-ZSTs, `raw` must point at a live allocation allocated with `A`
> that is sufficiently aligned for and holds a valid `T`. The caller
> passes ownership of the allocation to the `Box`.
I'm fine taking that, I'm not so sure about "live allocation" though, we don't
use this wording anywhere else. It's probably fine to just say "allocation",
since once it's freed it technically isn't an allocation anymore anyways.
> For ZSTs, the pointer must be non-null and aligned.
Technically, for ZSTs any pointer is aligned and NULL should be valid as well.
Maybe we just don't mentioned ZSTs at all, since we don't really need to enforce
anything for ZSTs.
>
> > +impl<T, A> From<Box<T, A>> for Pin<Box<T, A>>
> > +where
> > + T: ?Sized,
> > + A: Allocator,
> > +{
> > + /// Converts a `Box<T, A>` into a `Pin<Box<T, A>>`. If `T` does not implement [`Unpin`], then
> > + /// `*b` will be pinned in memory and can't be moved.
> > + ///
> > + /// See [`Box::into_pin`] for more details.
> > + fn from(b: Box<T, A>) -> Self {
> > + Box::into_pin(b)
>
> I still think it makes more sense to match std and only provide From
> and not an into_pin, but it's not a blocker.
Yeah, I just kept it since I'm not (yet) entirely sure what to think of the
`From` and `Into` stuff in some cases.
I don't really like that, depending on the context, it may hide relevant
details.
In the kernel, no matter how well documented an API is, I think it's rather
common to look at the code for some implementation details before using it.
Sometimes it might not be super trivial for the "occasional" reader to figure
out what's the type of some variable. Calling `into_pin` vs. just `into`
immediately tells the reader that things need to be pinned from there on.
However, I had no specific example in my mind and I'm also not overly concerned
to remove `into_pin`, but I want to at least share the reason why I kept it in
the first place.
>
> Alice
>
next prev parent reply other threads:[~2024-08-14 12:22 UTC|newest]
Thread overview: 95+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-12 18:22 [PATCH v5 00/26] Generic `Allocator` support for Rust Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 01/26] rust: alloc: add `Allocator` trait Danilo Krummrich
2024-08-14 16:13 ` Benno Lossin
2024-08-15 0:16 ` Danilo Krummrich
2024-08-15 13:49 ` Benno Lossin
2024-08-12 18:22 ` [PATCH v5 02/26] rust: alloc: separate `aligned_size` from `krealloc_aligned` Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 03/26] rust: alloc: rename `KernelAllocator` to `Kmalloc` Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 04/26] rust: alloc: implement `Allocator` for `Kmalloc` Danilo Krummrich
2024-08-14 7:51 ` Alice Ryhl
2024-08-14 13:36 ` Danilo Krummrich
2024-08-14 13:44 ` Alice Ryhl
2024-08-14 13:48 ` Danilo Krummrich
2024-08-14 13:50 ` Alice Ryhl
2024-08-14 14:00 ` Danilo Krummrich
2024-08-14 15:03 ` Miguel Ojeda
2024-08-14 15:19 ` Danilo Krummrich
2024-08-14 15:28 ` Benno Lossin
2024-08-14 16:01 ` Danilo Krummrich
2024-08-14 16:02 ` Miguel Ojeda
2024-08-14 16:16 ` Miguel Ojeda
2024-08-14 16:56 ` Danilo Krummrich
2024-08-14 16:21 ` Benno Lossin
2024-08-14 16:59 ` Danilo Krummrich
2024-08-14 17:02 ` Benno Lossin
2024-08-14 17:15 ` Danilo Krummrich
2024-08-14 21:07 ` Benno Lossin
2024-08-14 16:28 ` Benno Lossin
2024-08-14 17:13 ` Danilo Krummrich
2024-08-14 21:10 ` Benno Lossin
2024-08-12 18:22 ` [PATCH v5 05/26] rust: alloc: add module `allocator_test` Danilo Krummrich
2024-08-14 16:25 ` Benno Lossin
2024-08-12 18:22 ` [PATCH v5 06/26] rust: alloc: implement `Vmalloc` allocator Danilo Krummrich
2024-08-14 16:32 ` Benno Lossin
2024-08-14 22:12 ` Danilo Krummrich
2024-08-14 23:20 ` Danilo Krummrich
2024-08-15 6:48 ` Benno Lossin
2024-08-15 12:29 ` Danilo Krummrich
2024-08-15 13:44 ` Benno Lossin
2024-08-15 14:23 ` Danilo Krummrich
2024-08-15 19:08 ` Benno Lossin
2024-08-12 18:22 ` [PATCH v5 07/26] rust: alloc: implement `KVmalloc` allocator Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 08/26] rust: alloc: add __GFP_NOWARN to `Flags` Danilo Krummrich
2024-08-14 7:48 ` Alice Ryhl
2024-08-14 16:35 ` Benno Lossin
2024-08-12 18:22 ` [PATCH v5 09/26] rust: alloc: implement kernel `Box` Danilo Krummrich
2024-08-14 8:26 ` Alice Ryhl
2024-08-14 12:22 ` Danilo Krummrich [this message]
2024-08-14 12:29 ` Alice Ryhl
2024-08-14 17:01 ` Benno Lossin
2024-08-14 21:58 ` Danilo Krummrich
2024-08-15 12:44 ` Miguel Ojeda
2024-08-15 13:24 ` Benno Lossin
2024-08-15 14:00 ` Danilo Krummrich
2024-08-15 14:10 ` Benno Lossin
2024-08-15 14:17 ` Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 10/26] rust: treewide: switch to our kernel `Box` type Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 11/26] rust: alloc: remove `BoxExt` extension Danilo Krummrich
2024-08-14 11:55 ` Dirk Behme
2024-08-14 12:08 ` Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 12/26] rust: alloc: add `Box` to prelude Danilo Krummrich
2024-08-12 18:22 ` [PATCH v5 13/26] rust: alloc: implement kernel `Vec` type Danilo Krummrich
2024-08-14 8:42 ` Alice Ryhl
2024-08-14 12:29 ` Danilo Krummrich
2024-08-14 12:36 ` Alice Ryhl
2024-08-15 13:31 ` Benno Lossin
2024-08-14 22:46 ` Danilo Krummrich
2024-08-15 7:30 ` Alice Ryhl
2024-08-15 12:17 ` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 14/26] rust: alloc: implement `IntoIterator` for `Vec` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 15/26] rust: alloc: implement `collect` for `IntoIter` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 16/26] rust: treewide: switch to the kernel `Vec` type Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 17/26] rust: alloc: remove `VecExt` extension Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 18/26] rust: alloc: add `Vec` to prelude Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 19/26] rust: error: use `core::alloc::LayoutError` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 20/26] rust: error: check for config `test` in `Error::name` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 21/26] rust: alloc: implement `contains` for `Flags` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 22/26] rust: alloc: implement `Cmalloc` in module allocator_test Danilo Krummrich
2024-08-13 7:07 ` Heghedus Razvan
2024-08-13 12:34 ` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 23/26] rust: str: test: replace `alloc::format` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 24/26] rust: alloc: update module comment of alloc.rs Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 25/26] kbuild: rust: remove the `alloc` crate and `GlobalAlloc` Danilo Krummrich
2024-08-12 18:23 ` [PATCH v5 26/26] MAINTAINERS: add entry for the Rust `alloc` module Danilo Krummrich
2024-08-14 19:32 ` [PATCH v5 00/26] Generic `Allocator` support for Rust Boqun Feng
2024-08-14 20:53 ` Danilo Krummrich
2024-08-15 2:52 ` Danilo Krummrich
2024-08-15 9:20 ` Alice Ryhl
2024-08-15 12:33 ` Danilo Krummrich
2024-08-15 12:34 ` Alice Ryhl
2024-08-15 13:33 ` Danilo Krummrich
2024-08-15 13:39 ` Benno Lossin
2024-08-15 14:09 ` Danilo Krummrich
2024-08-15 14:19 ` Benno Lossin
2024-08-15 17:19 ` Boqun Feng
2024-08-15 17:31 ` Danilo Krummrich
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=Zryhae9OXD_dqfR8@pollux \
--to=dakr@kernel.org \
--cc=a.hindborg@samsung.com \
--cc=airlied@redhat.com \
--cc=ajanulgu@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=cjia@nvidia.com \
--cc=daniel.almeida@collabora.com \
--cc=faith.ekstrand@collabora.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=lina@asahilina.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lyude@redhat.com \
--cc=mcanal@igalia.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
--cc=zhiw@nvidia.com \
/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;
as well as URLs for NNTP newsgroup(s).