From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 159CB1CACF4; Fri, 4 Oct 2024 15:42:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056531; cv=none; b=SkCy397lqIZj923eRNllT5opyqM8kA4n0gryD4PERC7vjsdNYiDszTGD0kroMv8cMKkp1F+zXMdkF8vv5hcCZuD3g0+Og0VsIt1CIhrxm6AMfiF/a1R8X51GaC9L/Lg810S8EOlfpeu+H+7HA1lViREjkInY5MRtu80jvxV5SCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056531; c=relaxed/simple; bh=o9fTnK5hDeL2M1Gfsa2jfEjky3P6Jc8p9pXGxlscHLY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RpNfC2tWMmaFcticknfrm7M1GDqs8Ib/wqI/3xsFHzurep3pWzpLBlBqeYfmJLy4ZwZfx9e3zVg03wBm9dpujCyPcqgpZpkoZyqYR3NHVuMAapp5HYrjdSZbuMOoP1PrwfATFn2cu7EQwXOHfxSn8kUD0MlZd2HS1uIiO6VmsqA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RAW1ky8v; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RAW1ky8v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01F96C4CECF; Fri, 4 Oct 2024 15:42:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056530; bh=o9fTnK5hDeL2M1Gfsa2jfEjky3P6Jc8p9pXGxlscHLY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RAW1ky8v40yQnljYx1biN48PIk0ApY4J635Fj6cnMGkG86MNyra/loqlO2s+zH+ge HvnR6t1PEzGwWaD3RYS+E0Z4Ur6dNVxfI0JtDUIkPbXfZnS7l8g35iNhuaoUM0GdbD B/ywyJ5atXiiYow9VJFJCeetohINI3hbGhKZcIt92FBQBSFt2n6bb9W6k6X+ydxD+X k0L4x7kU17neqJDvrAxNE26LuXeI55q02amzcu6HpucIujT7a8BgE/kJbcXbuO7Rhd VufrwlMnPdbR8gnGDIUXl24001WgLhqYUHtiW+KvoHHC2OXo9mL6syokthlkVXz8/n MNZlQVYgzrjXw== From: Danilo Krummrich 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 Subject: [PATCH v9 01/29] rust: alloc: add `Allocator` trait Date: Fri, 4 Oct 2024 17:41:05 +0200 Message-ID: <20241004154149.93856-2-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a kernel specific `Allocator` trait, that in contrast to the one in Rust's core library doesn't require unstable features and supports GFP flags. Subsequent patches add the following trait implementors: `Kmalloc`, `Vmalloc` and `KVmalloc`. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 101 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 1966bd407017..4deeea3488be 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -11,6 +11,7 @@ /// Indicates an allocation error. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; +use core::{alloc::Layout, ptr::NonNull}; =20 /// Flags to be used when allocating memory. /// @@ -86,3 +87,103 @@ pub mod flags { /// small allocations. pub const GFP_NOWAIT: Flags =3D Flags(bindings::GFP_NOWAIT); } + +/// The kernel's [`Allocator`] trait. +/// +/// An implementation of [`Allocator`] can allocate, re-allocate and free = memory buffers described +/// via [`Layout`]. +/// +/// [`Allocator`] is designed to be implemented as a ZST; [`Allocator`] fu= nctions do not operate on +/// an object instance. +/// +/// In order to be able to support `#[derive(SmartPointer)]` later on, we = need to avoid a design +/// that requires an `Allocator` to be instantiated, hence its functions m= ust not contain any kind +/// of `self` parameter. +/// +/// # Safety +/// +/// - A memory allocation returned from an allocator must remain valid unt= il it is explicitly freed. +/// +/// - Any pointer to a valid memory allocation must be valid to be passed = to any other [`Allocator`] +/// function of the same type. +/// +/// - Implementers must ensure that all trait functions abide by the guara= ntees documented in the +/// `# Guarantees` sections. +pub unsafe trait Allocator { + /// Allocate memory based on `layout` and `flags`. + /// + /// On success, returns a buffer represented as `NonNull<[u8]>` that s= atisfies the layout + /// constraints (i.e. minimum size and alignment as specified by `layo= ut`). + /// + /// This function is equivalent to `realloc` when called with `None`. + /// + /// # Guarantees + /// + /// When the return value is `Ok(ptr)`, then `ptr` is + /// - valid for reads and writes for `layout.size()` bytes, until it i= s passed to + /// [`Allocator::free`] or [`Allocator::realloc`], + /// - aligned to `layout.align()`, + /// + /// Additionally, `Flags` are honored as documented in + /// . + fn alloc(layout: Layout, flags: Flags) -> Result, AllocE= rror> { + // SAFETY: Passing `None` to `realloc` is valid by it's safety req= uirements and asks for a + // new memory allocation. + unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags) } + } + + /// Re-allocate an existing memory allocation to satisfy the requested= `layout`. + /// + /// If the requested size is zero, `realloc` behaves equivalent to `fr= ee`. + /// + /// If the requested size is larger than the size of the existing allo= cation, a successful call + /// to `realloc` guarantees that the new or grown buffer has at least = `Layout::size` bytes, but + /// may also be larger. + /// + /// If the requested size is smaller than the size of the existing all= ocation, `realloc` may or + /// may not shrink the buffer; this is implementation specific to the = allocator. + /// + /// On allocation failure, the existing buffer, if any, remains valid. + /// + /// The buffer is represented as `NonNull<[u8]>`. + /// + /// # Safety + /// + /// - If `ptr =3D=3D Some(p)`, then `p` must point to an existing and = valid memory allocation + /// created by this [`Allocator`]; if `old_layout` is zero-sized `p`= does not need to be a + /// pointer returned by this [`Allocator`]. + /// - `ptr` is allowed to be `None`; in this case a new memory allocat= ion is created and + /// `old_layout` is ignored. + /// - `old_layout` must match the `Layout` the allocation has been cre= ated with. + /// + /// # Guarantees + /// + /// This function has the same guarantees as [`Allocator::alloc`]. Whe= n `ptr =3D=3D Some(p)`, then + /// it additionally guarantees that: + /// - the contents of the memory pointed to by `p` are preserved up to= the lesser of the new + /// and old size, i.e. `ret_ptr[0..min(layout.size(), old_layout.siz= e())] =3D=3D + /// p[0..min(layout.size(), old_layout.size())]`. + /// - when the return value is `Err(AllocError)`, then `ptr` is still = valid. + unsafe fn realloc( + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError>; + + /// Free an existing memory allocation. + /// + /// # Safety + /// + /// - `ptr` must point to an existing and valid memory allocation crea= ted by this [`Allocator`]; + /// if `old_layout` is zero-sized `p` does not need to be a pointer = returned by this + /// [`Allocator`]. + /// - `layout` must match the `Layout` the allocation has been created= with. + /// - The memory allocation at `ptr` must never again be read from or = written to. + unsafe fn free(ptr: NonNull, layout: Layout) { + // SAFETY: The caller guarantees that `ptr` points at a valid allo= cation created by this + // allocator. We are passing a `Layout` with the smallest possible= alignment, so it is + // smaller than or equal to the alignment previously used with thi= s allocation. + let _ =3D unsafe { Self::realloc(Some(ptr), Layout::new::<()>(), l= ayout, Flags(0)) }; + } +} --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C48F41DF845; Fri, 4 Oct 2024 15:42:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056538; cv=none; b=FD2sEx5nK1sytPDkXqV711TSXQRh6Bz5xpobRWMC8DknWgP7Hy4hUSjLsFF47GNr3jOBE/mB96Qb2q3NqRe6+4p7NGYVOPgdjUrIez7cEa9k7sZSjUG9j4nJInChGDWSt8cfrGtbwI0TINsRzf77pcFZQL/CSoI1ZAniG8Zw4pw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056538; c=relaxed/simple; bh=RKYOxaZlfRNBRkHBIioYvHfe6spLUu1mZk00Wam8Has=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aWzWufMQt2t3Rnz2CNUEPCqaRR7NuwjVDyd3VcnxnDqxltZp6FXHquCkpBXe16toOYS6an0pdEj76wTRBferYQeQrBqpHGXYnvnpHrYZySuBQSMnvr/NgHdqN24umeE6UQQsuFIKTQWkUOfpj6/JhUAewL/VkBReXZpqibd25Sw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f4eAqOAq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f4eAqOAq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 66D15C4CED0; Fri, 4 Oct 2024 15:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056536; bh=RKYOxaZlfRNBRkHBIioYvHfe6spLUu1mZk00Wam8Has=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=f4eAqOAq1FX1Ya1okjVZkz82mLxBGix6bkOeHOi5qGpTXizdIdI1HGcng3ZO30+Su 1ibtaobqiZMH2mWJtOhI2E22BuQcm7mIPwwS5ULuccazCkaUDYJw+2hT711xDBX7Ey 2oeYgJ2/Kmu3UizrBDNvRBFrFbYJ2zlcfPxejGlYIRW7zYvSuqi9yZcmfyaXj97ykj 3g0kRigDy/sekuNsh9ECtUeQiQxI41drqNILzFdrd1NaAbk/ATarkl7sM3abOV40da 892mB3SXd74TS2mDLL/LLHLP1h9PKePh79zBPjVLoVaqcxEfPsIOcDe7UlJaWr47Tu 9+LAnKXkQLjWA== From: Danilo Krummrich 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 Subject: [PATCH v9 02/29] rust: alloc: separate `aligned_size` from `krealloc_aligned` Date: Fri, 4 Oct 2024 17:41:06 +0200 Message-ID: <20241004154149.93856-3-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Separate `aligned_size` from `krealloc_aligned`. Subsequent patches implement `Allocator` derivates, such as `Kmalloc`, that require `aligned_size` and replace the original `krealloc_aligned`. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/allocator.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 91216b36af69..765f72d5bc21 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -8,6 +8,17 @@ =20 struct KernelAllocator; =20 +/// Returns a proper size to alloc a new object aligned to `new_layout`'s = alignment. +fn aligned_size(new_layout: Layout) -> usize { + // Customized layouts from `Layout::from_size_align()` can have size <= align, so pad first. + let layout =3D new_layout.pad_to_align(); + + // Note that `layout.size()` (after padding) is guaranteed to be a mul= tiple of `layout.align()` + // which together with the slab guarantees means the `krealloc` will r= eturn a properly aligned + // object (see comments in `kmalloc()` for more information). + layout.size() +} + /// Calls `krealloc` with a proper size to alloc a new object aligned to `= new_layout`'s alignment. /// /// # Safety @@ -15,13 +26,7 @@ /// - `ptr` can be either null or a pointer which has been allocated by th= is allocator. /// - `new_layout` must have a non-zero size. pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, fl= ags: Flags) -> *mut u8 { - // Customized layouts from `Layout::from_size_align()` can have size <= align, so pad first. - let layout =3D new_layout.pad_to_align(); - - // Note that `layout.size()` (after padding) is guaranteed to be a mul= tiple of `layout.align()` - // which together with the slab guarantees means the `krealloc` will r= eturn a properly aligned - // object (see comments in `kmalloc()` for more information). - let size =3D layout.size(); + let size =3D aligned_size(new_layout); =20 // SAFETY: // - `ptr` is either null or a pointer returned from a previous `k{re}= alloc()` by the --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D5911DF845; Fri, 4 Oct 2024 15:42:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056542; cv=none; b=V7u8Qq/FJaX3cCWP3rF6RQEq9GRhtyLWcYztLx92BnGJ6GTeqkNLpqV8NuU/1gFa8xxs+QO3ZodFkbniTDSSEuc/yvkiyGFTf7Q21pUN98zwiDOceX3HTC9sJSAKgPGsGNm9qqwm674hE7FTYXWfAyFZp0D4uXD3ATamkt3awjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056542; c=relaxed/simple; bh=axTTg7SsxXZNqW4CxUpwgLYR5awaQab7skyekwlvxHA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iOENmvO5bS3fYkesiEc2kg2oe8TKdivd4q78tWnUQDefd6YDFppORm4ChfAisf8kBBAZbBjcxoHHMM8KJks2hqJMHok9BtM+odmzeqHvaxge7up1Rjpmb/Sja2yYVJwUZ9QKgwupbZUnWpm4cufG1N4sh++oh3Fu0Lcc5CmkylY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iLntNC5G; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iLntNC5G" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CFD86C4CED1; Fri, 4 Oct 2024 15:42:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056541; bh=axTTg7SsxXZNqW4CxUpwgLYR5awaQab7skyekwlvxHA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iLntNC5GMO+JfUfJ8T+RToF/Q6zkfE7Zbk6QFUt/YDBi5fmDfvLnGjdsh/MmTD6nx JdHKLGahSiq+PTzPUi+dCZGcIHqfbnVbuAcjTZ+PuzemKlxbCcLs3jiVBtSFySOR3+ YqyOojHVpAFhUvR2z+/RUrIhKXbEnBB/mHKYMZp2SO2cs2APgp5zQiiPWue5mVIFyE aXhBqMr1Qbv9cGHI8RT7aaniTTWQL2W5hf5PlOIoHmtFHf/g+m6yLGcWsbhLsOqzOa RDJy4UgSrxf0zlREhw+BujKjRga7rESHFswoiVECMil4ZVX2lXo4rTVqzM2W0zOmeH EILZDqjGCWlUw== From: Danilo Krummrich 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 Subject: [PATCH v9 03/29] rust: alloc: rename `KernelAllocator` to `Kmalloc` Date: Fri, 4 Oct 2024 17:41:07 +0200 Message-ID: <20241004154149.93856-4-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Subsequent patches implement `Vmalloc` and `KVmalloc` allocators, hence align `KernelAllocator` to this naming scheme. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/allocator.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 765f72d5bc21..3b1c735ba409 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -6,7 +6,7 @@ use core::alloc::{GlobalAlloc, Layout}; use core::ptr; =20 -struct KernelAllocator; +struct Kmalloc; =20 /// Returns a proper size to alloc a new object aligned to `new_layout`'s = alignment. fn aligned_size(new_layout: Layout) -> usize { @@ -37,7 +37,7 @@ pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_l= ayout: Layout, flags: F } =20 // SAFETY: TODO. -unsafe impl GlobalAlloc for KernelAllocator { +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 s= ize by the function safety // requirement. @@ -74,7 +74,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { } =20 #[global_allocator] -static ALLOCATOR: KernelAllocator =3D KernelAllocator; +static ALLOCATOR: Kmalloc =3D Kmalloc; =20 // See . #[no_mangle] --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F7CA1DF845; Fri, 4 Oct 2024 15:42:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056548; cv=none; b=Y/KUDW2xkk5gadx9BnVLjskO5MJGELGAhyGDt/Nxlykp8inwDwNhhC0C42NzuxbS6FbWtlFSiC2WVnGYW/GFxAjO9EXV4Bjd85xnbP/hiczOGAVOSkt5KpI0q4um0+HWdSlUb/KS7Iy2wy9nvTVmPLnAAaWHtC36XpaL7ly4SWY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056548; c=relaxed/simple; bh=FjNpQ7WplEuJvZRXB9OKv92SNKAtpq7ActsyiT3/uto=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jQwg+Z0zFpeeDMPoHSrE3vZkuIRdFf5yKpVe23c66KDvf1mryFDcaLjlHT+5RH9/raHAPYw2afmtM1Hmz2isGGlsyrisVENafgt5+ZVcfuYmkKDqDJJe9WE3bBWVKA11F3kB4ZY8+4g+0nqH5lHU8HBLBLshaE+t9bTQsvm7S50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QVUR/08O; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QVUR/08O" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41F86C4CEC7; Fri, 4 Oct 2024 15:42:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056547; bh=FjNpQ7WplEuJvZRXB9OKv92SNKAtpq7ActsyiT3/uto=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QVUR/08O9+E1CNbbgPERgJT5Kwjss1sEY4YsIYtAHtUWpluZl24F8r65XdahkgBbQ KqsJ+pcUshMVHutDmTwYlUonLQLcUfNl0AiCnazXFGf5qr5JpfCGDIwiJ6KsyGztRX iQ3m3d/gWQT517HOJkSJcM4RfkInPGO+pW6mf3AjXK49jOp5beuavcWBoODmsUgU34 0PGUzUgE+v+RuLOz6Fk71tEy5IFx3IW1U+B6bVzWR6AjgLdjB9HMIuHFI+1N1mTxYn LQgA3F8cbXRDpAqi9uZyXziN5ChX3v8E2XeIQS2IbA78gm/hlC+0097YdthT8KcV56 rpe/FpWijamSA== From: Danilo Krummrich 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 Subject: [PATCH v9 04/29] rust: alloc: implement `ReallocFunc` Date: Fri, 4 Oct 2024 17:41:08 +0200 Message-ID: <20241004154149.93856-5-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" `ReallocFunc` is an abstraction for the kernel's realloc derivates, such as `krealloc`, `vrealloc` and `kvrealloc`. All of the named functions share the same function signature and implement the same semantics. The `ReallocFunc` abstractions provides a generalized wrapper around those, to trivialize the implementation of `Kmalloc`, `Vmalloc` and `KVmalloc` in subsequent patches. Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 8 ++++ rust/kernel/alloc/allocator.rs | 70 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 4deeea3488be..da49c5306431 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -187,3 +187,11 @@ unsafe fn free(ptr: NonNull, layout: Layout) { let _ =3D unsafe { Self::realloc(Some(ptr), Layout::new::<()>(), l= ayout, Flags(0)) }; } } + +/// Returns a properly aligned dangling pointer from the given `layout`. +pub(crate) fn dangling_from_layout(layout: Layout) -> NonNull { + let ptr =3D layout.align() as *mut u8; + + // SAFETY: `layout.align()` (and hence `ptr`) is guaranteed to be non-= zero. + unsafe { NonNull::new_unchecked(ptr) } +} diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 3b1c735ba409..e5bac90046a4 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -1,10 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 =20 //! Allocator support. +//! +//! Documentation for the kernel's memory allocators can found in the "Mem= ory Allocation Guide" +//! linked below. For instance, this includes the concept of "get free pag= e" (GFP) flags and the +//! typical application of the different kernel allocators. +//! +//! Reference: =20 use super::{flags::*, Flags}; use core::alloc::{GlobalAlloc, Layout}; use core::ptr; +use core::ptr::NonNull; + +use crate::alloc::AllocError; +use crate::bindings; =20 struct Kmalloc; =20 @@ -36,6 +46,66 @@ 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, fla= gs.0) as *mut u8 } } =20 +/// # Invariants +/// +/// One of the following `krealloc`, `vrealloc`, `kvrealloc`. +struct ReallocFunc( + unsafe extern "C" fn(*const core::ffi::c_void, usize, u32) -> *mut cor= e::ffi::c_void, +); + +#[expect(dead_code)] +impl ReallocFunc { + /// # Safety + /// + /// This method has the same safety requirements as [`Allocator::reall= oc`]. + /// + /// # Guarantees + /// + /// This method has the same guarantees as `Allocator::realloc`. Addit= ionally + /// - it accepts any pointer to a valid memory allocation allocated by= this function. + /// - memory allocated by this function remains valid until it is pass= ed to this function. + unsafe fn call( + &self, + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + let size =3D aligned_size(layout); + let ptr =3D match ptr { + Some(ptr) =3D> { + if old_layout.size() =3D=3D 0 { + ptr::null() + } else { + ptr.as_ptr() + } + } + None =3D> ptr::null(), + }; + + // SAFETY: + // - `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc` and th= us only requires that + // `ptr` is NULL or valid. + // - `ptr` is either NULL or valid by the safety requirements of t= his function. + // + // GUARANTEE: + // - `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc`. + // - Those functions provide the guarantees of this function. + let raw_ptr =3D unsafe { + // If `size =3D=3D 0` and `ptr !=3D NULL` the memory behind th= e pointer is freed. + self.0(ptr.cast(), size, flags.0).cast() + }; + + let ptr =3D if size =3D=3D 0 { + crate::alloc::dangling_from_layout(layout) + } else { + NonNull::new(raw_ptr).ok_or(AllocError)? + }; + + Ok(NonNull::slice_from_raw_parts(ptr, size)) + } +} + // SAFETY: TODO. unsafe impl GlobalAlloc for Kmalloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF99C1DF845; Fri, 4 Oct 2024 15:42:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056552; cv=none; b=Ffu1UvGQH7Gq8qr34sEoTsVo52gHsdaxK670KO4Ont0WTvb16PUQvcuZapRwDjJO34W8SI+XIv03dNPX34bQlhu5m5Wdl5ymM2zKRcZFEd50ePFE3zT8aAKY/81MdxNcdRfhvJE1DZ1Tx05hloTe+NF9c7tn+N6Luyiqg/mKWCY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056552; c=relaxed/simple; bh=sxl4tea78ipgv1w2ubiPdzaMlUQIlFJyy3VgFb/Bypk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hT4oUq1/lARTWMlMvV3ldhtac5YZ6gIzn4SbIXWwSsFwCSVgVZWJfW1IwLdY0qxTFHiKFr2KwWPCaQylA2d4lOzwjiN5oBNH2/243el4CKDlDvt3o51Lh6Jr29yx4zkf/vDxPAs2Tj1q8846cH/zkB8DmQsYx2XU0wN+QKsge/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qhlqp3tx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qhlqp3tx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A6BF7C4CECF; Fri, 4 Oct 2024 15:42:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056552; bh=sxl4tea78ipgv1w2ubiPdzaMlUQIlFJyy3VgFb/Bypk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qhlqp3txx5UGYepN445qb5tXqTXeQZscm663Ynhm+Ohg5Gwb+YVM0+JFs4NeKJ7+e YjiwFn7VhR7EHqC7Rba9eJU72m5sfpDiClPFKuEm+e09je3P9p4gWDRrGa9vJFbgWY 4JO9Syp6zwKtSI6lK//JJIlOkI9bX0GO2xSl3SyP8QORp4kG4SPToZatXFUjixyfiz gbNXh9FypFs1rNE5Tii93wyf785+4u28rNKxnnLbYqF0858HQzd3VVzcRTg8eiZnmY 4BoNHc0U9uIVEI1K90JWeHeoSgUJIt8kC8liAXfbHmhM1ZUuPD2V80f/ZYse2X0Iiu vFzgR5K95nw2g== From: Danilo Krummrich 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 Subject: [PATCH v9 05/29] rust: alloc: make `allocator` module public Date: Fri, 4 Oct 2024 17:41:09 +0200 Message-ID: <20241004154149.93856-6-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Subsequent patches implement allocators such as `Kmalloc`, `Vmalloc`, `KVmalloc`; we need them to be available outside of the kernel crate as well. Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index da49c5306431..91b2a26faf3d 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -4,7 +4,7 @@ =20 #[cfg(not(test))] #[cfg(not(testlib))] -mod allocator; +pub mod allocator; pub mod box_ext; pub mod vec_ext; =20 --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C93E1DF845; Fri, 4 Oct 2024 15:42:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056558; cv=none; b=RuqD1LuITCN7/5WNedezeVprt5HM/Jt2wmE58pMn7ltHu0bWqwVJppuebXfnzBhCvmgQFa8Xbpca11SY/Lg8Xo7BOCy8ATL4zVhWNwOJvShvdgN1LR3Wtfv2wvXDBJoycj5MbNmHD0F99HfbetEMc7T9IgR0o/goqrH50IPBDaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056558; c=relaxed/simple; bh=WMfOs4LG4FcoFF7HvER0kneu0SsNLoPkbGbTFCvgLjw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WGoeQtFz8vmT418sbyPtUpmxk33+K8T1wtko05ikqLybI8bdjSJMEabZ28Tt0hwcdjLLlOlig7XtbQZZ7PI7/5BlH+ToFLjUuhrj0obFWRbjuAWvCjJyLuGdkLotNAUhcNiNL1sz/8+18ROhNIwDEOae9CXuGfL/sZ4dFqlCmZ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qgIP+fTy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qgIP+fTy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1D46EC4CEC6; Fri, 4 Oct 2024 15:42:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056558; bh=WMfOs4LG4FcoFF7HvER0kneu0SsNLoPkbGbTFCvgLjw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qgIP+fTyX7lwjVlnpmUyGjOJZynK9iiYrJ1weIGyEyn4HIs0F5TN1pp1cwK2jj/oJ 41Rd3fxoq7eW1KKElQYZRH6QXoHEfGl8QtcapXpTVKm4+FaSiP5QIg2njJwHir2YsH jfTO1eTd6sZUn+4rporGAsUPmMVD75txon7Bk5OBZ5mTQDBCx9jfdeQ7pR/a5ED45e Q3GTVUw0R/LGjBm/hUASbRIBRsypT3vGThTkUmrnuwfbPMU5p+qV/hAc496btDURlO i5zN3rdjaPsfxoOGzu0yjs7POkDsibjNx9eySUuTBaPSC2bWajwdVUKDyosIU+4Wov ci7cEGqNZPRDA== From: Danilo Krummrich 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 Subject: [PATCH v9 06/29] rust: alloc: implement `Allocator` for `Kmalloc` Date: Fri, 4 Oct 2024 17:41:10 +0200 Message-ID: <20241004154149.93856-7-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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`. Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/allocator.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index e5bac90046a4..b1894c800448 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -13,10 +13,16 @@ use core::ptr; use core::ptr::NonNull; =20 -use crate::alloc::AllocError; +use crate::alloc::{AllocError, Allocator}; use crate::bindings; =20 -struct Kmalloc; +/// The contiguous kernel allocator. +/// +/// `Kmalloc` is typically used for physically contiguous allocations up t= o page size, but also +/// supports larger allocations up to `bindings::KMALLOC_MAX_SIZE`, which = is hardware specific. +/// +/// For more details see [self]. +pub struct Kmalloc; =20 /// Returns a proper size to alloc a new object aligned to `new_layout`'s = alignment. fn aligned_size(new_layout: Layout) -> usize { @@ -53,8 +59,10 @@ struct ReallocFunc( unsafe extern "C" fn(*const core::ffi::c_void, usize, u32) -> *mut cor= e::ffi::c_void, ); =20 -#[expect(dead_code)] impl ReallocFunc { + // INVARIANT: `krealloc` satisfies the type invariants. + const KREALLOC: Self =3D Self(bindings::krealloc); + /// # Safety /// /// This method has the same safety requirements as [`Allocator::reall= oc`]. @@ -106,6 +114,23 @@ unsafe fn call( } } =20 +// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// - memory remains valid until it is explicitly freed, +// - passing a pointer to a valid memory allocation is OK, +// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. +unsafe impl Allocator for Kmalloc { + #[inline] + unsafe fn realloc( + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + // SAFETY: `ReallocFunc::call` has the same safety requirements as= `Allocator::realloc`. + unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags= ) } + } +} + // SAFETY: TODO. unsafe impl GlobalAlloc for Kmalloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D20AB1C75EA; Fri, 4 Oct 2024 15:42:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056563; cv=none; b=Vv12z4BfxbujBrTBMR7lW16L8W1vQLHlCgijW6em5scLrD8qXdwnjBROb5mof8/D7TWBUIrDhdfjPF1vBT6W12oiHVTqI+qwLySh7GH2NWRbaHZTjzXg9CXcpjKPOZzaDITGukV3rOWIEL8EMTCUEqrUuy5Pzp7nx5nK6jIHUzU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056563; c=relaxed/simple; bh=qlNC8elt2DUs+OwvKv1BnkmPQ4QqoPQad7Orfyq3Sws=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PiMUIKSvoDoi7KcSDB/dAl1J0xgHpz8VhcwMlmBGZ0P58lXzCzEj/lTCLoOJsvX3pOu6oalzX/Dw6M3bqVtCjoJPIwx0ckL62brSnXcfzKbMgVAdjOzrdaV9afqW6YWMCQDzfsvTDdovBO4U4yEAPce7AqItZGyKQNE80U/BWRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RT8MltSI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RT8MltSI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7FCE4C4CEC7; Fri, 4 Oct 2024 15:42:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056563; bh=qlNC8elt2DUs+OwvKv1BnkmPQ4QqoPQad7Orfyq3Sws=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RT8MltSIAOaKHQso1eT6Z3mUjfi5RIvInL1mxMQG2SL1evErcWA4qcx+604Orhc0L KUqXykgrTTXpuWLEQAxwd3FKpElA8xCNwM/1ZapjJMEWlLcNT9oPJvY89Xk1XMyPky Fak8WyV30MuRnMLZyWdMaMh9ivSoAujvNZ1VyuDQm40yXjm2BM6dAPJAryWCYSjc7o D+OV1bXzZJm27Yox5GFTb45b2DsjWT/U64k4XrJvC4ATcbKOZKLfnY1H9RP8Fd5BVL KQ4swMp90bxNA+VGWSmMkRnrqZG8QzStP40GSzB2CILS6gTbVkSnXcQPKjiYwpl9mk b/VuM9UUxUjaw== From: Danilo Krummrich 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 Subject: [PATCH v9 07/29] rust: alloc: add module `allocator_test` Date: Fri, 4 Oct 2024 17:41:11 +0200 Message-ID: <20241004154149.93856-8-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" `Allocator`s, such as `Kmalloc`, will be used by e.g. `Box` and `Vec` in subsequent patches, and hence this dependency propagates throughout the whole kernel. Add the `allocator_test` module that provides an empty implementation for all `Allocator`s in the kernel, such that we don't break the `rusttest` make target in subsequent patches. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 9 +++++++-- rust/kernel/alloc/allocator_test.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 rust/kernel/alloc/allocator_test.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 91b2a26faf3d..f8ddc8d96da9 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -2,12 +2,17 @@ =20 //! Extensions to the [`alloc`] crate. =20 -#[cfg(not(test))] -#[cfg(not(testlib))] +#[cfg(not(any(test, testlib)))] pub mod allocator; pub mod box_ext; pub mod vec_ext; =20 +#[cfg(any(test, testlib))] +pub mod allocator_test; + +#[cfg(any(test, testlib))] +pub use self::allocator_test as allocator; + /// Indicates an allocation error. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/alloca= tor_test.rs new file mode 100644 index 000000000000..4785efc474a7 --- /dev/null +++ b/rust/kernel/alloc/allocator_test.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 + +#![allow(missing_docs)] + +use super::{AllocError, Allocator, Flags}; +use core::alloc::Layout; +use core::ptr::NonNull; + +pub struct Kmalloc; + +unsafe impl Allocator for Kmalloc { + unsafe fn realloc( + _ptr: Option>, + _layout: Layout, + _flags: Flags, + ) -> Result, AllocError> { + panic!(); + } +} --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4643B1E076A; Fri, 4 Oct 2024 15:42:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056569; cv=none; b=jb8nkbbPv8FCubOH5JSbfQYpeA5UHo0cJvd379B423bpW0zaCp6QesvFOY+pWk5pxdhkPY4yne5aPpAF2IoALaD2k/iHBLvNkw69FVE2Zk2QPw8vPnAkwQLooYL4ZCH6yqIvTF0TxhzD5YqiI0PRZ/pdV/fDEaIUw3eqeXnIn7Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056569; c=relaxed/simple; bh=ivWwJFghp2EePOEDw8b0kSPMmrO/dnpTdtxjr1CLz4w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bLTe54EsZnXI2imieWJsIPAkLBEJysdgZMzmm2X1QlNgbejIiUpVdgc9AqpxuQdNLZ73oqEJQnO26qdBo7QSOrpBAvW7EvFsShHUB/e2Y3Y03+Xdgr/XqbMo/YazJQcLhtQ1Sk6SSKBmSuU8izIt4UvyrbHIsoylM+Vnn0V6nDA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cSA2K6ze; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cSA2K6ze" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1B5EC4CECE; Fri, 4 Oct 2024 15:42:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056568; bh=ivWwJFghp2EePOEDw8b0kSPMmrO/dnpTdtxjr1CLz4w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cSA2K6zeVv53uZz9bvEnG58rmYxYWwi8m+G32sOaGwu7Rcjut8ag2DdcqHYX3Ft6G 1AtbO67RWiG43g1FNUdnf+HuXevV+6dbqHC9FSpn7vgyHsL7w6bYwpz5/a0+dc8nK9 ZwsbLcjfvaDAjSAIHEY3Rj8G3eZmoKFtGM25jukwyFLHVWS5VZvXg6tP8WYPLj1EhO ziQ1MnRkf9Az6ai+7ryVXTuCErMWEuVbtJTMthTpoMjRB/gSl6VKSpxAoCeyZeYbkE q5mIHNIx/0B2PM4AdS81GXikoT4rc4qjb6o+EOkO23+/TEmCWd/aupZx3/hET+9KpY /2UPc0f/gl1oA== From: Danilo Krummrich 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 Subject: [PATCH v9 08/29] rust: alloc: implement `Vmalloc` allocator Date: Fri, 4 Oct 2024 17:41:12 +0200 Message-ID: <20241004154149.93856-9-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement `Allocator` for `Vmalloc`, the kernel's virtually contiguous allocator, typically used for larger objects, (much) larger than page size. All memory allocations made with `Vmalloc` end up in `vrealloc()`. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/helpers/helpers.c | 1 + rust/helpers/vmalloc.c | 9 +++++++ rust/kernel/alloc/allocator.rs | 37 +++++++++++++++++++++++++++++ rust/kernel/alloc/allocator_test.rs | 1 + 4 files changed, 48 insertions(+) create mode 100644 rust/helpers/vmalloc.c diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 30f40149f3a9..20a0c69d5cc7 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -22,5 +22,6 @@ #include "spinlock.c" #include "task.c" #include "uaccess.c" +#include "vmalloc.c" #include "wait.c" #include "workqueue.c" diff --git a/rust/helpers/vmalloc.c b/rust/helpers/vmalloc.c new file mode 100644 index 000000000000..80d34501bbc0 --- /dev/null +++ b/rust/helpers/vmalloc.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void * __must_check __realloc_size(2) +rust_helper_vrealloc(const void *p, size_t size, gfp_t flags) +{ + return vrealloc(p, size, flags); +} diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index b1894c800448..5742ce7d0453 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -15,6 +15,7 @@ =20 use crate::alloc::{AllocError, Allocator}; use crate::bindings; +use crate::pr_warn; =20 /// The contiguous kernel allocator. /// @@ -24,6 +25,15 @@ /// For more details see [self]. pub struct Kmalloc; =20 +/// The virtually contiguous kernel allocator. +/// +/// `Vmalloc` allocates pages from the page level allocator and maps them = into the contiguous kernel +/// virtual space. It is typically used for large allocations. The memory = allocated with this +/// allocator is not physically contiguous. +/// +/// For more details see [self]. +pub struct Vmalloc; + /// Returns a proper size to alloc a new object aligned to `new_layout`'s = alignment. fn aligned_size(new_layout: Layout) -> usize { // Customized layouts from `Layout::from_size_align()` can have size <= align, so pad first. @@ -63,6 +73,9 @@ impl ReallocFunc { // INVARIANT: `krealloc` satisfies the type invariants. const KREALLOC: Self =3D Self(bindings::krealloc); =20 + // INVARIANT: `vrealloc` satisfies the type invariants. + const VREALLOC: Self =3D Self(bindings::vrealloc); + /// # Safety /// /// This method has the same safety requirements as [`Allocator::reall= oc`]. @@ -168,6 +181,30 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut = u8 { } } =20 +// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// - memory remains valid until it is explicitly freed, +// - passing a pointer to a valid memory allocation is OK, +// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. +unsafe impl Allocator for Vmalloc { + #[inline] + unsafe fn realloc( + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + // TODO: Support alignments larger than PAGE_SIZE. + if layout.align() > bindings::PAGE_SIZE { + pr_warn!("Vmalloc does not support alignments larger than PAGE= _SIZE yet.\n"); + return Err(AllocError); + } + + // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously + // allocated with this `Allocator`. + unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags= ) } + } +} + #[global_allocator] static ALLOCATOR: Kmalloc =3D Kmalloc; =20 diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/alloca= tor_test.rs index 4785efc474a7..e7bf2982f68f 100644 --- a/rust/kernel/alloc/allocator_test.rs +++ b/rust/kernel/alloc/allocator_test.rs @@ -7,6 +7,7 @@ use core::ptr::NonNull; =20 pub struct Kmalloc; +pub type Vmalloc =3D Kmalloc; =20 unsafe impl Allocator for Kmalloc { unsafe fn realloc( --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AB901C75E7; Fri, 4 Oct 2024 15:42:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056574; cv=none; b=DxfaTyZTmHU80+yYH9OXFBnn15pTNMoypr/6G6h60guO/e1cFUKKdGg/RRJ9h5Q51Uxfs6dF80vK7BI9416QS8EcRhUwJ7MHmw1FP52hOwou8w9sIcuQtzp5LUIUTuX+1E1ST9+DwAz7Sx3HQAltuklWFxqTDx/r1ABmwVYfMFw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056574; c=relaxed/simple; bh=bmN7ni692A736mVNYrpUELQFpNi/F1V47sEOIzb2Zxc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HRBP0LamQjWnWZ04bW+wnEQMU3robQLRkB5d8E5a7EB6kWATQ7xCwhbNhtU6NSr05xE2xHft5vVDbq+B2GnhFDYp9tidW85epsHrtGFKgFhhvtFNh/Yem7mUjnE75h5BrDlTp1NmJhaqvmCfBYCZclR+Iv9zPlG7aBgxZOq++TE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qKjQ8ZPm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qKjQ8ZPm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4CD91C4CEC7; Fri, 4 Oct 2024 15:42:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056574; bh=bmN7ni692A736mVNYrpUELQFpNi/F1V47sEOIzb2Zxc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qKjQ8ZPmnVtLHqr4nor207d5+lle0HUgclARf5EncF5XP8/iOOzpJ08rCz3Zf3K/q K+XtuJ8Un3vl+Adb3MVI6prusot2SL+Z/UwzTKQLoqlt68BtrM+123fOkwQXTrMhjH 89pD77I6HL94tZs/5aC52cRVLNRIILom+coxCtCDk1R+Aa19I135JJNEoC1pJr39Ar jOyml3k76DlaNKTwO6U9mfO1p/9EVrZug5sZopte54z/yzrBOhwDmvAnReyaZ8g4K/ VepMZe3eyDzdjg5iHBnqXzIHbrRBxVCc7ia98DqMjjvONZjKWXFbGZjnCfAsNdrKVh f/C5KfKLN6ySQ== From: Danilo Krummrich 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 Subject: [PATCH v9 09/29] rust: alloc: implement `KVmalloc` allocator Date: Fri, 4 Oct 2024 17:41:13 +0200 Message-ID: <20241004154149.93856-10-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement `Allocator` for `KVmalloc`, an `Allocator` that tries to allocate memory wth `kmalloc` first and, on failure, falls back to `vmalloc`. All memory allocations made with `KVmalloc` end up in `kvrealloc_noprof()`; all frees in `kvfree()`. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/helpers/slab.c | 6 +++++ rust/kernel/alloc/allocator.rs | 36 +++++++++++++++++++++++++++++ rust/kernel/alloc/allocator_test.rs | 1 + 3 files changed, 43 insertions(+) diff --git a/rust/helpers/slab.c b/rust/helpers/slab.c index f043e087f9d6..a842bfbddcba 100644 --- a/rust/helpers/slab.c +++ b/rust/helpers/slab.c @@ -7,3 +7,9 @@ rust_helper_krealloc(const void *objp, size_t new_size, gfp= _t flags) { return krealloc(objp, new_size, flags); } + +void * __must_check __realloc_size(2) +rust_helper_kvrealloc(const void *p, size_t size, gfp_t flags) +{ + return kvrealloc(p, size, flags); +} diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 5742ce7d0453..d9043ca42ce5 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -34,6 +34,15 @@ /// For more details see [self]. pub struct Vmalloc; =20 +/// The kvmalloc kernel allocator. +/// +/// `KVmalloc` attempts to allocate memory with `Kmalloc` first, but falls= back to `Vmalloc` upon +/// failure. This allocator is typically used when the size for the reques= ted allocation is not +/// known and may exceed the capabilities of `Kmalloc`. +/// +/// For more details see [self]. +pub struct KVmalloc; + /// Returns a proper size to alloc a new object aligned to `new_layout`'s = alignment. fn aligned_size(new_layout: Layout) -> usize { // Customized layouts from `Layout::from_size_align()` can have size <= align, so pad first. @@ -76,6 +85,9 @@ impl ReallocFunc { // INVARIANT: `vrealloc` satisfies the type invariants. const VREALLOC: Self =3D Self(bindings::vrealloc); =20 + // INVARIANT: `kvrealloc` satisfies the type invariants. + const KVREALLOC: Self =3D Self(bindings::kvrealloc); + /// # Safety /// /// This method has the same safety requirements as [`Allocator::reall= oc`]. @@ -205,6 +217,30 @@ unsafe fn realloc( } } =20 +// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// - memory remains valid until it is explicitly freed, +// - passing a pointer to a valid memory allocation is OK, +// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. +unsafe impl Allocator for KVmalloc { + #[inline] + unsafe fn realloc( + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + // TODO: Support alignments larger than PAGE_SIZE. + if layout.align() > bindings::PAGE_SIZE { + pr_warn!("KVmalloc does not support alignments larger than PAG= E_SIZE yet.\n"); + return Err(AllocError); + } + + // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously + // allocated with this `Allocator`. + unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flag= s) } + } +} + #[global_allocator] static ALLOCATOR: Kmalloc =3D Kmalloc; =20 diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/alloca= tor_test.rs index e7bf2982f68f..1b2642c547ec 100644 --- a/rust/kernel/alloc/allocator_test.rs +++ b/rust/kernel/alloc/allocator_test.rs @@ -8,6 +8,7 @@ =20 pub struct Kmalloc; pub type Vmalloc =3D Kmalloc; +pub type KVmalloc =3D Kmalloc; =20 unsafe impl Allocator for Kmalloc { unsafe fn realloc( --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C00361C7264; Fri, 4 Oct 2024 15:42:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056579; cv=none; b=RRchHDUvymavWsAtVV+PK0agTpd8peks1GsAEwmEY2lAiD7GmScPuEuW62HBGODDkEzqhju+6/xxq3EN6DYBhblw/ggZdAvfzVHKQdEl1xgwEips4ZrJUraSzMbOt5FbZKFspQZUftr7xkndwhkqp2twlpNUI//tDM1pVnwuSzI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056579; c=relaxed/simple; bh=k3fbnNVumq3p6Zkau+316hxp1LWKMWboxrOE8MJqOiY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VoRLd9pGbzjPDGBil9L3KKSpKJ0HDrzw8JLVy/fDD9KJrNyp2JXJhNCgtnQgYGf40ud6zYSU0B9t2ZR5FwFnFIhLlUiT4U0a/jkoFwBT/aCK0wPp0HL0lAuX9AjfRB9gCIhtUmZLGtkGmG8ud83f9guisNM8otDgjtv48uSucQU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G0SZdVWM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="G0SZdVWM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AEA1DC4CEC7; Fri, 4 Oct 2024 15:42:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056579; bh=k3fbnNVumq3p6Zkau+316hxp1LWKMWboxrOE8MJqOiY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G0SZdVWM49uPjrTKdSFLLtEup1HwgkGeO9v9ZDDnn5aHOC/i/t7QB+rI7DTTt8Uhq QGpzMmjDSv5/Qv/j/7F92bzQpromwD9bU8z7/bweJ/CYCoVL41kbiK/SbygAqIxBqN ibze+ncGEHEUljEJDwBQobzEi4pp4I/Pns6sFjuwbCew0cB3cspYtq0kXvPTFLk78v Aeb6O8+lSbL51Amuo3xpUiptRKKfFv4hWnWZuI711Rj8/Jweg3w+7pIusrhns+Cf39 Y6cq0XQxjySmgv72xnyort+/t+OcltdJQA1mHzJ2oDHuSaE7N3SLbHuRI5O+FZnjPk 4TnpYuFKDci8A== From: Danilo Krummrich 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 Subject: [PATCH v9 10/29] rust: alloc: add __GFP_NOWARN to `Flags` Date: Fri, 4 Oct 2024 17:41:14 +0200 Message-ID: <20241004154149.93856-11-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some test cases in subsequent patches provoke allocation failures. Add `__GFP_NOWARN` to enable test cases to silence unpleasant warnings. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/bindings/bindings_helper.h | 1 + rust/kernel/alloc.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index ae82e9c941af..a80783fcbe04 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -31,4 +31,5 @@ const gfp_t RUST_CONST_HELPER_GFP_KERNEL_ACCOUNT =3D GFP_= KERNEL_ACCOUNT; const gfp_t RUST_CONST_HELPER_GFP_NOWAIT =3D GFP_NOWAIT; const gfp_t RUST_CONST_HELPER___GFP_ZERO =3D __GFP_ZERO; const gfp_t RUST_CONST_HELPER___GFP_HIGHMEM =3D ___GFP_HIGHMEM; +const gfp_t RUST_CONST_HELPER___GFP_NOWARN =3D ___GFP_NOWARN; const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL =3D BLK_FEAT_RO= TATIONAL; diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index f8ddc8d96da9..97defee1d6a1 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -91,6 +91,11 @@ pub mod flags { /// use any filesystem callback. It is very likely to fail to allocat= e memory, even for very /// small allocations. pub const GFP_NOWAIT: Flags =3D Flags(bindings::GFP_NOWAIT); + + /// Suppresses allocation failure reports. + /// + /// This is normally or'd with other flags. + pub const __GFP_NOWARN: Flags =3D Flags(bindings::__GFP_NOWARN); } =20 /// The kernel's [`Allocator`] trait. --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 69CED1C726E; Fri, 4 Oct 2024 15:43:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056585; cv=none; b=svcz+FaVv+JaM7NNCORINVet7xqzEPlh/t1NnUirrAyZcwA8XQGDnrIaPcWrIrJLHUsnP75OtLdNzuRAu557BxPGMJiXfxoSIOTTMS6kKtS6MMTE+HIqibArd3ZsVaypoc1RTpDYiWcF6S7JjjfyTKJe0f1hpJX6K3zUGVAyHyE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056585; c=relaxed/simple; bh=0VH0Qd/HgPfKYpikkjjp9Q6BxVtxq41nH7v/a9brP/A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kpoKMSQs3YgSd8HYbXPAGXQzWN8OSETLn/dVcK1rmDJESGEnLNVlinfB9Jwer3P5tkBusvE7yb5EBwKBcwDiUQDmEySv3YDOuQ/vOHBSAxxnkkPq5W0mEXPwvFeAPE9gWyMPLMoZD2y3J61hqI+zjiWWcvriVXmT9si2JH4aXB0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aXA4MbT3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aXA4MbT3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1D188C4CECE; Fri, 4 Oct 2024 15:42:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056585; bh=0VH0Qd/HgPfKYpikkjjp9Q6BxVtxq41nH7v/a9brP/A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aXA4MbT3+vVTICINEc9lDElprcdefwnCKhj/v+Eph+7Txy08rabYZrIGdmcT7v/oi aLfx9CCe5vmQsMu4kMz/uGqPQ519vVq/Gls5n7o5vjSgrjrL17ftAjiS1D7dsbyHUh 6m52CIzWX33re0t+/vcDtBGJZMI6sjIWBROmVSGwHf6T+NmLtQV01BErg3WIDEmQUS vc17rSTGNBbLlk2rII/72OrZeaHSDZBkGeNNJrZv+Oauigo38u0FOLsR7SLqqxdnNF DSuJC0OCu61f+AoEV2jzt4nWceDsNRruQJehH4wFUs/6HbOD5plWnQJF7GbwZ1NoIc tAJI1sXLBpXaw== From: Danilo Krummrich 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 Subject: [PATCH v9 11/29] rust: alloc: implement kernel `Box` Date: Fri, 4 Oct 2024 17:41:15 +0200 Message-ID: <20241004154149.93856-12-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable `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. Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 6 + rust/kernel/alloc/kbox.rs | 456 ++++++++++++++++++++++++++++++++++++++ rust/kernel/prelude.rs | 2 +- 3 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/alloc/kbox.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 97defee1d6a1..12cd52f83222 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; =20 #[cfg(any(test, testlib))] @@ -13,6 +14,11 @@ #[cfg(any(test, testlib))] pub use self::allocator_test as allocator; =20 +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..ef1add933f60 --- /dev/null +++ b/rust/kernel/alloc/kbox.rs @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Implementation of [`Box`]. + +#[allow(unused_imports)] // Used in doc comments. +use super::allocator::{KVmalloc, Kmalloc, Vmalloc}; +use super::{AllocError, Allocator, Flags}; +use core::alloc::Layout; +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, InPlaceWrite, Init, PinInit}; +use crate::types::ForeignOwnable; + +/// The kernel's [`Box`] type -- a heap allocation for a single value of t= ype `T`. +/// +/// This is the kernel's version of the Rust stdlib's `Box`. There are sev= eral of differences, +/// for example no `noalias` attribute is emitted and partially moving out= of a `Box` is not +/// supported. There are also several API differences, e.g. `Box` always r= equires an [`Allocator`] +/// implementation to be passed as generic, page [`Flags`] when allocating= memory and all functions +/// that may allocate memory are fallible. +/// +/// `Box` works with any of the kernel's allocators, e.g. [`Kmalloc`], [`V= malloc`] or [`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 =3D KBox::::new(24_u64, GFP_KERNEL)?; +/// +/// assert_eq!(*b, 24_u64); +/// # Ok::<(), Error>(()) +/// ``` +/// +/// ``` +/// # use kernel::bindings; +/// const SIZE: usize =3D bindings::KMALLOC_MAX_SIZE as usize + 1; +/// struct Huge([u8; SIZE]); +/// +/// assert!(KBox::::new_uninit(GFP_KERNEL | __GFP_NOWARN).is_err()); +/// ``` +/// +/// ``` +/// # use kernel::bindings; +/// const SIZE: usize =3D bindings::KMALLOC_MAX_SIZE as usize + 1; +/// struct Huge([u8; SIZE]); +/// +/// assert!(KVBox::::new_uninit(GFP_KERNEL).is_ok()); +/// ``` +/// +/// # Invariants +/// +/// `self.0` is always properly aligned and either points to memory alloca= ted with `A` or, for +/// zero-sized types, is a dangling, well aligned pointer. +#[repr(transparent)] +pub struct Box(NonNull, PhantomData); + +/// Type alias for [`Box`] with a [`Kmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let b =3D KBox::new(24_u64, GFP_KERNEL)?; +/// +/// assert_eq!(*b, 24_u64); +/// # Ok::<(), Error>(()) +/// ``` +pub type KBox =3D Box; + +/// Type alias for [`Box`] with a [`Vmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let b =3D VBox::new(24_u64, GFP_KERNEL)?; +/// +/// assert_eq!(*b, 24_u64); +/// # Ok::<(), Error>(()) +/// ``` +pub type VBox =3D Box; + +/// Type alias for [`Box`] with a [`KVmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let b =3D KVBox::new(24_u64, GFP_KERNEL)?; +/// +/// assert_eq!(*b, 24_u64); +/// # Ok::<(), Error>(()) +/// ``` +pub type KVBox =3D Box; + +// SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`. +unsafe impl Send for Box +where + T: Send + ?Sized, + A: Allocator, +{ +} + +// SAFETY: `Box` is `Sync` if `T` is `Sync` because the `Box` owns a `T`. +unsafe impl Sync for Box +where + T: Sync + ?Sized, + A: Allocator, +{ +} + +impl Box +where + T: ?Sized, + A: Allocator, +{ + /// Creates a new `Box` from a raw pointer. + /// + /// # Safety + /// + /// For non-ZSTs, `raw` must point at an allocation allocated with `A`= that is sufficiently + /// aligned for and holds a valid `T`. The caller passes ownership of = the allocation to the + /// `Box`. + /// + /// For ZSTs, `raw` must be a dangling, well aligned pointer. + #[inline] + pub const unsafe fn from_raw(raw: *mut T) -> Self { + // INVARIANT: Validity of `raw` is guaranteed by the safety precon= ditions of this function. + // SAFETY: By the safety preconditions of this function, `raw` is = not a NULL pointer. + Self(unsafe { NonNull::new_unchecked(raw) }, PhantomData) + } + + /// Consumes the `Box` and returns a raw pointer. + /// + /// This will not run the destructor of `T` and for non-ZSTs the alloc= ation will stay alive + /// indefinitely. Use [`Box::from_raw`] to recover the [`Box`], drop t= he value and free the + /// allocation, if any. + /// + /// # Examples + /// + /// ``` + /// let x =3D KBox::new(24, GFP_KERNEL)?; + /// let ptr =3D KBox::into_raw(x); + /// // SAFETY: `ptr` comes from a previous call to `KBox::into_raw`. + /// let x =3D unsafe { KBox::from_raw(ptr) }; + /// + /// assert_eq!(*x, 24); + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + pub fn into_raw(b: Self) -> *mut T { + ManuallyDrop::new(b).0.as_ptr() + } + + /// Consumes and leaks the `Box` and returns a mutable reference. + /// + /// See [Box::into_raw] for more details. + #[inline] + pub fn leak<'a>(b: Self) -> &'a mut T { + // SAFETY: `Box::into_raw` always returns a properly aligned and d= ereferenceable pointer + // which points to an initialized instance of `T`. + unsafe { &mut *Box::into_raw(b) } + } +} + +impl Box, A> +where + A: Allocator, +{ + /// Converts a `Box, A>` to a `Box`. + /// + /// It is undefined behavior to call this function while the value ins= ide of `b` is not yet + /// fully initialized. + /// + /// # Safety + /// + /// Callers must ensure that the value inside of `b` is in an initiali= zed state. + pub unsafe fn assume_init(self) -> Box { + let raw =3D Self::into_raw(self); + + // SAFETY: `raw` comes from a previous call to `Box::into_raw`. By= the safety requirements + // of this function, the value inside the `Box` is in an initializ= ed state. Hence, it is + // safe to reconstruct the `Box` as `Box`. + unsafe { Box::from_raw(raw.cast()) } + } + + /// Writes the value and converts to `Box`. + pub fn write(mut self, value: T) -> Box { + (*self).write(value); + + // SAFETY: We've just initialized `b`'s value. + unsafe { self.assume_init() } + } +} + +impl Box +where + A: Allocator, +{ + /// Creates a new `Box` and initializes its contents with `x`. + /// + /// New memory is allocated with `A`. The allocation may fail, in whic= h case an error is + /// returned. For ZSTs no memory is allocated. + pub fn new(x: T, flags: Flags) -> Result { + let b =3D Self::new_uninit(flags)?; + Ok(Box::write(b, x)) + } + + /// Creates a new `Box` with uninitialized contents. + /// + /// New memory is allocated with `A`. The allocation may fail, in whic= h case an error is + /// returned. For ZSTs no memory is allocated. + /// + /// # Examples + /// + /// ``` + /// let b =3D KBox::::new_uninit(GFP_KERNEL)?; + /// let b =3D KBox::write(b, 24); + /// + /// assert_eq!(*b, 24_u64); + /// # Ok::<(), Error>(()) + /// ``` + pub fn new_uninit(flags: Flags) -> Result, A>, Allo= cError> { + let layout =3D Layout::new::>(); + let ptr =3D A::alloc(layout, flags)?; + + // INVARIANT: `ptr` is either a dangling pointer or points to memo= ry allocated with `A`, + // which is sufficient in size and alignment for storing a `T`. + Ok(Box(ptr.cast(), PhantomData)) + } + + /// Constructs a new `Pin>`. If `T` does not implement [`Unp= in`], then `x` will be + /// pinned in memory and can't be moved. + #[inline] + pub fn pin(x: T, flags: Flags) -> Result>, AllocError> + where + A: 'static, + { + Ok(Self::new(x, flags)?.into()) + } + + /// Forgets the contents (does not run the destructor), but keeps the = allocation. + fn forget_contents(this: Self) -> Box, A> { + let ptr =3D Self::into_raw(this); + + // SAFETY: `ptr` is valid, because it came from `Box::into_raw`. + unsafe { Box::from_raw(ptr.cast()) } + } + + /// Drops the contents, but keeps the allocation. + /// + /// # Examples + /// + /// ``` + /// let value =3D KBox::new([0; 32], GFP_KERNEL)?; + /// assert_eq!(*value, [0; 32]); + /// let value =3D KBox::drop_contents(value); + /// // Now we can re-use `value`: + /// let value =3D KBox::write(value, [1; 32]); + /// assert_eq!(*value, [1; 32]); + /// # Ok::<(), Error>(()) + /// ``` + pub fn drop_contents(this: Self) -> Box, A> { + let ptr =3D this.0.as_ptr(); + + // SAFETY: `ptr` is valid, because it came from `this`. After this= call we never access the + // value stored in `this` again. + unsafe { core::ptr::drop_in_place(ptr) }; + + Self::forget_contents(this) + } + + /// Moves the `Box`' value out of the `Box` and consumes the `Box`. + pub fn into_inner(b: Self) -> T { + // SAFETY: By the type invariant `&*b` is valid for `read`. + let value =3D unsafe { core::ptr::read(&*b) }; + let _ =3D Self::forget_contents(b); + value + } +} + +impl From> for Pin> +where + T: ?Sized, + A: Allocator, +{ + /// Converts a `Box` into a `Pin>`. If `T` does not im= plement [`Unpin`], then + /// `*b` will be pinned in memory and can't be moved. + /// + /// This moves `b` into `Pin` without moving `*b` or allocating and co= pying any memory. + fn from(b: Box) -> Self { + // SAFETY: The value wrapped inside a `Pin>` cannot be m= oved or replaced as long + // as `T` does not implement `Unpin`. + unsafe { Pin::new_unchecked(b) } + } +} + +impl InPlaceWrite for Box, A> +where + A: Allocator + 'static, +{ + type Initialized =3D Box; + + fn write_init(mut self, init: impl Init) -> Result { + let slot =3D self.as_mut_ptr(); + // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, + // slot is valid. + unsafe { init.__init(slot)? }; + // SAFETY: All fields have been initialized. + Ok(unsafe { Box::assume_init(self) }) + } + + fn write_pin_init(mut self, init: impl PinInit) -> Result, E> { + let slot =3D self.as_mut_ptr(); + // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, + // slot is valid and will not be moved, because we pin it later. + unsafe { init.__pinned_init(slot)? }; + // SAFETY: All fields have been initialized. + Ok(unsafe { Box::assume_init(self) }.into()) + } +} + +impl InPlaceInit for Box +where + A: Allocator + 'static, +{ + type PinnedSelf =3D Pin; + + #[inline] + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> + where + E: From, + { + Box::<_, A>::new_uninit(flags)?.write_pin_init(init) + } + + #[inline] + fn try_init(init: impl Init, flags: Flags) -> Result + where + E: From, + { + Box::<_, A>::new_uninit(flags)?.write_init(init) + } +} + +impl ForeignOwnable for Box +where + A: Allocator, +{ + type Borrowed<'a> =3D &'a T; + + fn into_foreign(self) -> *const core::ffi::c_void { + Box::into_raw(self) as _ + } + + unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { + // SAFETY: The safety requirements of this function ensure that `p= tr` comes from a previous + // call to `Self::into_foreign`. + unsafe { Box::from_raw(ptr as _) } + } + + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { + // SAFETY: The safety requirements of this method ensure that the = object remains alive and + // immutable for the duration of 'a. + unsafe { &*ptr.cast() } + } +} + +impl ForeignOwnable for Pin> +where + A: Allocator, +{ + type Borrowed<'a> =3D Pin<&'a T>; + + fn into_foreign(self) -> *const core::ffi::c_void { + // SAFETY: We are still treating the box as pinned. + Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _ + } + + unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { + // SAFETY: The safety requirements of this function ensure that `p= tr` comes from a previous + // call to `Self::into_foreign`. + unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) } + } + + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Pin<&'a T> { + // SAFETY: The safety requirements for this function ensure that t= he object is still alive, + // so it is safe to dereference the raw pointer. + // The safety requirements of `from_foreign` also ensure that the = object remains alive for + // the lifetime of the returned value. + let r =3D unsafe { &*ptr.cast() }; + + // SAFETY: This pointer originates from a `Pin>`. + unsafe { Pin::new_unchecked(r) } + } +} + +impl Deref for Box +where + T: ?Sized, + A: Allocator, +{ + type Target =3D T; + + fn deref(&self) -> &T { + // SAFETY: `self.0` is always properly aligned, dereferenceable an= d points to an initialized + // instance of `T`. + unsafe { self.0.as_ref() } + } +} + +impl DerefMut for Box +where + T: ?Sized, + A: Allocator, +{ + fn deref_mut(&mut self) -> &mut T { + // SAFETY: `self.0` is always properly aligned, dereferenceable an= d points to an initialized + // instance of `T`. + unsafe { self.0.as_mut() } + } +} + +impl fmt::Debug for Box +where + T: ?Sized + fmt::Debug, + A: Allocator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl Drop for Box +where + T: ?Sized, + A: Allocator, +{ + fn drop(&mut self) { + let layout =3D Layout::for_value::(self); + + // SAFETY: The pointer in `self.0` is guaranteed to be valid by th= e type invariant. + unsafe { core::ptr::drop_in_place::(self.deref_mut()) }; + + // SAFETY: + // - `self.0` was previously allocated with `A`. + // - `layout` is equal to the `Layout=C2=B4 `self.0` was allocated= with. + unsafe { A::free(self.0.cast(), layout) }; + } +} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 4571daec0961..a9210634a8c3 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{box_ext::BoxExt, flags::*, vec_ext::VecExt}; +pub use crate::alloc::{box_ext::BoxExt, flags::*, vec_ext::VecExt, KBox, K= VBox, VBox}; =20 #[doc(no_inline)] pub use alloc::{boxed::Box, vec::Vec}; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E70E121D2A8; Fri, 4 Oct 2024 15:43:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056591; cv=none; b=I/eIZnU2TWlD2gRc/cpQKNl/RUIdFauQCG5k8v5FZpHAaKY71/VV/6+cwCnDIIA87UnUHZ4XY+tjtEdVsy+EAZbbN1m0e89+pSIQcnhRiPBNV3JoiVh4V+MHTW8ACHUj9oAY1QbAc5VmaWo7x4dcarODEb14874OijgF226oE+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056591; c=relaxed/simple; bh=32n8JgdHO+8eRlSHJI2uTCIWYY9WmRtXv+48HzSp4yQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I6HkNRniDwB4lmTapS/vEQrD4vI3tX4KRkzFdnHPDO3X2FHcqBKRElcurZ51r4su7Ac/yde3JsJCB0a+t9uqB+qAgA6VKzRbr6SH7L1nlKEgxCqZN39f05GoFmuSf3flQTeFzvF/Md8xpYow+OG/tyUpw3kHVeGPjJaDdI3lxh0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QaWoBAj5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QaWoBAj5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 81019C4CED0; Fri, 4 Oct 2024 15:43:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056590; bh=32n8JgdHO+8eRlSHJI2uTCIWYY9WmRtXv+48HzSp4yQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QaWoBAj51CQQulLDgA+/1MISUmvSh6Lszi6gA5SuasW+PWmiOg2R9e4i0TjlqZKPE kiGKnr7Pc67AN/+909EVZ7/eLP3PZ7Hc8FJRqCdJLFzPVSm4TcbIW2K5RVBNPZIUfL m2jOcLFvFvPT3LyaRrTAszT2bISGm1L6NXqXgfWEBIVl+yLTSzvstMhkCt9j5DnHxs hwoGmxEIis6kbSj0TZG3Q9s1DjD+dAA5HgZjKJzM3aX8cNfZqdyqQXJk5MuYqKGpyl 6kWEM51LjQPa2W+nlbigu22gAeyOylhyrEmMG04mIYdrgkkd2R6Y0r0NwLHnU8Yn3M pWO4486P0b82A== From: Danilo Krummrich 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 Subject: [PATCH v9 12/29] rust: treewide: switch to our kernel `Box` type Date: Fri, 4 Oct 2024 17:41:16 +0200 Message-ID: <20241004154149.93856-13-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that we got the kernel `Box` type in place, convert all existing `Box` users to make use of it. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- drivers/block/rnull.rs | 4 +-- rust/kernel/init.rs | 51 ++++++++++++++++--------------- rust/kernel/init/__internal.rs | 2 +- rust/kernel/rbtree.rs | 49 ++++++++++++++++------------- rust/kernel/sync/arc.rs | 17 +++++------ rust/kernel/sync/condvar.rs | 4 +-- rust/kernel/sync/lock/mutex.rs | 2 +- rust/kernel/sync/lock/spinlock.rs | 2 +- rust/kernel/workqueue.rs | 20 ++++++------ rust/macros/lib.rs | 6 ++-- 10 files changed, 81 insertions(+), 76 deletions(-) diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs index b0227cf9ddd3..5de7223beb4d 100644 --- a/drivers/block/rnull.rs +++ b/drivers/block/rnull.rs @@ -32,7 +32,7 @@ } =20 struct NullBlkModule { - _disk: Pin>>>, + _disk: Pin>>>, } =20 impl kernel::Module for NullBlkModule { @@ -47,7 +47,7 @@ fn init(_module: &'static ThisModule) -> Result { .rotational(false) .build(format_args!("rnullb{}", 0), tagset)?; =20 - let disk =3D Box::pin_init(new_mutex!(disk, "nullb:disk"), flags::= GFP_KERNEL)?; + let disk =3D KBox::pin_init(new_mutex!(disk, "nullb:disk"), flags:= :GFP_KERNEL)?; =20 Ok(Self { _disk: disk }) } diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 25057cbed40b..c889f2640b56 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -13,7 +13,7 @@ //! To initialize a `struct` with an in-place constructor you will need tw= o things: //! - an in-place constructor, //! - a memory location that can hold your `struct` (this can be the [stac= k], an [`Arc`], -//! [`UniqueArc`], [`Box`] or any other smart pointer that impleme= nts [`InPlaceInit`]). +//! [`UniqueArc`], [`KBox`] or any other smart pointer that implem= ents [`InPlaceInit`]). //! //! To get an in-place constructor there are generally three options: //! - directly creating an in-place constructor using the [`pin_init!`] ma= cro, @@ -68,7 +68,7 @@ //! # a <- new_mutex!(42, "Foo::a"), //! # b: 24, //! # }); -//! let foo: Result>> =3D Box::pin_init(foo, GFP_KERNEL); +//! let foo: Result>> =3D KBox::pin_init(foo, GFP_KERNEL); //! ``` //! //! For more information see the [`pin_init!`] macro. @@ -92,14 +92,14 @@ //! struct DriverData { //! #[pin] //! status: Mutex, -//! buffer: Box<[u8; 1_000_000]>, +//! buffer: KBox<[u8; 1_000_000]>, //! } //! //! impl DriverData { //! fn new() -> impl PinInit { //! try_pin_init!(Self { //! status <- new_mutex!(0, "DriverData::status"), -//! buffer: Box::init(kernel::init::zeroed(), GFP_KERNEL)?, +//! buffer: KBox::init(kernel::init::zeroed(), GFP_KERNEL)?, //! }) //! } //! } @@ -211,7 +211,7 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ - alloc::{box_ext::BoxExt, AllocError, Flags}, + alloc::{box_ext::BoxExt, AllocError, Flags, KBox}, error::{self, Error}, sync::Arc, sync::UniqueArc, @@ -298,7 +298,7 @@ macro_rules! stack_pin_init { /// struct Foo { /// #[pin] /// a: Mutex, -/// b: Box, +/// b: KBox, /// } /// /// struct Bar { @@ -307,7 +307,7 @@ macro_rules! stack_pin_init { /// /// stack_try_pin_init!(let foo: Result, AllocError> =3D pin= _init!(Foo { /// a <- new_mutex!(42), -/// b: Box::new(Bar { +/// b: KBox::new(Bar { /// x: 64, /// }, GFP_KERNEL)?, /// })); @@ -324,7 +324,7 @@ macro_rules! stack_pin_init { /// struct Foo { /// #[pin] /// a: Mutex, -/// b: Box, +/// b: KBox, /// } /// /// struct Bar { @@ -333,7 +333,7 @@ macro_rules! stack_pin_init { /// /// stack_try_pin_init!(let foo: Pin<&mut Foo> =3D? pin_init!(Foo { /// a <- new_mutex!(42), -/// b: Box::new(Bar { +/// b: KBox::new(Bar { /// x: 64, /// }, GFP_KERNEL)?, /// })); @@ -391,7 +391,7 @@ macro_rules! stack_try_pin_init { /// }, /// }); /// # initializer } -/// # Box::pin_init(demo(), GFP_KERNEL).unwrap(); +/// # KBox::pin_init(demo(), GFP_KERNEL).unwrap(); /// ``` /// /// Arbitrary Rust expressions can be used to set the value of a variable. @@ -460,7 +460,7 @@ macro_rules! stack_try_pin_init { /// # }) /// # } /// # } -/// let foo =3D Box::pin_init(Foo::new(), GFP_KERNEL); +/// let foo =3D KBox::pin_init(Foo::new(), GFP_KERNEL); /// ``` /// /// They can also easily embed it into their own `struct`s: @@ -592,7 +592,7 @@ macro_rules! pin_init { /// use kernel::{init::{self, PinInit}, error::Error}; /// #[pin_data] /// struct BigBuf { -/// big: Box<[u8; 1024 * 1024 * 1024]>, +/// big: KBox<[u8; 1024 * 1024 * 1024]>, /// small: [u8; 1024 * 1024], /// ptr: *mut u8, /// } @@ -600,7 +600,7 @@ macro_rules! pin_init { /// impl BigBuf { /// fn new() -> impl PinInit { /// try_pin_init!(Self { -/// big: Box::init(init::zeroed(), GFP_KERNEL)?, +/// big: KBox::init(init::zeroed(), GFP_KERNEL)?, /// small: [0; 1024 * 1024], /// ptr: core::ptr::null_mut(), /// }? Error) @@ -692,16 +692,16 @@ macro_rules! init { /// # Examples /// /// ```rust -/// use kernel::{init::{PinInit, zeroed}, error::Error}; +/// use kernel::{alloc::KBox, init::{PinInit, zeroed}, error::Error}; /// struct BigBuf { -/// big: Box<[u8; 1024 * 1024 * 1024]>, +/// big: KBox<[u8; 1024 * 1024 * 1024]>, /// small: [u8; 1024 * 1024], /// } /// /// impl BigBuf { /// fn new() -> impl Init { /// try_init!(Self { -/// big: Box::init(zeroed(), GFP_KERNEL)?, +/// big: KBox::init(zeroed(), GFP_KERNEL)?, /// small: [0; 1024 * 1024], /// }? Error) /// } @@ -812,8 +812,8 @@ macro_rules! assert_pinned { /// A pin-initializer for the type `T`. /// /// To use this initializer, you will need a suitable memory location that= can hold a `T`. This can -/// be [`Box`], [`Arc`], [`UniqueArc`] or even the stack (see [`s= tack_pin_init!`]). Use the -/// [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc`] = on this. +/// be [`KBox`], [`Arc`], [`UniqueArc`] or even the stack (see [`= stack_pin_init!`]). Use +/// the [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc`] on this. /// /// Also see the [module description](self). /// @@ -893,7 +893,7 @@ fn pin_chain(self, f: F) -> ChainPinInit } =20 /// An initializer returned by [`PinInit::pin_chain`]. -pub struct ChainPinInit(I, F, __internal::Invariant<(E= , Box)>); +pub struct ChainPinInit(I, F, __internal::Invariant<(E= , KBox)>); =20 // SAFETY: The `__pinned_init` function is implemented such that it // - returns `Ok(())` on successful initialization, @@ -919,8 +919,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(= ), E> { /// An initializer for `T`. /// /// To use this initializer, you will need a suitable memory location that= can hold a `T`. This can -/// be [`Box`], [`Arc`], [`UniqueArc`] or even the stack (see [`s= tack_pin_init!`]). Use the -/// [`InPlaceInit::init`] function of a smart pointer like [`Arc`] on t= his. Because +/// be [`KBox`], [`Arc`], [`UniqueArc`] or even the stack (see [`= stack_pin_init!`]). Use +/// the [`InPlaceInit::init`] function of a smart pointer like [`Arc`] = on this. Because /// [`PinInit`] is a super trait, you can use every function that ta= kes it as well. /// /// Also see the [module description](self). @@ -992,7 +992,7 @@ fn chain(self, f: F) -> ChainInit } =20 /// An initializer returned by [`Init::chain`]. -pub struct ChainInit(I, F, __internal::Invariant<(E, B= ox)>); +pub struct ChainInit(I, F, __internal::Invariant<(E, K= Box)>); =20 // SAFETY: The `__init` function is implemented such that it // - returns `Ok(())` on successful initialization, @@ -1076,8 +1076,9 @@ pub fn uninit() -> impl Init, E>= { /// # Examples /// /// ```rust -/// use kernel::{error::Error, init::init_array_from_fn}; -/// let array: Box<[usize; 1_000]> =3D Box::init::(init_array_from_= fn(|i| i), GFP_KERNEL).unwrap(); +/// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn}; +/// let array: KBox<[usize; 1_000]> =3D +/// KBox::init::(init_array_from_fn(|i| i), GFP_KERNEL).unwrap(= ); /// assert_eq!(array.len(), 1_000); /// ``` pub fn init_array_from_fn( @@ -1453,7 +1454,7 @@ macro_rules! impl_zeroable { // // In this case we are allowed to use `T: ?Sized`, since all zeros is = the `None` variant. {} Option>, - {} Option>, + {} Option>, =20 // SAFETY: `null` pointer is valid. // diff --git a/rust/kernel/init/__internal.rs b/rust/kernel/init/__internal.rs index 44431fba7aab..74329cc3262c 100644 --- a/rust/kernel/init/__internal.rs +++ b/rust/kernel/init/__internal.rs @@ -105,7 +105,7 @@ fn make_closure(self, f: F) -> F } } =20 -pub struct AllData(PhantomData) -> Box>); +pub struct AllData(PhantomData) -> KBox>); =20 impl Clone for AllData { fn clone(&self) -> Self { diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs index d03e4aa1f481..cb4415a12258 100644 --- a/rust/kernel/rbtree.rs +++ b/rust/kernel/rbtree.rs @@ -7,7 +7,6 @@ //! Reference: =20 use crate::{alloc::Flags, bindings, container_of, error::Result, prelude::= *}; -use alloc::boxed::Box; use core::{ cmp::{Ord, Ordering}, marker::PhantomData, @@ -497,7 +496,7 @@ fn drop(&mut self) { // but it is not observable. The loop invariant is still maint= ained. =20 // SAFETY: `this` is valid per the loop invariant. - unsafe { drop(Box::from_raw(this.cast_mut())) }; + unsafe { drop(KBox::from_raw(this.cast_mut())) }; } } } @@ -764,7 +763,7 @@ pub fn remove_current(self) -> (Option, RBTreeNod= e) { // point to the links field of `Node` objects. let this =3D unsafe { container_of!(self.current.as_ptr(), Node, links) }.cast_mut(); // SAFETY: `this` is valid by the type invariants as described abo= ve. - let node =3D unsafe { Box::from_raw(this) }; + let node =3D unsafe { KBox::from_raw(this) }; let node =3D RBTreeNode { node }; // SAFETY: The reference to the tree used to create the cursor out= lives the cursor, so // the tree cannot change. By the tree invariant, all nodes are va= lid. @@ -809,7 +808,7 @@ fn remove_neighbor(&mut self, direction: Direction) -> = Option> // point to the links field of `Node` objects. let this =3D unsafe { container_of!(neighbor, Node, link= s) }.cast_mut(); // SAFETY: `this` is valid by the type invariants as described= above. - let node =3D unsafe { Box::from_raw(this) }; + let node =3D unsafe { KBox::from_raw(this) }; return Some(RBTreeNode { node }); } None @@ -1038,7 +1037,7 @@ fn next(&mut self) -> Option { /// It contains the memory needed to hold a node that can be inserted into= a red-black tree. One /// can be obtained by directly allocating it ([`RBTreeNodeReservation::ne= w`]). pub struct RBTreeNodeReservation { - node: Box>>, + node: KBox>>, } =20 impl RBTreeNodeReservation { @@ -1046,7 +1045,7 @@ impl RBTreeNodeReservation { /// call to [`RBTree::insert`]. pub fn new(flags: Flags) -> Result> { Ok(RBTreeNodeReservation { - node: as BoxExt<_>>::new_uninit(flags)?, + node: KBox::new_uninit(flags)?, }) } } @@ -1062,14 +1061,15 @@ impl RBTreeNodeReservation { /// Initialises a node reservation. /// /// It then becomes an [`RBTreeNode`] that can be inserted into a tree. - pub fn into_node(mut self, key: K, value: V) -> RBTreeNode { - self.node.write(Node { - key, - value, - links: bindings::rb_node::default(), - }); - // SAFETY: We just wrote to it. - let node =3D unsafe { self.node.assume_init() }; + pub fn into_node(self, key: K, value: V) -> RBTreeNode { + let node =3D KBox::write( + self.node, + Node { + key, + value, + links: bindings::rb_node::default(), + }, + ); RBTreeNode { node } } } @@ -1079,7 +1079,7 @@ pub fn into_node(mut self, key: K, value: V) -> RBTre= eNode { /// The node is fully initialised (with key and value) and can be inserted= into a tree without any /// extra allocations or failure paths. pub struct RBTreeNode { - node: Box>, + node: KBox>, } =20 impl RBTreeNode { @@ -1091,7 +1091,9 @@ pub fn new(key: K, value: V, flags: Flags) -> Result<= RBTreeNode> { =20 /// Get the key and value from inside the node. pub fn to_key_value(self) -> (K, V) { - (self.node.key, self.node.value) + let node =3D KBox::into_inner(self.node); + + (node.key, node.value) } } =20 @@ -1113,7 +1115,7 @@ impl RBTreeNode { /// may be freed (but only for the key/value; memory for the node itse= lf is kept for reuse). pub fn into_reservation(self) -> RBTreeNodeReservation { RBTreeNodeReservation { - node: Box::drop_contents(self.node), + node: KBox::drop_contents(self.node), } } } @@ -1164,7 +1166,7 @@ impl<'a, K, V> RawVacantEntry<'a, K, V> { /// The `node` must have a key such that inserting it here does not br= eak the ordering of this /// [`RBTree`]. fn insert(self, node: RBTreeNode) -> &'a mut V { - let node =3D Box::into_raw(node.node); + let node =3D KBox::into_raw(node.node); =20 // SAFETY: `node` is valid at least until we call `Box::from_raw`,= which only happens when // the node is removed or replaced. @@ -1238,21 +1240,24 @@ pub fn remove_node(self) -> RBTreeNode { // SAFETY: The node was a node in the tree, but we removed it,= so we can convert it // back into a box. node: unsafe { - Box::from_raw(container_of!(self.node_links, Node, l= inks).cast_mut()) + KBox::from_raw(container_of!(self.node_links, Node, = links).cast_mut()) }, } } =20 /// Takes the value of the entry out of the map, and returns it. pub fn remove(self) -> V { - self.remove_node().node.value + let rb_node =3D self.remove_node(); + let node =3D KBox::into_inner(rb_node.node); + + node.value } =20 /// Swap the current node for the provided node. /// /// The key of both nodes must be equal. fn replace(self, node: RBTreeNode) -> RBTreeNode { - let node =3D Box::into_raw(node.node); + let node =3D KBox::into_raw(node.node); =20 // SAFETY: `node` is valid at least until we call `Box::from_raw`,= which only happens when // the node is removed or replaced. @@ -1268,7 +1273,7 @@ fn replace(self, node: RBTreeNode) -> RBTreeNod= e { // - `self.node_ptr` produces a valid pointer to a node in the tre= e. // - Now that we removed this entry from the tree, we can convert = the node to a box. let old_node =3D - unsafe { Box::from_raw(container_of!(self.node_links, Node, links).cast_mut()) }; + unsafe { KBox::from_raw(container_of!(self.node_links, Node, links).cast_mut()) }; =20 RBTreeNode { node: old_node } } diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 9325cc5a16a4..db9da352d588 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -17,13 +17,12 @@ //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html =20 use crate::{ - alloc::{box_ext::BoxExt, AllocError, Flags}, + alloc::{AllocError, Flags, KBox}, bindings, init::{self, InPlaceInit, Init, PinInit}, try_init, types::{ForeignOwnable, Opaque}, }; -use alloc::boxed::Box; use core::{ alloc::Layout, fmt, @@ -201,11 +200,11 @@ pub fn new(contents: T, flags: Flags) -> Result { data: contents, }; =20 - let inner =3D as BoxExt<_>>::new(value, flags)?; + let inner =3D KBox::new(value, flags)?; =20 // SAFETY: We just created `inner` with a reference count of 1, wh= ich is owned by the new // `Arc` object. - Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) + Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) }) } } =20 @@ -398,8 +397,8 @@ fn drop(&mut self) { if is_zero { // The count reached zero, we must free the memory. // - // SAFETY: The pointer was initialised from the result of `Box= ::leak`. - unsafe { drop(Box::from_raw(self.ptr.as_ptr())) }; + // SAFETY: The pointer was initialised from the result of `KBo= x::leak`. + unsafe { drop(KBox::from_raw(self.ptr.as_ptr())) }; } } } @@ -641,7 +640,7 @@ pub fn new(value: T, flags: Flags) -> Result { /// Tries to allocate a new [`UniqueArc`] instance whose contents are = not initialised yet. pub fn new_uninit(flags: Flags) -> Result>, A= llocError> { // INVARIANT: The refcount is initialised to a non-zero value. - let inner =3D Box::try_init::( + let inner =3D KBox::try_init::( try_init!(ArcInner { // SAFETY: There are no safety requirements for this FFI c= all. refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) = }), @@ -651,8 +650,8 @@ pub fn new_uninit(flags: Flags) -> Result>, AllocError> )?; Ok(UniqueArc { // INVARIANT: The newly-created object has a refcount of 1. - // SAFETY: The pointer from the `Box` is valid. - inner: unsafe { Arc::from_inner(Box::leak(inner).into()) }, + // SAFETY: The pointer from the `KBox` is valid. + inner: unsafe { Arc::from_inner(KBox::leak(inner).into()) }, }) } } diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index dec2e5ffc919..a1a29c0bdb3a 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -70,8 +70,8 @@ macro_rules! new_condvar { /// } /// /// /// Allocates a new boxed `Example`. -/// fn new_example() -> Result>> { -/// Box::pin_init(pin_init!(Example { +/// fn new_example() -> Result>> { +/// KBox::pin_init(pin_init!(Example { /// value <- new_mutex!(0), /// value_changed <- new_condvar!(), /// }), GFP_KERNEL) diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs index 30632070ee67..f8f6d530db7d 100644 --- a/rust/kernel/sync/lock/mutex.rs +++ b/rust/kernel/sync/lock/mutex.rs @@ -58,7 +58,7 @@ macro_rules! new_mutex { /// } /// /// // Allocate a boxed `Example`. -/// let e =3D Box::pin_init(Example::new(), GFP_KERNEL)?; +/// let e =3D KBox::pin_init(Example::new(), GFP_KERNEL)?; /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spin= lock.rs index ea5c5bc1ce12..a9096a4dc42a 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -56,7 +56,7 @@ macro_rules! new_spinlock { /// } /// /// // Allocate a boxed `Example`. -/// let e =3D Box::pin_init(Example::new(), GFP_KERNEL)?; +/// let e =3D KBox::pin_init(Example::new(), GFP_KERNEL)?; /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 10d2bc62e2cf..4d1d2062f6eb 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -216,7 +216,7 @@ pub fn try_spawn( func: Some(func), }); =20 - self.enqueue(Box::pin_init(init, flags).map_err(|_| AllocError)?); + self.enqueue(KBox::pin_init(init, flags).map_err(|_| AllocError)?); Ok(()) } } @@ -239,9 +239,9 @@ fn project(self: Pin<&mut Self>) -> &mut Option { } =20 impl WorkItem for ClosureWork { - type Pointer =3D Pin>; + type Pointer =3D Pin>; =20 - fn run(mut this: Pin>) { + fn run(mut this: Pin>) { if let Some(func) =3D this.as_mut().project().take() { (func)() } @@ -297,7 +297,7 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self:= :EnqueueOutput =20 /// Defines the method that should be called directly when a work item is = executed. /// -/// This trait is implemented by `Pin>` and [`Arc`], and is main= ly intended to be +/// This trait is implemented by `Pin>` and [`Arc`], and is mai= nly intended to be /// implemented for smart pointer types. For your own structs, you would i= mplement [`WorkItem`] /// instead. The [`run`] method on this trait will usually just perform th= e appropriate /// `container_of` translation and then call into the [`run`][WorkItem::ru= n] method from the @@ -329,7 +329,7 @@ pub unsafe trait WorkItemPointer: RawWor= kItem { /// This trait is used when the `work_struct` field is defined using the [= `Work`] helper. pub trait WorkItem { /// The pointer type that this struct is wrapped in. This will typical= ly be `Arc` or - /// `Pin>`. + /// `Pin>`. type Pointer: WorkItemPointer; =20 /// The method that should be called when this work item is executed. @@ -567,7 +567,7 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self:= :EnqueueOutput } =20 // SAFETY: TODO. -unsafe impl WorkItemPointer for Pin> +unsafe impl WorkItemPointer for Pin> where T: WorkItem, T: HasWork, @@ -578,7 +578,7 @@ unsafe impl WorkItemPointer for P= in> // SAFETY: This computes the pointer that `__enqueue` got from `Ar= c::into_raw`. let ptr =3D unsafe { T::work_container_of(ptr) }; // SAFETY: This pointer comes from `Arc::into_raw` and we've been = given back ownership. - let boxed =3D unsafe { Box::from_raw(ptr) }; + let boxed =3D unsafe { KBox::from_raw(ptr) }; // SAFETY: The box was already pinned when it was enqueued. let pinned =3D unsafe { Pin::new_unchecked(boxed) }; =20 @@ -587,7 +587,7 @@ unsafe impl WorkItemPointer for P= in> } =20 // SAFETY: TODO. -unsafe impl RawWorkItem for Pin> +unsafe impl RawWorkItem for Pin> where T: WorkItem, T: HasWork, @@ -601,9 +601,9 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self:= :EnqueueOutput // SAFETY: We're not going to move `self` or any of its fields, so= its okay to temporarily // remove the `Pin` wrapper. let boxed =3D unsafe { Pin::into_inner_unchecked(self) }; - let ptr =3D Box::into_raw(boxed); + let ptr =3D KBox::into_raw(boxed); =20 - // SAFETY: Pointers into a `Box` point at a valid value. + // SAFETY: Pointers into a `KBox` point at a valid value. let work_ptr =3D unsafe { T::raw_get_work(ptr) }; // SAFETY: `raw_get_work` returns a pointer to a valid value. let work_ptr =3D unsafe { Work::raw_get(work_ptr) }; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index a626b1145e5c..ab93111a048c 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -243,7 +243,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// struct DriverData { /// #[pin] /// queue: Mutex>, -/// buf: Box<[u8; 1024 * 1024]>, +/// buf: KBox<[u8; 1024 * 1024]>, /// } /// ``` /// @@ -252,7 +252,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// struct DriverData { /// #[pin] /// queue: Mutex>, -/// buf: Box<[u8; 1024 * 1024]>, +/// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } /// @@ -282,7 +282,7 @@ pub fn pin_data(inner: TokenStream, item: TokenStream) = -> TokenStream { /// struct DriverData { /// #[pin] /// queue: Mutex>, -/// buf: Box<[u8; 1024 * 1024]>, +/// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } /// --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C165621D2BD; Fri, 4 Oct 2024 15:43:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056597; cv=none; b=JURRgsTNRIw/J0E5+T0m5FdEFOi2fL/yEmDBXQc8NHEpIQ6+WP/37fOKKgKvvKFaE6TPRveAzxdo6f4QZrcSRqf5qRqVq3ARIHlh461+p5leFrCXC2v/7rFe2ZTuTINr16EiJp7dzUmr/qIlsOq2+yAZEIJOz45rdoDdOwTKfjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056597; c=relaxed/simple; bh=kazRakNrpHOowneaJN4zcTb6ci/LaZH4uk5yeLlVimc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ucjDObFmAPebfPDKDpauW8TfuVunpyEXkf7hkxSdlZ3/L5PQrGmJASQ66TfOc+YIUhSq/SQPXbA6ZfbjoFloxC0e7JvFk1hcP5XRRBjjXWK9wJr+ScAw0VoTcP+WWhjmLvs3Npq4uUIc64LdpE2MtL5wmekI86sRQ3aqIr8SAkk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PY60yaBL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PY60yaBL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4582BC4CECE; Fri, 4 Oct 2024 15:43:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056596; bh=kazRakNrpHOowneaJN4zcTb6ci/LaZH4uk5yeLlVimc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PY60yaBLX5FkWroGne2wbiRf3YOduSZVZm5AHgfyk3WHkfWbM3EuOrVqXycz4PQq+ L7kLm6ETYxc6+1xIy6vIEplED3xtKssri1U63By0v6Aprb3PO7CD48G/KQPD32sgtJ vci/dSKvPyxY601jRKNuA/LQ03a7e2hPiAZLWPQqRQUms6VALZyIA9L5y8jP4wxwV7 O+XD4vvvKldAUaErm99zXSSYqGHqSfxaJm+IqSE2EyH5k/x7lOfsO7Gdrk0RwSzZXs UZB3fpr7e5dFB5csBMAGxrOWgFIN4xCvRqYtAUB2d6YvLLzFf1UgIPk0KrpdD0lUdG 7FqY3nKH27GTg== From: Danilo Krummrich 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 Subject: [PATCH v9 13/29] rust: alloc: remove extension of std's `Box` Date: Fri, 4 Oct 2024 17:41:17 +0200 Message-ID: <20241004154149.93856-14-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that all existing `Box` users were moved to the kernel `Box` type, remove the `BoxExt` extension and all other related extensions. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 - rust/kernel/alloc/box_ext.rs | 89 ------------------------------------ rust/kernel/init.rs | 46 +------------------ rust/kernel/lib.rs | 1 - rust/kernel/prelude.rs | 4 +- rust/kernel/types.rs | 50 -------------------- 6 files changed, 3 insertions(+), 188 deletions(-) delete mode 100644 rust/kernel/alloc/box_ext.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 12cd52f83222..ebe58247504f 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -4,7 +4,6 @@ =20 #[cfg(not(any(test, testlib)))] pub mod allocator; -pub mod box_ext; pub mod kbox; pub mod vec_ext; =20 diff --git a/rust/kernel/alloc/box_ext.rs b/rust/kernel/alloc/box_ext.rs deleted file mode 100644 index 7009ad78d4e0..000000000000 --- a/rust/kernel/alloc/box_ext.rs +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Extensions to [`Box`] for fallible allocations. - -use super::{AllocError, Flags}; -use alloc::boxed::Box; -use core::{mem::MaybeUninit, ptr, result::Result}; - -/// Extensions to [`Box`]. -pub trait BoxExt: Sized { - /// Allocates a new box. - /// - /// The allocation may fail, in which case an error is returned. - fn new(x: T, flags: Flags) -> Result; - - /// Allocates a new uninitialised box. - /// - /// The allocation may fail, in which case an error is returned. - fn new_uninit(flags: Flags) -> Result>, AllocError>; - - /// Drops the contents, but keeps the allocation. - /// - /// # Examples - /// - /// ``` - /// use kernel::alloc::{flags, box_ext::BoxExt}; - /// let value =3D Box::new([0; 32], flags::GFP_KERNEL)?; - /// assert_eq!(*value, [0; 32]); - /// let mut value =3D Box::drop_contents(value); - /// // Now we can re-use `value`: - /// value.write([1; 32]); - /// // SAFETY: We just wrote to it. - /// let value =3D unsafe { value.assume_init() }; - /// assert_eq!(*value, [1; 32]); - /// # Ok::<(), Error>(()) - /// ``` - fn drop_contents(this: Self) -> Box>; -} - -impl BoxExt for Box { - fn new(x: T, flags: Flags) -> Result { - let mut b =3D >::new_uninit(flags)?; - b.write(x); - // SAFETY: We just wrote to it. - Ok(unsafe { b.assume_init() }) - } - - #[cfg(any(test, testlib))] - fn new_uninit(_flags: Flags) -> Result>, AllocError= > { - Ok(Box::new_uninit()) - } - - #[cfg(not(any(test, testlib)))] - fn new_uninit(flags: Flags) -> Result>, AllocError>= { - let ptr =3D if core::mem::size_of::>() =3D=3D 0 { - core::ptr::NonNull::<_>::dangling().as_ptr() - } else { - let layout =3D core::alloc::Layout::new::>(); - - // SAFETY: Memory is being allocated (first arg is null). The = only other source of - // safety issues is sleeping on atomic context, which is addre= ssed by klint. Lastly, - // the type is not a SZT (checked above). - let ptr =3D - unsafe { super::allocator::krealloc_aligned(core::ptr::nul= l_mut(), layout, flags) }; - if ptr.is_null() { - return Err(AllocError); - } - - ptr.cast::>() - }; - - // SAFETY: For non-zero-sized types, we allocate above using the g= lobal allocator. For - // zero-sized types, we use `NonNull::dangling`. - Ok(unsafe { Box::from_raw(ptr) }) - } - - fn drop_contents(this: Self) -> Box> { - let ptr =3D Box::into_raw(this); - // SAFETY: `ptr` is valid, because it came from `Box::into_raw`. - unsafe { ptr::drop_in_place(ptr) }; - - // CAST: `MaybeUninit` is a transparent wrapper of `T`. - let ptr =3D ptr.cast::>(); - - // SAFETY: `ptr` is valid for writes, because it came from `Box::i= nto_raw` and it is valid for - // reads, since the pointer came from `Box::into_raw` and the type= is `MaybeUninit`. - unsafe { Box::from_raw(ptr) } - } -} diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index c889f2640b56..c9919ba0b683 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -211,13 +211,12 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ - alloc::{box_ext::BoxExt, AllocError, Flags, KBox}, + alloc::{AllocError, Flags, KBox}, error::{self, Error}, sync::Arc, sync::UniqueArc, types::{Opaque, ScopeGuard}, }; -use alloc::boxed::Box; use core::{ cell::UnsafeCell, convert::Infallible, @@ -588,7 +587,6 @@ macro_rules! pin_init { /// # Examples /// /// ```rust -/// # #![feature(new_uninit)] /// use kernel::{init::{self, PinInit}, error::Error}; /// #[pin_data] /// struct BigBuf { @@ -1245,26 +1243,6 @@ fn try_init(init: impl Init, flags: Flags) = -> Result } } =20 -impl InPlaceInit for Box { - type PinnedSelf =3D Pin; - - #[inline] - fn try_pin_init(init: impl PinInit, flags: Flags) -> Result - where - E: From, - { - as BoxExt<_>>::new_uninit(flags)?.write_pin_init(init) - } - - #[inline] - fn try_init(init: impl Init, flags: Flags) -> Result - where - E: From, - { - as BoxExt<_>>::new_uninit(flags)?.write_init(init) - } -} - impl InPlaceInit for UniqueArc { type PinnedSelf =3D Pin; =20 @@ -1301,28 +1279,6 @@ pub trait InPlaceWrite { fn write_pin_init(self, init: impl PinInit) -> Result, E>; } =20 -impl InPlaceWrite for Box> { - type Initialized =3D Box; - - fn write_init(mut self, init: impl Init) -> Result { - let slot =3D self.as_mut_ptr(); - // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, - // slot is valid. - unsafe { init.__init(slot)? }; - // SAFETY: All fields have been initialized. - Ok(unsafe { self.assume_init() }) - } - - fn write_pin_init(mut self, init: impl PinInit) -> Result, E> { - let slot =3D self.as_mut_ptr(); - // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, - // slot is valid and will not be moved, because we pin it later. - unsafe { init.__pinned_init(slot)? }; - // SAFETY: All fields have been initialized. - Ok(unsafe { self.assume_init() }.into()) - } -} - impl InPlaceWrite for UniqueArc> { type Initialized =3D UniqueArc; =20 diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index d59639e36db5..c9fb478f03b2 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -16,7 +16,6 @@ #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] #![feature(lint_reasons)] -#![feature(new_uninit)] #![feature(unsize)] =20 // Ensure conditional compilation based on the kernel configuration works; diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index a9210634a8c3..c1f8e5c832e2 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,10 +14,10 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{box_ext::BoxExt, flags::*, vec_ext::VecExt, KBox, K= VBox, VBox}; +pub use crate::alloc::{flags::*, vec_ext::VecExt, KBox, KVBox, VBox}; =20 #[doc(no_inline)] -pub use alloc::{boxed::Box, vec::Vec}; +pub use alloc::vec::Vec; =20 #[doc(no_inline)] pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable}; diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 28d9e5ea3df4..f567494d4e54 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -3,13 +3,11 @@ //! Kernel types. =20 use crate::init::{self, PinInit}; -use alloc::boxed::Box; use core::{ cell::UnsafeCell, marker::{PhantomData, PhantomPinned}, mem::{ManuallyDrop, MaybeUninit}, ops::{Deref, DerefMut}, - pin::Pin, ptr::NonNull, }; =20 @@ -71,54 +69,6 @@ unsafe fn try_from_foreign(ptr: *const core::ffi::c_void= ) -> Option { } } =20 -impl ForeignOwnable for Box { - type Borrowed<'a> =3D &'a T; - - fn into_foreign(self) -> *const core::ffi::c_void { - Box::into_raw(self) as _ - } - - unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { - // SAFETY: The safety requirements for this function ensure that t= he object is still alive, - // so it is safe to dereference the raw pointer. - // The safety requirements of `from_foreign` also ensure that the = object remains alive for - // the lifetime of the returned value. - unsafe { &*ptr.cast() } - } - - unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { - // SAFETY: The safety requirements of this function ensure that `p= tr` comes from a previous - // call to `Self::into_foreign`. - unsafe { Box::from_raw(ptr as _) } - } -} - -impl ForeignOwnable for Pin> { - type Borrowed<'a> =3D Pin<&'a T>; - - fn into_foreign(self) -> *const core::ffi::c_void { - // SAFETY: We are still treating the box as pinned. - Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _ - } - - unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Pin<&'a T> { - // SAFETY: The safety requirements for this function ensure that t= he object is still alive, - // so it is safe to dereference the raw pointer. - // The safety requirements of `from_foreign` also ensure that the = object remains alive for - // the lifetime of the returned value. - let r =3D unsafe { &*ptr.cast() }; - - // SAFETY: This pointer originates from a `Pin>`. - unsafe { Pin::new_unchecked(r) } - } - - unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { - // SAFETY: The safety requirements of this function ensure that `p= tr` comes from a previous - // call to `Self::into_foreign`. - unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) } - } -} - impl ForeignOwnable for () { type Borrowed<'a> =3D (); =20 --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13D6D21D2D7; Fri, 4 Oct 2024 15:43:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056602; cv=none; b=lf5az1Up6sw2wAu0sFR7VH7x/UtphvzurxETEjjyuDLMpZ4pOOsa0lCCiArRuV9pcJ11W96DcyDUKrWczGa/PcM1jiph22562t4lmw235qdeYgvpaEgPJ30JxaxMTQ0U44Wfdzkwy9MuR6VC7SiWsPvzCSoTX7xE0ec3pl7wBgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056602; c=relaxed/simple; bh=83eAnIr1D5O9vSM1uHBUzB+eFQ2uxXd/+rUZl+c6k2o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TCEOm4Tg13/u645po008aCfOQc+7b2156UGP6JKbIntiePgYuDk3RehdNoqWWtcFO2doQyJIMeTsU9AcVm3UgW2744R5cOp1rQd8NKTWoPniwb2AgI8Mmq1527EphBBvwyb4IgYcihd49YSrtG8A1W7mYdAoqfLdI1vHuFz133o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RAX5Fxuo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RAX5Fxuo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A84BBC4CED1; Fri, 4 Oct 2024 15:43:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056601; bh=83eAnIr1D5O9vSM1uHBUzB+eFQ2uxXd/+rUZl+c6k2o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RAX5FxuocB81c4eS/xKda7a1vgBAAor7uSqS3MWtBwA7kw+xQ3UyS2nA03SKUGH+Q pLhGAhPALTKoIQleAVL6AR3hqdHJEbrttt9mfwcZoRRbnLsIcq88/xrOL+IzCR8kPo YoNd6gYwsTQek/s0Z3T91AK3r9l/HO1hxOshZy3AsZJV5ba1DNcxjoEs1hit3lWLa+ ELkhPNrbPYlJQwcYLil7DckqarR2yCx59JC0TBqlq5eFefw8zweVV+nq8t2aQy1syn gBBaFWaEfo3J/eWy1zAi5mY80aDTblQfk8AXC2fYIo4PGhj7rGBd0WvvcBTMP2kCB2 uwabeVJOIAXxw== From: Danilo Krummrich 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 Subject: [PATCH v9 14/29] rust: alloc: add `Box` to prelude Date: Fri, 4 Oct 2024 17:41:18 +0200 Message-ID: <20241004154149.93856-15-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that we removed `BoxExt` and the corresponding includes in prelude.rs, add the new kernel `Box` type instead. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/prelude.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index c1f8e5c832e2..d5f2fe42d093 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{flags::*, vec_ext::VecExt, KBox, KVBox, VBox}; +pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, VBox}; =20 #[doc(no_inline)] pub use alloc::vec::Vec; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 303E41C7260; Fri, 4 Oct 2024 15:43:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056607; cv=none; b=QcoPQ6lTDhNO7Aw4/a9jjuEQL7dsdcSNrK4s2DCzOJ+znjezlKLw9u6dJ3z8T7Rg/JWGRchKzUK5wnjT9hgzOutKDTiIqTWTBKK5fxssSpLbp7f5lz/5F2jW1WKo/NScZHhue5JI/wP1OPt4iCdjVVRKOBZo1DAqIkreW76EcBs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056607; c=relaxed/simple; bh=Q+ML1ibWYAYZGeFhUyhzJzIY+ZOBQOky3D240qlJo4Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fzF9NYW+uO5d9LNMxMmZnRb1vipIYLe6rlrnxkJXvQuF/9wky9dZ0M4ooF9LDrQiSqrpsdxoAuTDwgoDNqqaIKuvYmhMPEgMZa2HsHjDFvJPmvkALEnMmhXabqAIB+AOgZ3i4tlRY74UIPPaYj5A/1fce6ugama1kaNHPe7ZmSc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mM3Uexz0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mM3Uexz0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 18E9FC4CEC6; Fri, 4 Oct 2024 15:43:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056607; bh=Q+ML1ibWYAYZGeFhUyhzJzIY+ZOBQOky3D240qlJo4Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mM3Uexz0BDtA61JTp90r4hhfmffR8zBUbDJS9Gck2GzwPkQJWdqGF2kXRaGcmrWMN 4Y8NSqhOW8sicnvOmy7Ak7+p+pdc6kyeteR2Cbv7utjnJkv7Gyl0gCgA3FSJbUhGz9 kORuqJ0DrEuV9XfjA6LDLbtV/iZ1GKQO4h4zfXR4goB+P+w/rg5I0gqUDQAoVLsLnw cercRS/hZcyU4baHwPeYm3rhtRMVvDUZZrXbG1O8+gULiTC2ecYEGj18pizpQ1g7qQ kSFtD72R8ROVqH7OsEpN3dXlKW13qg6430qMwWMIZ+nEeZEQvAcEz4dylkb/jGbzWs 5j4auh5MnXLQA== From: Danilo Krummrich 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 Subject: [PATCH v9 15/29] rust: alloc: introduce `ArrayLayout` Date: Fri, 4 Oct 2024 17:41:19 +0200 Message-ID: <20241004154149.93856-16-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Benno Lossin When allocating memory for arrays using allocators, the `Layout::array` function is typically used. It returns a result, since the given size might be too big. However, `Vec` and its iterators store their allocated capacity and thus they already did check that the size is not too big. The `ArrayLayout` type provides this exact behavior, as it can be infallibly converted into a `Layout`. Instead of a `usize` capacity, `Vec` and other similar array-storing types can use `ArrayLayout` instead. Reviewed-by: Gary Guo Signed-off-by: Benno Lossin Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 + rust/kernel/alloc/layout.rs | 91 +++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 rust/kernel/alloc/layout.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index ebe58247504f..bf143a71d53d 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 kbox; +pub mod layout; pub mod vec_ext; =20 #[cfg(any(test, testlib))] diff --git a/rust/kernel/alloc/layout.rs b/rust/kernel/alloc/layout.rs new file mode 100644 index 000000000000..7f0427a4d3d8 --- /dev/null +++ b/rust/kernel/alloc/layout.rs @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Memory layout. +//! +//! Custom layout types extending or improving [`Layout`]. + +use core::{alloc::Layout, marker::PhantomData}; + +/// Error when constructing an [`ArrayLayout`]. +pub struct LayoutError; + +/// A layout for an array `[T; n]`. +/// +/// # Invariants +/// +/// - `len * size_of::() <=3D isize::MAX` +pub struct ArrayLayout { + len: usize, + _phantom: PhantomData T>, +} + +impl Clone for ArrayLayout { + fn clone(&self) -> Self { + *self + } +} +impl Copy for ArrayLayout {} + +const ISIZE_MAX: usize =3D isize::MAX as usize; + +impl ArrayLayout { + /// Creates a new layout for `[T; 0]`. + pub const fn empty() -> Self { + // INVARIANT: `0 * size_of::() <=3D isize::MAX` + Self { + len: 0, + _phantom: PhantomData, + } + } + + /// Creates a new layout for `[T; len]`. + /// + /// # Errors + /// + /// When `len * size_of::()` overflows or when `len * size_of::(= ) > isize::MAX`. + pub const fn new(len: usize) -> Result { + match len.checked_mul(core::mem::size_of::()) { + Some(len) if len <=3D ISIZE_MAX =3D> { + // INVARIANT: we checked above that `len * size_of::() = <=3D isize::MAX` + Ok(Self { + len, + _phantom: PhantomData, + }) + } + _ =3D> Err(LayoutError), + } + } + + /// Creates a new layout for `[T; len]`. + /// + /// # Safety + /// + /// `len` must be a value, for which `len * size_of::() <=3D isize:= :MAX` is true. + pub unsafe fn new_unchecked(len: usize) -> Self { + // INVARIANT: By the safety requirements of this function + // `len * size_of::() <=3D isize::MAX`. + Self { + len, + _phantom: PhantomData, + } + } + + /// Returns the number of array elements represented by this layout. + pub const fn len(&self) -> usize { + self.len + } + + /// Returns `true` when no array elements are represented by this layo= ut. + pub const fn is_empty(&self) -> bool { + self.len =3D=3D 0 + } +} + +impl From> for Layout { + fn from(value: ArrayLayout) -> Self { + let res =3D Layout::array::(value.len); + // SAFETY: by the type invariant of `ArrayLayout` we have + // `len * size_of::() <=3D isize::MAX` and thus the result must= be `Ok`. + unsafe { res.unwrap_unchecked() } + } +} --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E91BB217906; Fri, 4 Oct 2024 15:43:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056613; cv=none; b=VVRjp10DLMF9jbnV+YcFQIpghKppqhNrMDOK5NXlkM1hkJ9b4SsyXqJ18B5ILamkFOurQL4kH4gbXx6ufZoVBCkxpHJszsk4H5jG+fJtMW+XkuBIcE+6U0DQPcGADDBY+1IrxCFA1hs3G94TiYh+fmT6CRSRFNMYqMiAJSw8ml0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056613; c=relaxed/simple; bh=urUND/M4698IVjZumaKDfSVmB/eKfMiMjzbdlOGJcEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=E0RmKjTmYEUJ2QBjShORvSb5qmf8VWVy6u64nFMMukYInA/lGHqNpTKO0QrPU+2mNCEb08gFjfh9gzqnkQkkfozBt6DKF/D6N+/X7QdYJFTtMM5q2wsdgKNsagB3Odxuet9zYS7vHZGCxSpz6XxuxuLHavgiQEkmRGWzdCLe5fw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UBhbEufK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UBhbEufK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84324C4CED1; Fri, 4 Oct 2024 15:43:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056612; bh=urUND/M4698IVjZumaKDfSVmB/eKfMiMjzbdlOGJcEY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UBhbEufKcxuCRY00KyIbVslslxEMIsPk9WUsIs783OrEc0mZ18t20DCCioLwVd1CR 1UfTUeTTIUP9ShwsQ1d0sNBf/KCN+Rpnp+XQO33XJXDfKl1p+xscG4TmrESRWPDaOs JeWwYHnhGA5YhAQq20eXafHKYRzFyPBANORhWwpaT3MZvyf+6k7Mmj+PC0+8d/9vot x3lNwP0/1k2vNG1CKBomy3RqW7liDAYigkC1beVZ+EqPRy6RbMqFgldSl0q7A5djNa yilRx8s7MuFSciJUyH/m/yxjvMfjwN0sfLHB9gaPHgNBOTuL08qmT6VFlccK3Bd8Ot MtvXCVnihQyxQ== From: Danilo Krummrich 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 Subject: [PATCH v9 16/29] rust: alloc: implement kernel `Vec` type Date: Fri, 4 Oct 2024 17:41:20 +0200 Message-ID: <20241004154149.93856-17-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" `Vec` provides a contiguous growable array type with contents allocated with the kernel's allocators (e.g. `Kmalloc`, `Vmalloc` or `KVmalloc`). In contrast to Rust's stdlib `Vec` type, the kernel `Vec` type considers the kernel's GFP flags for all appropriate functions, always reports allocation failures through `Result<_, AllocError>` and remains independent from unstable features. Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 6 + rust/kernel/alloc/kvec.rs | 650 ++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + rust/kernel/prelude.rs | 2 +- 4 files changed, 658 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/alloc/kvec.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index bf143a71d53d..961070daf6db 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 kbox; +pub mod kvec; pub mod layout; pub mod vec_ext; =20 @@ -19,6 +20,11 @@ pub use self::kbox::KVBox; pub use self::kbox::VBox; =20 +pub use self::kvec::KVVec; +pub use self::kvec::KVec; +pub use self::kvec::VVec; +pub use self::kvec::Vec; + /// Indicates an allocation error. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs new file mode 100644 index 000000000000..d41353b7653d --- /dev/null +++ b/rust/kernel/alloc/kvec.rs @@ -0,0 +1,650 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Implementation of [`Vec`]. + +use super::{ + allocator::{KVmalloc, Kmalloc, Vmalloc}, + layout::ArrayLayout, + AllocError, Allocator, Box, Flags, +}; +use core::{ + fmt, + marker::PhantomData, + mem::{ManuallyDrop, MaybeUninit}, + ops::Deref, + ops::DerefMut, + ops::Index, + ops::IndexMut, + ptr, + ptr::NonNull, + slice, + slice::SliceIndex, +}; + +/// Create a [`KVec`] containing the arguments. +/// +/// New memory is allocated with `GFP_KERNEL`. +/// +/// # Examples +/// +/// ``` +/// let mut v =3D kernel::kvec![]; +/// v.push(1, GFP_KERNEL)?; +/// assert_eq!(v, [1]); +/// +/// let mut v =3D kernel::kvec![1; 3]?; +/// v.push(4, GFP_KERNEL)?; +/// assert_eq!(v, [1, 1, 1, 4]); +/// +/// let mut v =3D kernel::kvec![1, 2, 3]?; +/// v.push(4, GFP_KERNEL)?; +/// assert_eq!(v, [1, 2, 3, 4]); +/// +/// # Ok::<(), Error>(()) +/// ``` +#[macro_export] +macro_rules! kvec { + () =3D> ( + $crate::alloc::KVec::new() + ); + ($elem:expr; $n:expr) =3D> ( + $crate::alloc::KVec::from_elem($elem, $n, GFP_KERNEL) + ); + ($($x:expr),+ $(,)?) =3D> ( + match $crate::alloc::KBox::new_uninit(GFP_KERNEL) { + Ok(b) =3D> Ok($crate::alloc::KVec::from($crate::alloc::KBox::w= rite(b, [$($x),+]))), + Err(e) =3D> Err(e), + } + ); +} + +/// The kernel's [`Vec`] type. +/// +/// A contiguous growable array type with contents allocated with the kern= el's allocators (e.g. +/// [`Kmalloc`], [`Vmalloc`] or [`KVmalloc`]), written `Vec`. +/// +/// For non-zero-sized values, a [`Vec`] will use the given allocator `A` = for its allocation. For +/// the most common allocators the type aliases [`KVec`], [`VVec`] and [`K= VVec`] exist. +/// +/// For zero-sized types the [`Vec`]'s pointer must be `dangling_mut::`= ; no memory is allocated. +/// +/// Generally, [`Vec`] consists of a pointer that represents the vector's = backing buffer, the +/// capacity of the vector (the number of elements that currently fit into= the vector), it's length +/// (the number of elements that are currently stored in the vector) and t= he `Allocator` type used +/// to allocate (and free) the backing buffer. +/// +/// A [`Vec`] can be deconstructed into and (re-)constructed from it's pre= viously named raw parts +/// and manually modified. +/// +/// [`Vec`]'s backing buffer gets, if required, automatically increased (r= e-allocated) when elements +/// are added to the vector. +/// +/// # Invariants +/// +/// - `self.ptr` is always properly aligned and either points to memory al= located with `A` or, for +/// zero-sized types, is a dangling, well aligned pointer. +/// +/// - `self.len` always represents the exact number of elements stored in = the vector. +/// +/// - `self.layout` represents the absolute number of elements that can be= stored within the vector +/// without re-allocation. For ZSTs `self.layout`'s capacity is zero. Ho= wever, it is legal for the +/// backing buffer to be larger than `layout`. +/// +/// - The `Allocator` type `A` of the vector is the exact same `Allocator`= type the backing buffer +/// was allocated with (and must be freed with). +pub struct Vec { + ptr: NonNull, + /// Represents the actual buffer size as `cap` times `size_of::` by= tes. + /// + /// Note: This isn't quite the same as `Self::capacity`, which in cont= rast returns the number of + /// elements we can still store without reallocating. + layout: ArrayLayout, + len: usize, + _p: PhantomData, +} + +/// Type alias for [`Vec`] with a [`Kmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let mut v =3D KVec::new(); +/// v.push(1, GFP_KERNEL)?; +/// assert_eq!(&v, &[1]); +/// +/// # Ok::<(), Error>(()) +/// ``` +pub type KVec =3D Vec; + +/// Type alias for [`Vec`] with a [`Vmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let mut v =3D VVec::new(); +/// v.push(1, GFP_KERNEL)?; +/// assert_eq!(&v, &[1]); +/// +/// # Ok::<(), Error>(()) +/// ``` +pub type VVec =3D Vec; + +/// Type alias for [`Vec`] with a [`KVmalloc`] allocator. +/// +/// # Examples +/// +/// ``` +/// let mut v =3D KVVec::new(); +/// v.push(1, GFP_KERNEL)?; +/// assert_eq!(&v, &[1]); +/// +/// # Ok::<(), Error>(()) +/// ``` +pub type KVVec =3D Vec; + +// SAFETY: `Vec` is `Send` if `T` is `Send` because `Vec` owns its element= s. +unsafe impl Send for Vec +where + T: Send, + A: Allocator, +{ +} + +// SAFETY: `Vec` is `Sync` if `T` is `Sync` because `Vec` owns its element= s. +unsafe impl Sync for Vec +where + T: Sync, + A: Allocator, +{ +} + +impl Vec +where + A: Allocator, +{ + #[inline] + const fn is_zst() -> bool { + core::mem::size_of::() =3D=3D 0 + } + + /// Returns the number of elements that can be stored within the vecto= r without allocating + /// additional memory. + pub fn capacity(&self) -> usize { + if const { Self::is_zst() } { + usize::MAX + } else { + self.layout.len() + } + } + + /// Returns the number of elements stored within the vector. + #[inline] + pub fn len(&self) -> usize { + self.len + } + + /// Forcefully sets `self.len` to `new_len`. + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`Self::capacity`]. + /// - If `new_len` is greater than `self.len`, all elements within the= interval + /// [`self.len`,`new_len`) must be initialized. + #[inline] + pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <=3D self.capacity()); + self.len =3D new_len; + } + + /// Returns a slice of the entire vector. + #[inline] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Returns a mutable slice of the entire vector. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Returns a mutable raw pointer to the vector's backing buffer, or, = if `T` is a ZST, a + /// dangling raw pointer. + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self.ptr.as_ptr() + } + + /// Returns a raw pointer to the vector's backing buffer, or, if `T` i= s a ZST, a dangling raw + /// pointer. + #[inline] + pub fn as_ptr(&self) -> *const T { + self.ptr.as_ptr() + } + + /// Returns `true` if the vector contains no elements, `false` otherwi= se. + /// + /// # Examples + /// + /// ``` + /// let mut v =3D KVec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1, GFP_KERNEL); + /// assert!(!v.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len() =3D=3D 0 + } + + /// Creates a new, empty Vec. + /// + /// This method does not allocate by itself. + #[inline] + pub const fn new() -> Self { + // INVARIANT: Since this is a new, empty `Vec` with no backing mem= ory yet, + // - `ptr` is a properly aligned dangling pointer for type `T`, + // - `layout` is an empty `ArrayLayout` (zero capacity) + // - `len` is zero, since no elements can be or have been stored, + // - `A` is always valid. + Self { + ptr: NonNull::dangling(), + layout: ArrayLayout::empty(), + len: 0, + _p: PhantomData::, + } + } + + /// Returns a slice of `MaybeUninit` for the remaining spare capaci= ty of the vector. + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: + // - `self.len` is smaller than `self.capacity` and hence, the res= ulting pointer is + // guaranteed to be part of the same allocated object. + // - `self.len` can not overflow `isize`. + let ptr =3D unsafe { self.as_mut_ptr().add(self.len) } as *mut May= beUninit; + + // SAFETY: The memory between `self.len` and `self.capacity` is gu= aranteed to be allocated + // and valid, but uninitialized. + unsafe { slice::from_raw_parts_mut(ptr, self.capacity() - self.len= ) } + } + + /// Appends an element to the back of the [`Vec`] instance. + /// + /// # Examples + /// + /// ``` + /// let mut v =3D KVec::new(); + /// v.push(1, GFP_KERNEL)?; + /// assert_eq!(&v, &[1]); + /// + /// v.push(2, GFP_KERNEL)?; + /// assert_eq!(&v, &[1, 2]); + /// # Ok::<(), Error>(()) + /// ``` + pub fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { + self.reserve(1, flags)?; + + // SAFETY: + // - `self.len` is smaller than `self.capacity` and hence, the res= ulting pointer is + // guaranteed to be part of the same allocated object. + // - `self.len` can not overflow `isize`. + let ptr =3D unsafe { self.as_mut_ptr().add(self.len) }; + + // SAFETY: + // - `ptr` is properly aligned and valid for writes. + unsafe { core::ptr::write(ptr, v) }; + + // SAFETY: We just initialised the first spare entry, so it is saf= e to increase the length + // by 1. We also know that the new length is <=3D capacity because= of the previous call to + // `reserve` above. + unsafe { self.set_len(self.len() + 1) }; + Ok(()) + } + + /// Creates a new [`Vec`] instance with at least the given capacity. + /// + /// # Examples + /// + /// ``` + /// let v =3D KVec::::with_capacity(20, GFP_KERNEL)?; + /// + /// assert!(v.capacity() >=3D 20); + /// # Ok::<(), Error>(()) + /// ``` + pub fn with_capacity(capacity: usize, flags: Flags) -> Result { + let mut v =3D Vec::new(); + + v.reserve(capacity, flags)?; + + Ok(v) + } + + /// Creates a Vec from a pointer, a length and a capacity using = the allocator `A`. + /// + /// # Examples + /// + /// ``` + /// let mut v =3D kernel::kvec![1, 2, 3]?; + /// v.reserve(1, GFP_KERNEL)?; + /// + /// let (mut ptr, mut len, cap) =3D v.into_raw_parts(); + /// + /// // SAFETY: We've just reserved memory for another element. + /// unsafe { ptr.add(len).write(4) }; + /// len +=3D 1; + /// + /// // SAFETY: We only wrote an additional element at the end of the `= KVec`'s buffer and + /// // correspondingly increased the length of the `KVec` by one. Othe= rwise, we construct it + /// // from the exact same raw parts. + /// let v =3D unsafe { KVec::from_raw_parts(ptr, len, cap) }; + /// + /// assert_eq!(v, [1, 2, 3, 4]); + /// + /// # Ok::<(), Error>(()) + /// ``` + /// + /// # Safety + /// + /// If `T` is a ZST: + /// + /// - `ptr` must be a dangling, well aligned pointer. + /// + /// Otherwise: + /// + /// - `ptr` must have been allocated with the allocator `A`. + /// - `ptr` must satisfy or exceed the alignment requirements of `T`. + /// - `ptr` must point to memory with a size of at least `size_of::= () * capacity`. + /// bytes. + /// - The allocated size in bytes must not be larger than `isize::MAX`. + /// - `length` must be less than or equal to `capacity`. + /// - The first `length` elements must be initialized values of type `= T`. + /// + /// It is also valid to create an empty `Vec` passing a dangling point= er for `ptr` and zero for + /// `cap` and `len`. + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usi= ze) -> Self { + let layout =3D if Self::is_zst() { + ArrayLayout::empty() + } else { + // SAFETY: By the safety requirements of this function, `capac= ity * size_of::()` is + // smaller than `isize::MAX`. + unsafe { ArrayLayout::new_unchecked(capacity) } + }; + + // INVARIANT: For ZSTs, we store an empty `ArrayLayout`, all other= type invariants are + // covered by the safety requirements of this function. + Self { + // SAFETY: By the safety requirements, `ptr` is either danglin= g or pointing to a valid + // memory allocation, allocated with `A`. + ptr: unsafe { NonNull::new_unchecked(ptr) }, + layout, + len: length, + _p: PhantomData::, + } + } + + /// Consumes the `Vec` and returns its raw components `pointer`,= `length` and `capacity`. + /// + /// This will not run the destructor of the contained elements and for= non-ZSTs the allocation + /// will stay alive indefinitely. Use [`Vec::from_raw_parts`] to recov= er the [`Vec`], drop the + /// elements and free the allocation, if any. + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me =3D ManuallyDrop::new(self); + let len =3D me.len(); + let capacity =3D me.capacity(); + let ptr =3D me.as_mut_ptr(); + (ptr, len, capacity) + } + + /// Ensures that the capacity exceeds the length by at least `addition= al` + /// elements. + /// + /// # Examples + /// + /// ``` + /// let mut v =3D KVec::new(); + /// v.push(1, GFP_KERNEL)?; + /// + /// v.reserve(10, GFP_KERNEL)?; + /// let cap =3D v.capacity(); + /// assert!(cap >=3D 10); + /// + /// v.reserve(10, GFP_KERNEL)?; + /// let new_cap =3D v.capacity(); + /// assert_eq!(new_cap, cap); + /// + /// # Ok::<(), Error>(()) + /// ``` + pub fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(= ), AllocError> { + let len =3D self.len(); + let cap =3D self.capacity(); + + if cap - len >=3D additional { + return Ok(()); + } + + if Self::is_zst() { + // The capacity is already `usize::MAX` for ZSTs, we can't go = higher. + return Err(AllocError); + } + + // We know that `cap <=3D isize::MAX` because of the type invarian= ts of `Self`. So the + // multiplication by two won't overflow. + let new_cap =3D core::cmp::max(cap * 2, len.checked_add(additional= ).ok_or(AllocError)?); + let layout =3D ArrayLayout::new(new_cap).map_err(|_| AllocError)?; + + // SAFETY: + // - `ptr` is valid because it's either `None` or comes from a pre= vious call to + // `A::realloc`. + // - `self.layout` matches the `ArrayLayout` of the preceeding all= ocation. + let ptr =3D unsafe { + A::realloc( + Some(self.ptr.cast()), + layout.into(), + self.layout.into(), + flags, + )? + }; + + // INVARIANT: + // - `layout` is some `ArrayLayout::`, + // - `ptr` has been created by `A::realloc` from `layout`. + self.ptr =3D ptr.cast(); + self.layout =3D layout; + + Ok(()) + } +} + +impl Vec { + /// Extend the vector by `n` clones of `value`. + pub fn extend_with(&mut self, n: usize, value: T, flags: Flags) -> Res= ult<(), AllocError> { + if n =3D=3D 0 { + return Ok(()); + } + + self.reserve(n, flags)?; + + let spare =3D self.spare_capacity_mut(); + + for item in spare.iter_mut().take(n - 1) { + item.write(value.clone()); + } + + // We can write the last element directly without cloning needless= ly. + spare[n - 1].write(value); + + // SAFETY: + // - `self.len() + n < self.capacity()` due to the call to reserve= above, + // - the loop and the line above initialized the next `n` elements. + unsafe { self.set_len(self.len() + n) }; + + Ok(()) + } + + /// Pushes clones of the elements of slice into the [`Vec`] instance. + /// + /// # Examples + /// + /// ``` + /// let mut v =3D KVec::new(); + /// v.push(1, GFP_KERNEL)?; + /// + /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?; + /// assert_eq!(&v, &[1, 20, 30, 40]); + /// + /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?; + /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]); + /// # Ok::<(), Error>(()) + /// ``` + pub fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Resu= lt<(), AllocError> { + self.reserve(other.len(), flags)?; + for (slot, item) in core::iter::zip(self.spare_capacity_mut(), oth= er) { + slot.write(item.clone()); + } + + // SAFETY: + // - `other.len()` spare entries have just been initialized, so it= is safe to increase + // the length by the same number. + // - `self.len() + other.len() <=3D self.capacity()` is guaranteed= by the preceding `reserve` + // call. + unsafe { self.set_len(self.len() + other.len()) }; + Ok(()) + } + + /// Create a new `Vec and extend it by `n` clones of `value`. + pub fn from_elem(value: T, n: usize, flags: Flags) -> Result { + let mut v =3D Self::with_capacity(n, flags)?; + + v.extend_with(n, value, flags)?; + + Ok(v) + } +} + +impl Drop for Vec +where + A: Allocator, +{ + fn drop(&mut self) { + // SAFETY: `self.as_mut_ptr` is guaranteed to be valid by the type= invariant. + unsafe { + ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut( + self.as_mut_ptr(), + self.len, + )) + }; + + // SAFETY: + // - `self.ptr` was previously allocated with `A`. + // - `self.layout` matches the `ArrayLayout` of the preceeding all= ocation. + unsafe { A::free(self.ptr.cast(), self.layout.into()) }; + } +} + +impl From> for Vec +where + A: Allocator, +{ + fn from(b: Box<[T; N], A>) -> Vec { + let len =3D b.len(); + let ptr =3D Box::into_raw(b); + + // SAFETY: + // - `b` has been allocated with `A`, + // - `ptr` fulfills the alignment requirements for `T`, + // - `ptr` points to memory with at least a size of `size_of::(= ) * len`, + // - all elements within `b` are initialized values of `T`, + // - `len` does not exceed `isize::MAX`. + unsafe { Vec::from_raw_parts(ptr as _, len, len) } + } +} + +impl Default for KVec { + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl fmt::Debug for Vec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl Deref for Vec +where + A: Allocator, +{ + type Target =3D [T]; + + #[inline] + fn deref(&self) -> &[T] { + // SAFETY: The memory behind `self.as_ptr()` is guaranteed to cont= ain `self.len` + // initialized elements of type `T`. + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +impl DerefMut for Vec +where + A: Allocator, +{ + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + // SAFETY: The memory behind `self.as_ptr()` is guaranteed to cont= ain `self.len` + // initialized elements of type `T`. + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + +impl Eq for Vec where A: Allocator {} + +impl, A> Index for Vec +where + A: Allocator, +{ + type Output =3D I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +impl, A> IndexMut for Vec +where + A: Allocator, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +macro_rules! impl_slice_eq { + ($([$($vars:tt)*] $lhs:ty, $rhs:ty,)*) =3D> { + $( + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] =3D=3D other= [..] } + } + )* + } +} + +impl_slice_eq! { + [A1: Allocator, A2: Allocator] Vec, Vec, + [A: Allocator] Vec, &[U], + [A: Allocator] Vec, &mut [U], + [A: Allocator] &[T], Vec, + [A: Allocator] &mut [T], Vec, + [A: Allocator] Vec, [U], + [A: Allocator] [T], Vec, + [A: Allocator, const N: usize] Vec, [U; N], + [A: Allocator, const N: usize] Vec, &[U; N], +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index c9fb478f03b2..01f40729810b 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -17,6 +17,7 @@ #![feature(dispatch_from_dyn)] #![feature(lint_reasons)] #![feature(unsize)] +#![feature(inline_const)] =20 // Ensure conditional compilation based on the kernel configuration works; // otherwise we may silently break things like initcall handling. diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index d5f2fe42d093..80223cdaa485 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, VBox}; +pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, KVVec,= KVec, VBox, VVec}; =20 #[doc(no_inline)] pub use alloc::vec::Vec; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 041072207E0; Fri, 4 Oct 2024 15:43:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056618; cv=none; b=djcEiTjzhywTAtHK/MR8FTThOeUddDKasPCE5FryDhmudopbH48PEd5HajO7o6A/9qsQuQjMYEeYEgG0y1pfGRpoZL555o8DuN6tSxjfFwxk0172zj2oJGmnO0E2X/aEB4sGAawGj21grmSOr5ANtBlwOJ6kE9rluLH9KBN+Rd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056618; c=relaxed/simple; bh=2sSsIzdACzoPnqvUhervrAOknVeczgrx1816hyZSkw4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qzs1SI92zu+SmqzwA0xwHvty6GNraYrBuz1BF1UH7CxE5PDR5iEgIlNegwXdNZRA7Jery84FvEl+leyIX8IVeM9OKfihBIOgAoKHNlG0s+nV/0jsiyXkz1sl0vfh4FFiJknp9ksaCr51y82Nnp4wNj2zopLQ4WbgBH8YxI4cAM8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fRSbsK68; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fRSbsK68" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E9DECC4CEC6; Fri, 4 Oct 2024 15:43:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056617; bh=2sSsIzdACzoPnqvUhervrAOknVeczgrx1816hyZSkw4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fRSbsK68TywYDweAzJmxnLHP52gywwuHTd3U0HBB6jz5L0XkmeuGK4tHtivRhzfHJ jA/tut0+mI3ZgS9I32hAcnIeJrDvWZXp5isJ+RWfbfvPkN32+uBawoWrYL5nou+Blx zdERRBRrfBllOMd5yv5grsEB8zrKexPjR5CqqIyHs7l2pwgJoe+dj7z+IHiIckZ4B7 3qmwiwXJ/Wztcs0M/fjlblqz/vkLqkD+leaiAjL8U625qPXa6hk8QJWo+9ZwzMPSuj CGPuU/nWAZqCth6223YP+dYTee+RT/rQb7ZPVKcaijxzCLHRAkVEolLhArocmgLuTg Fc9D2RN9mHdVA== From: Danilo Krummrich 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 Subject: [PATCH v9 17/29] rust: alloc: implement `IntoIterator` for `Vec` Date: Fri, 4 Oct 2024 17:41:21 +0200 Message-ID: <20241004154149.93856-18-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement `IntoIterator` for `Vec`, `Vec`'s `IntoIter` type, as well as `Iterator` for `IntoIter`. `Vec::into_iter` disassembles the `Vec` into its raw parts; additionally, `IntoIter` keeps track of a separate pointer, which is incremented correspondingsly as the iterator advances, while the length, or the count of elements, is decremented. This also means that `IntoIter` takes the ownership of the backing buffer and is responsible to drop the remaining elements and free the backing buffer, if it's dropped. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 + rust/kernel/alloc/kvec.rs | 170 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 961070daf6db..1d57bfe2acb1 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -20,6 +20,7 @@ pub use self::kbox::KVBox; pub use self::kbox::VBox; =20 +pub use self::kvec::IntoIter; pub use self::kvec::KVVec; pub use self::kvec::KVec; pub use self::kvec::VVec; diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index d41353b7653d..86382827f576 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -648,3 +648,173 @@ fn eq(&self, other: &$rhs) -> bool { self[..] =3D=3D = other[..] } [A: Allocator, const N: usize] Vec, [U; N], [A: Allocator, const N: usize] Vec, &[U; N], } + +impl<'a, T, A> IntoIterator for &'a Vec +where + A: Allocator, +{ + type Item =3D &'a T; + type IntoIter =3D slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec +where + A: Allocator, +{ + type Item =3D &'a mut T; + type IntoIter =3D slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +/// An [`Iterator`] implementation for [`Vec`] that moves elements out of = a vector. +/// +/// This structure is created by the [`Vec::into_iter`] method on [`Vec`] = (provided by the +/// [`IntoIterator`] trait). +/// +/// # Examples +/// +/// ``` +/// let v =3D kernel::kvec![0, 1, 2]?; +/// let iter =3D v.into_iter(); +/// +/// # Ok::<(), Error>(()) +/// ``` +pub struct IntoIter { + ptr: *mut T, + buf: NonNull, + len: usize, + layout: ArrayLayout, + _p: PhantomData, +} + +impl Iterator for IntoIter +where + A: Allocator, +{ + type Item =3D T; + + /// # Examples + /// + /// ``` + /// let v =3D kernel::kvec![1, 2, 3]?; + /// let mut it =3D v.into_iter(); + /// + /// assert_eq!(it.next(), Some(1)); + /// assert_eq!(it.next(), Some(2)); + /// assert_eq!(it.next(), Some(3)); + /// assert_eq!(it.next(), None); + /// + /// # Ok::<(), Error>(()) + /// ``` + fn next(&mut self) -> Option { + if self.len =3D=3D 0 { + return None; + } + + let current =3D self.ptr; + + // SAFETY: We can't overflow; decreasing `self.len` by one every t= ime we advance `self.ptr` + // by one guarantees that. + unsafe { self.ptr =3D self.ptr.add(1) }; + + self.len -=3D 1; + + // SAFETY: `current` is guaranteed to point at a valid element wit= hin the buffer. + Some(unsafe { current.read() }) + } + + /// # Examples + /// + /// ``` + /// let v: KVec =3D kernel::kvec![1, 2, 3]?; + /// let mut iter =3D v.into_iter(); + /// let size =3D iter.size_hint().0; + /// + /// iter.next(); + /// assert_eq!(iter.size_hint().0, size - 1); + /// + /// iter.next(); + /// assert_eq!(iter.size_hint().0, size - 2); + /// + /// iter.next(); + /// assert_eq!(iter.size_hint().0, size - 3); + /// + /// # Ok::<(), Error>(()) + /// ``` + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +impl Drop for IntoIter +where + A: Allocator, +{ + fn drop(&mut self) { + // SAFETY: `self.ptr` is guaranteed to be valid by the type invari= ant. + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.ptr= , self.len)) }; + + // SAFETY: + // - `self.buf` was previously allocated with `A`. + // - `self.layout` matches the `ArrayLayout` of the preceeding all= ocation. + unsafe { A::free(self.buf.cast(), self.layout.into()) }; + } +} + +impl IntoIterator for Vec +where + A: Allocator, +{ + type Item =3D T; + type IntoIter =3D IntoIter; + + /// Consumes the `Vec` and creates an `Iterator`, which moves ea= ch value out of the + /// vector (from start to end). + /// + /// # Examples + /// + /// ``` + /// let v =3D kernel::kvec![1, 2]?; + /// let mut v_iter =3D v.into_iter(); + /// + /// let first_element: Option =3D v_iter.next(); + /// + /// assert_eq!(first_element, Some(1)); + /// assert_eq!(v_iter.next(), Some(2)); + /// assert_eq!(v_iter.next(), None); + /// + /// # Ok::<(), Error>(()) + /// ``` + /// + /// ``` + /// let v =3D kernel::kvec![]; + /// let mut v_iter =3D v.into_iter(); + /// + /// let first_element: Option =3D v_iter.next(); + /// + /// assert_eq!(first_element, None); + /// + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + fn into_iter(self) -> Self::IntoIter { + let buf =3D self.ptr; + let layout =3D self.layout; + let (ptr, len, _) =3D self.into_raw_parts(); + + IntoIter { + ptr, + buf, + len, + layout, + _p: PhantomData::, + } + } +} --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6CD3A1E2822; Fri, 4 Oct 2024 15:43:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056623; cv=none; b=cyZ2th8jEKsIHO0hmwCFZxFmGnQLsAuRs4K0y01zfWj9mDFLkmX+laS1eq/mI4f+/xuZdXdjwZyMQonrqbkWyBfp3zE7kUi5hTtkFv9L6VWVuPFjd7RYxf6i+vcwXjTxksf1O+huy+ZOJQ2bTG3c1h1iYcyMeDr8dS3yBGcs2kA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056623; c=relaxed/simple; bh=AaRhWJzhXeNmb7koJrUIhcIZp+NJ7YnTtkDq/65dn0w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ro18ycqsCb7TDc8qfUzhrapxfp6a6DyZt6dsiHKcGK8nQNJNGVX86B7Ez153aJ4bOQgDsgN9BKLdrKFOmXqz4eRBGWXLBXdwuzbD3ZN9EMUuEI1H6GkV/8ZIK+Kmh+arBvOIiNP/Vm7QhWXgHAia/0P6JeRyzlKiyOAECD4+8f8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qHqXPqqt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qHqXPqqt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56752C4CECE; Fri, 4 Oct 2024 15:43:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056623; bh=AaRhWJzhXeNmb7koJrUIhcIZp+NJ7YnTtkDq/65dn0w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qHqXPqqtK505FnU3TTT6/Ji6dpr2PBjGmIlIN7KTNr7b/n8nmzyALSiHSoiLUQoNb KtUvqcut7lfST4w7g9rLwKr9uH386s/XGHuPMY2lMezaoM/i4dPAolBGABBTcYq/hk uDdhPGfUf8SR858gmtd9UZlfuO3ndAZchUHfRPwFdZwQk5LoRnsBB1xcrrGre3MkD8 gaYPhS97lcGwbRYMOC6v+jXUJ5WydyEO/G0w69lm2Xx9WcRshRlUVHLnRS8moapyaA YnuBVVZiJT+mwr1eLbJM/5tuGkT/xjhcDrKa38LRZxLVzsEouk1asvDeB6WXKelqZ2 brqZEsq6FxgXw== From: Danilo Krummrich 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 Subject: [PATCH v9 18/29] rust: alloc: implement `collect` for `IntoIter` Date: Fri, 4 Oct 2024 17:41:22 +0200 Message-ID: <20241004154149.93856-19-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, we can't implement `FromIterator`. There are a couple of issues with this trait in the kernel, namely: - Rust's specialization feature is unstable. This prevents us to optimze for the special case where `I::IntoIter` equals `Vec`'s `IntoIter` type. - We also can't use `I::IntoIter`'s type ID either to work around this, since `FromIterator` doesn't require this type to be `'static`. - `FromIterator::from_iter` does return `Self` instead of `Result`, hence we can't properly handle allocation failures. - Neither `Iterator::collect` nor `FromIterator::from_iter` can handle additional allocation flags. Instead, provide `IntoIter::collect`, such that we can at least convert `IntoIter` into a `Vec` again. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/kvec.rs | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index 86382827f576..119b5a4dbf77 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -694,6 +694,100 @@ pub struct IntoIter { _p: PhantomData, } =20 +impl IntoIter +where + A: Allocator, +{ + fn into_raw_parts(self) -> (*mut T, NonNull, usize, usize) { + let me =3D ManuallyDrop::new(self); + let ptr =3D me.ptr; + let buf =3D me.buf; + let len =3D me.len; + let cap =3D me.layout.len(); + (ptr, buf, len, cap) + } + + /// Same as `Iterator::collect` but specialized for `Vec`'s `IntoIter`. + /// + /// # Examples + /// + /// ``` + /// let v =3D kernel::kvec![1, 2, 3]?; + /// let mut it =3D v.into_iter(); + /// + /// assert_eq!(it.next(), Some(1)); + /// + /// let v =3D it.collect(GFP_KERNEL); + /// assert_eq!(v, [2, 3]); + /// + /// # Ok::<(), Error>(()) + /// ``` + /// # Implementation Details + /// + /// Currently, we can't implement `FromIterator`. There are a couple o= f issues with this trait + /// in the kernel, namely: + /// + /// - Rust's specialization feature is unstable. This prevents us to o= ptimze for the special + /// case where `I::IntoIter` equals `Vec`'s `IntoIter` type. + /// - We also can't use `I::IntoIter`'s type ID either to work around = this, since `FromIterator` + /// doesn't require this type to be `'static`. + /// - `FromIterator::from_iter` does return `Self` instead of `Result<= Self, AllocError>`, hence + /// we can't properly handle allocation failures. + /// - Neither `Iterator::collect` nor `FromIterator::from_iter` can ha= ndle additional allocation + /// flags. + /// + /// Instead, provide `IntoIter::collect`, such that we can at least co= nvert a `IntoIter` into a + /// `Vec` again. + /// + /// Note that `IntoIter::collect` doesn't require `Flags`, since it re= -uses the existing backing + /// buffer. However, this backing buffer may be shrunk to the actual c= ount of elements. + pub fn collect(self, flags: Flags) -> Vec { + let old_layout =3D self.layout; + let (mut ptr, buf, len, mut cap) =3D self.into_raw_parts(); + let has_advanced =3D ptr !=3D buf.as_ptr(); + + if has_advanced { + // Copy the contents we have advanced to at the beginning of t= he buffer. + // + // SAFETY: + // - `ptr` is valid for reads of `len * size_of::()` bytes, + // - `buf.as_ptr()` is valid for writes of `len * size_of::= ()` bytes, + // - `ptr` and `buf.as_ptr()` are not be subject to aliasing r= estrictions relative to + // each other, + // - both `ptr` and `buf.ptr()` are properly aligned. + unsafe { ptr::copy(ptr, buf.as_ptr(), len) }; + ptr =3D buf.as_ptr(); + + // SAFETY: `len` is guaranteed to be smaller than `self.layout= .len()`. + let layout =3D unsafe { ArrayLayout::::new_unchecked(len) }; + + // SAFETY: `buf` points to the start of the backing buffer and= `len` is guaranteed to be + // smaller than `cap`. Depending on `alloc` this operation may= shrink the buffer or leaves + // it as it is. + ptr =3D match unsafe { + A::realloc(Some(buf.cast()), layout.into(), old_layout.int= o(), flags) + } { + // If we fail to shrink, which likely can't even happen, c= ontinue with the existing + // buffer. + Err(_) =3D> ptr, + Ok(ptr) =3D> { + cap =3D len; + ptr.as_ptr().cast() + } + }; + } + + // SAFETY: If the iterator has been advanced, the advanced element= s have been copied to + // the beginning of the buffer and `len` has been adjusted accordi= ngly. + // + // - `ptr` is guaranteed to point to the start of the backing buff= er. + // - `cap` is either the original capacity or, after shrinking the= buffer, equal to `len`. + // - `alloc` is guaranteed to be unchanged since `into_iter` has b= een called on the original + // `Vec`. + unsafe { Vec::from_raw_parts(ptr, len, cap) } + } +} + impl Iterator for IntoIter where A: Allocator, --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F69F1E2822; Fri, 4 Oct 2024 15:43:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056629; cv=none; b=qAljjRV2HsQU7S0pWN6pDDVlajILhf+bKFr2UOrOllR9WuB9RD7RjM4AEz1as3TEI4f/PWzrcWnbi+LCl5ScHpi7DPP0tbz7jG9zlpM/9sDU9rBZiyVT7HNszO35kedIQtpEV8WdhewHaluDub0PdOdjEwVRGI4CHBpgNefHSfg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056629; c=relaxed/simple; bh=X/Is4V205f6dqcKBfBpL0xDEX/xfJQD4IPyW6qzXB1A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o9YKThG2XUrKyNgnJCkmMjpDWT7OmSGbfns1jUcs43DWjRATT+3U9Vc2xMg1N92qIWwpZS9+q3VwJYQ4O9JghY9PDzZ/PpOcCx58YrkZHE8lqui33bLGjJWzl5z/RMcA67LGtkSEqNGcj6ORjz+l8VYcu76cHSiT81EoyTI02/8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PB6q1555; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PB6q1555" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBDE7C4CEC7; Fri, 4 Oct 2024 15:43:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056628; bh=X/Is4V205f6dqcKBfBpL0xDEX/xfJQD4IPyW6qzXB1A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PB6q1555s6lkEk59Szp9aC/Xt1Y+gF8vd8klrAs1++eyPrEsFCqzYFDQitAQlo8Kk j64FUARo1KpIdN9UO0vAxPH1DWO224hAptzgZN9vgpJ1gNwHSiwOVbNe57Mswryi+/ ffnZOuw96WvWU+hN4o3GQI2/L8rXWTzN6kkwiQ4rjkKhH6VAV9mIzMaQG29nhBATPx XYFWpRjvc588kQqqac/P4wDrICCA4DNVRsjkjWU7/d1UkVdB3fykoGljTDJiEPKYQ6 N9WUr7aTSolBX59wQNlhqAr9lz3zIUu7p3LGU0RD67SqLSVjtSY8FBX16xoOKk4kFh 8XAi7qjDlV+Hw== From: Danilo Krummrich 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 Subject: [PATCH v9 19/29] rust: treewide: switch to the kernel `Vec` type Date: Fri, 4 Oct 2024 17:41:23 +0200 Message-ID: <20241004154149.93856-20-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that we got the kernel `Vec` in place, convert all existing `Vec` users to make use of it. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/str.rs | 12 +++++------- rust/kernel/sync/locked_by.rs | 2 +- rust/kernel/types.rs | 2 +- rust/kernel/uaccess.rs | 17 +++++++---------- rust/macros/lib.rs | 6 +++--- samples/rust/rust_minimal.rs | 4 ++-- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 66d4527f6c6f..6053bc7a98d1 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,8 +2,7 @@ =20 //! String representations. =20 -use crate::alloc::{flags::*, vec_ext::VecExt, AllocError}; -use alloc::vec::Vec; +use crate::alloc::{flags::*, AllocError, KVec}; use core::fmt::{self, Write}; use core::ops::{self, Deref, DerefMut, Index}; =20 @@ -791,7 +790,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result { /// assert_eq!(s.is_ok(), false); /// ``` pub struct CString { - buf: Vec, + buf: KVec, } =20 impl CString { @@ -804,7 +803,7 @@ pub fn try_from_fmt(args: fmt::Arguments<'_>) -> Result= { let size =3D f.bytes_written(); =20 // Allocate a vector with the required number of bytes, and write = to it. - let mut buf =3D as VecExt<_>>::with_capacity(size, GFP_KER= NEL)?; + let mut buf =3D KVec::with_capacity(size, GFP_KERNEL)?; // SAFETY: The buffer stored in `buf` is at least of size `size` a= nd is valid for writes. let mut f =3D unsafe { Formatter::from_buffer(buf.as_mut_ptr(), si= ze) }; f.write_fmt(args)?; @@ -851,10 +850,9 @@ impl<'a> TryFrom<&'a CStr> for CString { type Error =3D AllocError; =20 fn try_from(cstr: &'a CStr) -> Result { - let mut buf =3D Vec::new(); + let mut buf =3D KVec::new(); =20 - as VecExt<_>>::extend_from_slice(&mut buf, cstr.as_bytes_w= ith_nul(), GFP_KERNEL) - .map_err(|_| AllocError)?; + buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?; =20 // INVARIANT: The `CStr` and `CString` types have the same invaria= nts for // the string data, and we copied it over without changes. diff --git a/rust/kernel/sync/locked_by.rs b/rust/kernel/sync/locked_by.rs index babc731bd5f6..b94517231fcc 100644 --- a/rust/kernel/sync/locked_by.rs +++ b/rust/kernel/sync/locked_by.rs @@ -43,7 +43,7 @@ /// struct InnerDirectory { /// /// The sum of the bytes used by all files. /// bytes_used: u64, -/// _files: Vec, +/// _files: KVec, /// } /// /// struct Directory { diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index f567494d4e54..40e39161fd7a 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -135,7 +135,7 @@ unsafe fn from_foreign(_: *const core::ffi::c_void) -> = Self {} /// # use kernel::types::ScopeGuard; /// fn example3(arg: bool) -> Result { /// let mut vec =3D -/// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {}= elements\n", v.len())); +/// ScopeGuard::new_with_data(KVec::new(), |v| pr_info!("vec had {= } elements\n", v.len())); /// /// vec.push(10u8, GFP_KERNEL)?; /// if arg { diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index e9347cff99ab..bc011061de45 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -11,7 +11,6 @@ prelude::*, types::{AsBytes, FromBytes}, }; -use alloc::vec::Vec; use core::ffi::{c_ulong, c_void}; use core::mem::{size_of, MaybeUninit}; =20 @@ -46,7 +45,6 @@ /// every byte in the region. /// /// ```no_run -/// use alloc::vec::Vec; /// use core::ffi::c_void; /// use kernel::error::Result; /// use kernel::uaccess::{UserPtr, UserSlice}; @@ -54,7 +52,7 @@ /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result<()> { /// let (read, mut write) =3D UserSlice::new(uptr, len).reader_writer(= ); /// -/// let mut buf =3D Vec::new(); +/// let mut buf =3D KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// for b in &mut buf { @@ -69,7 +67,6 @@ /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. /// /// ```no_run -/// use alloc::vec::Vec; /// use core::ffi::c_void; /// use kernel::error::{code::EINVAL, Result}; /// use kernel::uaccess::{UserPtr, UserSlice}; @@ -78,21 +75,21 @@ /// fn is_valid(uptr: UserPtr, len: usize) -> Result { /// let read =3D UserSlice::new(uptr, len).reader(); /// -/// let mut buf =3D Vec::new(); +/// let mut buf =3D KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// todo!() /// } /// /// /// Returns the bytes behind this user pointer if they are valid. -/// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result> { +/// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result> { /// if !is_valid(uptr, len)? { /// return Err(EINVAL); /// } /// /// let read =3D UserSlice::new(uptr, len).reader(); /// -/// let mut buf =3D Vec::new(); +/// let mut buf =3D KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// // THIS IS A BUG! The bytes could have changed since we checked th= em. @@ -130,7 +127,7 @@ pub fn new(ptr: UserPtr, length: usize) -> Self { /// Reads the entirety of the user slice, appending it to the end of t= he provided buffer. /// /// Fails with [`EFAULT`] if the read happens on a bad address. - pub fn read_all(self, buf: &mut Vec, flags: Flags) -> Result { + pub fn read_all(self, buf: &mut KVec, flags: Flags) -> Result { self.reader().read_all(buf, flags) } =20 @@ -291,9 +288,9 @@ pub fn read(&mut self) -> Result { /// Reads the entirety of the user slice, appending it to the end of t= he provided buffer. /// /// Fails with [`EFAULT`] if the read happens on a bad address. - pub fn read_all(mut self, buf: &mut Vec, flags: Flags) -> Result { + pub fn read_all(mut self, buf: &mut KVec, flags: Flags) -> Result { let len =3D self.length; - VecExt::::reserve(buf, len, flags)?; + buf.reserve(len, flags)?; =20 // The call to `try_reserve` was successful, so the spare capacity= is at least `len` bytes // long. diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index ab93111a048c..8d4ac914b48b 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -242,7 +242,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// #[pin_data] /// struct DriverData { /// #[pin] -/// queue: Mutex>, +/// queue: Mutex>, /// buf: KBox<[u8; 1024 * 1024]>, /// } /// ``` @@ -251,7 +251,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// #[pin_data(PinnedDrop)] /// struct DriverData { /// #[pin] -/// queue: Mutex>, +/// queue: Mutex>, /// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } @@ -281,7 +281,7 @@ pub fn pin_data(inner: TokenStream, item: TokenStream) = -> TokenStream { /// #[pin_data(PinnedDrop)] /// struct DriverData { /// #[pin] -/// queue: Mutex>, +/// queue: Mutex>, /// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs index 2a9eaab62d1c..4aaf117bf8e3 100644 --- a/samples/rust/rust_minimal.rs +++ b/samples/rust/rust_minimal.rs @@ -13,7 +13,7 @@ } =20 struct RustMinimal { - numbers: Vec, + numbers: KVec, } =20 impl kernel::Module for RustMinimal { @@ -21,7 +21,7 @@ fn init(_module: &'static ThisModule) -> Result { pr_info!("Rust minimal sample (init)\n"); pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); =20 - let mut numbers =3D Vec::new(); + let mut numbers =3D KVec::new(); numbers.push(72, GFP_KERNEL)?; numbers.push(108, GFP_KERNEL)?; numbers.push(200, GFP_KERNEL)?; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA085221690; Fri, 4 Oct 2024 15:43:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056634; cv=none; b=GLZME9TU5TXkafKzhxliD8TB+zgm3YwqwF5UFXBZ5UEODu/UDjh7LwTYz8tPL3ZXQtVEo2GxeSuRY7NsdgOAOPDViAQif6qBHhwCXzPdFgDNutCrdQ/Y3td/RpV5hAN9/nU0uh9a3hKyG4ibuBFdhuHqlyDORDRXr1dNhc+Ell8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056634; c=relaxed/simple; bh=IBiqOJrVjNjDKaz5y8ARXywOWvCMKwjrfiOMMbLXtzM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iloOpYvV2Kl+gdtCAahxHQBisCiXMRD4cYjjyz3ul2QyklSs703tIPEmRRTZTG8SZvAAasP2EQN39IdTuhAGgZsJJElgkL8Kzz1/JgMq3D2/v0nkP8WXwOIu+g670jRq2IYCXNW+91mCBQcckWd+6wFZo8wvd6nS9hy/67WJ4QU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Eoyarmk2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Eoyarmk2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4F8FEC4CEC6; Fri, 4 Oct 2024 15:43:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056634; bh=IBiqOJrVjNjDKaz5y8ARXywOWvCMKwjrfiOMMbLXtzM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Eoyarmk2KG+SUowJp1Ym3nmczdQguqMr0OdYG7jPc+BocVKELOy8LxEfTgsE0tCkr vQFSiX5Al0/2nZGX+YX/CN2ALD6iKOcaMI+jhF/QaqftyRR3HgtKeGIa66ouPwtc9l xj8JDKWOH+votd53/VlKzJkOFMBTM0uIIqIl/SJQZphZ4WYMTg8O12Uv6gfc/96l0U 61hS72Nae9c1eBYKHK89CtolEehenOPW9u6JhYWCIZKD0mRbEPTzWf6mI7SWxAN6no sEJq5k938MgzzxC465odYDYyPopbvfh1vYZXbO3wEBq9QCvpvpVtvIJIziKW2cTq5J uEsB/gO7OfdZg== From: Danilo Krummrich 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 Subject: [PATCH v9 20/29] rust: alloc: remove `VecExt` extension Date: Fri, 4 Oct 2024 17:41:24 +0200 Message-ID: <20241004154149.93856-21-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that all existing `Vec` users were moved to the kernel `Vec` type, remove the `VecExt` extension. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 - rust/kernel/alloc/vec_ext.rs | 185 ----------------------------------- rust/kernel/prelude.rs | 5 +- 3 files changed, 1 insertion(+), 190 deletions(-) delete mode 100644 rust/kernel/alloc/vec_ext.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 1d57bfe2acb1..e8955340fe62 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -7,7 +7,6 @@ pub mod kbox; pub mod kvec; pub mod layout; -pub mod vec_ext; =20 #[cfg(any(test, testlib))] pub mod allocator_test; diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs deleted file mode 100644 index 1297a4be32e8..000000000000 --- a/rust/kernel/alloc/vec_ext.rs +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Extensions to [`Vec`] for fallible allocations. - -use super::{AllocError, Flags}; -use alloc::vec::Vec; - -/// Extensions to [`Vec`]. -pub trait VecExt: Sized { - /// Creates a new [`Vec`] instance with at least the given capacity. - /// - /// # Examples - /// - /// ``` - /// let v =3D Vec::::with_capacity(20, GFP_KERNEL)?; - /// - /// assert!(v.capacity() >=3D 20); - /// # Ok::<(), Error>(()) - /// ``` - fn with_capacity(capacity: usize, flags: Flags) -> Result; - - /// Appends an element to the back of the [`Vec`] instance. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// assert_eq!(&v, &[1]); - /// - /// v.push(2, GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 2]); - /// # Ok::<(), Error>(()) - /// ``` - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>; - - /// Pushes clones of the elements of slice into the [`Vec`] instance. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// - /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 20, 30, 40]); - /// - /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]); - /// # Ok::<(), Error>(()) - /// ``` - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(= ), AllocError> - where - T: Clone; - - /// Ensures that the capacity exceeds the length by at least `addition= al` elements. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// - /// v.reserve(10, GFP_KERNEL)?; - /// let cap =3D v.capacity(); - /// assert!(cap >=3D 10); - /// - /// v.reserve(10, GFP_KERNEL)?; - /// let new_cap =3D v.capacity(); - /// assert_eq!(new_cap, cap); - /// - /// # Ok::<(), Error>(()) - /// ``` - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), A= llocError>; -} - -impl VecExt for Vec { - fn with_capacity(capacity: usize, flags: Flags) -> Result { - let mut v =3D Vec::new(); - >::reserve(&mut v, capacity, flags)?; - Ok(v) - } - - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { - >::reserve(self, 1, flags)?; - let s =3D self.spare_capacity_mut(); - s[0].write(v); - - // SAFETY: We just initialised the first spare entry, so it is saf= e to increase the length - // by 1. We also know that the new length is <=3D capacity because= of the previous call to - // `reserve` above. - unsafe { self.set_len(self.len() + 1) }; - Ok(()) - } - - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(= ), AllocError> - where - T: Clone, - { - >::reserve(self, other.len(), flags)?; - for (slot, item) in core::iter::zip(self.spare_capacity_mut(), oth= er) { - slot.write(item.clone()); - } - - // SAFETY: We just initialised the `other.len()` spare entries, so= it is safe to increase - // the length by the same amount. We also know that the new length= is <=3D capacity because - // of the previous call to `reserve` above. - unsafe { self.set_len(self.len() + other.len()) }; - Ok(()) - } - - #[cfg(any(test, testlib))] - fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), = AllocError> { - Vec::reserve(self, additional); - Ok(()) - } - - #[cfg(not(any(test, testlib)))] - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), A= llocError> { - let len =3D self.len(); - let cap =3D self.capacity(); - - if cap - len >=3D additional { - return Ok(()); - } - - if core::mem::size_of::() =3D=3D 0 { - // The capacity is already `usize::MAX` for SZTs, we can't go = higher. - return Err(AllocError); - } - - // We know cap is <=3D `isize::MAX` because `Layout::array` fails = if the resulting byte size - // is greater than `isize::MAX`. So the multiplication by two won'= t overflow. - let new_cap =3D core::cmp::max(cap * 2, len.checked_add(additional= ).ok_or(AllocError)?); - let layout =3D core::alloc::Layout::array::(new_cap).map_err(|_= | AllocError)?; - - let (old_ptr, len, cap) =3D destructure(self); - - // We need to make sure that `ptr` is either NULL or comes from a = previous call to - // `krealloc_aligned`. A `Vec`'s `ptr` value is not guaranteed = to be NULL and might be - // dangling after being created with `Vec::new`. Instead, we can r= ely on `Vec`'s capacity - // to be zero if no memory has been allocated yet. - let ptr =3D if cap =3D=3D 0 { - core::ptr::null_mut() - } else { - old_ptr - }; - - // SAFETY: `ptr` is valid because it's either NULL or comes from a= previous call to - // `krealloc_aligned`. We also verified that the type is not a ZST. - let new_ptr =3D unsafe { super::allocator::krealloc_aligned(ptr.ca= st(), layout, flags) }; - if new_ptr.is_null() { - // SAFETY: We are just rebuilding the existing `Vec` with no c= hanges. - unsafe { rebuild(self, old_ptr, len, cap) }; - Err(AllocError) - } else { - // SAFETY: `ptr` has been reallocated with the layout for `new= _cap` elements. New cap - // is greater than `cap`, so it continues to be >=3D `len`. - unsafe { rebuild(self, new_ptr.cast::(), len, new_cap) }; - Ok(()) - } - } -} - -#[cfg(not(any(test, testlib)))] -fn destructure(v: &mut Vec) -> (*mut T, usize, usize) { - let mut tmp =3D Vec::new(); - core::mem::swap(&mut tmp, v); - let mut tmp =3D core::mem::ManuallyDrop::new(tmp); - let len =3D tmp.len(); - let cap =3D tmp.capacity(); - (tmp.as_mut_ptr(), len, cap) -} - -/// Rebuilds a `Vec` from a pointer, length, and capacity. -/// -/// # Safety -/// -/// The same as [`Vec::from_raw_parts`]. -#[cfg(not(any(test, testlib)))] -unsafe fn rebuild(v: &mut Vec, ptr: *mut T, len: usize, cap: usize) { - // SAFETY: The safety requirements from this function satisfy those of= `from_raw_parts`. - let mut tmp =3D unsafe { Vec::from_raw_parts(ptr, len, cap) }; - core::mem::swap(&mut tmp, v); -} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 80223cdaa485..07daccf6ca8e 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,10 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, KVVec,= KVec, VBox, VVec}; - -#[doc(no_inline)] -pub use alloc::vec::Vec; +pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec= }; =20 #[doc(no_inline)] pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable}; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 80B6F2216BF; Fri, 4 Oct 2024 15:44:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056640; cv=none; b=YkgZoQbH5r1rJpI8TTdibbuEtTaFpc/cNBZMQ96V6+omz8rT90GUKfuhD5qu+zCCtk/93VmbD+0tv/zphRhY2ax7JBY1UKFF3hoAq/sGO/yIVl9hViCDtc7f1jlSl0vHSooSxR8kDy3Db/t1KCSSjgHg2vKBr27XRHgjVqGezjM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056640; c=relaxed/simple; bh=ZNs0Dj/ExXP/FTdJ3MujwXiT4/A3eVE5pzPxpi0CaOY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TX7jmIRKr/5mnrFrchdhkLXnxqG5TSBTSpYCRCLDN/MI8TCIHzbfVK/GU6fkEOvQzfx30dubUhnXRB/JlaLGaMbDuftpOOxLmkAeYAscZgRxuk0GpaLc32aJ5NV327Z27dX/nF+sc+pz2HbpqKHfeBLYwfAOr1tYegkM9t04A1Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=naxFRuUs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="naxFRuUs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 12092C4CED4; Fri, 4 Oct 2024 15:43:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056640; bh=ZNs0Dj/ExXP/FTdJ3MujwXiT4/A3eVE5pzPxpi0CaOY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=naxFRuUsVrevYd57QkeZy71i1FomL2fbRGU99i6Eh4OdJhiBcD++cCd7C4lZZ6t6l J13m9IC9seV1XcxefMzLNy6XnqX5JtRiasb1Lxflmkb359reiUagWZUxFke+M9Jhag rITOiBJu/rhFJ+UBXkRFf4Jy900Sw2dU/yYly44Pgh1bm1fJ0h/fmvBTYHcIg69vA7 oCDZqjN6iNov7iYvNUiLF3rgYhcXkRdzrVLT3i0o2jI3oyohGXhXO5VzVo/Ggq+eCU jdOl5SBpFNmasg7O04LxeChbme/vLh8PcoLmClEUB6EZwAvt1gI1+VeBQFe4prdEn/ GtHC+mUKMSV1A== From: Danilo Krummrich 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 Subject: [PATCH v9 21/29] rust: alloc: add `Vec` to prelude Date: Fri, 4 Oct 2024 17:41:25 +0200 Message-ID: <20241004154149.93856-22-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that we removed `VecExt` and the corresponding includes in prelude.rs, add the new kernel `Vec` type instead. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/prelude.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 07daccf6ca8e..8bdab9aa0d16 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec= }; +pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec= , Vec}; =20 #[doc(no_inline)] pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable}; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6A741E2849; Fri, 4 Oct 2024 15:44:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056646; cv=none; b=ghJcxqL25ypktUFFnnp3jKV8jfUTbIqHW4PMe/TZbFB0FRniP9PswHdxiaMdp04wd7SlxfgGlWZIYgI9VAV1TNpJJ6fjr+ALsop+kDv7Ot8BfQJZDIWMPf6MmmerHE43zFlzzr2GM25Mrsmq1kg4vF2amlk1XY1wYt/hAMmRSuE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056646; c=relaxed/simple; bh=qja4/b6sVnAwfQIKsU5lFy64XWyVYKZfs5Hg8rSPng8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gW3dM2FjQxvNczA/sVeITDAxNIdxNGsyuVOjYLLBwjwTUW45t/VF0YBd8TPkyJw9QPgJqM3Ix755VmWGrM4CDk/DISQ4qljVCpz4BXt41AakeGo2/VsYZg84IIFJi1U3sgxtqJyt2b1pj6XwqPA6/0A/5HK2638mSO2vL7riSss= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VtrLQqOW; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VtrLQqOW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD494C4CEC6; Fri, 4 Oct 2024 15:44:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056646; bh=qja4/b6sVnAwfQIKsU5lFy64XWyVYKZfs5Hg8rSPng8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VtrLQqOWPhsua2MiiwHzfBRPtDZBUM4nukUln7OZcH+uO8VGfzl9qTUcUMQ8O8sHx /ZQ5pQgnEhXA9wmaNudiiSJoWSZOzdV/+hTQzbtIStWz7jbFltFtR+/T8VpzqtMh4Z 7QdhrRnqgG6sQDDwPVnGcLPxpGi3oDjR3OJ7ZYZIt13f6QS5wu2uMEWRqKhPucUtZn tRGYA0j1FyATkN+gUk6kfxXg9ZfLOHlGinUq2UQGUNDm6zqb9P5qFkgTvECWlClxXK 6Us3ipus/DIagEIP8Gb5Lx2uB2nRZSnjTNhIBJmwB/LNx8kmOFSUz7C5ONTyktziYJ bX6v3bR1AVziA== From: Danilo Krummrich 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 Subject: [PATCH v9 22/29] rust: error: use `core::alloc::LayoutError` Date: Fri, 4 Oct 2024 17:41:26 +0200 Message-ID: <20241004154149.93856-23-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use `core::alloc::LayoutError` instead of `alloc::alloc::LayoutError` in preparation to get rid of Rust's alloc crate. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 2f1e4b783bfb..ca957bd262df 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -6,7 +6,7 @@ =20 use crate::{alloc::AllocError, str::CStr}; =20 -use alloc::alloc::LayoutError; +use core::alloc::LayoutError; =20 use core::fmt; use core::num::TryFromIntError; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AC1E1E285B; Fri, 4 Oct 2024 15:44:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056652; cv=none; b=FSVtwPVDZRgjAJcWrLUKHTnF89npzEa1w8zTQJrkPPawp4PTTcP8FfYLvjCGD8kMcH4A2ZFcQazioF+dHW4Ecn/Tk1bt8IqN8chvqtb95GUQeX4u8rKa5pp2BR/pBt1eT8FHDMb1R1RgpqN2Duo/sYLaG2R+n2K5MOCTghGB5/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056652; c=relaxed/simple; bh=VajjPpTKjd92I7r04pL25dRwn4WQWZ1yOCCgBSYIXyw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sp2xEGn6nntzaWgNlzT7UIFT7QvA7GcbkfnAVPk4QDu9K4l22HjBV4J2DRWHefB/qW5JsM771uM93U1tTthiTESNJlRTltWxs8cGd9avR7LgHmd2QXBCJetD9WbupRuBCfvW3QfLz3P3Z2aM9YZGSwqwgW0sciUsbPfHcZycWRs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HPfYaikd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HPfYaikd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DFC5DC4CECF; Fri, 4 Oct 2024 15:44:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056652; bh=VajjPpTKjd92I7r04pL25dRwn4WQWZ1yOCCgBSYIXyw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HPfYaikd0L/Vx+JqKeDTWx4hMoyf5HUOadWTknz+gONqrexWgDlw1ZuDMy1brwY88 GtyfW1b2JKLCI1bQN6crBsF7amgUYsB1MNPSbPzIToO8N7xZ1iB+tvWogaPb/pis6E 7scY361XwbntTfDE+WcJS9wSd62G0hKmXzmkaiwFcfelOZfj16trTfEETlcaW6nxSt pi2ABhYIO9QggEAtYzZheUDGuPHsVMqacsseRUGKmHuUhUtOIwS4Vh+jS+0AujyAo+ JR8dVh76tKj5pcblkzaTkc2uvj6D97PC3eLEf5hAmjPyZjlN9YJTXlwMcQQvmjWyMf P/hOEN+8Mty6Q== From: Danilo Krummrich 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 Subject: [PATCH v9 23/29] rust: error: check for config `test` in `Error::name` Date: Fri, 4 Oct 2024 17:41:27 +0200 Message-ID: <20241004154149.93856-24-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Additional to `testlib` also check for `test` in `Error::name`. This is required by a subsequent patch that (indirectly) uses `Error` in test cases. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index ca957bd262df..99d505cd5ae1 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -142,7 +142,7 @@ pub fn to_ptr(self) -> *mut T { } =20 /// Returns a string representing the error, if one exists. - #[cfg(not(testlib))] + #[cfg(not(any(test, testlib)))] pub fn name(&self) -> Option<&'static CStr> { // SAFETY: Just an FFI call, there are no extra safety requirement= s. let ptr =3D unsafe { bindings::errname(-self.0) }; @@ -159,7 +159,7 @@ pub fn name(&self) -> Option<&'static CStr> { /// When `testlib` is configured, this always returns `None` to avoid = the dependency on a /// kernel function so that tests that use this (e.g., by calling [`Re= sult::unwrap`]) can still /// run in userspace. - #[cfg(testlib)] + #[cfg(any(test, testlib))] pub fn name(&self) -> Option<&'static CStr> { None } --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36EE41C729E; Fri, 4 Oct 2024 15:44:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056659; cv=none; b=VX50kEfdkJJjhLO2atS9sXruNbtM1h7JR4XHu+/VGNBaNzmsv3DN44ROdsP4HI+7ZM9bZ3UrQedMZt8db2gauWlUJPrZyHMG2ZWpt5f2jkt9osxVi+ehndhASBxs95fNpGft3LlBTmr4TaOvLIFNp5YbCfICifDLjnggRdyMd3c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056659; c=relaxed/simple; bh=ZDmHNLUIwFFHS+R3VBXXGD9KVgIi1Tkfsy4gCUrqKAQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G8E+2HdLSekv29pWFTSDfL48hUc3u09n/zdvhwqB/L9XZ4FleW2AoomdXecgGBpqyS1ZmLthF7kB+tOwaGbMl+0XffZM5S3VBuAY0Cy9L2ezyQE3DOowRxB+JJ/9QfSk6JfzypivFFHFoQQsRZFVc5unmpU1fSTKukWCgMd3Sps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m/1oasy2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="m/1oasy2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C6F94C4CED0; Fri, 4 Oct 2024 15:44:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056657; bh=ZDmHNLUIwFFHS+R3VBXXGD9KVgIi1Tkfsy4gCUrqKAQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m/1oasy24Cg4tn73r5ay0ehOqtkvBqrOSpcYKK3cBYeqKnDuemnNCxap5ZpiTC1ky 8yY41UMuGwH4SHMAt8L9/bkl2mU0Ldiq36xAcZn9oRXdGrODP0ctZdz2E9s9RzL/As ffZt9RiMcsOvJtoIM59/Dxhh3g2xGB37pDSiyRQnGsBXXL8ov+s4SBV8+gpxYUo0aE I8sshYOkrsW+17NczK26zO1xu4nFjgyWR4HzbZCOm8vIG8kdCPsYnJ90J1n1p94kte OAwnDbfF9i/+9HC+bSZBHW12/Tlw88mUSlnfcwluRSpKXQYq2sSEFyJke/ZCPEY6ra 1PuZUwr/XS+1w== From: Danilo Krummrich 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 Subject: [PATCH v9 24/29] rust: alloc: implement `contains` for `Flags` Date: Fri, 4 Oct 2024 17:41:28 +0200 Message-ID: <20241004154149.93856-25-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Provide a simple helper function to check whether given flags do contain one or multiple other flags. This is used by a subsequent patch implementing the Cmalloc `Allocator` to check for __GFP_ZERO. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index e8955340fe62..8acaa24a8f1f 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -35,7 +35,7 @@ /// They can be combined with the operators `|`, `&`, and `!`. /// /// Values can be used from the [`flags`] module. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub struct Flags(u32); =20 impl Flags { @@ -43,6 +43,11 @@ impl Flags { pub(crate) fn as_raw(self) -> u32 { self.0 } + + /// Check whether `flags` is contained in `self`. + pub fn contains(self, flags: Flags) -> bool { + (self & flags) =3D=3D flags + } } =20 impl core::ops::BitOr for Flags { --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D1472225A0; Fri, 4 Oct 2024 15:44:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056663; cv=none; b=IGMFVDOvSLjfoPlyTHCcYEt0OdALTKFp/0ygDxacw4O3pnfcOCkwp2kQqoWAmSeU0Oyfsbnaz1N4zN+hajH7IFBNuYkbO0BW7cBUEGnrN4wzN6UHbbTkQMoAakdvJyhN3nMrEc7vbrwjPyQHUOWRcbytOq7ZwbrJEnAh0ClXei0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056663; c=relaxed/simple; bh=co+B+qJ8g94Julx8Nci+IYL+QVSNE672qLhlTjw/JNg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dTWnWzZga8k9n3rL2XPPDTwiKu+4sK+XlpZoDY1aKrzYx6/SFH7lRY2aXdQXDW5Aw/nnUvhV5gRenJEhxXbd7nRoUMV0bi/UNs23IzCEOVvy5EO7F0uGFRp/dV7UDi4ayXfcgPvhVeofkWQAcxpRj6HX0LGA+4n6uB8EfVppFLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=isdAQEK+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="isdAQEK+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5594AC4CEC6; Fri, 4 Oct 2024 15:44:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056663; bh=co+B+qJ8g94Julx8Nci+IYL+QVSNE672qLhlTjw/JNg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=isdAQEK+fyU9LQiPmikCYp+he+tsGnTfNWAcIIkeyh6V5XNcGEHFQYit/ZlRDcAa2 IOa1mMRJ6iOotZftnaTIpKf1+8I1A3Hg/20Da19AY13ysIGSwD2d6wdd9//ouP18cz y0vK4k+8CyjavjrnlM+d4IT9RtcikiE1zAT01ZjYBvp2LjtiMNLnYUBi+tMpu9okhH 5o0W0NG6ln3yvuNyu4svUcpGRnWXsdthSUKYBLl5LxTgriaBcAVdVYh1O90kT6E8zM 5+MyZjCtVE8HQAt0w4vXmUNmEaGCrcmgt79gmeSW+lbC0PhJyxa1jKO7Uuym76dtZO rkkHlrWKeoMAg== From: Danilo Krummrich 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 Subject: [PATCH v9 25/29] rust: alloc: implement `Cmalloc` in module allocator_test Date: Fri, 4 Oct 2024 17:41:29 +0200 Message-ID: <20241004154149.93856-26-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- 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/alloca= tor_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 =20 +//! So far the kernel's `Box` and `Vec` types can't be used by userspace t= est cases, since all users +//! of those types (e.g. `CString`) use kernel allocators for instantiatio= n. +//! +//! In order to allow userspace test cases to make use of such types as we= ll, implement the +//! `Cmalloc` allocator within the allocator_test module and type alias al= l kernel allocators to +//! `Cmalloc`. The `Cmalloc` allocator uses libc's realloc() function as a= llocator backend. + #![allow(missing_docs)] =20 -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; =20 -pub struct Kmalloc; +/// The userspace allocator based on libc. +pub struct Cmalloc; + +pub type Kmalloc =3D Cmalloc; pub type Vmalloc =3D Kmalloc; pub type KVmalloc =3D Kmalloc; =20 -unsafe impl Allocator for Kmalloc { +extern "C" { + #[link_name =3D "aligned_alloc"] + fn libc_aligned_alloc(align: usize, size: usize) -> *mut core::ffi::c_= void; + + #[link_name =3D "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 `Alloc= ator` is always OK, +// - `realloc` provides the guarantees as provided in the `# Guarantees` s= ection. +unsafe impl Allocator for Cmalloc { unsafe fn realloc( - _ptr: Option>, - _layout: Layout, - _flags: Flags, + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, ) -> Result, AllocError> { - panic!(); + let src =3D match ptr { + Some(src) =3D> { + if old_layout.size() =3D=3D 0 { + ptr::null_mut() + } else { + src.as_ptr() + } + } + None =3D> ptr::null_mut(), + }; + + if layout.size() =3D=3D 0 { + // SAFETY: `src` is either NULL or was previously allocated wi= th 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 =3D unsafe { libc_aligned_alloc(layout.align(), layout.siz= e()) } as *mut u8; + let dst =3D NonNull::new(dst).ok_or(AllocError)?; + + if flags.contains(__GFP_ZERO) { + // SAFETY: The preceeding calls to `libc_aligned_alloc` and `N= onNull::new` + // guarantee that `dst` points to memory of at least `layout.s= ize()` 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 r= eads 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 t= his `Allocator` + unsafe { libc_free(src.cast()) }; + + Ok(NonNull::slice_from_raw_parts(dst, layout.size())) } } --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C86C52225D1; Fri, 4 Oct 2024 15:44:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056668; cv=none; b=H8picMCv5P3pxVrCafWh/AzsQMUnfPeAmb0O3oLxqqXVxG8ZqCitbkiKtVYC3w8ZVHrf0vUM6geczK+eUKvJia30kXQQ+UVmddgh+8dEXbB63wgldkasxXuGXhFNSKdhg+EbjjAU/gbzNufNeJaiPcGZfxn7vJaV+nbx2xhcGvk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056668; c=relaxed/simple; bh=+flMXZQfIhSSa3rmdG7sm/b2ESf50jZzxj0uBuhzVdQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FG8uaM2eMtI/ei2DaeEVmh7iAulPePLPirUMTS1QiVvMvazLNiYirqRbtH79/jRUdEuz0p3OOyy0neJGj7K7yTvjoTOZOaKkr4IvjTTH1wBMfdaHq7ZS1C3hAcCFUn2EsVJJugaQY2t8pP++Fgn7M1Oyd0m/B/z1ZQGGtqnhisg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fnNeEXxR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fnNeEXxR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B8C23C4CEC7; Fri, 4 Oct 2024 15:44:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056668; bh=+flMXZQfIhSSa3rmdG7sm/b2ESf50jZzxj0uBuhzVdQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fnNeEXxR7mvP92yIfBbZLKQgeMPUx20LLtjjEtRpZbG5b21h9I1Q266YhULU7we5G nIKnt7Ig2nVe5gPYYo/WacZZO+8P/BkpLtAFIfmf5m6S5lMNkXsZJ4yTPSmqgK7scw /kUUR7mXbJJ8XXO3LP2dNem62eLLl2KpL1XH3Xle8t6v18Drlsi691bL1jeRJWyQR7 4cxmM1JClD1M0QJ2FXgsJ/ZrZEQRzaQYn9D+5MrpBEY9ABXsinpdgYKX9rn2EjyRUz pNO82/M6amgupFvVov/hqqXNHS/+rEi1aMJOiy/7d+sQYdu0oHywrQ7+1ynfWF9luu TmZWjk4vJOhrA== From: Danilo Krummrich 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 Subject: [PATCH v9 26/29] rust: str: test: replace `alloc::format` Date: Fri, 4 Oct 2024 17:41:30 +0200 Message-ID: <20241004154149.93856-27-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current implementation of tests in str.rs use `format!` to format strings for comparison, which, internally, creates a new `String`. In order to prepare for getting rid of Rust's alloc crate, we have to cut this dependency. Instead, implement `format!` for `CString`. Note that for userspace tests, `Kmalloc`, which is backing `CString`'s memory, is just a type alias to `Cmalloc`. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/str.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 6053bc7a98d1..aff6baa521d4 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -524,7 +524,28 @@ macro_rules! c_str { #[cfg(test)] mod tests { use super::*; - use alloc::format; + + struct String(CString); + + impl String { + fn from_fmt(args: fmt::Arguments<'_>) -> Self { + String(CString::try_from_fmt(args).unwrap()) + } + } + + impl Deref for String { + type Target =3D str; + + fn deref(&self) -> &str { + self.0.to_str().unwrap() + } + } + + macro_rules! format { + ($($f:tt)*) =3D> ({ + &*String::from_fmt(kernel::fmt!($($f)*)) + }) + } =20 const ALL_ASCII_CHARS: &'static str =3D "\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d= \\x0e\\x0f\ --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 371AF1E32B7; Fri, 4 Oct 2024 15:44:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056674; cv=none; b=UacwhYrNNp+hroKcLwKLnNGtxq0APf8eE5U8Ac6Q8WZcouB227Eee1LOaHBSwNMbK6xekf845ANYlfdqW1hJbvVIRd7cSlXcg556Cko/RyK6kRqnVjS/U/GCdIv7T2Oul1qy4a7sbZYTSq65IalhKz7ladxGPglAQP1f61aHU6o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056674; c=relaxed/simple; bh=GR6bCjuYYHRgHCOsPDduyYPPq8CvkGfa1JPMMj7rInU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=geWfZM0MtmNKj0AMbyO4nIF+cSLN6xSFF4norRdZXnKEEzokBiY6EKcTzlhJyNpaCiKCO1fyhDbbOkARx4F9Ciz3KbjgeZSwfb35krAIXtQLlpx16lsOYLtHy5UO7gey/NdU5alJWG32TL5qtlrK3Z1AdUsUZJ6590mSskKf/A4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HInwzaMg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HInwzaMg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2632AC4CEC6; Fri, 4 Oct 2024 15:44:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056674; bh=GR6bCjuYYHRgHCOsPDduyYPPq8CvkGfa1JPMMj7rInU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HInwzaMg4J2W7s1jrkgNdeeywo/XEmyb9ionzx1z7DF543TSyLE5cmftSnOF4QSj+ 6r9x5wDRez306psxF3BKCgCH96wCu1MU5YU4GygFh36+FmUef6U8xv+b9V0tcKM7Eu OUpq6xZDzJz63Jili2hXOHV1eiGiWCy/G/aL4dTfnTmhn+Dcjx0ERts9kBPhDSQhNK pOC1l7WQ3f1YFq6tblCtZQi82nJa3DCrdQDfXLlgx3MwcwdIbtfOJbyNYnGoNXnyKp MGU5BspVs3/hpEf7o65ljYnzndSi7AIqY86E00RcksQQPufiCG9hhsJPdrbelIAMOA EWy2hs58e3Cyg== From: Danilo Krummrich 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 Subject: [PATCH v9 27/29] rust: alloc: update module comment of alloc.rs Date: Fri, 4 Oct 2024 17:41:31 +0200 Message-ID: <20241004154149.93856-28-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Before we remove Rust's alloc crate, rewrite the module comment in alloc.rs to avoid a rustdoc warning. Besides that, the module comment in alloc.rs isn't correct anymore, we're no longer extending Rust's alloc crate. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 8acaa24a8f1f..b4e65454e695 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 =20 -//! Extensions to the [`alloc`] crate. +//! Implementation of the kernel's memory allocation infrastructure. =20 #[cfg(not(any(test, testlib)))] pub mod allocator; --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECDB71DAC84; Fri, 4 Oct 2024 15:44:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056680; cv=none; b=sZ+6SjM6EP2ORf4kgyQShLAkfSyY+PKg+pFwZtMriD1d2kxwgi+b7YuwzMtPdLBTr5lYtwo2TAGYZfrlSxOMR6O1ezmMJjm6SIoYDk6p4cJHel1L+QeCNM0m2D/zb60fMUDm39Dc+6Nybrpqvfe5H2TBqcddImKp0KYMXp0eMkA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056680; c=relaxed/simple; bh=o672VVH3AmvwpLuEYS8c++RfA9LDqdgouc73MUW9aPw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dAUzfAjJHbnON1JUOhc6hgb4WCUFZ/DD0nbv1mtxcThqmXRhkW6tLaO9GypR9WiwNeUKF1bpkgn3vLikvtftxF9KYbaDU7JrgYuAIM62Li9MAXnlLdtgXA+Nm31ne67ae1zudCEuL+IyzSHjUhkFvfAf4P85TrKip5VZ/jZBgIY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=idrN8R3f; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="idrN8R3f" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8B9FFC4CECE; Fri, 4 Oct 2024 15:44:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056679; bh=o672VVH3AmvwpLuEYS8c++RfA9LDqdgouc73MUW9aPw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=idrN8R3fHUStsOpR9WkFppMYshHLSeMsQMDZRS0zWz9IL3jb+lWGY4FL+g86NT39B cHqWMrkYi89dyJSJR4/GhDW7SO5wD5DxiJMv/yMXTbtoC4gnJKzJX85o0EsaxdHEm0 Kcfx/mAmf9LY7Jq6TS9OO44DX+bj97zNgInmTu3VLuCMQBK2JCu3mGc1SAamIikoHK WP4ouzpb5w+ZzfeQSpu7CoSMId6JBZtW7yMQd0FSmVqgrYznD8PZopFfV3XlIrupnH MN6mfhlLfg6qFzRZZSke/8jk6OUq3pJQR0t31VcNzeIf4oP3vatHFuyY8VZTLblFyM bzEcjkvWs0DdA== From: Danilo Krummrich 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 Subject: [PATCH v9 28/29] kbuild: rust: remove the `alloc` crate and `GlobalAlloc` Date: Fri, 4 Oct 2024 17:41:32 +0200 Message-ID: <20241004154149.93856-29-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that we have our own `Allocator`, `Box` and `Vec` types we can remove Rust's `alloc` crate and the `new_uninit` unstable feature. Also remove `Kmalloc`'s `GlobalAlloc` implementation -- we can't remove this in a separate patch, since the `alloc` crate requires a `#[global_allocator]` to set, that implements `GlobalAlloc`. Signed-off-by: Danilo Krummrich --- rust/Makefile | 43 +++++--------------- rust/exports.c | 1 - rust/kernel/alloc/allocator.rs | 65 +------------------------------ scripts/Makefile.build | 4 +- scripts/generate_rust_analyzer.py | 11 +----- 5 files changed, 16 insertions(+), 108 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index 0856fd6bc610..3678e79317f1 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -15,8 +15,8 @@ always-$(CONFIG_RUST) +=3D libmacros.so no-clean-files +=3D libmacros.so =20 always-$(CONFIG_RUST) +=3D bindings/bindings_generated.rs bindings/binding= s_helpers_generated.rs -obj-$(CONFIG_RUST) +=3D alloc.o bindings.o kernel.o -always-$(CONFIG_RUST) +=3D exports_alloc_generated.h exports_helpers_gener= ated.h \ +obj-$(CONFIG_RUST) +=3D bindings.o kernel.o +always-$(CONFIG_RUST) +=3D exports_helpers_generated.h \ exports_bindings_generated.h exports_kernel_generated.h =20 always-$(CONFIG_RUST) +=3D uapi/uapi_generated.rs @@ -53,11 +53,6 @@ endif core-cfgs =3D \ --cfg no_fp_fmt_parse =20 -alloc-cfgs =3D \ - --cfg no_global_oom_handling \ - --cfg no_rc \ - --cfg no_sync - quiet_cmd_rustdoc =3D RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc =3D \ OBJTREE=3D$(abspath $(objtree)) \ @@ -81,7 +76,7 @@ quiet_cmd_rustdoc =3D RUSTDOC $(if $(rustdoc_host),H, ) $< # command-like flags to solve the issue. Meanwhile, we use the non-custom = case # and then retouch the generated files. rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ - rustdoc-alloc rustdoc-kernel + rustdoc-kernel $(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.= files/ $(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/sta= tic.files/ $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed = -Ei \ @@ -108,20 +103,11 @@ rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs FORCE rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE +$(call if_changed,rustdoc) =20 -# We need to allow `rustdoc::broken_intra_doc_links` because some -# `no_global_oom_handling` functions refer to non-`no_global_oom_handling` -# functions. Ideally `rustdoc` would have a way to distinguish broken links -# due to things that are "configured out" vs. entirely non-existing ones. -rustdoc-alloc: private rustc_target_flags =3D $(alloc-cfgs) \ - -Arustdoc::broken_intra_doc_links -rustdoc-alloc: $(RUST_LIB_SRC)/alloc/src/lib.rs rustdoc-core rustdoc-compi= ler_builtins FORCE - +$(call if_changed,rustdoc) - -rustdoc-kernel: private rustc_target_flags =3D --extern alloc \ +rustdoc-kernel: private rustc_target_flags =3D \ --extern build_error --extern macros=3D$(objtree)/$(obj)/libmacros.so \ --extern bindings --extern uapi rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \ - rustdoc-compiler_builtins rustdoc-alloc $(obj)/libmacros.so \ + rustdoc-compiler_builtins $(obj)/libmacros.so \ $(obj)/bindings.o FORCE +$(call if_changed,rustdoc) =20 @@ -165,7 +151,7 @@ quiet_cmd_rustdoc_test_kernel =3D RUSTDOC TK $< mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ OBJTREE=3D$(abspath $(objtree)) \ $(RUSTDOC) --test $(rust_flags) \ - -L$(objtree)/$(obj) --extern alloc --extern kernel \ + -L$(objtree)/$(obj) --extern kernel \ --extern build_error --extern macros \ --extern bindings --extern uapi \ --no-run --crate-name kernel -Zunstable-options \ @@ -201,7 +187,7 @@ rusttest-macros: $(src)/macros/lib.rs FORCE +$(call if_changed,rustc_test) +$(call if_changed,rustdoc_test) =20 -rusttest-kernel: private rustc_target_flags =3D --extern alloc \ +rusttest-kernel: private rustc_target_flags =3D \ --extern build_error --extern macros --extern bindings --extern uapi rusttest-kernel: $(src)/kernel/lib.rs \ rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \ @@ -314,9 +300,6 @@ quiet_cmd_exports =3D EXPORTS $@ $(obj)/exports_core_generated.h: $(obj)/core.o FORCE $(call if_changed,exports) =20 -$(obj)/exports_alloc_generated.h: $(obj)/alloc.o FORCE - $(call if_changed,exports) - # Even though Rust kernel modules should never use the bindings directly, # symbols from the `bindings` crate and the C helpers need to be exported # because Rust generics and inlined functions may not get their code gener= ated @@ -363,7 +346,7 @@ quiet_cmd_rustc_library =3D $(if $(skip_clippy),RUSTC,$= (RUSTC_OR_CLIPPY_QUIET)) L =20 rust-analyzer: $(Q)$(srctree)/scripts/generate_rust_analyzer.py \ - --cfgs=3D'core=3D$(core-cfgs)' --cfgs=3D'alloc=3D$(alloc-cfgs)' \ + --cfgs=3D'core=3D$(core-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \ $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json @@ -401,12 +384,6 @@ $(obj)/compiler_builtins.o: private rustc_objcopy =3D = -w -W '__*' $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE +$(call if_changed_rule,rustc_library) =20 -$(obj)/alloc.o: private skip_clippy =3D 1 -$(obj)/alloc.o: private skip_flags =3D -Wunreachable_pub -$(obj)/alloc.o: private rustc_target_flags =3D $(alloc-cfgs) -$(obj)/alloc.o: $(RUST_LIB_SRC)/alloc/src/lib.rs $(obj)/compiler_builtins.= o FORCE - +$(call if_changed_rule,rustc_library) - $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FOR= CE +$(call if_changed_rule,rustc_library) =20 @@ -421,9 +398,9 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \ $(obj)/uapi/uapi_generated.rs FORCE +$(call if_changed_rule,rustc_library) =20 -$(obj)/kernel.o: private rustc_target_flags =3D --extern alloc \ +$(obj)/kernel.o: private rustc_target_flags =3D \ --extern build_error --extern macros --extern bindings --extern uapi -$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \ +$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \ $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE +$(call if_changed_rule,rustc_library) =20 diff --git a/rust/exports.c b/rust/exports.c index e5695f3b45b7..82a037381798 100644 --- a/rust/exports.c +++ b/rust/exports.c @@ -16,7 +16,6 @@ #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym) =20 #include "exports_core_generated.h" -#include "exports_alloc_generated.h" #include "exports_helpers_generated.h" #include "exports_bindings_generated.h" #include "exports_kernel_generated.h" diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index d9043ca42ce5..067719f11d13 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -8,8 +8,8 @@ //! //! Reference: =20 -use super::{flags::*, Flags}; -use core::alloc::{GlobalAlloc, Layout}; +use super::Flags; +use core::alloc::Layout; use core::ptr; use core::ptr::NonNull; =20 @@ -54,23 +54,6 @@ fn aligned_size(new_layout: Layout) -> usize { layout.size() } =20 -/// Calls `krealloc` with a proper size to alloc a new object aligned to `= new_layout`'s alignment. -/// -/// # Safety -/// -/// - `ptr` can be either null or a pointer which has been allocated by th= is allocator. -/// - `new_layout` must have a non-zero size. -pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, fl= ags: Flags) -> *mut u8 { - let size =3D aligned_size(new_layout); - - // SAFETY: - // - `ptr` is either null or a pointer returned from a previous `k{re}= alloc()` by the - // function safety requirement. - // - `size` is greater than 0 since it's from `layout.size()` (which c= annot be zero according - // to the function safety requirement) - unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, fla= gs.0) as *mut u8 } -} - /// # Invariants /// /// One of the following `krealloc`, `vrealloc`, `kvrealloc`. @@ -156,43 +139,6 @@ unsafe fn realloc( } } =20 -// SAFETY: TODO. -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 s= ize by the function safety - // requirement. - unsafe { krealloc_aligned(ptr::null_mut(), layout, GFP_KERNEL) } - } - - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - // SAFETY: TODO. - unsafe { - bindings::kfree(ptr as *const core::ffi::c_void); - } - } - - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize= ) -> *mut u8 { - // SAFETY: - // - `new_size`, when rounded up to the nearest multiple of `layou= t.align()`, will not - // overflow `isize` by the function safety requirement. - // - `layout.align()` is a proper alignment (i.e. not zero and mus= t be a power of two). - let layout =3D unsafe { Layout::from_size_align_unchecked(new_size= , layout.align()) }; - - // SAFETY: - // - `ptr` is either null or a pointer allocated by this allocator= by the function safety - // requirement. - // - the size of `layout` is not zero because `new_size` is not ze= ro by the function safety - // requirement. - unsafe { krealloc_aligned(ptr, layout, GFP_KERNEL) } - } - - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero s= ize by the function safety - // requirement. - unsafe { krealloc_aligned(ptr::null_mut(), layout, GFP_KERNEL | __= GFP_ZERO) } - } -} - // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, @@ -240,10 +186,3 @@ unsafe fn realloc( unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flag= s) } } } - -#[global_allocator] -static ALLOCATOR: Kmalloc =3D Kmalloc; - -// See . -#[no_mangle] -static __rust_no_alloc_shim_is_unstable: u8 =3D 0; diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 64518c2f3d9c..2bba59e790b8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -248,7 +248,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE # Compile Rust sources (.rs) # ------------------------------------------------------------------------= --- =20 -rust_allowed_features :=3D arbitrary_self_types,lint_reasons,new_uninit +rust_allowed_features :=3D arbitrary_self_types,lint_reasons =20 # `--out-dir` is required to avoid temporaries being created by `rustc` in= the # current working directory, which may be not accessible in the out-of-tree @@ -258,7 +258,7 @@ rust_common_cmd =3D \ -Zallow-features=3D$(rust_allowed_features) \ -Zcrate-attr=3Dno_std \ -Zcrate-attr=3D'feature($(rust_allowed_features))' \ - -Zunstable-options --extern force:alloc --extern kernel \ + -Zunstable-options --extern kernel \ --crate-type rlib -L $(objtree)/rust/ \ --crate-name $(basename $(notdir $@)) \ --sysroot=3D/dev/null \ diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_anal= yzer.py index d2bc63cde8c6..09e1d166d8d2 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -64,13 +64,6 @@ def generate_crates(srctree, objtree, sysroot_src, exter= nal_src, cfgs): [], ) =20 - append_crate( - "alloc", - sysroot_src / "alloc" / "src" / "lib.rs", - ["core", "compiler_builtins"], - cfg=3Dcrates_cfgs.get("alloc", []), - ) - append_crate( "macros", srctree / "rust" / "macros" / "lib.rs", @@ -96,7 +89,7 @@ def generate_crates(srctree, objtree, sysroot_src, extern= al_src, cfgs): append_crate( "kernel", srctree / "rust" / "kernel" / "lib.rs", - ["core", "alloc", "macros", "build_error", "bindings"], + ["core", "macros", "build_error", "bindings"], cfg=3Dcfg, ) crates[-1]["source"] =3D { @@ -133,7 +126,7 @@ def generate_crates(srctree, objtree, sysroot_src, exte= rnal_src, cfgs): append_crate( name, path, - ["core", "alloc", "kernel"], + ["core", "kernel"], cfg=3Dcfg, ) =20 --=20 2.46.1 From nobody Thu Nov 14 03:56:40 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CA261DACA5; Fri, 4 Oct 2024 15:44:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056685; cv=none; b=lKc/mjyT2OEEmaI/SOALS8/Ninmc96GRoo3aFCIvggGIDARuQx7N9Kl3SWGbKDYA0NfyJxL0YDEUotIC1lDuFHL5Rytgc4hz52iRtDNrvdnhzYdTtTZYuETTHRLRc9DAJ/SOfr+UWYo03pjehb5F9VY9Ot47pseBIR96kL9jcyc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728056685; c=relaxed/simple; bh=LdzqPbgEKI128eCZYKb03oyNMyTA/dv0Gv7wqQmMX2Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=spyTb7K1aI3BWxPjqgxlFVete6rGcplGQclQedjLdrvylIcfyegk8FZTQj33b0x9lBeQT0uZC/CXhGSbY6c7DC0bAY9iyfFdPfshMd4jSac/mFVAI814ndTGGeqJ334FeK8edOHjzVshSF+F+b7JlxnC7ltv0s/OU/jublqV2Yo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BwEfrzFA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BwEfrzFA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC34AC4CEC6; Fri, 4 Oct 2024 15:44:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728056684; bh=LdzqPbgEKI128eCZYKb03oyNMyTA/dv0Gv7wqQmMX2Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BwEfrzFAPdp4OWI26Vyob0+ciU7heTInmH5hXtmwaC+7O3Pvo6QP8pRMhkfZCUh7W qmx00+qBV+Vk3YE6eIiTiigQRtr8Ur069zHII6bJEp3a8+jVrhgVnfTd9zPrxPkO6v HoTXtL/Nv1k5wa5fUd7csJhRgcIUbaVIwm4yn93X8bVoBDlb0DgISPoJ1HaRDCUOhj iW05DEBQo1hiA3F8fKTiHU0PnFbMTDK5XwV7RxHVY/oX0mEgu77q7Af+/t6NyoNW2W wviRjO1xkrf0ZonCjFrg84ILr1fRTAoOjyyyUslrzz7UDVekl42NGaiT0eHD7EZj9q SvMT1iEUYNPIQ== From: Danilo Krummrich 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 Subject: [PATCH v9 29/29] MAINTAINERS: add entry for the Rust `alloc` module Date: Fri, 4 Oct 2024 17:41:33 +0200 Message-ID: <20241004154149.93856-30-dakr@kernel.org> X-Mailer: git-send-email 2.46.1 In-Reply-To: <20241004154149.93856-1-dakr@kernel.org> References: <20241004154149.93856-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add maintainers entry for the Rust `alloc` module. Currently, this includes the `Allocator` API itself, `Allocator` implementations, such as `Kmalloc` or `Vmalloc`, as well as the kernel's implementation of the primary memory allocation data structures, `Box` and `Vec`. Signed-off-by: Danilo Krummrich --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 67f9f2b8bb50..aa3b124e4989 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20226,6 +20226,13 @@ F: scripts/*rust* F: tools/testing/selftests/rust/ K: \b(?i:rust)\b =20 +RUST [ALLOC] +M: Danilo Krummrich +L: rust-for-linux@vger.kernel.org +S: Maintained +F: rust/kernel/alloc.rs +F: rust/kernel/alloc/ + RXRPC SOCKETS (AF_RXRPC) M: David Howells M: Marc Dionne --=20 2.46.1