From nobody Sat Feb 7 15:09:42 2026 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 0D5151891D6; Mon, 12 Aug 2024 18:24:13 +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=1723487054; cv=none; b=Y/DcIAegMtxyXJwoUv6wRKsz9i/uTXYphY4cW16jOU0NRWnTJnrIQZ2ZHTIyz6goU3Vr8wxgXC0jsb9ygUjOedxZr9GB9CO/2LzEKMcc6VSRnv/IzG1rv/zempoORwzti9cb9fTXt9yNFuPBXfbQDJgMKbFTxm6fQhN5orus3ng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487054; c=relaxed/simple; bh=M1Wwvc1PMQiy2tSYLyMdNK6lKzi7oyHYDv/dPN7vzzs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BmnlSzur+yyKkurrz1hWI51wUpzbz1sWn1mBYAZzz9TYc4wIer/Po4lebWB8DtitmXi0R5ITxYUt0Qty20BYRf1gTe9lsJqhgDFIqYe83dwg2cxRMp1eu/ZicxZAAR07H14N9wwXdAul7j+geWCOCEcDS3AZ26TQ56mXfuMDi9A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y0S8qU3y; 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="Y0S8qU3y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8F796C4AF0C; Mon, 12 Aug 2024 18:24:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487053; bh=M1Wwvc1PMQiy2tSYLyMdNK6lKzi7oyHYDv/dPN7vzzs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y0S8qU3yW9xyw0FV2WFxe5tJ6xfV6A4RAetYAlao35rcuYSGc3kxSqYYOSIyvSGlg K8gPFxuu8eGEvuDuHp3ZV3P0n7swgSZjhvDt9zUqOVkjrhDqRVAi1HStM8lFhN5MNr nNuR0gbj94xcaN4MVpSpjulAxr4U5pGB7IsCuEUSxTatJDviLEojsaGJv6I80fmkEM wkossGl3of7NM3pu7JsEEQ7ht8amVK9+dr2vIUWHKOBt8uGBn/HHv21Z4IbjnTqNGD +AEzlU/2/bQ5SghHXgTa+OqtHrdSQbt2bzs4J9GWPWPGrO5IvTd9rPEFopHNBoBKWX 5l+1AxcAqop7Q== 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 v5 01/26] rust: alloc: add `Allocator` trait Date: Mon, 12 Aug 2024 20:22:47 +0200 Message-ID: <20240812182355.11641-2-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 1966bd407017..194745498a75 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,83 @@ 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 buffer 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 +/// +/// Memory returned from an allocator must point to a valid memory buffer = and remain valid until +/// it is explicitly freed. +/// +/// Any pointer to a memory buffer which is currently allocated must be va= lid to be passed to any +/// other [`Allocator`] function of the same type. +/// +/// If `realloc` is called with: +/// - a size of zero, the given memory allocation, if any, must be freed +/// - `None`, a new memory allocation must be created +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`. + 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, flags) } + } + + /// Re-allocate an existing memory allocation to satisfy the requested= `layout`. If the + /// requested size is zero, `realloc` behaves equivalent to `free`. + /// + /// 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 Some(p)`, then `p` must point to an existing and valid= memory allocation created + /// by this allocator. The alignment encoded in `layout` must be small= er than or equal to the + /// alignment requested in the previous `alloc` or `realloc` call of t= he same allocation. + /// + /// Additionally, `ptr` is allowed to be `None`; in this case a new me= mory allocation is + /// created. + unsafe fn realloc( + ptr: Option>, + layout: Layout, + flags: Flags, + ) -> Result, AllocError>; + + /// Free an existing memory allocation. + /// + /// # Safety + /// + /// `ptr` must point to an existing and valid memory allocation create= d by this `Allocator` and + /// must not be a dangling pointer. + /// + /// The memory allocation at `ptr` must never again be read from or wr= itten to. + unsafe fn free(ptr: NonNull) { + // 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::<()>(), F= lags(0)) }; + } +} --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 5546F1891D6; Mon, 12 Aug 2024 18:24:19 +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=1723487059; cv=none; b=DR6/P0ylGzpFUc89acYhMOAKYJzNFmvA5n+iMlVtJl7FyxLIMCYZOCnaHon4NuWMnj4NFnvRtKrR26tVoJ6KkJOey7EJ7XoOBadFeNXuws7Qrit3P1/o2ryovJZqE/YoOXRqgL1USG0rBzCBbGAeuat4OPkDb04qklijzC1RJlc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487059; c=relaxed/simple; bh=p++mQr6O15JhVUHtMmsU1D7fc1KQnWeRmH3GDyn4naw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aB0hdadmCD4CYF4PNNHP2T7D9VVHhqwPfn2AsO9vvbx2P0SfKjN9H0oFhsH3d7C9F5rICMAHN1CijVyesishgs+CZMFBUsTzyvyyyhzJc96QGbytZLiIWcDD2TYV5pNFQ9G/9FNB2DwmW4yfUH+R33jWVuZUy+9zcYgxTedNnmc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c0I8hd5A; 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="c0I8hd5A" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F08F9C4AF0D; Mon, 12 Aug 2024 18:24:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487058; bh=p++mQr6O15JhVUHtMmsU1D7fc1KQnWeRmH3GDyn4naw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c0I8hd5AqEtUJ1AqcltnJQJXgDifadIagb8OT4ht7RND3/LIpX13gvQjzt3gLQowI ftjf2eUBi+kRnz1lX7eL9vGAeiEQ8VSt/93xhlmq3bo51SkTTtLhVlA1JeSJlhL1vO kKy1fu1ZpAWRTSx0A6dHnPwjSFST7YO372xKlpVClxYIjCcUPHvkSj+fQ1ApyURzYL iEsA/zOqK25c8hP18hXK60sIIPLcYcpYrmTHnk0vQhpz7wJPKOG5cBX2AXOvB7Pt59 OuPvw6w4Pra2zExwy8Z5Xaqski4YFdaIJkkvFVea5Z2LMfKRfUtJYYqefeQFClV0Vt gsbOh1+Jy/6+Q== 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 v5 02/26] rust: alloc: separate `aligned_size` from `krealloc_aligned` Date: Mon, 12 Aug 2024 20:22:48 +0200 Message-ID: <20240812182355.11641-3-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 e6ea601f38c6..c83b6dff896d 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 C97591917C0; Mon, 12 Aug 2024 18:24:24 +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=1723487064; cv=none; b=PxbCJtSYWDRFsW9ub4Fap1Ttk2qmD4n63pce+atfCILlY1JCLsSqynO146Q5fPPEW9quip0kLoaJZ1aNgk688fOJFtO78PzZRoL0YKtvjtdV2cd6rAhiO7gdxOq39zGoLzkgQ9eZQ2vClfJl4BfrI3H++RJSAqN58yVmVvvL7do= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487064; c=relaxed/simple; bh=8oAuOdisYUjDdGnujzu+qdpGOC9b4wPMkAAnWfvuI7o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rQGOGfeuAfjIjhRGduUvgCZ9D/zRqSF6/E1uU6qJPj8s4q1e6Z/MB9ncPbCC1G2QjQuzrjDOA4aoYhrZnG+fICUCyMYN6A3bM3H8ZMmtZqK0VvFelXgUZs73hv1S8CY2rzLWXNranKnWstcl8shawipkdcoTd9O9eGjQ7Hx7Dr8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jwDjo9Cz; 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="jwDjo9Cz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63A19C4AF0F; Mon, 12 Aug 2024 18:24:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487064; bh=8oAuOdisYUjDdGnujzu+qdpGOC9b4wPMkAAnWfvuI7o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jwDjo9Cz4msrN2OFv+80NjQx4rMmA203HaSKUMopmbA9GF9wV37pGy0wmAtVUds1f KMhgSVyZ3/x3j2p/33Ix6HNljGcAKQlS+dFv8JEmhsHX80rI7/JAXQKKrfMmP2e5tH TTHy+3GPqdb2nFkTn4mLZKS0VspwdWH3/BdIKLZPMkqeR2xc4tgsPcMLywfYnui0fN mILcDkSB2mO9sY5G80rk+PeTOoAPDCQz3Vxlv2N1H6RhptAoytES93kq/BrFwUJRCa EnW1AdyGLUeQjxjWCaTInoiz4pVCEB5o2ZpTdlTiAMi03PmlgvurTvgjpWC+2J4RC7 a9LV7QnrU4Ngw== 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 v5 03/26] rust: alloc: rename `KernelAllocator` to `Kmalloc` Date: Mon, 12 Aug 2024 20:22:49 +0200 Message-ID: <20240812182355.11641-4-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 c83b6dff896d..e32182f91167 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 { @@ -36,7 +36,7 @@ pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_l= ayout: Layout, flags: F unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, fla= gs.0) as *mut u8 } } =20 -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. @@ -72,7 +72,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 45BF2192B89; Mon, 12 Aug 2024 18:24:29 +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=1723487070; cv=none; b=ohtu7BL4R2ZyXn3w5nll4ZHO0wIqi/79pCqLXOIvb3ynovnigI18hO00SIv+1VgSstWZuhxzHk8XzQZLiWodxFpjCm4vdsxZZ9u+OcgSdcx5oThV3Q9StbkaHGpxXT1PZ1DJSVQQWW25Y0nCQKUIHCL6WaiaRZC1+DGkzT2Szkc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487070; c=relaxed/simple; bh=gb9gRmfntU6sLvTnzwOy0nZzExJzcMuzdJXh+XZXxrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ecQdvdPl8fUi1+5Dc0TBvit+uwWUg4Q+g8sZCdb7QoDexB+d5dCT3Sd8Ure6KyAbkPxmwz+4U4uCDEZEgmO7dP46ymfrHV+rgL8O2EfefOJDZtgrb1YsaOYD3ZwTSlJab7vgLmAyaRNzrsnOeTaw+NiKhMVoRyVzmkyPVECp4Cg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ax0ovfo+; 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="ax0ovfo+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C61ADC4AF09; Mon, 12 Aug 2024 18:24:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487069; bh=gb9gRmfntU6sLvTnzwOy0nZzExJzcMuzdJXh+XZXxrI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ax0ovfo+JPuw2LDf+OJPpzMSsXQE9YksuOJXuCo+WmnrW8NlGUwys0w3f+ygfqrio 28tnbwcxAKYNJidKiK73kPcgYOc6OCZK1i6y2SxKcgsiDpu8N1EYsTOhK4wawo2hLx 7GCa3TWWOFDAZVPaF+qPrr9g3pcy8XO77lCAchTLje0bB8y2vjHl8+wlBQ7ev3qVsU 5+46tl5L6he6oy/hfmoF53lwjEIN5lkT7hJHA0CUNtw/edL+OwQ7p+0rhTSM9Io9Av v+Fr10KAWwevX78GGFCLCpub/wgqkPU0baB6gUAY0fL3TZH2iMpz0J+I3zivupq8N1 OdkMYTzQx2l7Q== 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 v5 04/26] rust: alloc: implement `Allocator` for `Kmalloc` Date: Mon, 12 Aug 2024 20:22:50 +0200 Message-ID: <20240812182355.11641-5-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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`. Signed-off-by: Danilo Krummrich --- rust/helpers.c | 3 +- rust/kernel/alloc.rs | 2 +- rust/kernel/alloc/allocator.rs | 63 +++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/rust/helpers.c b/rust/helpers.c index 92d3c03ae1bd..9f7275493365 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -193,8 +193,7 @@ void rust_helper_init_work_with_key(struct work_struct = *work, work_func_t func, } EXPORT_SYMBOL_GPL(rust_helper_init_work_with_key); =20 -void * __must_check __realloc_size(2) -rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags) +void *rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags) { return krealloc(objp, new_size, flags); } diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 194745498a75..b732720cfb95 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 diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index e32182f91167..b46883d87715 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -5,8 +5,16 @@ use super::{flags::*, Flags}; use core::alloc::{GlobalAlloc, Layout}; use core::ptr; +use core::ptr::NonNull; =20 -struct Kmalloc; +use crate::alloc::{AllocError, Allocator}; +use crate::bindings; + +/// The contiguous kernel allocator. +/// +/// The contiguous kernel allocator only ever allocates physically contigu= ous memory through +/// `bindings::krealloc`. +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 { @@ -36,6 +44,59 @@ 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, +); + +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::reallo= c`. + unsafe fn call( + &self, + ptr: Option>, + layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + let size =3D aligned_size(layout); + let ptr =3D match ptr { + Some(ptr) =3D> ptr.as_ptr(), + None =3D> ptr::null(), + }; + + // SAFETY: `ptr` is either NULL or valid by the safety requirement= s 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 { + NonNull::dangling() + } else { + NonNull::new(raw_ptr).ok_or(AllocError)? + }; + + Ok(NonNull::slice_from_raw_parts(ptr, size)) + } +} + +unsafe impl Allocator for Kmalloc { + unsafe fn realloc( + ptr: Option>, + layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + // SAFETY: `ReallocFunc::call` has the same safety requirements as= `Allocator::realloc`. + unsafe { ReallocFunc::KREALLOC.call(ptr, layout, flags) } + } +} + 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 --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 AF31D194122; Mon, 12 Aug 2024 18:24:35 +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=1723487075; cv=none; b=h8VvPWD3PncVkU8+e1JY3iPqevxCW/0IKxq/nrGBGRdvNUhtlAAXrZiwk33DJgNIw2dNYxYlm2X6QYNwMmSqgnqGBU6kkdlL/eAE63wv7spV8NiNqJJgdy2+sRSymrGSYbn+VW5mz6tx1dR+p/GJybnFbOp002Qn71DI6d90VGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487075; c=relaxed/simple; bh=qBBwndXchuTUBdgsnYPoDfZNxNBpxLvVcMvZVRMmc6s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h8eppr5zpFaR3tFjKecWtpLxzbf2aJHHxEsbE1+XF9NmlphjIWL0FoJogUPGzJg3RZUz+WzESl6hYLeQEztT5xzPCjvsU63Be8eELrnF4a7UZaIQEQAvfAl8pCa3sQGGh6+lyJNzh9rzCpmerDV8JW5lSoJYaK093qDdoRJI8JY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m5lNQLNQ; 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="m5lNQLNQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 370A7C4AF12; Mon, 12 Aug 2024 18:24:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487075; bh=qBBwndXchuTUBdgsnYPoDfZNxNBpxLvVcMvZVRMmc6s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m5lNQLNQYt0Ppd0yuQfm7lGeTmotnrWGIWreHjtdouOP5zlDu/8/lEW1TJFBFN/hs 62DOmFEz4VvqDZ+mYVc/8des9VGhvZBbhKuMl9lUNT76ZKWEHKiG+QfD7Zb0j6ea/e aIa3mtkwEY/YoNKIxouC4NSrLYhRpyXdj2kZHOotMcS4y/TKI7JRKiEuUcmX5+0j8J 8ANlNtS+jIWN1IOkNw5Ajw4S3wij2VvAWr8CVuGFfiA3ueyEFcNhiiLgAHdeF4jhJW CH3DBtylU1WYpSPJL2kmykV28Pue4pqbsXKFAoXIK0AjVfw6pC2Dk4KaVLd3FhTPlm Ynb7j8zyApx7A== 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 v5 05/26] rust: alloc: add module `allocator_test` Date: Mon, 12 Aug 2024 20:22:51 +0200 Message-ID: <20240812182355.11641-6-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich Reviewed-by: Benno Lossin --- 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 b732720cfb95..f0c80ab78602 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 A8C9D194C73; Mon, 12 Aug 2024 18:24:40 +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=1723487080; cv=none; b=c6CAXRcmwuO1ktwmneYQOY1X3SZRlWygDWAQhJVOrg+aCfXLTZEg7lARXnzSIRhtO/XnfR7Iwb/CYdauLINyuOMBKOgSJUi0IaYlPzJ9KdMBH3Hgh3GeXnxSjDVwI9zqTHmLTYo5hWCIDChZKnjpi6fdoLbDzd5I4SQip8XuQZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487080; c=relaxed/simple; bh=h5pfzEktHmh1N0L77l+cZ8kzDdEbRgd13sQHut0w7XY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HfcR/hNTouGmEFCwE64tBsHxDRnRBMGTQLCPpmdFLtUaRwQHf8TtuoPyL3Td3N3AajKl1BA21m4AN9oU5JGO5/Z0Q7xvpE7/MbSTGaXW9kZilEJF4/PGHFDYZhqXSJAeC1ngp2aWZ7a7dH6/4ktu5o9cOWQ0qgbw3sLMTek8fMM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NFvp3rUV; 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="NFvp3rUV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 975EFC4AF0F; Mon, 12 Aug 2024 18:24:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487080; bh=h5pfzEktHmh1N0L77l+cZ8kzDdEbRgd13sQHut0w7XY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NFvp3rUVlsJ+UIxsUGlMKE8VTsD2Aq8HQxJ6wXype4vyAHL2JtkK3mOcnqC2DvnGf RmFkZ/Axmc1yYu1S60+J355btuuhvCl8k6va48DkEb1AE+kv7+2ACKRPMVx/RA1Grm 8ju+i4zFpn3C6CpUsSopqqg9VC2Kra0gRKGL1W4dTZsSFnQcsgfnAGX3XZd6bP7Y1Q XOhWkTqlAKYoyI90KBpS3koeohXNoO4UW7OLvdIrC0VU1eFvFuJRTaJnyUP/w1XMaZ +Zcszs4mggLiSYZhQUaYYRApDVKuKQNFVkwynM6kBwM8NIb1v+WthEPX/Jcg0D/T4v rZ4s5Ccnx/0jw== 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 v5 06/26] rust: alloc: implement `Vmalloc` allocator Date: Mon, 12 Aug 2024 20:22:52 +0200 Message-ID: <20240812182355.11641-7-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- rust/helpers.c | 7 +++++++ rust/kernel/alloc/allocator.rs | 28 ++++++++++++++++++++++++++++ rust/kernel/alloc/allocator_test.rs | 1 + 3 files changed, 36 insertions(+) diff --git a/rust/helpers.c b/rust/helpers.c index 9f7275493365..7406943f887d 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include =20 @@ -199,6 +200,12 @@ void *rust_helper_krealloc(const void *objp, size_t ne= w_size, gfp_t flags) } EXPORT_SYMBOL_GPL(rust_helper_krealloc); =20 +void *rust_helper_vrealloc(const void *p, size_t size, gfp_t flags) +{ + return vrealloc(p, size, flags); +} +EXPORT_SYMBOL_GPL(rust_helper_vrealloc); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indi= ces. diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index b46883d87715..fdda22c6983f 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -9,6 +9,7 @@ =20 use crate::alloc::{AllocError, Allocator}; use crate::bindings; +use crate::pr_warn; =20 /// The contiguous kernel allocator. /// @@ -16,6 +17,12 @@ /// `bindings::krealloc`. pub struct Kmalloc; =20 +/// The virtually contiguous kernel allocator. +/// +/// The vmalloc allocator allocates pages from the page level allocator an= d maps them into the +/// contiguous kernel virtual space. +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. @@ -55,6 +62,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::reallo= c`. @@ -132,6 +142,24 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut = u8 { } } =20 +unsafe impl Allocator for Vmalloc { + unsafe fn realloc( + ptr: Option>, + 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, 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 5A7A5197A6E; Mon, 12 Aug 2024 18:24:46 +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=1723487086; cv=none; b=BLfnXBSQtBJ7LFe7n5j5zn/AItAxHPG2bYxhMbhiWd7EUa+MKFGpqSBZ6tQ2RqBKRo9nU6fqYXQozfDwKiL11aPoKS79E1XRXEescLK1/E/YiKdMEoAqjwSumPjiZW/PSlx8e+tE3ik6dUtxSgSqW7U29zqqKlCOqa7tXU88/OA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487086; c=relaxed/simple; bh=ITHOVb+qmodDUzbraOhMnm/IPfqxkdSYWt9L0/6UUHg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FFoVUrnS/6fJFr4UK2EedIpkgtf/ZYDkdnLsVKvvLY37ygWcBsEE4lYdW5TFnpySIVRgyJBq+Dp48IpclfOi5XGr1G/Bcj9AJlEsU7LAy9l4qLdTP1zdlR+hwA9VXjScgNKNyp6ZD9TfYwMsnvR3CDVtSDo4AbxB4BC9jdJlzxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=R2PRrRzm; 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="R2PRrRzm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02FB5C4AF0C; Mon, 12 Aug 2024 18:24:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487085; bh=ITHOVb+qmodDUzbraOhMnm/IPfqxkdSYWt9L0/6UUHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R2PRrRzm+sxi6h0mbRIbj3sVO7A7/Rs9qf3CP6nSz1dh8f0SNA64zrjrpVVLruHlQ 3BFVUU3jvJcUVpqzGx4jNLWpDl+hSQupHUBTsfko5zSpxspOjFOgtOUUF6QLp4Eu2R P2Jwf3jgK2PvwPhtagm2rdrcySOoF9SrhGJL6HMf4A9loJ4iyl2lfIaFtfpx7L7asW tBaeenOsbRAjdWleNZtLtRAzjqOFlzIb6Hq34YSFJ6Ol265wgDMcjQOv+/pj/DQ+nK RVxXOrl8/btgq+is4+yhBy3Pohr5grqiaqeVr6zRrI98GAQel/Rdo/n6yQDvwAgyEi vs0Zb3VCnxxqQ== 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 v5 07/26] rust: alloc: implement `KVmalloc` allocator Date: Mon, 12 Aug 2024 20:22:53 +0200 Message-ID: <20240812182355.11641-8-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- rust/helpers.c | 6 ++++++ rust/kernel/alloc/allocator.rs | 27 +++++++++++++++++++++++++++ rust/kernel/alloc/allocator_test.rs | 1 + 3 files changed, 34 insertions(+) diff --git a/rust/helpers.c b/rust/helpers.c index 7406943f887d..3285a85765ff 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -206,6 +206,12 @@ void *rust_helper_vrealloc(const void *p, size_t size,= gfp_t flags) } EXPORT_SYMBOL_GPL(rust_helper_vrealloc); =20 +void *rust_helper_kvrealloc(const void *p, size_t size, gfp_t flags) +{ + return kvrealloc(p, size, flags); +} +EXPORT_SYMBOL_GPL(rust_helper_kvrealloc); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indi= ces. diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index fdda22c6983f..243d8c49a57b 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -23,6 +23,12 @@ /// contiguous kernel virtual space. pub struct Vmalloc; =20 +/// The kvmalloc kernel allocator. +/// +/// Attempt to allocate physically contiguous memory, but upon failure, fa= ll back to non-contiguous +/// (vmalloc) allocation. +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. @@ -65,6 +71,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::reallo= c`. @@ -160,6 +169,24 @@ unsafe fn realloc( } } =20 +unsafe impl Allocator for KVmalloc { + unsafe fn realloc( + ptr: Option>, + 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, 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 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 74CCE198E71; Mon, 12 Aug 2024 18:24:51 +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=1723487091; cv=none; b=CwvM2z2HnIJ4dZ6LJqC1mTtusg5o+RUzaUeE2L67+xHV66MrM6MAAYzSRKIbTHgv16952QGB5Qy/ZrzUayZ8YEPbtwW8SutD8FkeGMvA2W+bJOyL+Sd6kdtiME8PC9dnAlRaPIJc5sCfwpx5q3OmDVUSN+6UriL/oO45v1agAIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487091; c=relaxed/simple; bh=agb767SEFvgiUIEEXO9aVEplEpFhszjniHeGVU9yvoo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Vyqkx4eglBkzB/T3V0XL3i3tAMiKS/nB6nIo9VBHRLipdAB2xmepdPTF2As2pLAQOOMGR0WmsJgMTXWh3LJj0hcLx/lXfs8A0r24FU/BvFQ6nBGAxmxYseHzaN8vkxf54S1yVo6t0Sb2YbG2cjuihO0aNKHdfEedeV7zpa7onYI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=reVFN/xm; 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="reVFN/xm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6456EC4AF0F; Mon, 12 Aug 2024 18:24:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487091; bh=agb767SEFvgiUIEEXO9aVEplEpFhszjniHeGVU9yvoo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=reVFN/xm1E8Zs+oww/Sm//2DAa2Rw+MuElDOYO76uoQ2MsmfiIDVMGPd3+hhKDUl+ ZKQ3On9ODtNcI1ec9Gz1esyaAfQgqu+caq+k+7BGJnkg4smIDMVmgLUMUzNBXsYHr2 wRMNNMkdq4gIyw8dCsSrjMSGSDiHLJ58KmnljgsSHRfbnClljfdgmafKb9Hlv/KcPn ZX+XPgkq446EUBGjR/c6fi3nsvTH/p3kI5Qu4gFCrqbAjky1zQB6UceDRGvu4d7xzO BkgNAqSFBF8Zc1vzaEIFNgbgYYyxRX8ki24XnarQxBT9QqrJaxvJuGcoSD2KFGaOAQ eOnr0J9FrL41w== 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 v5 08/26] rust: alloc: add __GFP_NOWARN to `Flags` Date: Mon, 12 Aug 2024 20:22:54 +0200 Message-ID: <20240812182355.11641-9-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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. Signed-off-by: Danilo Krummrich Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin --- 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 b940a5777330..7f781256fda9 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 f0c80ab78602..295107777a12 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 587941990D3; Mon, 12 Aug 2024 18:24:57 +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=1723487097; cv=none; b=OTJVXTq2UGYCXtQLO1H7+4IWTBp98hRn3z6XNt0po3i4F5lWJyB+yw+ChId4eN5+CobxJiqRypajryAqDwcc71o9zydJTjnDd0gEW17+rOc/x2lWnAyNPkgoGLd8ZuuOexA0j/Z2UuYcXR+qaTQW3FKuDNzLxjhmIR4pLVkR6AU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487097; c=relaxed/simple; bh=h2D2etA1eZNDRwBqJ9/ejeC1ErIkz2eqBdYlpphzKNY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pMKz3kbvcCglzLlKN9v09AfZyRwP2/tzM2jOwMJOQhd1jItwcmZKln8SMRlYiEkSkO7+oT+OuTf+K4kuiUSVui+a5oWCsHvWKSzdbHRdCQqF9qFdY0q6jNqsf1Z+AugMLNL7ZLXrK0yO5kAhUHIjqjqaXd91D7mVQkGWTYXo3DY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NiNDPl/B; 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="NiNDPl/B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5BC5C4AF0C; Mon, 12 Aug 2024 18:24:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487096; bh=h2D2etA1eZNDRwBqJ9/ejeC1ErIkz2eqBdYlpphzKNY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NiNDPl/BH7gnS+WaQDWmkoUYMZGIY11LwdqswyAFjBtp7nWvam6Qad7zM3WvALbLw Z9Q0Dy+5BO7YvTLFc5wX25MSJV0vrpfVTN1d1GcNc249YnQcaLQDlZpjm/6+hyosgp i/VLiHir3nj/f337rNNFEbuWeURVLXTKIDrv26iubos8SlG+am3grIqvw2rioGrOwd 6fmW1vh1dj+KRTGlkGlWV1er8GTI2zt52QeYvAOORZUopb21d4Hg7Wkw+rUMrnOje8 5m/QjV5qeBJ9Y7fFGHbKGrosFBHWwiRwenV5ckmAI9W9zSz9/FBccNnnbsf4CSgveT WLkX1y9hJRNrw== 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 v5 09/26] rust: alloc: implement kernel `Box` Date: Mon, 12 Aug 2024 20:22:55 +0200 Message-ID: <20240812182355.11641-10-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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" `Box` provides the simplest way to allocate memory for a generic type with one of the kernel's allocators, e.g. `Kmalloc`, `Vmalloc` or `KVmalloc`. In contrast to Rust's `Box` type, the kernel `Box` type considers the kernel's GFP flags for all appropriate functions, always reports allocation failures through `Result<_, AllocError>` and remains independent from unstable features. Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 6 + rust/kernel/alloc/kbox.rs | 423 ++++++++++++++++++++++++++++++++++++++ rust/kernel/prelude.rs | 2 +- 3 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/alloc/kbox.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 295107777a12..ed46b69204d0 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -5,6 +5,7 @@ #[cfg(not(any(test, testlib)))] pub mod allocator; pub mod box_ext; +pub mod kbox; pub mod vec_ext; =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..67bdfc0712d2 --- /dev/null +++ b/rust/kernel/alloc/kbox.rs @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Implementation of [`Box`]. + +use super::{AllocError, Allocator, Flags}; +use core::fmt; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::mem::MaybeUninit; +use core::ops::{Deref, DerefMut}; +use core::pin::Pin; +use core::ptr::NonNull; +use core::result::Result; + +use crate::init::{InPlaceInit, Init, PinInit}; +use crate::types::ForeignOwnable; + +/// The kernel's [`Box`] type - a heap allocation for a single value of ty= pe `T`. +/// +/// This is the kernel's version of the Rust stdlib's `Box`. There are a c= ouple of differences, +/// for example no `noalias` attribute is emitted and partially moving out= of a `Box` is not +/// supported. +/// +/// `Box` works with any of the kernel's allocators, e.g. [`super::allocat= or::Kmalloc`], +/// [`super::allocator::Vmalloc`] or [`super::allocator::KVmalloc`]. There= are aliases for `Box` +/// with these allocators ([`KBox`], [`VBox`], [`KVBox`]). +/// +/// When dropping a [`Box`], the value is also dropped and the heap memory= is automatically freed. +/// +/// # Examples +/// +/// ``` +/// let b =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 +/// +/// The [`Box`]' pointer always properly aligned and either points to memo= ry allocated with `A` or, +/// for zero-sized types, is a dangling pointer. +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 data referenced by= `self.0` is unaliased. +unsafe impl Send for Box +where + T: Send + ?Sized, + A: Allocator, +{ +} + +// SAFETY: `Box` is `Sync` if `T` is `Sync` because the data referenced by= `self.0` is unaliased. +unsafe impl Sync for Box +where + T: Send + ?Sized, + A: Allocator, +{ +} + +impl Box +where + T: ?Sized, + A: Allocator, +{ + /// Creates a new `Box` from a raw pointer. + /// + /// # Safety + /// + /// `raw` must point to valid memory, previously be allocated with `A`= , and provide at least + /// the size of type `T`. For ZSTs `raw` must be a dangling pointer. + #[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); + /// let x =3D unsafe { KBox::from_raw(ptr) }; + /// + /// assert_eq!(*x, 24); + /// + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + pub fn into_raw(b: Self) -> *mut T { + let b =3D ManuallyDrop::new(b); + + 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 + where + T: 'a, + { + // 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) } + } + + /// 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. + #[inline] + pub fn into_pin(b: Self) -> Pin { + // 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 Box, A> +where + A: Allocator, +{ + /// Converts a `Box, A>` to a `Box`. + /// + /// # Safety + /// + /// Callers must ensure that the value inside of `b` is in an initiali= zed state. It is + /// undefined behavior to call this function while the value inside of= `b` is not yet fully + /// initialized. + pub unsafe fn assume_init(b: Self) -> Box { + let raw =3D Self::into_raw(b); + + // 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 as *mut T) } + } + + /// Writes the value and converts to `Box`. + pub fn write(mut b: Self, value: T) -> Box { + (*b).write(value); + // SAFETY: We've just initialized `boxed`'s value. + unsafe { Self::assume_init(b) } + } +} + +impl Box +where + A: Allocator, +{ + fn is_zst() -> bool { + core::mem::size_of::() =3D=3D 0 + } + + /// 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 ptr =3D if Self::is_zst() { + NonNull::dangling() + } else { + let layout =3D core::alloc::Layout::new::>(); + let ptr =3D A::alloc(layout, flags)?; + + ptr.cast() + }; + + Ok(Box(ptr, 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()) + } +} + +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. + /// + /// See [`Box::into_pin`] for more details. + fn from(b: Box) -> Self { + Box::into_pin(b) + } +} + +impl InPlaceInit for Box +where + A: Allocator + 'static, +{ + #[inline] + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> + where + E: From, + { + let mut this =3D Box::<_, A>::new_uninit(flags)?; + let slot =3D this.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(this) }.into()) + } + + #[inline] + fn try_init(init: impl Init, flags: Flags) -> Result + where + E: From, + { + let mut this =3D Box::<_, A>::new_uninit(flags)?; + let slot =3D this.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(this) }) + } +} + +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 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> +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 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 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 size =3D core::mem::size_of_val::(self); + + // SAFETY: We need to drop `self.0` in place, before we free the b= acking memory. + unsafe { core::ptr::drop_in_place(self.0.as_ptr()) }; + + if size !=3D 0 { + // SAFETY: `ptr` was previously allocated with `A`. + unsafe { A::free(self.0.cast()) }; + } + } +} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index b37a0b3180fb..39f9331a48e2 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 AE0D118C33F; Mon, 12 Aug 2024 18:25:02 +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=1723487103; cv=none; b=C9YJMbFpiKIbNtm7t2m7CfSAd/Iv3m04yXTDH74WGP2RDDBd052VAdZyD7OslDTvIZsedMXRdM7Br5+4rtpGBAggpEnB+mLgLtmSi0RJ/tE2kLiCCFWg3rlOYH+1mOIhe/S7oThvqKncAA+k3BCKPy3b/ICvdzXDjrmY55D+KF0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487103; c=relaxed/simple; bh=aL2zVuDOiic5J7pGULj5cj3jRLb//Q08+HJ/i/n5Y/8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MFJsiBt0hZztVOMzNz3hHRGZ1bIhGjZ4BLichezc/ArHW/HXRdJAia0TI6Ja39lAUD+NS5BvbwY5+t91eukMsRQoW2L/RojWHw283wfPfflDWAkwX5DP5/7qg9CAOMG/QgJpaonDZ9hQORwwrzf8x1Qqr3A1Si3n+1aSXoDrE2A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EO3VgrTo; 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="EO3VgrTo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 60905C32782; Mon, 12 Aug 2024 18:24:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487102; bh=aL2zVuDOiic5J7pGULj5cj3jRLb//Q08+HJ/i/n5Y/8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EO3VgrTo4+t616bab23cFHTtcNc4zrDlT23wwidhHJ6AIXhXSP1Pe4ZuOe+WnvX6Y w44Zmclgc9RL7E+KUdKJFDpEEL1wSHJgRQH0QlJOnbYFguq0vbJH8pbIewv481xrPp o1F2yd9D9bo4DOPIIAx0/Vm5t5YtIcgkytXm04TeP4A6q6zEc/7jpC3C/nCEu/u5cI USXq63KTqx2FljVTn5w54tSbn4YB6k+gHc+Y5eaKvptMgZfiQ4P+ZShi5INlmIoMuv eiexBhlmvO8uo/YAYKetZniNkeThRc6n9COyI2MNyX8Thc8wGVLQD7wdGFwsz2kx9B jrHaW7Fy9Q+kA== 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 v5 10/26] rust: treewide: switch to our kernel `Box` type Date: Mon, 12 Aug 2024 20:22:56 +0200 Message-ID: <20240812182355.11641-11-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- drivers/block/rnull.rs | 4 +-- rust/kernel/init.rs | 51 ++++++++++++++++--------------- rust/kernel/init/__internal.rs | 2 +- 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 ++-- 9 files changed, 54 insertions(+), 54 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 495c09ebe3a3..d3639243f8c7 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. @@ -93,14 +93,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::UniqueArc, types::{Opaque, ScopeGuard}, @@ -297,7 +297,7 @@ macro_rules! stack_pin_init { /// struct Foo { /// #[pin] /// a: Mutex, -/// b: Box, +/// b: KBox, /// } /// /// struct Bar { @@ -306,7 +306,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)?, /// })); @@ -323,7 +323,7 @@ macro_rules! stack_pin_init { /// struct Foo { /// #[pin] /// a: Mutex, -/// b: Box, +/// b: KBox, /// } /// /// struct Bar { @@ -332,7 +332,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. @@ -461,7 +461,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: @@ -593,7 +593,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, /// } @@ -601,7 +601,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) @@ -693,16 +693,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) /// } @@ -745,8 +745,8 @@ macro_rules! try_init { /// 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). /// @@ -825,7 +825,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, @@ -851,8 +851,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). @@ -924,7 +924,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, @@ -1008,8 +1008,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( @@ -1316,7 +1317,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 db3372619ecd..dfb2204918c7 100644 --- a/rust/kernel/init/__internal.rs +++ b/rust/kernel/init/__internal.rs @@ -102,7 +102,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/sync/arc.rs b/rust/kernel/sync/arc.rs index 3673496c2363..b5c84995d7d2 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -16,13 +16,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}, error::{self, Error}, init::{self, InPlaceInit, Init, PinInit}, try_init, types::{ForeignOwnable, Opaque}, }; -use alloc::boxed::Box; use core::{ alloc::Layout, fmt, @@ -203,11 +202,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 /// Use the given initializer to in-place initialize a `T`. @@ -422,8 +421,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())) }; } } } @@ -668,7 +667,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) = }), @@ -678,8 +677,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 2b306afbe56d..2081932bb4b9 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 553a5cba2adc..94318472507f 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. @@ -565,7 +565,7 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self:= :EnqueueOutput } } =20 -unsafe impl WorkItemPointer for Pin> +unsafe impl WorkItemPointer for Pin> where T: WorkItem, T: HasWork, @@ -576,7 +576,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 @@ -584,7 +584,7 @@ unsafe impl WorkItemPointer for P= in> } } =20 -unsafe impl RawWorkItem for Pin> +unsafe impl RawWorkItem for Pin> where T: WorkItem, T: HasWork, @@ -598,9 +598,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 159e75292970..c327fe0617c8 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -239,7 +239,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// struct DriverData { /// #[pin] /// queue: Mutex>, -/// buf: Box<[u8; 1024 * 1024]>, +/// buf: KBox<[u8; 1024 * 1024]>, /// } /// ``` /// @@ -248,7 +248,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, /// } /// @@ -278,7 +278,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 D73CD18E05B; Mon, 12 Aug 2024 18:25:07 +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=1723487107; cv=none; b=gmthmv4hPqfPvhCPYRq6+pfoas2dVV0gHRTU2RVKXLkV9AAfCkIiOJ9F010vyb/dLn4jzzFyIJAeKYSDomm8Ynpvj7lHSi0KwSwyE1QtMHn4LJ9R9898+/q4lbXeLrkPy7//We59uFSVkLMGmyDJhq5tXtBfQKFnZfjCzoWNUcw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487107; c=relaxed/simple; bh=vJmxOB7AGqLlyQmlorOYiNjZzw+KKAXmcrFSlXxsvFE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oiYz2DXyljtbXpTjDMSbYlK9Sc1CDCy30FRflnq5bDlERJHOyAF5kdr62nkwIN6LwltCjzr9Z2lh4pW1unlRSNZUdWDy7uwhVrSjqb1dX7P9bSMprfm98a9mVxz2ejm4cpmxiJQJJFtnF3sDBM6XGkXGS363Xljh5fZGRm3JDJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gzQfQXuq; 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="gzQfQXuq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C1AE9C4AF0C; Mon, 12 Aug 2024 18:25:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487107; bh=vJmxOB7AGqLlyQmlorOYiNjZzw+KKAXmcrFSlXxsvFE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gzQfQXuq96ggnJND706Rt7zVvArRkbVlxihfPz2TakWWKbNovhjxdEGVcquoZwmFg YsMVtZIUTpE7D8VdukUyTJwr899ZiJagclA2fZKv8TBXdUEi9jasTkt01z0AOPwEVL LdX3kdN6KvSSBhlLgnD7eGk544BOMeyE7mLhd5w5kCPuyt77cJZPIStrslTgYV54oa cX0c2+ij3qFs8quP7TlNABPeFe19JFHrm1+bJJ/DMuWlGWnjeDRpyiVhWhHGrp8mbT VOPiQDdY6vdbJOF56Fl/t9OSc2cKyZkHcrOfFb/cQ8Asc/ssNxPM06LvBB/vC1Y3Do gJUacAnLc725w== 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 v5 11/26] rust: alloc: remove `BoxExt` extension Date: Mon, 12 Aug 2024 20:22:57 +0200 Message-ID: <20240812182355.11641-12-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 - rust/kernel/alloc/box_ext.rs | 56 ------------------------------------ rust/kernel/init.rs | 34 +--------------------- rust/kernel/lib.rs | 1 - rust/kernel/prelude.rs | 4 +-- rust/kernel/types.rs | 23 --------------- 6 files changed, 3 insertions(+), 116 deletions(-) delete mode 100644 rust/kernel/alloc/box_ext.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index ed46b69204d0..47cab5bd803e 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 829cb1c1cf9e..000000000000 --- a/rust/kernel/alloc/box_ext.rs +++ /dev/null @@ -1,56 +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; - -/// 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>; -} - -impl BoxExt for Box { - fn new(x: T, flags: Flags) -> Result { - let b =3D >::new_uninit(flags)?; - Ok(Box::write(b, x)) - } - - #[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) }) - } -} diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index d3639243f8c7..eb55787eddee 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -211,12 +211,11 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ - alloc::{box_ext::BoxExt, AllocError, Flags, KBox}, + alloc::{AllocError, Flags, KBox}, error::{self, Error}, sync::UniqueArc, types::{Opaque, ScopeGuard}, }; -use alloc::boxed::Box; use core::{ cell::UnsafeCell, convert::Infallible, @@ -589,7 +588,6 @@ macro_rules! pin_init { /// # Examples /// /// ```rust -/// # #![feature(new_uninit)] /// use kernel::{init::{self, PinInit}, error::Error}; /// #[pin_data] /// struct BigBuf { @@ -1149,36 +1147,6 @@ fn init(init: impl Init, flags: Flags) -> e= rror::Result } } =20 -impl InPlaceInit for Box { - #[inline] - fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> - where - E: From, - { - let mut this =3D as BoxExt<_>>::new_uninit(flags)?; - let slot =3D this.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 { this.assume_init() }.into()) - } - - #[inline] - fn try_init(init: impl Init, flags: Flags) -> Result - where - E: From, - { - let mut this =3D as BoxExt<_>>::new_uninit(flags)?; - let slot =3D this.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 { this.assume_init() }) - } -} - impl InPlaceInit for UniqueArc { #[inline] fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 274bdc1b0a82..042f05c45214 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -14,7 +14,6 @@ #![no_std] #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] -#![feature(new_uninit)] #![feature(receiver_trait)] #![feature(unsize)] =20 diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 39f9331a48e2..a8018ef2e691 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 bd189d646adb..f48704db33c1 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -3,7 +3,6 @@ //! Kernel types. =20 use crate::init::{self, PinInit}; -use alloc::boxed::Box; use core::{ cell::UnsafeCell, marker::{PhantomData, PhantomPinned}, @@ -67,28 +66,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 () { type Borrowed<'a> =3D (); =20 --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 AC2A31991AF; Mon, 12 Aug 2024 18:25:13 +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=1723487113; cv=none; b=uJfF5auXjh4raNJKcY9TAl6Gjh5e+BBF9G4Xsx/PsP9BsO6baCStIToK+QBjYf2fDIfZi0MCK0FSaGkRWgt/iLfvzSTRIbvw82QUk7xkPFV/z0BRRqdflej1uQUFObM9hDYA6m2RPUaVsfhfjh/egJE1YrIwhXos6uescmS/Lfk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487113; c=relaxed/simple; bh=T1FuSmy3wKKtte/FIc8FwS4B4+fz3kPLj/bCRcKqMJQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Wj4G9qC1ciW+SPbuZs5Ufv+vtR85QY/nk+bIV/iV1Db+H4ewo0Wb4hkAZ7b11afs4z4JS8R/N7q+cQ5TKtxLIhRr6mFvgw93NECWlMQ6AblZWj6vD9eYtngAEEgfEoyv0mGSzzYOi1L1mX2Dxi/RqPT6bgJ4GjrJhIDgS6GqT8g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tv5GuWoQ; 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="tv5GuWoQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32487C4AF0C; Mon, 12 Aug 2024 18:25:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487113; bh=T1FuSmy3wKKtte/FIc8FwS4B4+fz3kPLj/bCRcKqMJQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tv5GuWoQlwKbMwwjnKoMTrb4grtNMZEHotZjBmBsuaqEFBKhwQNv9xRogc3nnqQRs UFvpo+qQd+H4kCiuXK/SFpJtltvWgWCrflqvvBmrHvwYPjQ5YbEESlchJbh5dm++Ra oUNwdkg/bK+xdupv706WHrQJ6X3GGbjgYMpoziDIO++aRAmCgDc2CLPZTscx0oP1Ik gPZ1Fs+Jkeof0ff6yyBebVf2aBekQ6Huvdx47F1yRvBr5FsMp2snsObG9loYWAnZw6 dNu8ugaSnnz4153ZUOesYJJ0F0WzRxPBqY4q/l+YODCVZJjjwG2mXaCAbomuWVgj+E MPJ+ew6WAqoxw== 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 v5 12/26] rust: alloc: add `Box` to prelude Date: Mon, 12 Aug 2024 20:22:58 +0200 Message-ID: <20240812182355.11641-13-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 a8018ef2e691..6bf77577eae7 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 195DA199225; Mon, 12 Aug 2024 18:25:18 +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=1723487119; cv=none; b=MOb+iZa/L2eoZev3vACpNRFsDlM0i9D8UIyOL1xK6sLgALHY2jzS2BbKXIvg/9Iry9e3vYGHviWI+E07+yoMQg0IKg/GABbN7/iMg3ZukFA4UNlrDBmLtgbe7TEjTb88HZQQSYM+17jF1+PgnrLTVJrIc89iPaRvlc3u1nEy868= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487119; c=relaxed/simple; bh=8cg9wKbQuvsA1DHr/ARpLKQtv/43NG0iFT8VBNeBpMA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jHo3yh6JnAHc5dcOdm6Q9YZHNt7LWOgr+uIP1ZS0/S0iznhEDyQvnbcbst6+0WFQF88ncUL7Hs5WhJZbypJivIjQCBhOrOdDJTq2Jfzb02vIUA6TvPzZDxW8me1RwThmI5/kB1pUyFgcFwDIyb3vb2rG5JC0wssGC9AGsntIlz0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=teMUFWqf; 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="teMUFWqf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A09C6C32782; Mon, 12 Aug 2024 18:25:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487118; bh=8cg9wKbQuvsA1DHr/ARpLKQtv/43NG0iFT8VBNeBpMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=teMUFWqfczNMBEEN4u6dBQ/n2BH0v+ID6U/4BUYy20oyGRAU7iFhNAfSg2ASmZfWm 8iiG2F5NhedAI7dlk63WWX88GVuR4QY27fimyvQOJQ91WK5Y1zqldK8ROMd62XqUgp 0heNuompL715Gmlqh0qLKEbC0NfZHw/CoXb3f1lBa0QSsw3eKHfkQOAepV8EFsfqQV Pu/2BcDChpH1Be+kOJahWRbWLn19snB0mf+Rxi7cZ569HWBdnsqMuAz/6K3FJFgm09 VfGW45orELU3WGYgfH79RIbWK3VQ4xVx4TDHFc8CqwQXjcqdJotIQtYKlpx9E9tPei ntnYViPxkQxBA== 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 v5 13/26] rust: alloc: implement kernel `Vec` type Date: Mon, 12 Aug 2024 20:22:59 +0200 Message-ID: <20240812182355.11641-14-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 (such as `Vec`) with contents allocated with the kernel's allocators (e.g. `Kmalloc`, `Vmalloc` or `KVmalloc`). In contrast to Rust's `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. Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 6 + rust/kernel/alloc/kbox.rs | 16 +- rust/kernel/alloc/kvec.rs | 613 ++++++++++++++++++++++++++++++++++++++ rust/kernel/prelude.rs | 2 +- 4 files changed, 635 insertions(+), 2 deletions(-) create mode 100644 rust/kernel/alloc/kvec.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 47cab5bd803e..4d7190594076 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 vec_ext; =20 #[cfg(any(test, testlib))] @@ -18,6 +19,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/kbox.rs b/rust/kernel/alloc/kbox.rs index 67bdfc0712d2..d67f97550224 100644 --- a/rust/kernel/alloc/kbox.rs +++ b/rust/kernel/alloc/kbox.rs @@ -2,7 +2,7 @@ =20 //! Implementation of [`Box`]. =20 -use super::{AllocError, Allocator, Flags}; +use super::{AllocError, Allocator, Flags, Vec}; use core::fmt; use core::marker::PhantomData; use core::mem::ManuallyDrop; @@ -183,6 +183,20 @@ pub fn into_pin(b: Self) -> Pin { } } =20 +impl Box<[T; N], A> +where + A: Allocator, +{ + /// Convert a `Box<[T, N], A>` to a `Vec`. + pub fn into_vec(b: Self) -> Vec { + let len =3D b.len(); + unsafe { + let ptr =3D Self::into_raw(b); + Vec::from_raw_parts(ptr as _, len, len) + } + } +} + impl Box, A> where A: Allocator, diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs new file mode 100644 index 000000000000..351c4f1702db --- /dev/null +++ b/rust/kernel/alloc/kvec.rs @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Implementation of [`Vec`]. + +use super::{AllocError, Allocator, Flags}; +use core::{ + fmt, + marker::PhantomData, + mem::{ManuallyDrop, MaybeUninit}, + ops::Deref, + ops::DerefMut, + ops::Index, + ops::IndexMut, + ptr::NonNull, + slice, + slice::SliceIndex, +}; + +/// Create a [`Vec`] containing the arguments. +/// +/// # 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([$($x),+], GFP_KERNEL) { + Ok(b) =3D> Ok($crate::alloc::KBox::into_vec(b)), + 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 `KVVec`= 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 +/// +/// The [`Vec`] backing buffer's pointer is always properly aligned and ei= ther points to memory +/// allocated with `A` or, for zero-sized types, is a dangling pointer. +/// +/// The length of the vector always represents the exact number of element= s stored in the vector. +/// +/// The capacity of the vector always represents the absolute number of el= ements that can be stored +/// within the vector without re-allocation. However, it is legal for the = backing buffer to be +/// larger than `size_of` times the capacity. +/// +/// The `Allocator` type `A` of the vector is the exact same `Allocator` t= ype 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. + /// + /// # Invariants + /// + /// `cap` must be in the `0..=3Disize::MAX` range. + cap: usize, + 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 the data referenced by= `self.ptr` is unaliased. +unsafe impl Send for Vec +where + T: Send, + A: Allocator, +{ +} + +// SAFETY: `Vec` is `Sync` if `T` is `Sync` because the data referenced by= `self.ptr` is unaliased. +unsafe impl Sync for Vec +where + T: Send, + A: Allocator, +{ +} + +impl Vec +where + A: Allocator, +{ + #[inline] + 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 Self::is_zst() { + usize::MAX + } else { + self.cap + } + } + + /// 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) { + self.len =3D new_len; + } + + /// Returns a slice of the entire vector. + /// + /// Equivalent to `&s[..]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Returns a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + #[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(&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.as_mut_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 { + Self { + ptr: NonNull::dangling(), + cap: 0, + 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: The memory between `self.len` and `self.capacity` is gu= aranteed to be allocated + // and valid, but uninitialized. + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + 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> { + Vec::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(()) + } + + /// 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(); + + Self::reserve(&mut v, capacity, flags)?; + + Ok(v) + } + + /// 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> + where + T: Clone, + { + self.reserve(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(()) + } + + /// Creates a Vec from a pointer, a length and a capacity using = the allocator `A`. + /// + /// # Safety + /// + /// If `T` is a ZST: + /// + /// - `ptr` must be a dangling pointer. + /// - `capacity` must be zero. + /// - `length` must be smaller than or equal to `usize::MAX`. + /// + /// 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::= ` times the `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`. + /// + /// # 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>(()) + /// ``` + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usi= ze) -> Self { + let cap =3D if Self::is_zst() { 0 } else { capacity }; + + 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) }, + cap, + 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 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 SZTs, we can't go = higher. + return Err(AllocError); + } + + // We know `cap` is <=3D `isize::MAX` because of it's type invaria= nt. 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)?; + + // We need to make sure that `ptr` is either NULL or comes from a = previous call to + // `realloc_flags`. 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 { + None + } else { + Some(self.ptr.cast()) + }; + + // SAFETY: `ptr` is valid because it's either `None` or comes from= a previous call to + // `A::realloc`. We also verified that the type is not a ZST. + let ptr =3D unsafe { A::realloc(ptr, layout, flags)? }; + + self.ptr =3D ptr.cast(); + + // INVARIANT: `Layout::array` fails if the resulting byte size is = greater than `isize::MAX`. + self.cap =3D new_cap; + + 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> { + 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.reserve` not bailing out with an error guarantees= that we're not + // exceeding the capacity of this `Vec`. + unsafe { self.set_len(self.len() + n) }; + + 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: We need to drop the vector's elements in place, before = we free the backing + // memory. + unsafe { + core::ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut( + self.as_mut_ptr(), + self.len, + )) + }; + + // If `cap =3D=3D 0` we never allocated any memory in the first pl= ace. + if self.cap !=3D 0 { + // SAFETY: `self.ptr` was previously allocated with `A`. + unsafe { A::free(self.ptr.cast()) }; + } + } +} + +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 $(where $ty:ty: $bound:ident)?) =3D> { + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] =3D=3D other[..]= } + } + } +} + +__impl_slice_eq! { [A1: Allocator, A2: Allocator] Vec, Vec } +__impl_slice_eq! { [A: Allocator] Vec, &[U] } +__impl_slice_eq! { [A: Allocator] Vec, &mut [U] } +__impl_slice_eq! { [A: Allocator] &[T], Vec } +__impl_slice_eq! { [A: Allocator] &mut [T], Vec } +__impl_slice_eq! { [A: Allocator] Vec, [U] } +__impl_slice_eq! { [A: Allocator] [T], Vec } +__impl_slice_eq! { [A: Allocator, const N: usize] Vec, [U; N] } +__impl_slice_eq! { [A: Allocator, const N: usize] Vec, &[U; N] } diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 6bf77577eae7..bb80a43d20fb 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 7B2BE199253; Mon, 12 Aug 2024 18:25:24 +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=1723487124; cv=none; b=J4rsfIczHC8OhQXBTwgaeF6n112LLtQkfgWnv5GeZAWKJPJ5fddlBgDbi4hxhz9ayPRT3MCvJ8PUZtgzLnAd+WLrpjnS1qWUJZOP+0GY9fv34VXAbj4O69hzVNMUmXssWNqvwQLdPlDBkNw6xrqMonqDQDVs7ZszuXFz/ZZM8UU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487124; c=relaxed/simple; bh=0DSeKEWLXJuqwaFBkmO+F7vBvNPyAyPpY0O8t3RwT4Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HIQoCege+pbTAY6EsrV/QkkHljNwLaevmDSVcjbji6MqMNOmOeZ1DB5DA1h9phqJOu9fs3dQa9h6biK1nBPqq4UgV97cwI6eIFSU7U9NO/qGvyewILyQCiqfIWNEFefEq/6dMGOItrslWCU4zN2jBUia/k2PNZTbKF3VafmOT8c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DzWbtvOL; 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="DzWbtvOL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A7CDC4AF0D; Mon, 12 Aug 2024 18:25:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487124; bh=0DSeKEWLXJuqwaFBkmO+F7vBvNPyAyPpY0O8t3RwT4Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DzWbtvOLiWrMOUXG/qelU1xQ8qo72M+ErF8g+N9WKMUpaKdzkCMw3Pcp+65+lpkdg nHiF7XNu6z9JZ7HHR/o8Vwh3Ksbdz8jmxdZCPUvGSNMrW1AYnlbSBk4UQcg1zrWj5W jzqXjT9F51KHwg0Q7rYyPT02u0/Bkz1egaE5BYR8x7klRCsoyEwqcO3LUoLOEI4SYK KPnLvbJmMYz9zUV/mgmU287ki/YZ4UTEkuslHHNnKpO6E/eui1r52+B0Z1OVddG5e1 BCr2KdFXi2WiN4UW7x2CBq700z3FF5Nhj6dprjns6t66FeWibt+ir93XSqxqRKfZJy 2fSASsmLBWMNQ== 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 v5 14/26] rust: alloc: implement `IntoIterator` for `Vec` Date: Mon, 12 Aug 2024 20:23:00 +0200 Message-ID: <20240812182355.11641-15-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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. Signed-off-by: Danilo Krummrich --- rust/kernel/alloc.rs | 1 + rust/kernel/alloc/kvec.rs | 184 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 4d7190594076..4035644b5dca 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -19,6 +19,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 351c4f1702db..cc8f3c555d1e 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -11,6 +11,7 @@ ops::DerefMut, ops::Index, ops::IndexMut, + ptr, ptr::NonNull, slice, slice::SliceIndex, @@ -611,3 +612,186 @@ fn eq(&self, other: &$rhs) -> bool { self[..] =3D=3D = other[..] } __impl_slice_eq! { [A: Allocator] [T], Vec } __impl_slice_eq! { [A: Allocator, const N: usize] Vec, [U; N] } __impl_slice_eq! { [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`] (p= rovided 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, + cap: usize, + _p: PhantomData, +} + +impl IntoIter +where + A: Allocator, +{ + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr, self.len) + } +} + +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 ptr =3D self.ptr; + if !Vec::::is_zst() { + // SAFETY: We can't overflow; `end` is guaranteed to mark the = end of the buffer. + unsafe { self.ptr =3D self.ptr.add(1) }; + } else { + // For ZST `ptr` has to stay where it is to remain aligned, so= we just reduce `self.len` + // by 1. + } + self.len -=3D 1; + + // SAFETY: `ptr` is guaranteed to point at a valid element within = the buffer. + Some(unsafe { ptr.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: Drop the remaining vector's elements in place, before w= e free the backing + // memory. + unsafe { ptr::drop_in_place(self.as_raw_mut_slice()) }; + + // If `cap =3D=3D 0` we never allocated any memory in the first pl= ace. + if self.cap !=3D 0 { + // SAFETY: `self.buf` was previously allocated with `A`. + unsafe { A::free(self.buf.cast()) }; + } + } +} + +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 (ptr, len, cap) =3D self.into_raw_parts(); + + IntoIter { + ptr, + // SAFETY: `ptr` is either a dangling pointer or a pointer to = a valid memory + // allocation, allocated with `A`. + buf: unsafe { NonNull::new_unchecked(ptr) }, + len, + cap, + _p: PhantomData::, + } + } +} --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 7FAE5190057; Mon, 12 Aug 2024 18:25:29 +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=1723487129; cv=none; b=GqZCwmQJKxlScdkDwuMWShE3z/F12Kv6Jf2sI++PCh2TwhshOxzs9um9yqwrG3NXZTicQ+bbCliNcAYpoYs7VTlXV7CQKkIGR8m152R4vjvlFXt9ijdR6F0v2LnrDe9vHNy6JzMqRQFm5eFEZye5hjltL1mRtkxBpGl8bILyPIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487129; c=relaxed/simple; bh=mGfLMacmI9WDRKwXe7Dbjq2onMgKyS4ooeQ6tXyvXVU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XVqUb2Brz16GVIj5wiau/qGqa62RQnW5KFOEzrJGCquBtEChFL9PNoDswCmAKy0az+PLuCnWm7vDx3CMfYkQxBWv9AzjxXHqJ8dGgmTGKv/CVUDq7Na0d6jhjudCUmOLNbb+q5C+P8HZYgYbJzglkV0QE1X7p99BydUhnCtRJOc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aUAfrY2L; 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="aUAfrY2L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C829C4AF0F; Mon, 12 Aug 2024 18:25:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487129; bh=mGfLMacmI9WDRKwXe7Dbjq2onMgKyS4ooeQ6tXyvXVU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aUAfrY2LujU/UqM2eFzPgifWU2KN+zf4RZN2dHFqJ+3IFJko9zyAO+izB4L54XRR2 LwvFMGpAflvg4EvIkKuiaJfGM1D7tphFfc1Shb/m/I4CmkcSpApOJVX2JXT5MoCdt8 juPxgQNxSF60Xomyz0tTsocIX23l55U2zkGayA9RwpTgrUGEIU8ZGlYzGYs606VbG5 SZdo+LCGAg6LbZl+8ti45727MdmV8ltrSNRmTZp28Inuodv+in4hWC26wjTF+ZffDn sZjNiVEon9nWrjyN4sqITxTgCUIrfDIeYX0hYqnHkx5HqnQBeMMuY1so0J4SRXZBSA baU3gqDD0ASyQ== 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 v5 15/26] rust: alloc: implement `collect` for `IntoIter` Date: Mon, 12 Aug 2024 20:23:01 +0200 Message-ID: <20240812182355.11641-16-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/kvec.rs | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index cc8f3c555d1e..db58e764db4b 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -665,6 +665,84 @@ impl IntoIter fn as_raw_mut_slice(&mut self) -> *mut [T] { ptr::slice_from_raw_parts_mut(self.ptr, self.len) } + + 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.cap; + (ptr, buf, len, cap) + } + + /// Same as `Iterator::collect` but specialized for `Vec`'s `IntoIter`. + /// + /// 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. + /// + /// # 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>(()) + /// ``` + pub fn collect(self, flags: Flags) -> Vec { + let (mut ptr, buf, len, mut cap) =3D self.into_raw_parts(); + let has_advanced =3D ptr !=3D buf.as_ptr(); + + if has_advanced { + // SAFETY: Copy the contents we have advanced to at the beginn= ing of the buffer. + // `ptr` is guaranteed to be between `buf` and `buf.add(cap)` = and `ptr.add(len)` is + // guaranteed to be smaller than `buf.add(cap)`. + unsafe { ptr::copy(ptr, buf.as_ptr(), len) }; + ptr =3D buf.as_ptr(); + } + + // This can never fail, `len` is guaranteed to be smaller than `ca= p`. + let layout =3D core::alloc::Layout::array::(len).unwrap(); + + // SAFETY: `buf` points to the start of the backing buffer and `le= n` is guaranteed to be + // smaller than `cap`. Depending on `alloc` this operation may shr= ink the buffer or leaves + // it as it is. + ptr =3D match unsafe { A::realloc(Some(buf.cast()), layout, flags)= } { + // If we fail to shrink, which likely can't even happen, conti= nue 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 buffer. `cap` is either th= e original capacity or, + // after shrinking the buffer, equal to `len`. `alloc` is guarante= ed to be unchanged since + // `into_iter` has been called on the original `Vec`. + unsafe { Vec::from_raw_parts(ptr, len, cap) } + } } =20 impl Iterator for IntoIter --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 34D86192B70; Mon, 12 Aug 2024 18:25: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=1723487135; cv=none; b=SW94F2iYzN+H5+R7Y7hIlE0PeunHgfhjYa/i6JXLejiVZ4bIszsIuQMGsmjQueOedzhbGC2FZvuZveXl9ZtoE16sYSlY0GScf1ctrzjvlc8s3B4LBDXxf4F6LA+4M9/yxt5fMba0FartBlD2chFaX60WBekBhiMtW7aryt9OYQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487135; c=relaxed/simple; bh=OOOwgVRJfePu8PY+REcfTzHgRHI6ksicI60irRAmGTI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bOwsKC85tN7CgrmIsfes/NicFFUENa2bOEfoQ13qDQbjS+7N4BxzcFMO8tiFieN6PpqnGtYqYsRvSVFxhVJX3fVAu6bB5yVTltr8UB0MYUtxlvUPqazk4p84tHvjipdesSsKLqbPanwjyPjKzpVQaMiAy0NOrQOjoW0+csjSmPE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mVtAY1mW; 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="mVtAY1mW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D0069C4AF14; Mon, 12 Aug 2024 18:25:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487134; bh=OOOwgVRJfePu8PY+REcfTzHgRHI6ksicI60irRAmGTI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mVtAY1mWFugPVxOUM9PJ/yXnWtCliEGpVKwDTimyad7a1Rv8QsFzGDFxAhFDDBNh+ xr8VuK2bfnQktrv8PCU+FJNu7ZRdtKAIslM3iSCV8pAOwjAobwUuMiCnnJnv88ojm4 Cy2e3GPtNHaxKuMlMGR4ZDcgabHxC9cmlTXDWP1JBh1yewOZnsWpXLwkdbbZpYgngO Q2EIYuG6L4h/7t9ZsbcM9ILpreAZg9NxIjaeRRVQ7zAOLCOrxAeY3hk03CEhfc0FMp oha6Y0mhw4uK5fN2gwB23kpfyb3HiRMQBTjRwnq2VshAyLXpsI774JNrbQyQGw+9Jx g+z6UgAzMzfOA== 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 v5 16/26] rust: treewide: switch to the kernel `Vec` type Date: Mon, 12 Aug 2024 20:23:02 +0200 Message-ID: <20240812182355.11641-17-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 bb8d4f41475b..209ad1bb1a49 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 @@ -790,7 +789,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 { @@ -803,7 +802,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)?; @@ -850,10 +849,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 f48704db33c1..3c66f2fbd737 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -132,7 +132,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 c327fe0617c8..a733168d40f9 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -238,7 +238,7 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream { /// #[pin_data] /// struct DriverData { /// #[pin] -/// queue: Mutex>, +/// queue: Mutex>, /// buf: KBox<[u8; 1024 * 1024]>, /// } /// ``` @@ -247,7 +247,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, /// } @@ -277,7 +277,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 514C2192B70; Mon, 12 Aug 2024 18:25:40 +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=1723487140; cv=none; b=rMVKYfbb6Ee61OEPIDMRu4sJVK+JkULkJpfRQWExa+fnYFTCpWmzF0k87Fm+PudJ3AK9eBtgVSHjZOb31jgAngNrI3SLmVCTB8XYFWR3nLKCQpvbBWpFw7BvKTS8xmxkm4O3ZHofhWag7hvEJuJ75Uzbe4kh56/emuXiuv3BExk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487140; c=relaxed/simple; bh=m7HbTZHBJlRggfNUaOoLamnAddQQ70J0syR4UcM8PHQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F8sbqg7NYuQBxHkp0bBpNMKPY7sypiAXsX5Hj6OqnqT8ClFkhXidQa3GdSyg+IufMup8sug//ZnnuYrDZBFnFkR4LK7rZj3CorkkUx4Va4g3OkkqaQavaB2sAnLGAj0DC262iQ/BzT+y2/DVsgovWxXQDyFTZc7902rBjoNsy/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sJY0rk4M; 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="sJY0rk4M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E33AC4AF0C; Mon, 12 Aug 2024 18:25:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487140; bh=m7HbTZHBJlRggfNUaOoLamnAddQQ70J0syR4UcM8PHQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sJY0rk4M9CRwGFBQj6kA3sbwR/ZmLcxfe+tIJ4uV0rcOTwIIqbB7WbzkqHXgsu2Mm UROXeQoa0dDch3iwyW68ngAgaeNXpooPE7Nqm5RZceLi2EYWlv5HItx7etZ5EiPv5D vLE24RkZvPAPEH1zjsIz30yONsus8VI0Cb5th5wU/I2O2/ZLZhPi8wsvUPK3HOJpfX y8xMsFR4Apdry2bcw0so3b5sQahNPk4ItAQkzUV2a4auoi9oK4t98KDEBfjijJN75t Qha7iHPu9kFSUD9pxxFxIHNkgNlC/hEx9cMJTQm6vTyEp3PBOIzKvT73rUI6Us6maq Ly2irV4fbwLcw== 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 v5 17/26] rust: alloc: remove `VecExt` extension Date: Mon, 12 Aug 2024 20:23:03 +0200 Message-ID: <20240812182355.11641-18-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 4035644b5dca..820ef6072e02 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -6,7 +6,6 @@ pub mod allocator; pub mod kbox; pub mod kvec; -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 bb80a43d20fb..fcc8656fdb51 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 C440019412F; Mon, 12 Aug 2024 18:25: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=1723487145; cv=none; b=KgV/QXcWyNQV8pS8q/z1u/ID0pl4ZqoFZ6FuDzcxPBXGCVNv+/lfTaw3xSUamIhJOJ0aCKsRfvfxH0OP0q8rMpSyacPRifacJWvbQ5NE6jjN8DEl1LGu9XuFsqi0A5qmercN8Dvkxwg5UkM0OFkmLF5qi5MXNvsrBAWkUOBMNVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487145; c=relaxed/simple; bh=vy8jMGyAXJW8mhTpujuxbveXx/4kmHcgFJLvoNpXzVk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MHZswqxPCz5r/UBSLvn+3M9qk71ClByFWUYxTaF5bT1bEkpHZJyz55qm2zkboPXqkeoyb+DSpE01gmdcmVnUp2W5iGGE0+FpRMX6Ima3ZcBRwlg+TuB11Stoi0bA2xkShvmYMmOCkRFrVgccY5vKGIKnowYKqsBbbII+GsNVpg4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Auu0ERRR; 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="Auu0ERRR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A1AB1C4AF14; Mon, 12 Aug 2024 18:25:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487145; bh=vy8jMGyAXJW8mhTpujuxbveXx/4kmHcgFJLvoNpXzVk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Auu0ERRRl9iKXCUlp+SoDSPzRZnO6/enifkp7q/lRVDC359BYyHjhZIp3yRatrfYF S3ccNm4tHObneYmnWQKVsryy2upOOW8E8rI+fkP9NEOVwlxld6DMJnxx8AOeygcl7V +Q082Cm/kttOPG40J20BMGYsBqeouZsvblgAsois/QIOy/WXveFj3AhYFQAUHHobT3 r0SLJX91V7pQno0s86X7/UzrtBDTnvD9NZulQ9yqyVGlD2zoeGMT0kdTG8n6jaAgSd tUHgiQ3e1KWZAAPB7UbIyMgBTSCmkGb4iyYgxsFJDcR663RNTI3JqDxrNYQ4EznMO+ b5v0rZ4k+hpOg== 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 v5 18/26] rust: alloc: add `Vec` to prelude Date: Mon, 12 Aug 2024 20:23:04 +0200 Message-ID: <20240812182355.11641-19-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 fcc8656fdb51..b049ab96202e 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 2ABF519A282; Mon, 12 Aug 2024 18:25:51 +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=1723487151; cv=none; b=WEfd5RfFn1DGGq95GT1t9+Rbitk8fChOBHNS5o3hY2Idx6oYnw6Q1p0tyqSX1TtiYNez+AW0jhVWY0pIXT+1M2mY3QuSLSC/ltHs0/n5F4ebiHEK6+oHQGvX2CbcuAogMlXm+6WnIoKnOSCkLblqqyIg/9u0fIoCux8VmnJ3bek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487151; c=relaxed/simple; bh=0dpQ6RwX2xjp+lowuXDw7W+vANiY3byDZScI1bxbWmI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ItPIfNVWvUkrM5UjHyMaZGStktCS8+DQjTYZPKmHFECttdXtQmnpdO4EkPK2SfDrMamizZ6YKbpTG6HVWyDPPODjQ7mr7ZkCJ19FHrSqF507VaeMCQ6CMFftGgd3EyUSADfSLIq/4nDuw11IEn+qt1C4+LWQBSn19tq931lJSY8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RFANQs8K; 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="RFANQs8K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1086BC4AF0D; Mon, 12 Aug 2024 18:25:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487151; bh=0dpQ6RwX2xjp+lowuXDw7W+vANiY3byDZScI1bxbWmI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RFANQs8KnWUbqjWcgpReCK3akBNyTxN5G7+ALY8zDgxdFBUbg91hMAYGLm8Cyy46y 8hQ3vT0NqM6HMBHSF7PX/VMuaWGV6mqSQsdqCsquwk3VNxrZsONORzV7d1nPVvZhFR g2ojtllxh+Pkc9ypjJW9hBOU5J/CAVz2utpgqVYP5Ty+Itj77oCQRABIyPQHSL6bv3 cbZFxVx2do+sVzOMzZnlTpud1jdCOey3VwBjhOOZqaQYrwBUvp1JySoJIiPfkjS5Zp E+FgglRyvAii+4VL4l9l8d129f9gLgWwCHBKnPLqu9NtmuAn2KirH56B/V7DCIW5gY wP2q8rBP7VSEg== 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 v5 19/26] rust: error: use `core::alloc::LayoutError` Date: Mon, 12 Aug 2024 20:23:05 +0200 Message-ID: <20240812182355.11641-20-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 145f5c397009..2d012cc3881a 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 C56F519414A; Mon, 12 Aug 2024 18:25:56 +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=1723487156; cv=none; b=aA83sOuroVU2wab47mbF64Yp+RxovU4aIV4VzuXFiDfi48tARw3NxgN/XSTv7gTtPvQd29nuhYBsN1oNK6sKV8Zz7pzcIHCzrdKBuPheXcD7U+6EfTspLBw9G9D0luC31d4ZgUVGYB+oliPtiAtVMKUy8DrWp2eV02EaTv/zA8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487156; c=relaxed/simple; bh=2F6Eq8ZEErgwGsu4sxTQuCutTP6qKEaQ1vvV8Sy7t1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NfKS5vrz+nLJ/WcqmGhxT1y/jtE+I8ww+p12aKPbsd/dF/f02Oz1qJ2KXpF6cyUro4rb/ChTnoICq4PPWyz0c6zuJcBHcTdvn6ETxtbRFvVQyOYdMgzgb4sAFWad7dC9Fp9Svugwa5jAN5xBT7HF4xGKPhBbH6PRAna0roQjti4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p6j+mJpZ; 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="p6j+mJpZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B5DDC4AF09; Mon, 12 Aug 2024 18:25:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487156; bh=2F6Eq8ZEErgwGsu4sxTQuCutTP6qKEaQ1vvV8Sy7t1I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p6j+mJpZtX+GQyemhh1YN3z+WuLKkO07HkID9hB60cEgOmMMs5DJr4cHKl1pgGPeR 2zIpFnJHzziufgeTVg+xA5uce22bQeLWbfLDPV5oiSEq+SNKklaaVdlEROb6c81rIQ Q8CDN418goWJaq0ttWBuLX4VyQ7c24iY7eQ9d+3oJ7Gp9lREGXADM9jAIKJ3qTMJq4 eV4yUFZsIj6KTKDzj/3ZaX3CItDMBhnlUIwrWi7BQ819hVr6+KgPLw13G5v6DLQ6K8 tTVj59KMhsXhTZd8JhgIDl+XQxhKQiN4I+WuM2Eg0yLzJBA4rY+drE+cbFM0avdu4N sSJ85j4Uw23OQ== 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 v5 20/26] rust: error: check for config `test` in `Error::name` Date: Mon, 12 Aug 2024 20:23:06 +0200 Message-ID: <20240812182355.11641-21-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 2d012cc3881a..7adf889b9526 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -140,7 +140,7 @@ pub(crate) 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) }; @@ -157,7 +157,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 3B40F194A75; Mon, 12 Aug 2024 18:26:01 +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=1723487162; cv=none; b=Qy+PhNtkDNmL8y3GFSBIVANLUvo3qWViHgZ1aBUKgPoXWfI/ZQdT8n2+ewW59UJTl3uCacl1IYDOYxmPRjjnjpy15LPDd156mCIQAmK/pKxK6A9Kd74jCEGn7phjWr+mzqUxEaN9O/HLEhMPXEfOtcGANQ6w/3tPEeFetp7jq7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487162; c=relaxed/simple; bh=tl80HVK20EtCGNYhPnG7N36D8g8ociS1KN//HywX5k4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KfesOG/kfwG82XZ6QsVckvHsr+JevRe3njBy8mclQlIk1J7sQF/u0xIuNauyrVix/k5GPSVCOwmprW1dzrAFc7BpcBc+UnJBUMcDjTTQ2aj+fdtRZkEIIfXy1/bDyINlr/KNDnoelvJQkOjHswNReeu6hw1BLKVG8miXrzHW8v4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fE8d51Uy; 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="fE8d51Uy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DAB24C32782; Mon, 12 Aug 2024 18:25:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487161; bh=tl80HVK20EtCGNYhPnG7N36D8g8ociS1KN//HywX5k4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fE8d51Uywi9gQkO5aVDXQS6bCB1Esv9I/pGSi59+t323AQL2pLKex1YwXjRRlx6d5 /eMp8maDX8Z24YUglnm+TSz8p7tRMIXY6wA+hBLiVjTzJB8Z8UI4V7rfMUIySu8X05 NbpWU0BEcdDgCiWUCEJnk3RlTEtUoBjFYUZ8WYduUgOgZvaMJuvH5NX8w8Gb1L7yJN UOC7iLtJy1PUyPNFyWha7v5bQqsNZqK1J4V/j69V+bjeeiTqX8Fh8BY5ogM0CUP9H0 XS038gpPB6uo1XOmJhNY4JDsPmsllDzyaQFHv2n1Vfa6YQEuYH9rcE9xx7NjVAw0lk iaDfSWN3spO5A== 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 v5 21/26] rust: alloc: implement `contains` for `Flags` Date: Mon, 12 Aug 2024 20:23:07 +0200 Message-ID: <20240812182355.11641-22-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 820ef6072e02..be2bd0f1e74a 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -34,7 +34,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 { @@ -42,6 +42,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 5B81B1922DA; Mon, 12 Aug 2024 18:26:07 +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=1723487167; cv=none; b=P2iy3qEkT/ChLgJqhTcZaus+Pc+VZ46aH4RewlASIXW8hLjPkkpKqVBifG7PsykGLUCM307IMEB1Dm4qNnakTutB6KunDK4QPRFXlo1zpUACHHUFmQ0M0FTHmwRyfvQBEQiNDC4JcvPnali8uDSWEWKge5O+/FvosMujaX3qIqY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487167; c=relaxed/simple; bh=LmCPyxbPqQaXkN27gPwAem4xdq5E92W3egezxGjW9eU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qrhx01adzN0UC/Z4Gv0fvd8K9LL5tM4QYPqS/TPr1bM9bY9kHD0PpgE0MwgwQWIO9O/hIVYXA6ofz2BJ2MkwE1JRwwYQQZJKlXv94NsRfiFID5jxvsuuR4Rx2k+filVW4zldmkA79K7BSnU2RsnC2oSQYlKT3MvbzngJ2l7kBYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t3GTSs4f; 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="t3GTSs4f" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4597DC4AF09; Mon, 12 Aug 2024 18:26:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487167; bh=LmCPyxbPqQaXkN27gPwAem4xdq5E92W3egezxGjW9eU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t3GTSs4fGkfZXM4GLdYx9cwZTTgUpoGrI0FQ223qj2qmxXFuUgIMzF4mwsPA9A3yy BKqXYJAHNzPxxGAjf7IjZg4vgB+VEqDp3cwR26u8qhpueJz5nMUkX4oD5+lJnEUjlo Trc5yTqDP1rBNSwPP63aaqdyBmLmnuG+/DrA2WGrn25kZ6YYpOLVwaHaCA01tpcGLd 3tZ2/FjPyFZPZLiVItLdCy4hktujV38iB7QGnGR7ZmEjK6oqIlsYfe40y4V6BNrkfR X7F2nplRpLsGngdaeXX6A6GfmvQD7B4Ijwd4cvNhZi2oqIfdv9xtqgfh5JUIb4zMBh 4CA5NswVVefPA== 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 v5 22/26] rust: alloc: implement `Cmalloc` in module allocator_test Date: Mon, 12 Aug 2024 20:23:08 +0200 Message-ID: <20240812182355.11641-23-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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. Signed-off-by: Danilo Krummrich --- I know, having an `old_size` parameter would indeed help implementing `Cmal= loc`. However, I really don't want test infrastructure to influence the design of kernel internal APIs. It's on the test infrastructure to find a way to deal with it, even if it's= more complicated. --- rust/kernel/alloc/allocator_test.rs | 175 ++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 7 deletions(-) diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/alloca= tor_test.rs index 1b2642c547ec..7a20e64431ea 100644 --- a/rust/kernel/alloc/allocator_test.rs +++ b/rust/kernel/alloc/allocator_test.rs @@ -2,20 +2,181 @@ =20 #![allow(missing_docs)] =20 -use super::{AllocError, Allocator, Flags}; +use super::{flags::*, AllocError, Allocator, Flags}; use core::alloc::Layout; +use core::cmp; +use core::mem; +use core::ptr; use core::ptr::NonNull; =20 -pub struct Kmalloc; +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); +} + +struct CmallocData { + // The actual size as requested through `Cmalloc::alloc` or `Cmalloc::= realloc`. + size: usize, + // The offset from the pointer returned to the caller of `Cmalloc::all= oc` or `Cmalloc::realloc` + // to the actual base address of the allocation. + offset: usize, +} + +impl Cmalloc { + /// Adjust the size and alignment such that we can additionally store = `CmallocData` right + /// before the actual data described by `layout`. + /// + /// Example: + /// + /// For `CmallocData` assume an alignment of 8 and a size of 16. + /// For `layout` assume and alignment of 16 and a size of 64. + /// + /// 0 16 32 = 96 + /// |----------------|----------------|-------------------------------= -----------------| + /// empty CmallocData data + /// + /// For this example the returned `Layout` has an alignment of 32 and = a size of 96. + fn layout_adjust(layout: Layout) -> Result { + let layout =3D layout.pad_to_align(); + + // Ensure that `CmallocData` fits into half the alignment. Additio= nally, this guarantees + // that advancing a pointer aligned to `align` by `align / 2` we s= till satisfy or exceed + // the alignment requested through `layout`. + let align =3D cmp::max( + layout.align(), + mem::size_of::().next_power_of_two(), + ) * 2; + + // Add the additional space required for `CmallocData`. + let size =3D layout.size() + mem::size_of::(); + + Ok(Layout::from_size_align(size, align) + .map_err(|_| AllocError)? + .pad_to_align()) + } + + fn alloc_store_data(layout: Layout) -> Result, AllocError>= { + let requested_size =3D layout.size(); + + let layout =3D Self::layout_adjust(layout)?; + let min_align =3D layout.align() / 2; + + // SAFETY: Returns either NULL or a pointer to a memory allocation= that satisfies or + // exceeds the given size and alignment requirements. + let raw_ptr =3D unsafe { libc_aligned_alloc(layout.align(), layout= .size()) } as *mut u8; + + let priv_ptr =3D NonNull::new(raw_ptr).ok_or(AllocError)?; + + // SAFETY: Advance the pointer by `min_align`. The adjustments fro= m `Self::layout_adjust` + // ensure that after this operation the original size and alignmen= t requirements are still + // satisfied or exceeded. + let ptr =3D unsafe { priv_ptr.as_ptr().add(min_align) }; + + // SAFETY: `min_align` is greater than or equal to the size of `Cm= allocData`, hence we + // don't exceed the allocation boundaries. + let data_ptr: *mut CmallocData =3D unsafe { ptr.sub(mem::size_of::= ()) }.cast(); + + let data =3D CmallocData { + size: requested_size, + offset: min_align, + }; + + // SAFETY: `data_ptr` is properly aligned and within the allocatio= n boundaries reserved for + // `CmallocData`. + unsafe { data_ptr.write(data) }; + + NonNull::new(ptr).ok_or(AllocError) + } + + /// # Safety + /// + /// `ptr` must have been previously allocated with `Self::alloc_store_= data`. + unsafe fn data<'a>(ptr: NonNull) -> &'a CmallocData { + // SAFETY: `Self::alloc_store_data` stores the `CmallocData` right= before the address + // returned to callers of `Self::alloc_store_data`. + let data_ptr: *mut CmallocData =3D + unsafe { ptr.as_ptr().sub(mem::size_of::()) }.cas= t(); + + // SAFETY: The `CmallocData` has been previously stored at this of= fset with + // `Self::alloc_store_data`. + unsafe { &*data_ptr } + } + + /// # Safety + /// + /// This function must not be called more than once for the same alloc= ation. + /// + /// `ptr` must have been previously allocated with `Self::alloc_store_= data`. + unsafe fn free_read_data(ptr: NonNull) { + // SAFETY: `ptr` has been created by `Self::alloc_store_data`. + let data =3D unsafe { Self::data(ptr) }; + + // SAFETY: `ptr` has been created by `Self::alloc_store_data`. + let priv_ptr =3D unsafe { ptr.as_ptr().sub(data.offset) }; + + // SAFETY: `priv_ptr` has previously been allocatored with this `A= llocator`. + unsafe { libc_free(priv_ptr.cast()) }; + } +} + +unsafe impl Allocator for Cmalloc { + fn alloc(layout: Layout, flags: Flags) -> Result, AllocE= rror> { + if layout.size() =3D=3D 0 { + return Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0= )); + } + + let ptr =3D Self::alloc_store_data(layout)?; + + if flags.contains(__GFP_ZERO) { + // SAFETY: `Self::alloc_store_data` guarantees that `ptr` poin= ts to memory of at least + // `layout.size()` bytes. + unsafe { ptr.as_ptr().write_bytes(0, layout.size()) }; + } + + Ok(NonNull::slice_from_raw_parts(ptr, layout.size())) + } + unsafe fn realloc( - _ptr: Option>, - _layout: Layout, - _flags: Flags, + ptr: Option>, + layout: Layout, + flags: Flags, ) -> Result, AllocError> { - panic!(); + let src: NonNull =3D if let Some(src) =3D ptr { + src.cast() + } else { + return Self::alloc(layout, flags); + }; + + if layout.size() =3D=3D 0 { + // SAFETY: `src` has been created by `Self::alloc_store_data`. + unsafe { Self::free_read_data(src) }; + + return Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0= )); + } + + let dst =3D Self::alloc(layout, flags)?; + + // SAFETY: `src` has been created by `Self::alloc_store_data`. + let data =3D unsafe { Self::data(src) }; + + // SAFETY: `src` has previously been allocated with this `Allocato= r`; `dst` has just been + // newly allocated. Copy up to the smaller of both sizes. + unsafe { + ptr::copy_nonoverlapping( + src.as_ptr(), + dst.as_ptr().cast(), + cmp::min(layout.size(), data.size), + ) + }; + + Ok(dst) } } --=20 2.45.2 From nobody Sat Feb 7 15:09:42 2026 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 BD7401922DA; Mon, 12 Aug 2024 18:26: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=1723487172; cv=none; b=T2W1QiQ7ZvvklgpFyu1sJBfBJFwA1ljLLznmXlzu8VzrPoGUnrJtAC7E1VR3cfnpnuAAL0Je3YsH8xnFxqLD8dTOLovoahl7R46NEjyv1YeH5/abvPsUkzOOcqU5iIuJhxMFzFRf1v/2ZrCV2ov/Y4/rgYMWDr4YBli+dlzUUeU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487172; c=relaxed/simple; bh=SxIIf+SSSfq/ByqB+qb2+RtiJyH5BPK+PFBZGcm3qDM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pZLMtUTa6KsM4VtqL6skSmMmi8Q/tnTD0SqMEWXA6E2iuTVZO2Chk1kfO23PIwFsX+lwmj1Evv544n8g3Z+8R5pYRXSmJhEwzTlgAlb13Xlu47tFOdIxRL/RFMRZxOM3SUe+WD85kC/lz4lcgP+AhEo2r5UwqH8vZsHXA+KGxWI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K7jG6z+3; 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="K7jG6z+3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD867C4AF09; Mon, 12 Aug 2024 18:26:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487172; bh=SxIIf+SSSfq/ByqB+qb2+RtiJyH5BPK+PFBZGcm3qDM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K7jG6z+3m6ZxFsGXWBawNolBPj9HDFiJ+jJbgWgSYU/Bo/BLz6Pp3ReAsC31yciEI RmHM57eHf3FgMPfF4E0cuk0P3mTZJe1gWJuKYbnyDPUaA04ll0yzwsvXSaCJ3BlBck WyO81o6zRTQMz831jpTuwtl4Jh9LVcLBhNeAGQfpu9rcJHNTSEEJNYF71Go5BM5bX6 S2y4NTJ1ealfzYlRIIGKlxwSAwRHoeKbSk1QtVAoFmRDWgr7GXsHjl643pPGylZTW3 RFedq47VIXKszDfEcxP1PJkcuDHYtpF7oC2Z4s6hqB/DvMsvDUMO8neVPx1WuCqKbp g1ggCMovo94Pw== 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 v5 23/26] rust: str: test: replace `alloc::format` Date: Mon, 12 Aug 2024 20:23:09 +0200 Message-ID: <20240812182355.11641-24-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 209ad1bb1a49..726329530338 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -523,7 +523,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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 2B31419B3EC; Mon, 12 Aug 2024 18:26:18 +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=1723487178; cv=none; b=lUHgW1NWeQPEGhtHjLoxjKDbM/AjMfnGEzrcA6zl5UTXKCFAIESy+xo0xI1MUfe5V6DSbtHQ71hoq40BJECHEohwgzC83AjQa51jw16FTmHoBUcDjU2GuN9ZJ9+h2SbrkJMbVLh3DKee4RiPrvFTuID3JXgOHaAFIpZnORsEk20= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487178; c=relaxed/simple; bh=blDL6gfz+IKgF0QGtqP0bU2aIjtbW4lMlGcoQxrbKCw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GgbtsI7e4r0iQfPZo7jJdIEAO32iHSUPEEr0dyLJoaGaJiIHsJZ6IokxAihtf2rQiRNIbY0v4+EBz2uD5FbGC7NSE2RXeY5A41DhwpexemiMDbufOxBvAK8To2VT9aOi1BtZdYs5AHEaQ4gYhcO4Uj8uXL/UtgRP5MoK2WNi3/0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j0ejD2cK; 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="j0ejD2cK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1BC2FC4AF0C; Mon, 12 Aug 2024 18:26:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487178; bh=blDL6gfz+IKgF0QGtqP0bU2aIjtbW4lMlGcoQxrbKCw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j0ejD2cKN1Yda7MLbZ1sGcQbdEykpeupJ5GzPzGRGxYBhzuKhNwTbgYdHuXLkWvDK /RUO4uugW0iM0P/QTXZA2Iph+OGwWBO9VpBZ83LwxJo2DOVZ0IBnRNYEgUhKSQU91u yxvHaWSNEezuB/y14tKW15XS1MF/Ir6HnqsiRxpnlZxXYfUw6KDF491K8qq3ZI8Xil 9USenuaFeAd6QGmwCPocQ2MUj5Jklpflnt32sggrRqvJkEftwifrXb5ZLM9ZzncQJJ pnX0qMZiwpWdiOFwhZpC73tM7TKDkRnSm5IEiUHlSwSiz2+KeEiAADLfFw9leKcXL8 L8lVNrPJBzkzg== 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 v5 24/26] rust: alloc: update module comment of alloc.rs Date: Mon, 12 Aug 2024 20:23:10 +0200 Message-ID: <20240812182355.11641-25-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 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 be2bd0f1e74a..b2a41359a18d 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 C75E819CCEB; Mon, 12 Aug 2024 18:26: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=1723487183; cv=none; b=fLvTWZM3iWXM1tlEXLAJO1y8dFXUfNuffbLj7RYmNuV/ysg+J1qFL5UJNf+LSCZg7t0Sis/kaP1lyudRjNpAyDlb4QB4L5YaMCHiQOgDQQAEenlOI77ZpyLLpYOxB+Y58d2gU+pI/qE+b94UsJ+n/ZACDF9FR3E/su6LXgxaqII= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487183; c=relaxed/simple; bh=hgqCEKFBsyL+bevkPQnvZdQLN9AhKh3OlQraSfmVBSQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Eu6UcpriXEIjxqwbONuDUBFMegKK9g1PDV8NV62GAhp5tv4O2+3bXtoj3xL6GRiUmL1S+//cZDWdkaisjaNN1w5DlZHcRwp5Yogg0OzO1LVN64EOYM3rZuW0fNchCSeWmJOB35HXo+aGPky2bxbZI5wDSVpekNqfWeLtbrOv2p8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hxAVZOB3; 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="hxAVZOB3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B5D7C4AF09; Mon, 12 Aug 2024 18:26:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487183; bh=hgqCEKFBsyL+bevkPQnvZdQLN9AhKh3OlQraSfmVBSQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hxAVZOB30txHaSBwNvrnh50bmOB3ceSc6NeV11kFNLhvnvTZNZ/+gexWW6jxTqkng t2HhVZUfSlX3zuf804kywEinA7H8t8cox81+rl7TROlFFadluDpoNUk6qPzeAT4eBq vgnMDcUwcLwLLuKRXP+bqZ1biIU+T6tw/CWUtF+42Vx5dUiD/3GgLsjHGv7Mr6asIe kdMUodxwGB+MgZHejZv1lCoyVWNehPT4R6uiFoJ78NFApdLK5xUZJ59ciaR7okUzcV IVHOg/E/WLZEhlkI+UWVGxtVdD1jZjAM0Ija4GxLZ8rFaMn4G56zIxOTs26e1YFqYg ZmIHskGQifxOA== 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 v5 25/26] kbuild: rust: remove the `alloc` crate and `GlobalAlloc` Date: Mon, 12 Aug 2024 20:23:11 +0200 Message-ID: <20240812182355.11641-26-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 | 44 ++++++----------------- rust/exports.c | 1 - rust/kernel/alloc/allocator.rs | 59 ++----------------------------- scripts/Makefile.build | 7 +--- scripts/generate_rust_analyzer.py | 11 ++---- 5 files changed, 15 insertions(+), 107 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index 1f10f92737f2..8900c3d06573 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -15,9 +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_bindings_gene= rated.h \ - exports_kernel_generated.h +obj-$(CONFIG_RUST) +=3D bindings.o kernel.o +always-$(CONFIG_RUST) +=3D exports_bindings_generated.h exports_kernel_gen= erated.h =20 always-$(CONFIG_RUST) +=3D uapi/uapi_generated.rs obj-$(CONFIG_RUST) +=3D uapi.o @@ -53,11 +52,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)) \ @@ -80,7 +74,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 \ @@ -104,20 +98,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 @@ -161,7 +146,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 \ @@ -197,7 +182,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 \ @@ -310,9 +295,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) - $(obj)/exports_bindings_generated.h: $(obj)/bindings.o FORCE $(call if_changed,exports) =20 @@ -348,7 +330,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)) \ $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \ $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json @@ -380,12 +362,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_dep,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_dep,rustc_library) - $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FOR= CE +$(call if_changed_dep,rustc_library) =20 @@ -400,9 +376,9 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \ $(obj)/uapi/uapi_generated.rs FORCE +$(call if_changed_dep,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_dep,rustc_library) =20 diff --git a/rust/exports.c b/rust/exports.c index 3803c21d1403..1b870e8e83ea 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_bindings_generated.h" #include "exports_kernel_generated.h" =20 diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 243d8c49a57b..b1580534947d 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -2,8 +2,8 @@ =20 //! Allocator support. =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 @@ -40,23 +40,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`. @@ -116,41 +99,6 @@ unsafe fn realloc( } } =20 -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) { - 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) } - } -} - unsafe impl Allocator for Vmalloc { unsafe fn realloc( ptr: Option>, @@ -187,9 +135,6 @@ unsafe fn realloc( } } =20 -#[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 efacca63c897..7e7b6b3d5bb9 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -262,18 +262,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE =20 # Compile Rust sources (.rs) # ------------------------------------------------------------------------= --- - -rust_allowed_features :=3D new_uninit - # `--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 # modules case. rust_common_cmd =3D \ RUST_MODFILE=3D$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ - -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 f270c7b0cf34..3421a9ea3604 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.45.2 From nobody Sat Feb 7 15:09:42 2026 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 46E1419CCEB; Mon, 12 Aug 2024 18:26: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=1723487189; cv=none; b=BcEEV1jVVA1PIzMqaMc1YD/daQbRfAxNqNRCQop4az7DFJwtw6tdSG8Zz1JtO6OpzJTVrr6PdNGP1YTPNPvt9aEUjXgR1V8oB6/ZgVWmN7LI66AixKylKhsBUhoHSfdRNtxmITWeQIWqTdIq9mFLYdyBj3pUHn4idwvaBf+XpWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723487189; c=relaxed/simple; bh=pq9p+3MKfusrm9d+dkS4M59Yq++w7zxN0VRikqPFNQM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZR4+YSX6jdjbbLRgQCRSasIes2TVrXpQJlvjnwwpywXjQv6U0/NMqQ6Jqo7KZctYDa8XhSIwEsZZOpENU7RzwqsphAizXFdLgiFO7ME3dhS8FqImu8h8wnfxDRik0w36AaoEohpnrue9wKeex5jwwxwG2Zh5KAyeOYrIFgg7OYE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IrewnQXR; 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="IrewnQXR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9884C4AF15; Mon, 12 Aug 2024 18:26:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1723487188; bh=pq9p+3MKfusrm9d+dkS4M59Yq++w7zxN0VRikqPFNQM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IrewnQXRBh0PBYuwXSIQzmoElmSkGlvcMIqqYkJoje+DqQVUvmpLyAjNKgHZj2XyC bLeNJWuUkdDY83SrJNoBjfbUX/5YEjdHOr2qvbI08G7Y8m/JJ9C9PWI7gEj7NEdg56 QMfJavksWPUfcD+0yrlxQqeXCHHsLY//EgheijRgeFWVjkW8fiAINf04QtccJXnICd zX4WVPUZ6XkHAB9nTETApAZM7kDsvWEMYZW0Ds5g9QfWDJtXvff/bLThXq6pF6eTdN eHpJ9utvJFX4N4z0b7ivpkyafVprJqj/0uvR1l/Hd/U+aH/x++mqll/JMs5mbzrMTI ImMXMjHnkjaeQ== 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 v5 26/26] MAINTAINERS: add entry for the Rust `alloc` module Date: Mon, 12 Aug 2024 20:23:12 +0200 Message-ID: <20240812182355.11641-27-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812182355.11641-1-dakr@kernel.org> References: <20240812182355.11641-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 42decde38320..560516b3aaf4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19925,6 +19925,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.45.2