rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: 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,
	aliceryhl@google.com, akpm@linux-foundation.org
Cc: 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,
	Danilo Krummrich <dakr@kernel.org>
Subject: [PATCH v9 25/29] rust: alloc: implement `Cmalloc` in module allocator_test
Date: Fri,  4 Oct 2024 17:41:29 +0200	[thread overview]
Message-ID: <20241004154149.93856-26-dakr@kernel.org> (raw)
In-Reply-To: <20241004154149.93856-1-dakr@kernel.org>

So far the kernel's `Box` and `Vec` types can't be used by userspace
test cases, since all users of those types (e.g. `CString`) use kernel
allocators for instantiation.

In order to allow userspace test cases to make use of such types as
well, implement the `Cmalloc` allocator within the allocator_test module
and type alias all kernel allocators to `Cmalloc`. The `Cmalloc`
allocator uses libc's realloc() function as allocator backend.

Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
 rust/kernel/alloc/allocator_test.rs | 88 ++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 7 deletions(-)

diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/allocator_test.rs
index 1b2642c547ec..47c2b509898e 100644
--- a/rust/kernel/alloc/allocator_test.rs
+++ b/rust/kernel/alloc/allocator_test.rs
@@ -1,21 +1,95 @@
 // SPDX-License-Identifier: GPL-2.0
 
+//! So far the kernel's `Box` and `Vec` types can't be used by userspace test cases, since all users
+//! of those types (e.g. `CString`) use kernel allocators for instantiation.
+//!
+//! In order to allow userspace test cases to make use of such types as well, implement the
+//! `Cmalloc` allocator within the allocator_test module and type alias all kernel allocators to
+//! `Cmalloc`. The `Cmalloc` allocator uses libc's realloc() function as allocator backend.
+
 #![allow(missing_docs)]
 
-use super::{AllocError, Allocator, Flags};
+use super::{flags::*, AllocError, Allocator, Flags};
 use core::alloc::Layout;
+use core::cmp;
+use core::ptr;
 use core::ptr::NonNull;
 
-pub struct Kmalloc;
+/// The userspace allocator based on libc.
+pub struct Cmalloc;
+
+pub type Kmalloc = Cmalloc;
 pub type Vmalloc = Kmalloc;
 pub type KVmalloc = Kmalloc;
 
-unsafe impl Allocator for Kmalloc {
+extern "C" {
+    #[link_name = "aligned_alloc"]
+    fn libc_aligned_alloc(align: usize, size: usize) -> *mut core::ffi::c_void;
+
+    #[link_name = "free"]
+    fn libc_free(ptr: *mut core::ffi::c_void);
+}
+
+// SAFETY:
+// - memory remains valid until it is explicitly freed,
+// - passing a pointer to a valid memory allocation created by this `Allocator` is always OK,
+// - `realloc` provides the guarantees as provided in the `# Guarantees` section.
+unsafe impl Allocator for Cmalloc {
     unsafe fn realloc(
-        _ptr: Option<NonNull<u8>>,
-        _layout: Layout,
-        _flags: Flags,
+        ptr: Option<NonNull<u8>>,
+        layout: Layout,
+        old_layout: Layout,
+        flags: Flags,
     ) -> Result<NonNull<[u8]>, AllocError> {
-        panic!();
+        let src = match ptr {
+            Some(src) => {
+                if old_layout.size() == 0 {
+                    ptr::null_mut()
+                } else {
+                    src.as_ptr()
+                }
+            }
+            None => ptr::null_mut(),
+        };
+
+        if layout.size() == 0 {
+            // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
+            unsafe { libc_free(src.cast()) };
+
+            return Ok(NonNull::slice_from_raw_parts(
+                crate::alloc::dangling_from_layout(layout),
+                0,
+            ));
+        }
+
+        // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or
+        // exceeds the given size and alignment requirements.
+        let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) } as *mut u8;
+        let dst = NonNull::new(dst).ok_or(AllocError)?;
+
+        if flags.contains(__GFP_ZERO) {
+            // SAFETY: The preceeding calls to `libc_aligned_alloc` and `NonNull::new`
+            // guarantee that `dst` points to memory of at least `layout.size()` bytes.
+            unsafe { dst.as_ptr().write_bytes(0, layout.size()) };
+        }
+
+        if !src.is_null() {
+            // SAFETY:
+            // - `src` has previously been allocated with this `Allocator`; `dst` has just been
+            //   newly allocated, hence the memory regions do not overlap.
+            // - both` src` and `dst` are properly aligned and valid for reads and writes
+            unsafe {
+                ptr::copy_nonoverlapping(
+                    src,
+                    dst.as_ptr(),
+                    cmp::min(layout.size(), old_layout.size()),
+                )
+            };
+        }
+
+        // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
+        unsafe { libc_free(src.cast()) };
+
+        Ok(NonNull::slice_from_raw_parts(dst, layout.size()))
     }
 }
-- 
2.46.1


  parent reply	other threads:[~2024-10-04 15:44 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-04 15:41 [PATCH v9 00/29] Generic `Allocator` support for Rust Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 01/29] rust: alloc: add `Allocator` trait Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 02/29] rust: alloc: separate `aligned_size` from `krealloc_aligned` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 03/29] rust: alloc: rename `KernelAllocator` to `Kmalloc` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 04/29] rust: alloc: implement `ReallocFunc` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 05/29] rust: alloc: make `allocator` module public Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 06/29] rust: alloc: implement `Allocator` for `Kmalloc` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 07/29] rust: alloc: add module `allocator_test` Danilo Krummrich
2024-10-08 13:10   ` Boqun Feng
2024-10-08 14:28     ` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 08/29] rust: alloc: implement `Vmalloc` allocator Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 09/29] rust: alloc: implement `KVmalloc` allocator Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 10/29] rust: alloc: add __GFP_NOWARN to `Flags` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 11/29] rust: alloc: implement kernel `Box` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 12/29] rust: treewide: switch to our kernel `Box` type Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 13/29] rust: alloc: remove extension of std's `Box` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 14/29] rust: alloc: add `Box` to prelude Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 15/29] rust: alloc: introduce `ArrayLayout` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 16/29] rust: alloc: implement kernel `Vec` type Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 17/29] rust: alloc: implement `IntoIterator` for `Vec` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 18/29] rust: alloc: implement `collect` for `IntoIter` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 19/29] rust: treewide: switch to the kernel `Vec` type Danilo Krummrich
2024-10-07 14:34   ` Alice Ryhl
2024-10-07 15:21     ` Danilo Krummrich
2024-10-07 19:41       ` Miguel Ojeda
2024-10-04 15:41 ` [PATCH v9 20/29] rust: alloc: remove `VecExt` extension Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 21/29] rust: alloc: add `Vec` to prelude Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 22/29] rust: error: use `core::alloc::LayoutError` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 23/29] rust: error: check for config `test` in `Error::name` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 24/29] rust: alloc: implement `contains` for `Flags` Danilo Krummrich
2024-10-04 15:41 ` Danilo Krummrich [this message]
2024-10-08 14:32   ` [PATCH v9 25/29] rust: alloc: implement `Cmalloc` in module allocator_test Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 26/29] rust: str: test: replace `alloc::format` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 27/29] rust: alloc: update module comment of alloc.rs Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 28/29] kbuild: rust: remove the `alloc` crate and `GlobalAlloc` Danilo Krummrich
2024-10-04 15:41 ` [PATCH v9 29/29] MAINTAINERS: add entry for the Rust `alloc` module Danilo Krummrich
2024-10-15 21:13 ` [PATCH v9 00/29] Generic `Allocator` support for Rust Miguel Ojeda
2024-11-15 11:32 ` Asahi Lina
2024-11-15 14:00   ` Alice Ryhl
2024-11-16 14:21     ` Janne Grunau

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=20241004154149.93856-26-dakr@kernel.org \
    --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).