From nobody Wed Oct 8 11:50:47 2025 Received: from mailrelay-egress12.pub.mailoutpod2-cph3.one.com (mailrelay-egress12.pub.mailoutpod2-cph3.one.com [46.30.211.187]) (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 1EDAD13BAE3 for ; Sat, 28 Jun 2025 10:25:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.30.211.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106352; cv=none; b=fOXFKQr+hyrAbh6EgHpqMWTdbke1S2IjNQTU/gRjZTDmnAMSpqUv649RurlPfrZbogoFbGH07bihCEMIv3zgbW4rPh0LgV9/ia0TGtWeAore1/TwfIetGu2RTuj27vOhc0eOzGyoMvXJN/Osg9rnvtNkRybtv51YQZxBVxgyne8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106352; c=relaxed/simple; bh=nZYbj1yAtgECMipsnUNlHPUK4pJhICc9gnUVyRAhqpM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oFoZov1LlxuEQRi7zHBORZqz0YiW4OY/oOxowGMgpyazgxvv9Q+kjFL67zDbzFNVIpEtdrLPvCY9P2lvYnY+CM6GOYcZuCG/2suy+FMMFi7aSR2/kSiupFGicOOcyL/i4swztuFIqa+zPDaZ4bCmOPnl7QrYGZ/MhU47ElLi/G8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se; spf=none smtp.mailfrom=konsulko.se; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=tKbMwsNy; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=3Cx0u+rk; arc=none smtp.client-ip=46.30.211.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=konsulko.se Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="tKbMwsNy"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="3Cx0u+rk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751106343; x=1751711143; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=cg6Mb0y63NoDrvRbc/wKLzTLQZaf3be1Lhc8PUfhwzc=; b=tKbMwsNyIkt/bTwNj0rS4UH6zvFFzJGbmhgbVHAJ8ZrDQvIffWCH35ZERPZcXT9QhCH71fR4StMiM jVjszMRLvMi6fdD7suY6HOypKZ5Se3srobtzUe8Hk4TfqtL+iygxsb0RkqmWhGOGDCqlehnaX+7NrU bBb8c24fuxRzXVM/DuRegAdlOfit1b5a04jbiQPJX7fjZjga5wIn4s1CQq1wbTk4/YSqxZwB+sRG0v 10KWxXiKk2KJdntER5viXvFyBhWY8ioy0B+diRjvU/iUOE1eJtMJtWgBAdHBIHqlUaVlz2pa0zbT6S bZVlamSlWDszecFpA9LaMXbCEnp8VBg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751106343; x=1751711143; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=cg6Mb0y63NoDrvRbc/wKLzTLQZaf3be1Lhc8PUfhwzc=; b=3Cx0u+rk5lfa4MfnUhs/vJ1SknAS8kGUuR/1qfyj1wr2+IhX8NDzDPItusiR62t0dkPGSm1AIytPe cIi3ui7Dg== X-HalOne-ID: 3d44602b-540a-11f0-b10f-85eb291bc831 Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay5.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 3d44602b-540a-11f0-b10f-85eb291bc831; Sat, 28 Jun 2025 10:25:42 +0000 (UTC) From: Vitaly Wool To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, Uladzislau Rezki , Danilo Krummrich , Alice Ryhl , rust-for-linux@vger.kernel.org, Vitaly Wool Subject: [PATCH v8 1/4] mm/vmalloc: allow to set node and align in vrealloc Date: Sat, 28 Jun 2025 12:25:37 +0200 Message-Id: <20250628102537.2542789-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250628102315.2542656-1-vitaly.wool@konsulko.se> References: <20250628102315.2542656-1-vitaly.wool@konsulko.se> 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" Reimplement vrealloc() to be able to set node and alignment should a user need to do so. Rename the function to vrealloc_node_align() to better match what it actually does now and introduce macros for vrealloc() and friends for backward compatibility. With that change we also provide the ability for the Rust part of the kernel to set node and aligmnent in its allocations. Signed-off-by: Vitaly Wool --- include/linux/vmalloc.h | 12 +++++++++--- mm/vmalloc.c | 20 ++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index fdc9aeb74a44..68791f7cb3ba 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -197,9 +197,15 @@ extern void *__vcalloc_noprof(size_t n, size_t size, g= fp_t flags) __alloc_size(1 extern void *vcalloc_noprof(size_t n, size_t size) __alloc_size(1, 2); #define vcalloc(...) alloc_hooks(vcalloc_noprof(__VA_ARGS__)) =20 -void * __must_check vrealloc_noprof(const void *p, size_t size, gfp_t flag= s) - __realloc_size(2); -#define vrealloc(...) alloc_hooks(vrealloc_noprof(__VA_ARGS__)) +void *__must_check vrealloc_node_align_noprof(const void *p, size_t size, + unsigned long align, gfp_t flags, int nid) __realloc_size(2); +#define vrealloc_node_noprof(_p, _s, _f, _nid) \ + vrealloc_node_align_noprof(_p, _s, 1, _f, _nid) +#define vrealloc_noprof(_p, _s, _f) \ + vrealloc_node_align_noprof(_p, _s, 1, _f, NUMA_NO_NODE) +#define vrealloc_node_align(...) alloc_hooks(vrealloc_node_align_noprof(_= _VA_ARGS__)) +#define vrealloc_node(...) alloc_hooks(vrealloc_node_noprof(__VA_ARGS__)) +#define vrealloc(...) alloc_hooks(vrealloc_noprof(__VA_ARGS__)) =20 extern void vfree(const void *addr); extern void vfree_atomic(const void *addr); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6dbcdceecae1..d633ac0ff977 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -4089,12 +4089,15 @@ void *vzalloc_node_noprof(unsigned long size, int n= ode) EXPORT_SYMBOL(vzalloc_node_noprof); =20 /** - * vrealloc - reallocate virtually contiguous memory; contents remain unch= anged + * vrealloc_node_align_noprof - reallocate virtually contiguous memory; co= ntents + * remain unchanged * @p: object to reallocate memory for * @size: the size to reallocate + * @align: requested alignment * @flags: the flags for the page level allocator + * @nid: node id * - * If @p is %NULL, vrealloc() behaves exactly like vmalloc(). If @size is = 0 and + * If @p is %NULL, vrealloc_XXX() behaves exactly like vmalloc(). If @size= is 0 and * @p is not a %NULL pointer, the object pointed to is freed. * * If __GFP_ZERO logic is requested, callers must ensure that, starting wi= th the @@ -4111,7 +4114,8 @@ EXPORT_SYMBOL(vzalloc_node_noprof); * Return: pointer to the allocated memory; %NULL if @size is zero or in c= ase of * failure */ -void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) +void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long= align, + gfp_t flags, int nid) { struct vm_struct *vm =3D NULL; size_t alloced_size =3D 0; @@ -4135,6 +4139,13 @@ void *vrealloc_noprof(const void *p, size_t size, gf= p_t flags) if (WARN(alloced_size < old_size, "vrealloc() has mismatched area vs requested sizes (%p)\n", p)) return NULL; + if (WARN(nid !=3D NUMA_NO_NODE && nid !=3D page_to_nid(vmalloc_to_page(p= )), + "vrealloc() has mismatched nids\n")) + return NULL; + if (WARN((uintptr_t)p & (align - 1), + "will not reallocate with a bigger alignment (0x%lx)\n", + align)) + return NULL; } =20 /* @@ -4166,7 +4177,8 @@ void *vrealloc_noprof(const void *p, size_t size, gfp= _t flags) } =20 /* TODO: Grow the vm_area, i.e. allocate and map additional pages. */ - n =3D __vmalloc_noprof(size, flags); + n =3D __vmalloc_node_noprof(size, align, flags, nid, __builtin_return_add= ress(0)); + if (!n) return NULL; =20 --=20 2.39.2 From nobody Wed Oct 8 11:50:47 2025 Received: from mailrelay3-3.pub.mailoutpod3-cph3.one.com (mailrelay3-3.pub.mailoutpod3-cph3.one.com [46.30.212.2]) (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 4488221ADAE for ; Sat, 28 Jun 2025 10:26:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.30.212.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106365; cv=none; b=XSlbrbEaoGCGCuxDumxAR5S5WGKAv7GG2vVQB6eWWldg/NEruJDGY9KkxRUqgXhPn3p8JmM+KRlS414C2o5l88jcaJkimEA5aE+yuQrHYB8YBg0yvpwwyKffypVdQQzxs8a9cCUDt1UM8ghzVs6ylmNmW5W7bFT5zLUwhvySha4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106365; c=relaxed/simple; bh=NoHgq+K26IsAvEj6C2qrVRM6ACWDYkgMMicsGvtZPXI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ss3ggLlKFzz4NvbxBtknwIN5jU35XGcGu555jEt6QaRNJiX1UO/SXEY4WL7jZ3Pe2/LLjN832MemvGzWiFgE5g5dxrab1nJ1OaSYcyBNOGS/jiHvmFJ9X5JQ/X+wG3uuifqI+E0zMW2WwPFrhrvnUPCU+TBLlqtzy3Vpynttggs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se; spf=none smtp.mailfrom=konsulko.se; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=CY72p/GA; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=7quBsTVQ; arc=none smtp.client-ip=46.30.212.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=konsulko.se Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="CY72p/GA"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="7quBsTVQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751106360; x=1751711160; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=4ZIeiPu/zic9E4s7Al+vArUw1KwvYwIAaepoA+hvdNI=; b=CY72p/GA46qhHX+X7eqno86I9FBm9pjk8KHgj9fIMIAUucDlWZ7HlB3gbj2emqV2sbufq8CgK43WI C8hjYPNUhLMC8hfCQXyUklvZuBITan2biDIZUAnMHDGQ6o8uvzPHfuCcFdPyIC6DWR0Nxko8txVmrk T3qXe6hayKCYrJ4T0AdUoiXIpx/Z29HYyUpMmRwt7u4VbN4llUFBOniuxryhKs51Yt3aoshetBHbTx CHVnNrXL6uHGaDQJBi10h6Gk8lBtVaWgpUVyngYtstzZgVmA0wxBOdzip1WqgvD1Z0WAZ/tRV3a4zu cicXQkKBI8MMfMgyUr+f0wzbkSNKkhg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751106360; x=1751711160; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=4ZIeiPu/zic9E4s7Al+vArUw1KwvYwIAaepoA+hvdNI=; b=7quBsTVQt9qd1r8VSm44KNmBO+N55FIXNrmHMJqAb/DZU1OmNVyExxgdDFrYUmFg5AxHSYyu17sNS IxXsGPLDQ== X-HalOne-ID: 47d75440-540a-11f0-af5d-2b8368a4d5c5 Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay3.pub.mailoutpod3-cph3.one.com (Halon) with ESMTPSA id 47d75440-540a-11f0-af5d-2b8368a4d5c5; Sat, 28 Jun 2025 10:25:59 +0000 (UTC) From: Vitaly Wool To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, Uladzislau Rezki , Danilo Krummrich , Alice Ryhl , rust-for-linux@vger.kernel.org, Vitaly Wool Subject: [PATCH v8 2/4] mm/slub: allow to set node and align in k[v]realloc Date: Sat, 28 Jun 2025 12:25:58 +0200 Message-Id: <20250628102558.2542886-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250628102315.2542656-1-vitaly.wool@konsulko.se> References: <20250628102315.2542656-1-vitaly.wool@konsulko.se> 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" Reimplement k[v]realloc_node() to be able to set node and alignment should a user need to do so. In order to do that while retaining the maximal backward compatibility, add k[v]realloc_node_align() functions and redefine the rest of API using these new ones. With that change we also provide the ability for the Rust part of the kernel to set node and aligmnent in its K[v]xxx [re]allocations. Signed-off-by: Vitaly Wool --- include/linux/slab.h | 40 +++++++++++++++++++--------- mm/nommu.c | 3 ++- mm/slub.c | 63 ++++++++++++++++++++++++++++++-------------- 3 files changed, 72 insertions(+), 34 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index d5a8ab98035c..13abcf4ada22 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -465,9 +465,15 @@ int kmem_cache_shrink(struct kmem_cache *s); /* * Common kmalloc functions provided by all allocators */ -void * __must_check krealloc_noprof(const void *objp, size_t new_size, - gfp_t flags) __realloc_size(2); -#define krealloc(...) alloc_hooks(krealloc_noprof(__VA_ARGS__)) +void * __must_check krealloc_node_align_noprof(const void *objp, size_t ne= w_size, + unsigned long align, + gfp_t flags, int nid) __realloc_size(2); +#define krealloc_node_noprof(_p, _s, _f, _n) \ + krealloc_node_align_noprof(_p, _s, 1, _f, _n) +#define krealloc_noprof(...) krealloc_node_noprof(__VA_ARGS__, NUMA_NO_NO= DE) +#define krealloc_node_align(...) alloc_hooks(krealloc_node_align_noprof(__= VA_ARGS__)) +#define krealloc_node(...) alloc_hooks(krealloc_node_noprof(__VA_ARGS__)) +#define krealloc(...) alloc_hooks(krealloc_noprof(__VA_ARGS__)) =20 void kfree(const void *objp); void kfree_sensitive(const void *objp); @@ -1041,18 +1047,23 @@ static inline __alloc_size(1) void *kzalloc_noprof(= size_t size, gfp_t flags) #define kzalloc(...) alloc_hooks(kzalloc_noprof(__VA_ARGS__)) #define kzalloc_node(_size, _flags, _node) kmalloc_node(_size, (_flags)|__= GFP_ZERO, _node) =20 -void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), gfp_t flags, int= node) __alloc_size(1); -#define kvmalloc_node_noprof(size, flags, node) \ - __kvmalloc_node_noprof(PASS_BUCKET_PARAMS(size, NULL), flags, node) +void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), unsigned long al= ign, + gfp_t flags, int node) __alloc_size(1); +#define kvmalloc_node_align_noprof(_size, _align, _flags, _node) \ + __kvmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, NULL), _align, _flags, _= node) +#define kvmalloc_node_noprof(_size, _flags, _node) \ + kvmalloc_node_align_noprof(_size, 1, _flags, _node) +#define kvmalloc_node_align(...) \ + alloc_hooks(kvmalloc_node_align_noprof(__VA_ARGS__)) #define kvmalloc_node(...) alloc_hooks(kvmalloc_node_noprof(__VA_ARGS__)) =20 -#define kvmalloc(_size, _flags) kvmalloc_node(_size, _flags, NUMA_NO_NOD= E) -#define kvmalloc_noprof(_size, _flags) kvmalloc_node_noprof(_size, _flags= , NUMA_NO_NODE) +#define kvmalloc_noprof(...) kvmalloc_node_noprof(__VA_ARGS__, NUMA_NO_N= ODE) +#define kvmalloc(...) alloc_hooks(kvmalloc_noprof(__VA_ARGS__)) #define kvzalloc(_size, _flags) kvmalloc(_size, (_flags)|__GFP_ZERO) =20 -#define kvzalloc_node(_size, _flags, _node) kvmalloc_node(_size, (_flags)|= __GFP_ZERO, _node) +#define kvzalloc_node(_s, _f, _n) kvmalloc_node(_s, (_f)|__GFP_ZERO, _n) #define kmem_buckets_valloc(_b, _size, _flags) \ - alloc_hooks(__kvmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags,= NUMA_NO_NODE)) + alloc_hooks(__kvmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), 1, _fla= gs, NUMA_NO_NODE)) =20 static inline __alloc_size(1, 2) void * kvmalloc_array_node_noprof(size_t n, size_t size, gfp_t flags, int node) @@ -1068,13 +1079,16 @@ kvmalloc_array_node_noprof(size_t n, size_t size, g= fp_t flags, int node) #define kvmalloc_array_noprof(...) kvmalloc_array_node_noprof(__VA_ARGS__= , NUMA_NO_NODE) #define kvcalloc_node_noprof(_n,_s,_f,_node) kvmalloc_array_node_noprof(_n= ,_s,(_f)|__GFP_ZERO,_node) #define kvcalloc_noprof(...) kvcalloc_node_noprof(__VA_ARGS__, NUMA_NO_N= ODE) - #define kvmalloc_array(...) alloc_hooks(kvmalloc_array_noprof(__VA_ARGS_= _)) #define kvcalloc_node(...) alloc_hooks(kvcalloc_node_noprof(__VA_ARGS__)) #define kvcalloc(...) alloc_hooks(kvcalloc_noprof(__VA_ARGS__)) =20 -void *kvrealloc_noprof(const void *p, size_t size, gfp_t flags) - __realloc_size(2); +void *kvrealloc_node_align_noprof(const void *p, size_t size, unsigned lon= g align, + gfp_t flags, int nid) __realloc_size(2); +#define kvrealloc_node_align(...) kvrealloc_node_align_noprof(__VA_ARGS__) +#define kvrealloc_node_noprof(_p, _s, _f, _n) kvrealloc_node_align_noprof(= _p, _s, 1, _f, _n) +#define kvrealloc_node(...) alloc_hooks(kvrealloc_node_noprof(__VA_ARGS_= _)) +#define kvrealloc_noprof(...) kvrealloc_node_noprof(__VA_ARGS__, NUMA_NO= _NODE) #define kvrealloc(...) alloc_hooks(kvrealloc_noprof(__VA_ARGS__)) =20 extern void kvfree(const void *addr); diff --git a/mm/nommu.c b/mm/nommu.c index 87e1acab0d64..8359b2025b9f 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -119,7 +119,8 @@ void *__vmalloc_noprof(unsigned long size, gfp_t gfp_ma= sk) } EXPORT_SYMBOL(__vmalloc_noprof); =20 -void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) +void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long= align, + gfp_t flags, int node) { return krealloc_noprof(p, size, (flags | __GFP_COMP) & ~__GFP_HIGHMEM); } diff --git a/mm/slub.c b/mm/slub.c index c4b64821e680..ec355ce31965 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4845,7 +4845,7 @@ void kfree(const void *object) EXPORT_SYMBOL(kfree); =20 static __always_inline __realloc_size(2) void * -__do_krealloc(const void *p, size_t new_size, gfp_t flags) +__do_krealloc(const void *p, size_t new_size, unsigned long align, gfp_t f= lags, int nid) { void *ret; size_t ks =3D 0; @@ -4859,6 +4859,19 @@ __do_krealloc(const void *p, size_t new_size, gfp_t = flags) if (!kasan_check_byte(p)) return NULL; =20 + /* refuse to proceed if alignment is bigger than what kmalloc() provides = */ + if (((uintptr_t)p & (align - 1)) || new_size < align) + return NULL; + + /* + * it is possible to support reallocation with a different nid, but + * it doesn't go well with the concept of krealloc(). Such + * reallocation should be done explicitly instead. + */ + if (WARN(nid !=3D NUMA_NO_NODE && nid !=3D page_to_nid(virt_to_page(p)), + "krealloc() has mismatched nids\n")) + return NULL; + if (is_kfence_address(p)) { ks =3D orig_size =3D kfence_ksize(p); } else { @@ -4903,7 +4916,7 @@ __do_krealloc(const void *p, size_t new_size, gfp_t f= lags) return (void *)p; =20 alloc_new: - ret =3D kmalloc_node_track_caller_noprof(new_size, flags, NUMA_NO_NODE, _= RET_IP_); + ret =3D kmalloc_node_track_caller_noprof(new_size, flags, nid, _RET_IP_); if (ret && p) { /* Disable KASAN checks as the object's redzone is accessed. */ kasan_disable_current(); @@ -4915,10 +4928,12 @@ __do_krealloc(const void *p, size_t new_size, gfp_t= flags) } =20 /** - * krealloc - reallocate memory. The contents will remain unchanged. + * krealloc_node_align - reallocate memory. The contents will remain uncha= nged. * @p: object to reallocate memory for. * @new_size: how many bytes of memory are required. + * @align: desired alignment. * @flags: the type of memory to allocate. + * @nid: NUMA node or NUMA_NO_NODE * * If @p is %NULL, krealloc() behaves exactly like kmalloc(). If @new_size * is 0 and @p is not a %NULL pointer, the object pointed to is freed. @@ -4947,7 +4962,8 @@ __do_krealloc(const void *p, size_t new_size, gfp_t f= lags) * * Return: pointer to the allocated memory or %NULL in case of error */ -void *krealloc_noprof(const void *p, size_t new_size, gfp_t flags) +void *krealloc_node_align_noprof(const void *p, size_t new_size, unsigned = long align, + gfp_t flags, int nid) { void *ret; =20 @@ -4956,13 +4972,13 @@ void *krealloc_noprof(const void *p, size_t new_siz= e, gfp_t flags) return ZERO_SIZE_PTR; } =20 - ret =3D __do_krealloc(p, new_size, flags); + ret =3D __do_krealloc(p, new_size, align, flags, nid); if (ret && kasan_reset_tag(p) !=3D kasan_reset_tag(ret)) kfree(p); =20 return ret; } -EXPORT_SYMBOL(krealloc_noprof); +EXPORT_SYMBOL(krealloc_node_align_noprof); =20 static gfp_t kmalloc_gfp_adjust(gfp_t flags, size_t size) { @@ -4993,6 +5009,7 @@ static gfp_t kmalloc_gfp_adjust(gfp_t flags, size_t s= ize) * failure, fall back to non-contiguous (vmalloc) allocation. * @size: size of the request. * @b: which set of kmalloc buckets to allocate from. + * @align: desired alignment. * @flags: gfp mask for the allocation - must be compatible (superset) wit= h GFP_KERNEL. * @node: numa node to allocate from * @@ -5005,19 +5022,22 @@ static gfp_t kmalloc_gfp_adjust(gfp_t flags, size_t= size) * * Return: pointer to the allocated memory of %NULL in case of failure */ -void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), gfp_t flags, int= node) +void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), unsigned long al= ign, + gfp_t flags, int node) { void *ret; =20 /* * It doesn't really make sense to fallback to vmalloc for sub page - * requests + * requests and small alignments */ - ret =3D __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), - kmalloc_gfp_adjust(flags, size), - node, _RET_IP_); - if (ret || size <=3D PAGE_SIZE) - return ret; + if (size >=3D align) { + ret =3D __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), + kmalloc_gfp_adjust(flags, size), + node, _RET_IP_); + if (ret || size <=3D PAGE_SIZE) + return ret; + } =20 /* non-sleeping allocations are not supported by vmalloc */ if (!gfpflags_allow_blocking(flags)) @@ -5035,7 +5055,7 @@ void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size,= b), gfp_t flags, int node) * about the resulting pointer, and cannot play * protection games. */ - return __vmalloc_node_range_noprof(size, 1, VMALLOC_START, VMALLOC_END, + return __vmalloc_node_range_noprof(size, align, VMALLOC_START, VMALLOC_EN= D, flags, PAGE_KERNEL, VM_ALLOW_HUGE_VMAP, node, __builtin_return_address(0)); } @@ -5079,10 +5099,12 @@ void kvfree_sensitive(const void *addr, size_t len) EXPORT_SYMBOL(kvfree_sensitive); =20 /** - * kvrealloc - reallocate memory; contents remain unchanged + * kvrealloc_node_align - reallocate memory; contents remain unchanged * @p: object to reallocate memory for * @size: the size to reallocate + * @align: desired alignment * @flags: the flags for the page level allocator + * @nid: NUMA node id * * If @p is %NULL, kvrealloc() behaves exactly like kvmalloc(). If @size i= s 0 * and @p is not a %NULL pointer, the object pointed to is freed. @@ -5100,17 +5122,18 @@ EXPORT_SYMBOL(kvfree_sensitive); * * Return: pointer to the allocated memory or %NULL in case of error */ -void *kvrealloc_noprof(const void *p, size_t size, gfp_t flags) +void *kvrealloc_node_align_noprof(const void *p, size_t size, unsigned lon= g align, + gfp_t flags, int nid) { void *n; =20 if (is_vmalloc_addr(p)) - return vrealloc_noprof(p, size, flags); + return vrealloc_node_align_noprof(p, size, align, flags, nid); =20 - n =3D krealloc_noprof(p, size, kmalloc_gfp_adjust(flags, size)); + n =3D krealloc_node_align_noprof(p, size, align, kmalloc_gfp_adjust(flags= , size), nid); if (!n) { /* We failed to krealloc(), fall back to kvmalloc(). */ - n =3D kvmalloc_noprof(size, flags); + n =3D kvmalloc_node_align_noprof(size, align, flags, nid); if (!n) return NULL; =20 @@ -5126,7 +5149,7 @@ void *kvrealloc_noprof(const void *p, size_t size, gf= p_t flags) =20 return n; } -EXPORT_SYMBOL(kvrealloc_noprof); +EXPORT_SYMBOL(kvrealloc_node_align_noprof); =20 struct detached_freelist { struct slab *slab; --=20 2.39.2 From nobody Wed Oct 8 11:50:47 2025 Received: from mailrelay-egress12.pub.mailoutpod2-cph3.one.com (mailrelay-egress12.pub.mailoutpod2-cph3.one.com [46.30.211.187]) (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 9576623313E for ; Sat, 28 Jun 2025 10:26:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.30.211.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106381; cv=none; b=PkBOvae8ZJObwJjR+zKy5Z9w1I/9b8yedXAAcvVTdTS4UImHLoz2btdPXRQNPGS4HQPBBGZn305f8Q/UoA7uOrAz7g3vuv//dp97tw32fexXQxxa/DSJcguAw9lGg4Uxwb/A3w6bxhAdG5QkU7oyeW8B9kVkZ8MkaX0pOt01pUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106381; c=relaxed/simple; bh=BQSKhNT8Rw4EJx4HfiqyQ0cJMICt7sK1eiY9Zem9N9Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Apk4Dm5cWe4VCkupuoCk9cVL2rosGxoRiSLhTIJ7cVgqKwhxNdivqUPAAVVgm0Kxjv21fGmSNbrW/KidzpgP0OUTCkKkR5lE2nPZ7JNqqUbqR+NJo37HOX1i18Bfut65Fzuy2Jo7rQ2b+JD/EhG3Vka+ZRLaeS4AI7oc1ikc2ak= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se; spf=none smtp.mailfrom=konsulko.se; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=HVm6M2aL; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=50Nca+fz; arc=none smtp.client-ip=46.30.211.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=konsulko.se Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="HVm6M2aL"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="50Nca+fz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751106376; x=1751711176; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=e7OFYRStytxd8Whe4eCeFCBlvkMdhmB5TspEZhahhgg=; b=HVm6M2aLeqjQ221hWwXOAEKW/ApfNWub6cuEClecQKM7A9O/aMumBWURZ0AB1jV0WI0aoC9l+eS1v 8NF8nVh/qvC67uRTvZmxJxm1Iv5fjFtBjk8iXhMi9vNgd2c/PDbzetgKX01vCTVGu5s40DQAkhWl6e XuMdUORxje37M0c4OZtK0syUDyvka1tCRIx8F8nC9Y0nnKANZjSc34V30yKkh0BivzNJ5BT+xFM01e P0rTDhUdIwTqRcEuBBvz+60IYeMpQRpY6JMta3Wg995e71QlbrH/mkXYholqXWivFJC2c+qXfHeAI4 GcHqlmIqmXiW0p4a7wDcG0nOiT3g77A== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751106376; x=1751711176; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=e7OFYRStytxd8Whe4eCeFCBlvkMdhmB5TspEZhahhgg=; b=50Nca+fzb0wFHPT2wt+wp30wSPsiTApV00BjbCDof9pid25ZiwzfZD2sUM76FDM9Y0fpujU04kMMM 8lJBVJtBg== X-HalOne-ID: 5164ff25-540a-11f0-bd12-f78b1f841584 Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay1.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 5164ff25-540a-11f0-bd12-f78b1f841584; Sat, 28 Jun 2025 10:26:15 +0000 (UTC) From: Vitaly Wool To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, Uladzislau Rezki , Danilo Krummrich , Alice Ryhl , rust-for-linux@vger.kernel.org, Vitaly Wool Subject: [PATCH v8 3/4] rust: add support for NUMA ids in allocations Date: Sat, 28 Jun 2025 12:26:11 +0200 Message-Id: <20250628102611.2542910-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250628102315.2542656-1-vitaly.wool@konsulko.se> References: <20250628102315.2542656-1-vitaly.wool@konsulko.se> 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 new type to support specifying NUMA identifiers in Rust allocators and extend the allocators to have NUMA id as a parameter. Thus, modify ReallocFunc to use the new extended realloc primitives from the C side of the kernel (i. e. k[v]realloc_node_align/vrealloc_node_align) and add the new function alloc_node to the Allocator trait while keeping the existing one (alloc) for backward compatibility. This will allow to specify node to use for allocation of e. g. {KV}Box, as well as for future NUMA aware users of the API. Signed-off-by: Vitaly Wool --- rust/helpers/slab.c | 8 ++-- rust/helpers/vmalloc.c | 4 +- rust/kernel/alloc.rs | 77 ++++++++++++++++++++++++++++++++-- rust/kernel/alloc/allocator.rs | 42 +++++++++++-------- 4 files changed, 104 insertions(+), 27 deletions(-) diff --git a/rust/helpers/slab.c b/rust/helpers/slab.c index a842bfbddcba..8472370a4338 100644 --- a/rust/helpers/slab.c +++ b/rust/helpers/slab.c @@ -3,13 +3,13 @@ #include =20 void * __must_check __realloc_size(2) -rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags) +rust_helper_krealloc_node(const void *objp, size_t new_size, gfp_t flags, = int node) { - return krealloc(objp, new_size, flags); + return krealloc_node(objp, new_size, flags, node); } =20 void * __must_check __realloc_size(2) -rust_helper_kvrealloc(const void *p, size_t size, gfp_t flags) +rust_helper_kvrealloc_node(const void *p, size_t size, gfp_t flags, int no= de) { - return kvrealloc(p, size, flags); + return kvrealloc_node(p, size, flags, node); } diff --git a/rust/helpers/vmalloc.c b/rust/helpers/vmalloc.c index 80d34501bbc0..62d30db9a1a6 100644 --- a/rust/helpers/vmalloc.c +++ b/rust/helpers/vmalloc.c @@ -3,7 +3,7 @@ #include =20 void * __must_check __realloc_size(2) -rust_helper_vrealloc(const void *p, size_t size, gfp_t flags) +rust_helper_vrealloc_node(const void *p, size_t size, gfp_t flags, int nod= e) { - return vrealloc(p, size, flags); + return vrealloc_node(p, size, flags, node); } diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index a2c49e5494d3..8d2b046bf947 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -28,7 +28,9 @@ /// Indicates an allocation error. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; + use core::{alloc::Layout, ptr::NonNull}; +use crate::error::{code::EINVAL, Result}; =20 /// Flags to be used when allocating memory. /// @@ -115,6 +117,30 @@ pub mod flags { pub const __GFP_NOWARN: Flags =3D Flags(bindings::__GFP_NOWARN); } =20 +/// Non Uniform Memory Access (NUMA) node identifier +#[derive(Clone, Copy, PartialEq)] +pub struct NumaNode(i32); + +impl NumaNode { + /// create a new NUMA node identifer (non-negative integer) + /// returns EINVAL if a negative id is specified + pub fn new(node: i32) -> Result { + if node < 0 { + return Err(EINVAL); + } + Ok(Self(node)) + } +} + +/// Specify necessary constant to pass the information to Allocator that t= he caller doesn't care +/// about the NUMA node to allocate memory from +pub mod numa { + use super::NumaNode; + + /// No preference for NUMA node + pub const NUMA_NO_NODE: NumaNode =3D NumaNode(bindings::NUMA_NO_NODE); +} + /// The kernel's [`Allocator`] trait. /// /// An implementation of [`Allocator`] can allocate, re-allocate and free = memory buffers described @@ -148,7 +174,7 @@ pub unsafe trait Allocator { /// /// When the return value is `Ok(ptr)`, then `ptr` is /// - valid for reads and writes for `layout.size()` bytes, until it i= s passed to - /// [`Allocator::free`] or [`Allocator::realloc`], + /// [`Allocator::free`], [`Allocator::realloc`] or [`Allocator::real= loc_node`], /// - aligned to `layout.align()`, /// /// Additionally, `Flags` are honored as documented in @@ -159,7 +185,36 @@ fn alloc(layout: Layout, flags: Flags) -> Result, AllocError> { unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags) } } =20 - /// Re-allocate an existing memory allocation to satisfy the requested= `layout`. + /// Allocate memory based on `layout`, `flags` and `nid`. + /// + /// 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_node` when called with `No= ne`. + /// + /// # Guarantees + /// + /// When the return value is `Ok(ptr)`, then `ptr` is + /// - valid for reads and writes for `layout.size()` bytes, until it i= s passed to + /// [`Allocator::free`], [`Allocator::realloc`] or [`Allocator::real= loc_node`], + /// - aligned to `layout.align()`, + /// + /// Additionally, `Flags` are honored as documented in + /// . + fn alloc_node(layout: Layout, flags: Flags, nid: NumaNode) + -> Result, AllocError> { + // SAFETY: Passing `None` to `realloc_node` is valid by its safety= requirements and + // asks for a new memory allocation. + unsafe { Self::realloc_node(None, layout, Layout::new::<()>(), fla= gs, nid) } + } + + /// Re-allocate an existing memory allocation to satisfy the requested= `layout` and + /// optionally a specific NUMA node request to allocate the memory for. + /// Systems employing a Non Uniform Memory Access (NUMA) architecture = contain + /// collections of hardware resources including processors, memory, an= d I/O buses, + /// that comprise what is commonly known as a NUMA node. + /// `nid` stands for NUMA id, i. e. NUMA node identifier, which is a n= on-negative + /// integer if a node needs to be specified, or NUMA_NO_NODE if the ca= ller doesn't care. /// /// If the requested size is zero, `realloc` behaves equivalent to `fr= ee`. /// @@ -191,13 +246,29 @@ fn alloc(layout: Layout, flags: Flags) -> Result, AllocError> { /// and old size, i.e. `ret_ptr[0..min(layout.size(), old_layout.siz= e())] =3D=3D /// p[0..min(layout.size(), old_layout.size())]`. /// - when the return value is `Err(AllocError)`, then `ptr` is still = valid. - unsafe fn realloc( + unsafe fn realloc_node( ptr: Option>, layout: Layout, old_layout: Layout, flags: Flags, + nid: NumaNode, ) -> Result, AllocError>; =20 + + /// Re-allocate an existing memory allocation to satisfy the requested= `layout`. This + /// function works exactly as realloc_node() but it doesn't give the a= bility to specify + /// the NUMA node in the call. + unsafe fn realloc( + ptr: Option>, + layout: Layout, + old_layout: Layout, + flags: Flags, + ) -> Result, AllocError> { + // SAFETY: guaranteed by realloc_node() + unsafe { Self::realloc_node(ptr, layout, old_layout, flags, numa::= NUMA_NO_NODE) } + } + + /// Free an existing memory allocation. /// /// # Safety diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index aa2dfa9dca4c..2e86e9839a1b 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -13,7 +13,7 @@ use core::ptr; use core::ptr::NonNull; =20 -use crate::alloc::{AllocError, Allocator}; +use crate::alloc::{AllocError, Allocator, NumaNode}; use crate::bindings; use crate::pr_warn; =20 @@ -58,18 +58,20 @@ fn aligned_size(new_layout: Layout) -> usize { /// /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. struct ReallocFunc( - unsafe extern "C" fn(*const crate::ffi::c_void, usize, u32) -> *mut cr= ate::ffi::c_void, + unsafe extern "C" fn( + *const crate::ffi::c_void, usize, u32, crate::ffi::c_int, + ) -> *mut crate::ffi::c_void, ); =20 impl ReallocFunc { - // INVARIANT: `krealloc` satisfies the type invariants. - const KREALLOC: Self =3D Self(bindings::krealloc); + // INVARIANT: `krealloc_node` satisfies the type invariants. + const KREALLOC: Self =3D Self(bindings::krealloc_node); =20 - // INVARIANT: `vrealloc` satisfies the type invariants. - const VREALLOC: Self =3D Self(bindings::vrealloc); + // INVARIANT: `vrealloc_node` satisfies the type invariants. + const VREALLOC: Self =3D Self(bindings::vrealloc_node); =20 - // INVARIANT: `kvrealloc` satisfies the type invariants. - const KVREALLOC: Self =3D Self(bindings::kvrealloc); + // INVARIANT: `kvrealloc_node` satisfies the type invariants. + const KVREALLOC: Self =3D Self(bindings::kvrealloc_node); =20 /// # Safety /// @@ -87,6 +89,7 @@ unsafe fn call( layout: Layout, old_layout: Layout, flags: Flags, + nid: NumaNode, ) -> Result, AllocError> { let size =3D aligned_size(layout); let ptr =3D match ptr { @@ -110,7 +113,7 @@ unsafe fn call( // - Those functions provide the guarantees of this function. let raw_ptr =3D unsafe { // If `size =3D=3D 0` and `ptr !=3D NULL` the memory behind th= e pointer is freed. - self.0(ptr.cast(), size, flags.0).cast() + self.0(ptr.cast(), size, flags.0, nid.0).cast() }; =20 let ptr =3D if size =3D=3D 0 { @@ -123,34 +126,36 @@ unsafe fn call( } } =20 -// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// SAFETY: `realloc_node` delegates to `ReallocFunc::call`, which guarante= es that // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. unsafe impl Allocator for Kmalloc { #[inline] - unsafe fn realloc( + unsafe fn realloc_node( ptr: Option>, layout: Layout, old_layout: Layout, flags: Flags, + nid: NumaNode, ) -> Result, AllocError> { // SAFETY: `ReallocFunc::call` has the same safety requirements as= `Allocator::realloc`. - unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags= ) } + unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags= , nid) } } } =20 -// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// SAFETY: `realloc_node` delegates to `ReallocFunc::call`, which guarante= es that // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. unsafe impl Allocator for Vmalloc { #[inline] - unsafe fn realloc( + unsafe fn realloc_node( ptr: Option>, layout: Layout, old_layout: Layout, flags: Flags, + nid: NumaNode, ) -> Result, AllocError> { // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { @@ -160,21 +165,22 @@ unsafe fn realloc( =20 // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously // allocated with this `Allocator`. - unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags= ) } + unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags= , nid) } } } =20 -// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees th= at +// SAFETY: `realloc_node` delegates to `ReallocFunc::call`, which guarante= es that // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the= same. unsafe impl Allocator for KVmalloc { #[inline] - unsafe fn realloc( + unsafe fn realloc_node( ptr: Option>, layout: Layout, old_layout: Layout, flags: Flags, + nid: NumaNode, ) -> Result, AllocError> { // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { @@ -184,6 +190,6 @@ unsafe fn realloc( =20 // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously // allocated with this `Allocator`. - unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flag= s) } + unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flag= s, nid) } } } --=20 2.39.2 From nobody Wed Oct 8 11:50:47 2025 Received: from mailrelay4-3.pub.mailoutpod3-cph3.one.com (mailrelay4-3.pub.mailoutpod3-cph3.one.com [46.30.212.3]) (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 BCD67224AE6 for ; Sat, 28 Jun 2025 10:26:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.30.212.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106394; cv=none; b=Tu87RP1m1EuyBjma+3cfC6/avQT9AmiWdYKC18DGzeGQAdBob7NADY/PQNhzpaxgGV8JHh5VAEuf37SmtPBwlZc9pB+4p1VmGeFswE+Bmp1gVRPwxIrL6aQYRnN4uDy8JjtimUVinSAC2NlWiJaTgH7T4yoawzLI7KQwTO6XZLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751106394; c=relaxed/simple; bh=+icoHdD16rtAElqIFrplkTciRveLhQeWCFCs/gsB+ig=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NpmiNzyDeaffOJDZn6UzhTzNP1X094g3E5Xlensdn3wBCCyFrngjYFWEfFvPjJyH+IcliQSNsQJ9R27qD/Ir3Rd/5wNonPqQSNiErcEiDoc8A6XE2tgRAGsRZHhNClOGxEw4p2nxFWOReirqWX3Fvuh5cO8KrVDckUJ8llYRcUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se; spf=none smtp.mailfrom=konsulko.se; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=QSZ+lYJi; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=NuIaGDGg; arc=none smtp.client-ip=46.30.212.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=konsulko.se Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=konsulko.se Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="QSZ+lYJi"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="NuIaGDGg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751106390; x=1751711190; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=xlhdGuz/Z+dkJo2xYiSj4xZE1JqckJSK1NBWLMJ0VOE=; b=QSZ+lYJiZSB7Toib+iyiSJ3/SIzdf98oKheYebvFNLbjGPu8zBZE2g7L5gOuiAPO4E7A90ZoPAIJE 6matMIx8TFsgWmyt3HIIySVFKoSE3hkywtECygbxMCT1u67m4QY2GypMiGmblTtgCsMeQ8ujIbkA7B S5hkwzBE+tzBGCsrwxuowfMXp9xzYw+dmrzZLseZo/5C2sFtiHx3ZHe6sqYEBna47HXkgDsI0lqu+F T1f4HsOLmTC0Zrvgi/jjIdZTZa3nuw5JsOeU3tNyf9vX5+TEPvvSYSi+6QuXcuj2a79UU+taGa9zV7 gKsLpnBifkaSwOft3eGF2QRWV1kQXFA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751106390; x=1751711190; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=xlhdGuz/Z+dkJo2xYiSj4xZE1JqckJSK1NBWLMJ0VOE=; b=NuIaGDGgweqG2u/jIxj6mcXd/5JQk5UQSVMztjkrY8ddwsuy+pc/9KcXSDnDjnWYikhdkRmzsvHdj MSJLU5HDg== X-HalOne-ID: 59c0416d-540a-11f0-8548-29b2d794c87d Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay4.pub.mailoutpod3-cph3.one.com (Halon) with ESMTPSA id 59c0416d-540a-11f0-8548-29b2d794c87d; Sat, 28 Jun 2025 10:26:30 +0000 (UTC) From: Vitaly Wool To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, Uladzislau Rezki , Danilo Krummrich , Alice Ryhl , rust-for-linux@vger.kernel.org, Vitaly Wool Subject: [PATCH v8 4/4] rust: support large alignments in allocations Date: Sat, 28 Jun 2025 12:26:26 +0200 Message-Id: <20250628102626.2542946-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250628102315.2542656-1-vitaly.wool@konsulko.se> References: <20250628102315.2542656-1-vitaly.wool@konsulko.se> 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 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 _node_align() functions and start using those. Signed-off-by: Vitaly Wool --- rust/helpers/slab.c | 10 ++++++---- rust/helpers/vmalloc.c | 5 +++-- rust/kernel/alloc/allocator.rs | 28 ++++++++-------------------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/rust/helpers/slab.c b/rust/helpers/slab.c index 8472370a4338..d729be798f31 100644 --- a/rust/helpers/slab.c +++ b/rust/helpers/slab.c @@ -3,13 +3,15 @@ #include =20 void * __must_check __realloc_size(2) -rust_helper_krealloc_node(const void *objp, size_t new_size, gfp_t flags, = int node) +rust_helper_krealloc_node_align(const void *objp, size_t new_size, unsigne= d long align, + gfp_t flags, int node) { - return krealloc_node(objp, new_size, flags, node); + return krealloc_node_align(objp, new_size, align, flags, node); } =20 void * __must_check __realloc_size(2) -rust_helper_kvrealloc_node(const void *p, size_t size, gfp_t flags, int no= de) +rust_helper_kvrealloc_node_align(const void *p, size_t size, unsigned long= align, + gfp_t flags, int node) { - return kvrealloc_node(p, size, flags, node); + return kvrealloc_node_align(p, size, align, flags, node); } diff --git a/rust/helpers/vmalloc.c b/rust/helpers/vmalloc.c index 62d30db9a1a6..7d7f7336b3d2 100644 --- a/rust/helpers/vmalloc.c +++ b/rust/helpers/vmalloc.c @@ -3,7 +3,8 @@ #include =20 void * __must_check __realloc_size(2) -rust_helper_vrealloc_node(const void *p, size_t size, gfp_t flags, int nod= e) +rust_helper_vrealloc_node_align(const void *p, size_t size, unsigned long = align, + gfp_t flags, int node) { - return vrealloc_node(p, size, flags, node); + return vrealloc_node_align(p, size, align, flags, node); } diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 2e86e9839a1b..58e5bf78c159 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -59,19 +59,19 @@ fn aligned_size(new_layout: Layout) -> usize { /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. struct ReallocFunc( unsafe extern "C" fn( - *const crate::ffi::c_void, usize, u32, crate::ffi::c_int, + *const crate::ffi::c_void, usize, crate::ffi::c_ulong, u32, crate:= :ffi::c_int, ) -> *mut crate::ffi::c_void, ); =20 impl ReallocFunc { - // INVARIANT: `krealloc_node` satisfies the type invariants. - const KREALLOC: Self =3D Self(bindings::krealloc_node); + // INVARIANT: `krealloc_node_align` satisfies the type invariants. + const KREALLOC: Self =3D Self(bindings::krealloc_node_align); =20 - // INVARIANT: `vrealloc_node` satisfies the type invariants. - const VREALLOC: Self =3D Self(bindings::vrealloc_node); + // INVARIANT: `vrealloc_node_align` satisfies the type invariants. + const VREALLOC: Self =3D Self(bindings::vrealloc_node_align); =20 - // INVARIANT: `kvrealloc_node` satisfies the type invariants. - const KVREALLOC: Self =3D Self(bindings::kvrealloc_node); + // INVARIANT: `kvrealloc_node_align` satisfies the type invariants. + const KVREALLOC: Self =3D Self(bindings::kvrealloc_node_align); =20 /// # Safety /// @@ -113,7 +113,7 @@ unsafe fn call( // - Those functions provide the guarantees of this function. let raw_ptr =3D unsafe { // If `size =3D=3D 0` and `ptr !=3D NULL` the memory behind th= e pointer is freed. - self.0(ptr.cast(), size, flags.0, nid.0).cast() + self.0(ptr.cast(), size, layout.align(), flags.0, nid.0).cast() }; =20 let ptr =3D if size =3D=3D 0 { @@ -157,12 +157,6 @@ unsafe fn realloc_node( flags: Flags, nid: NumaNode, ) -> Result, AllocError> { - // TODO: Support alignments larger than PAGE_SIZE. - if layout.align() > bindings::PAGE_SIZE { - pr_warn!("Vmalloc does not support alignments larger than PAGE= _SIZE yet.\n"); - return Err(AllocError); - } - // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously // allocated with this `Allocator`. unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags= , nid) } @@ -182,12 +176,6 @@ unsafe fn realloc_node( flags: Flags, nid: NumaNode, ) -> Result, AllocError> { - // TODO: Support alignments larger than PAGE_SIZE. - if layout.align() > bindings::PAGE_SIZE { - pr_warn!("KVmalloc does not support alignments larger than PAG= E_SIZE yet.\n"); - return Err(AllocError); - } - // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously // allocated with this `Allocator`. unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flag= s, nid) } --=20 2.39.2