From: Danilo Krummrich <dakr@kernel.org>
To: Benno Lossin <benno.lossin@proton.me>
Cc: ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com,
boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
a.hindborg@samsung.com, aliceryhl@google.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 v6 04/26] rust: alloc: implement `Allocator` for `Kmalloc`
Date: Tue, 3 Sep 2024 13:48:08 +0200 [thread overview]
Message-ID: <Ztb3eOoiHs2rLCoH@pollux> (raw)
In-Reply-To: <962b7014-4f8b-4abe-8774-636b612a051c@proton.me>
On Fri, Aug 30, 2024 at 02:45:35PM +0000, Benno Lossin wrote:
> On 30.08.24 00:04, Danilo Krummrich wrote:
> > On Thu, Aug 29, 2024 at 06:32:42PM +0000, Benno Lossin wrote:
> >> On 16.08.24 02:10, Danilo Krummrich wrote:
> >>> Implement `Allocator` for `Kmalloc`, the kernel's default allocator,
> >>> typically used for objects smaller than page size.
> >>>
> >>> All memory allocations made with `Kmalloc` end up in `krealloc()`.
> >>>
> >>> It serves as allocator for the subsequently introduced types `KBox` and
> >>> `KVec`.
> >>>
> >>> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
> >>> ---
> >>> rust/kernel/alloc.rs | 2 +-
> >>> rust/kernel/alloc/allocator.rs | 72 +++++++++++++++++++++++++++++++++-
> >>> 2 files changed, 72 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
> >>> index 9932f21b0539..477dbe3c5a2f 100644
> >>> --- a/rust/kernel/alloc.rs
> >>> +++ b/rust/kernel/alloc.rs
> >>> @@ -4,7 +4,7 @@
> >>>
> >>> #[cfg(not(test))]
> >>> #[cfg(not(testlib))]
> >>> -mod allocator;
> >>> +pub mod allocator;
> >>> pub mod box_ext;
> >>> pub mod vec_ext;
> >>>
> >>> diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs
> >>> index e32182f91167..78e7d5488843 100644
> >>> --- a/rust/kernel/alloc/allocator.rs
> >>> +++ b/rust/kernel/alloc/allocator.rs
> >>> @@ -1,12 +1,28 @@
> >>> // SPDX-License-Identifier: GPL-2.0
> >>>
> >>> //! Allocator support.
> >>> +//!
> >>> +//! Documentation for the kernel's memory allocators can found in the "Memory Allocation Guide"
> >>> +//! linked below. For instance, this includes the concept of "get free page" (GFP) flags and the
> >>> +//! typical application of the different kernel allocators.
> >>> +//!
> >>> +//! Reference: <https://docs.kernel.org/core-api/memory-allocation.html>
> >>
> >> Thanks, this nice.
> >>
> >>>
> >>> use super::{flags::*, Flags};
> >>> use core::alloc::{GlobalAlloc, Layout};
> >>> use core::ptr;
> >>> +use core::ptr::NonNull;
> >>>
> >>> -struct Kmalloc;
> >>> +use crate::alloc::{AllocError, Allocator};
> >>> +use crate::bindings;
> >>> +
> >>> +/// The contiguous kernel allocator.
> >>> +///
> >>> +/// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also
> >>> +/// supports larger allocations up to `bindings::KMALLOC_MAX_SIZE`, which is hardware specific.
> >>
> >> Does putting a link here work? (I guess we don't yet export the bindings
> >> documentation, so it will probably fail... When we decide to enable it,
> >> we should create an issue to add missing links)
> >>
> >>> +///
> >>> +/// For more details see [self].
> >>> +pub struct Kmalloc;
> >>>
> >>> /// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment.
> >>> fn aligned_size(new_layout: Layout) -> usize {
> >>> @@ -36,6 +52,60 @@ pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: F
> >>> unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags.0) as *mut u8 }
> >>> }
> >>>
> >>> +/// # Invariants
> >>> +///
> >>> +/// One of the following `krealloc`, `vrealloc`, `kvrealloc`.
> >>> +struct ReallocFunc(
> >>> + unsafe extern "C" fn(*const core::ffi::c_void, usize, u32) -> *mut core::ffi::c_void,
> >>> +);
> >>> +
> >>> +impl ReallocFunc {
> >>> + // INVARIANT: `krealloc` satisfies the type invariants.
> >>> + const KREALLOC: Self = Self(bindings::krealloc);
> >>> +
> >>> + /// # Safety
> >>> + ///
> >>> + /// This method has the same safety requirements as [`Allocator::realloc`].
> >>> + unsafe fn call(
> >>> + &self,
> >>> + ptr: Option<NonNull<u8>>,
> >>> + layout: Layout,
> >>> + flags: Flags,
> >>> + ) -> Result<NonNull<[u8]>, AllocError> {
> >>> + let size = aligned_size(layout);
> >>> + let ptr = match ptr {
> >>> + Some(ptr) => ptr.as_ptr(),
> >>> + None => ptr::null(),
> >>> + };
> >>> +
> >>> + // SAFETY: `ptr` is either NULL or valid by the safety requirements of this function.
> >>
> >> You need some justification as to why calling the three allowed
> >> functions here.
> >
> > What kind of justification do I need? Can you please share some more details on
> > what you think is missing here?
>
> So, you are calling a function pointer to an `unsafe` function. This
> means that through some invariant you have to know what the safety
> requirements are (otherwise how can you guarantee that this is OK?). You
> have the invariant that the pointer points at one of the three functions
> mentioned above. What are the safety requirements of those functions? I
> would assume that the only one is that `ptr` is valid. So you can use:
>
> // SAFETY:
> // - `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc` and thus only requires that `ptr` is
> // NULL or valid.
I'm fine adding it, but I'd like to understand why you think it's required in
the safety comment here? Isn't this implicit by being the type invariant?
> // - `ptr` is either NULL or valid by the safety requirements of this function.
This is the part I already have.
>
> >>> + let raw_ptr = unsafe {
> >>> + // If `size == 0` and `ptr != NULL` the memory behind the pointer is freed.
> >>> + self.0(ptr.cast(), size, flags.0).cast()
> >>> + };
> >>> +
> >>> + let ptr = if size == 0 {
> >>> + NonNull::dangling()
> >>> + } else {
> >>> + NonNull::new(raw_ptr).ok_or(AllocError)?
> >>> + };
> >>> +
> >>> + Ok(NonNull::slice_from_raw_parts(ptr, size))
> >>> + }
> >>> +}
> >>> +
> >>> +unsafe impl Allocator for Kmalloc {
> >>
> >> Missing SAFETY comment.
> >
> > Yeah, I think we came across this in an earlier version of the series. I asked
> > you about the content and usefulness of a comment here, since I'd just end up
> > re-iterating what the `Allocator` trait documentation says.
> >
> > IIRC, you replied that you want to think of something that'd make sense to add
> > here.
>
> Oh yeah, sorry I forgot about that.
>
> > What do you think should be written here?
>
> I think the best way to do it, would be to push this question down into
> `ReallocFunc::call`. So we would put this on the trait:
>
> // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that
> // - memory remains valid until it is explicitly freed,
> // - passing a pointer to a vaild memory allocation is OK,
> // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
So, we'd also need the same for:
- `unsafe impl Allocator for Vmalloc`
- `unsafe impl Allocator for KVmalloc`
>
> We then need to put this on `ReallocFunc::call`:
>
> /// # Guarantees
> ///
> /// This method has the same guarantees as `Allocator::realloc`. Additionally
> /// - it accepts any pointer to a valid memory allocation allocated by this function.
You propose this, since for `Allocator::realloc` memory allocated with
`Allocator::alloc` would be fine too I guess.
But if e.g. `Kmalloc` wouldn't use the default `Allocator::alloc`, this would be
valid too.
We could instead write something like:
"it accepts any pointer to a valid memory allocation allocated with the same
kernel allocator."
> /// - memory allocated by this function remains valid until it is passed to this function.
Same here, `Kmalloc` could implement its own `Allocator::free`.
Maybe just "...until it is explicitly freed.".
Anyway, I'm fine with both, since non of the kernel allocators uses anything
else than `ReallocFunc::call` to allocate and free memory.
>
> Finally, we need a `GUARANTEE` comment (just above the return [^1]
> value) that establishes these guarantees:
>
> // GUARANTEE: Since we called `self.0` with `size` above and by the type invariants of `Self`,
> // `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc`. Those functions provide the guarantees of
> // this function.
>
> I am not really happy with the last sentence, but I also don't think
> that there is value in listing out all the guarantees, only to then say
> "all of this is guaranteed by us calling one of these three functions.
>
>
> [^1]: I am not sure that there is the right place. If you have any
> suggestions, feel free to share them.
Either way, I'm fine with this proposal.
>
>
> >>> + #[inline]
> >>> + unsafe fn realloc(
> >>> + ptr: Option<NonNull<u8>>,
> >>> + layout: Layout,
> >>> + flags: Flags,
> >>> + ) -> Result<NonNull<[u8]>, AllocError> {
> >>> + // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`.
> >>> + unsafe { ReallocFunc::KREALLOC.call(ptr, layout, flags) }
> >>> + }
> >>> +}
>
> Oh one more thing, I know that you already have a lot of patches in this
> series, but could you split this one into two? So the first one should
> introduce `ReallocFunc` and the second one add the impl for `Kmalloc`?
> I managed to confuse me twice because of that :)
Generally, I'm fine with that, but I'm not sure if I can avoid an intermediate
compiler warning about unused code doing that.
>
> ---
> Cheers,
> Benno
>
> >>> +
> >>> unsafe impl GlobalAlloc for Kmalloc {
> >>> unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
> >>> // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety
> >>> --
> >>> 2.46.0
> >>>
> >>
>
next prev parent reply other threads:[~2024-09-03 11:48 UTC|newest]
Thread overview: 100+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-16 0:10 [PATCH v6 00/26] Generic `Allocator` support for Rust Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 01/26] rust: alloc: add `Allocator` trait Danilo Krummrich
2024-08-29 18:19 ` Benno Lossin
2024-08-29 21:56 ` Danilo Krummrich
2024-08-30 13:06 ` Benno Lossin
2024-09-03 11:56 ` Danilo Krummrich
2024-09-10 13:03 ` Benno Lossin
2024-09-10 13:23 ` Danilo Krummrich
2024-09-10 19:37 ` Benno Lossin
2024-08-30 13:44 ` Benno Lossin
2024-08-31 12:01 ` Gary Guo
2024-08-16 0:10 ` [PATCH v6 02/26] rust: alloc: separate `aligned_size` from `krealloc_aligned` Danilo Krummrich
2024-08-31 12:16 ` Gary Guo
2024-08-16 0:10 ` [PATCH v6 03/26] rust: alloc: rename `KernelAllocator` to `Kmalloc` Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 04/26] rust: alloc: implement `Allocator` for `Kmalloc` Danilo Krummrich
2024-08-29 18:32 ` Benno Lossin
2024-08-29 22:04 ` Danilo Krummrich
2024-08-30 14:45 ` Benno Lossin
2024-09-03 11:48 ` Danilo Krummrich [this message]
2024-09-10 13:11 ` Benno Lossin
2024-09-10 13:37 ` Danilo Krummrich
2024-09-10 19:42 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 05/26] rust: alloc: add module `allocator_test` Danilo Krummrich
2024-08-31 12:18 ` Gary Guo
2024-08-16 0:10 ` [PATCH v6 06/26] rust: alloc: implement `Vmalloc` allocator Danilo Krummrich
2024-08-31 5:21 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 07/26] rust: alloc: implement `KVmalloc` allocator Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 08/26] rust: alloc: add __GFP_NOWARN to `Flags` Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 09/26] rust: alloc: implement kernel `Box` Danilo Krummrich
2024-08-20 9:47 ` Alice Ryhl
2024-08-20 15:26 ` Danilo Krummrich
2024-08-27 19:21 ` Boqun Feng
2024-08-31 5:39 ` Benno Lossin
2024-09-10 17:40 ` Danilo Krummrich
2024-09-10 19:49 ` Benno Lossin
2024-09-10 23:25 ` Danilo Krummrich
2024-09-11 8:36 ` Benno Lossin
2024-09-11 11:02 ` Danilo Krummrich
2024-09-11 13:26 ` Benno Lossin
2024-09-11 13:27 ` Alice Ryhl
2024-09-11 14:50 ` Danilo Krummrich
2024-09-12 8:03 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 10/26] rust: treewide: switch to our kernel `Box` type Danilo Krummrich
2024-08-29 18:35 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 11/26] rust: alloc: remove `BoxExt` extension Danilo Krummrich
2024-08-29 18:38 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 12/26] rust: alloc: add `Box` to prelude Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 13/26] rust: alloc: implement kernel `Vec` type Danilo Krummrich
2024-09-03 19:08 ` Boqun Feng
2024-09-10 18:26 ` Danilo Krummrich
2024-09-10 19:33 ` Benno Lossin
2024-09-10 19:32 ` Benno Lossin
2024-09-11 0:18 ` Danilo Krummrich
2024-09-11 8:46 ` Benno Lossin
2024-09-10 20:07 ` Benno Lossin
2024-09-11 21:59 ` Danilo Krummrich
2024-09-23 9:24 ` Alice Ryhl
2024-08-16 0:10 ` [PATCH v6 14/26] rust: alloc: implement `IntoIterator` for `Vec` Danilo Krummrich
2024-09-04 10:29 ` Alice Ryhl
2024-09-10 20:04 ` Benno Lossin
2024-09-10 23:39 ` Danilo Krummrich
2024-09-11 8:52 ` Benno Lossin
2024-09-11 11:32 ` Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 15/26] rust: alloc: implement `collect` for `IntoIter` Danilo Krummrich
2024-09-10 20:12 ` Benno Lossin
2024-09-11 0:22 ` Danilo Krummrich
2024-09-11 8:53 ` Benno Lossin
2024-09-11 11:33 ` Danilo Krummrich
2024-08-16 0:10 ` [PATCH v6 16/26] rust: treewide: switch to the kernel `Vec` type Danilo Krummrich
2024-08-29 18:41 ` Benno Lossin
2024-08-16 0:10 ` [PATCH v6 17/26] rust: alloc: remove `VecExt` extension Danilo Krummrich
2024-08-16 0:11 ` [PATCH v6 18/26] rust: alloc: add `Vec` to prelude Danilo Krummrich
2024-08-16 0:11 ` [PATCH v6 19/26] rust: error: use `core::alloc::LayoutError` Danilo Krummrich
2024-08-16 0:11 ` [PATCH v6 20/26] rust: error: check for config `test` in `Error::name` Danilo Krummrich
2024-08-29 18:41 ` Benno Lossin
2024-08-16 0:11 ` [PATCH v6 21/26] rust: alloc: implement `contains` for `Flags` Danilo Krummrich
2024-08-29 18:42 ` Benno Lossin
2024-08-16 0:11 ` [PATCH v6 22/26] rust: alloc: implement `Cmalloc` in module allocator_test Danilo Krummrich
2024-08-29 19:14 ` Benno Lossin
2024-08-29 22:25 ` Danilo Krummrich
2024-08-30 12:56 ` Benno Lossin
2024-09-11 12:31 ` Danilo Krummrich
2024-09-11 13:32 ` Benno Lossin
2024-09-11 14:37 ` Danilo Krummrich
2024-09-12 8:18 ` Benno Lossin
2024-08-16 0:11 ` [PATCH v6 23/26] rust: str: test: replace `alloc::format` Danilo Krummrich
2024-08-29 18:43 ` Benno Lossin
2024-08-16 0:11 ` [PATCH v6 24/26] rust: alloc: update module comment of alloc.rs Danilo Krummrich
2024-08-16 0:11 ` [PATCH v6 25/26] kbuild: rust: remove the `alloc` crate and `GlobalAlloc` Danilo Krummrich
2024-08-21 21:34 ` Benno Lossin
2024-08-16 0:11 ` [PATCH v6 26/26] MAINTAINERS: add entry for the Rust `alloc` module Danilo Krummrich
2024-08-31 12:57 ` Gary Guo
2024-09-03 12:03 ` Danilo Krummrich
2024-09-04 10:15 ` Alice Ryhl
2024-09-04 12:51 ` Benno Lossin
2024-09-04 12:57 ` Miguel Ojeda
2024-09-10 13:26 ` Benno Lossin
2024-09-10 13:42 ` Danilo Krummrich
2024-09-10 14:27 ` Benno Lossin
2024-08-27 19:17 ` [PATCH v6 00/26] Generic `Allocator` support for Rust Boqun Feng
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=Ztb3eOoiHs2rLCoH@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.