Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: support large alignments in allocations

Add support for large (> PAGE_SIZE) alignments in Rust allocators. All
the preparations on the C side are already done, we just need to add
bindings for <alloc>_node_align() functions and start using those.

Link: https://lkml.kernel.org/r/20250806125552.1727073-1-vitaly.wool@konsulko.se
Signed-off-by: Vitaly Wool <vitaly.wool@konsulko.se>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Acked-by: Alice Ryhl <aliceryhl@google.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Jann Horn <jannh@google.com>
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Uladzislau Rezki (Sony) <urezki@gmail.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Vitaly Wool and committed by
Andrew Morton
17387969 7760b642

+18 -27
+6 -4
rust/helpers/slab.c
··· 3 3 #include <linux/slab.h> 4 4 5 5 void * __must_check __realloc_size(2) 6 - rust_helper_krealloc_node(const void *objp, size_t new_size, gfp_t flags, int node) 6 + rust_helper_krealloc_node_align(const void *objp, size_t new_size, unsigned long align, 7 + gfp_t flags, int node) 7 8 { 8 - return krealloc_node(objp, new_size, flags, node); 9 + return krealloc_node_align(objp, new_size, align, flags, node); 9 10 } 10 11 11 12 void * __must_check __realloc_size(2) 12 - rust_helper_kvrealloc_node(const void *p, size_t size, gfp_t flags, int node) 13 + rust_helper_kvrealloc_node_align(const void *p, size_t size, unsigned long align, 14 + gfp_t flags, int node) 13 15 { 14 - return kvrealloc_node(p, size, flags, node); 16 + return kvrealloc_node_align(p, size, align, flags, node); 15 17 }
+3 -2
rust/helpers/vmalloc.c
··· 3 3 #include <linux/vmalloc.h> 4 4 5 5 void * __must_check __realloc_size(2) 6 - rust_helper_vrealloc_node(const void *p, size_t size, gfp_t flags, int node) 6 + rust_helper_vrealloc_node_align(const void *p, size_t size, unsigned long align, 7 + gfp_t flags, int node) 7 8 { 8 - return vrealloc_node(p, size, flags, node); 9 + return vrealloc_node_align(p, size, align, flags, node); 9 10 }
+9 -21
rust/kernel/alloc/allocator.rs
··· 15 15 16 16 use crate::alloc::{AllocError, Allocator, NumaNode}; 17 17 use crate::bindings; 18 - use crate::pr_warn; 19 18 20 19 /// The contiguous kernel allocator. 21 20 /// ··· 44 45 45 46 /// # Invariants 46 47 /// 47 - /// One of the following: `krealloc_node`, `vrealloc_node`, `kvrealloc_node`. 48 + /// One of the following: `krealloc_node_align`, `vrealloc_node_align`, `kvrealloc_node_align`. 48 49 struct ReallocFunc( 49 50 unsafe extern "C" fn( 50 51 *const crate::ffi::c_void, 51 52 usize, 53 + crate::ffi::c_ulong, 52 54 u32, 53 55 crate::ffi::c_int, 54 56 ) -> *mut crate::ffi::c_void, 55 57 ); 56 58 57 59 impl ReallocFunc { 58 - // INVARIANT: `krealloc_node` satisfies the type invariants. 59 - const KREALLOC: Self = Self(bindings::krealloc_node); 60 + // INVARIANT: `krealloc_node_align` satisfies the type invariants. 61 + const KREALLOC: Self = Self(bindings::krealloc_node_align); 60 62 61 - // INVARIANT: `vrealloc_node` satisfies the type invariants. 62 - const VREALLOC: Self = Self(bindings::vrealloc_node); 63 + // INVARIANT: `vrealloc_node_align` satisfies the type invariants. 64 + const VREALLOC: Self = Self(bindings::vrealloc_node_align); 63 65 64 - // INVARIANT: `kvrealloc_node` satisfies the type invariants. 65 - const KVREALLOC: Self = Self(bindings::kvrealloc_node); 66 + // INVARIANT: `kvrealloc_node_align` satisfies the type invariants. 67 + const KVREALLOC: Self = Self(bindings::kvrealloc_node_align); 66 68 67 69 /// # Safety 68 70 /// ··· 105 105 // - Those functions provide the guarantees of this function. 106 106 let raw_ptr = unsafe { 107 107 // If `size == 0` and `ptr != NULL` the memory behind the pointer is freed. 108 - self.0(ptr.cast(), size, flags.0, nid.0).cast() 108 + self.0(ptr.cast(), size, layout.align(), flags.0, nid.0).cast() 109 109 }; 110 110 111 111 let ptr = if size == 0 { ··· 162 162 flags: Flags, 163 163 nid: NumaNode, 164 164 ) -> Result<NonNull<[u8]>, AllocError> { 165 - // TODO: Support alignments larger than PAGE_SIZE. 166 - if layout.align() > bindings::PAGE_SIZE { 167 - pr_warn!("Vmalloc does not support alignments larger than PAGE_SIZE yet.\n"); 168 - return Err(AllocError); 169 - } 170 - 171 165 // SAFETY: If not `None`, `ptr` is guaranteed to point to valid memory, which was previously 172 166 // allocated with this `Allocator`. 173 167 unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags, nid) } ··· 184 190 // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc` 185 191 // compatible layout. 186 192 let layout = Kmalloc::aligned_layout(layout); 187 - 188 - // TODO: Support alignments larger than PAGE_SIZE. 189 - if layout.align() > bindings::PAGE_SIZE { 190 - pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n"); 191 - return Err(AllocError); 192 - } 193 193 194 194 // SAFETY: If not `None`, `ptr` is guaranteed to point to valid memory, which was previously 195 195 // allocated with this `Allocator`.