From nobody Wed Oct 8 13:25:00 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 27239293C42 for ; Fri, 27 Jun 2025 09:35:47 +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=1751016950; cv=none; b=Y4Nt5DtH/TKFkcoVWPTW75REdp2K++SAHUcVFs9lG2xJ0NsshVZ71nsM/DOrzbDNVyu5h4UQNllhitiTt5L7kkSKWT1Op4jdsd6ibVKqak773uDFhezBaVdyJpLjDEITEEII5n3ovp943zPaWjLI9msNT29pmtL6wWLUSE524l8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751016950; c=relaxed/simple; bh=3IEBar6mLVB3kmmqhzy1fX6Y8cIw4YGiIaa7fdoQdlw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JFzABOZ8YLS1JqOKP87tqJeSiRhe8kS3sNcH5/FVKCIa9QCNeJyoxrh86v/XGjATJ0zNhzT7oKKC7SG86d6ZNwln482e9tO88Wt2Nd43hpyEGW+C6tOWgRwMBFe20TIVX198dxxEA2oiQP0o/KIXDVn2vo5kS1tncZOssKGQLAA= 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=YaSWyKXm; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=Bzs1mKGt; 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="YaSWyKXm"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="Bzs1mKGt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751016940; x=1751621740; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=zkwJ4i4dwDao2rWYOJehq905CyIjzLTLMDu2gHmT6vw=; b=YaSWyKXmot4ncdE1drt7pMeviwBdIcXqNoGY6NnytCBGbPkJX1xNXgA0MIBpC6okkiNTFDfQ0V8EJ CuekJCuGEPlainh8aj2VEeFrFMXUsjzgjerhC8zO6zOECq5RCUWVr29wSPRU/iHuePLowbM191wn5w B1k6uJQ32mgdd/pUG/mN5UUOWPBIOtfMAqN/AeZorsB3PTj7WKq6jn41HTR3vU701QwHMLl1Fx+unW nFezrdhwhJY96HA99BRw1dwu6VQSPwKIg/rgWBCY56L+sCo1YOh7nBeARmNumwVGe+gGh1LykHx2ls CDncwNGw2R5KujtjU61XzUudSB5tSaw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751016940; x=1751621740; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=zkwJ4i4dwDao2rWYOJehq905CyIjzLTLMDu2gHmT6vw=; b=Bzs1mKGtY2ZkvDPgn4Jsuquqs4SwAtKFF7QBvPxrxar+jfnNHX/5QUBRHAib5ALJZLOWEY3N11pxU Rle9gJJAQ== X-HalOne-ID: 1567cdf5-533a-11f0-83c2-e90f2b8e16ca Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay2.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 1567cdf5-533a-11f0-83c2-e90f2b8e16ca; Fri, 27 Jun 2025 09:35:39 +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 v5 1/4] mm/vmalloc: allow to set node and align in vrealloc Date: Fri, 27 Jun 2025 11:35:29 +0200 Message-Id: <20250627093529.389311-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250627092901.356909-1-vitaly.wool@konsulko.se> References: <20250627092901.356909-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() to better match what it actually does now and introduce a macro for vrealloc() 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 Reviewed-by: "Uladzislau Rezki (Sony)" --- include/linux/vmalloc.h | 8 +++++--- mm/nommu.c | 3 ++- mm/vmalloc.c | 16 +++++++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index fdc9aeb74a44..7d5251287687 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -197,9 +197,11 @@ 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_noprof(const void *p, size_t size, + unsigned long align, gfp_t flags, int nid) __realloc_size(2); +#define vrealloc_noprof(p, s, f) vrealloc_node_noprof(p, s, 1, f, NUMA_NO_= NODE) +#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/nommu.c b/mm/nommu.c index 87e1acab0d64..6cec05c3312c 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_noprof(const void *p, size_t size, unsigned long align, + gfp_t flags, int nid) { return krealloc_noprof(p, size, (flags | __GFP_COMP) & ~__GFP_HIGHMEM); } diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6dbcdceecae1..412bf5b8d3ff 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -4089,10 +4089,12 @@ 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 - reallocate virtually contiguous memory; contents 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 * @p is not a %NULL pointer, the object pointed to is freed. @@ -4111,7 +4113,7 @@ 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_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 +4137,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 +4175,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 13:25:00 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 7C01F233714 for ; Fri, 27 Jun 2025 09:37:28 +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=1751017051; cv=none; b=WrlkAzw6Tgtm37+qfUUF1RwJUTBEvtH9fR2Z3ROeCsF1XYGXRnpd/igAq8ge5EnVvhOgt8enyJ3vm4Ihst+yOkWHXafb9+OxAS4mm1cCSXCmEIF9plrNDFx/joZqjW1DY3TXJAzER27DN1oqwvySMpgwgt9I1NdANsJ+tp1XSaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751017051; c=relaxed/simple; bh=Jthb+UJKcxktJpwPe2XaOxtycF1+lXV4NRkk2tIVbFo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qAFtPd/ZP0eW+Jso7ikBlIxohCbXBz+zYl9OEk+T7tsgOl0qihMBJHlDvZfmkd+BJLliL6bcm1+2DeoxhsPasf6ZYRP0+JxE5ghDsNVeWA7Vmg876wC+CSFQ7FzE6JmvKEbVgzYfcXoU5KnS5kVqukEwZBj5Uzoxm8kF+Q15h4w= 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=bbR2Cvfn; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=ktnaALU5; 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="bbR2Cvfn"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="ktnaALU5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751017047; x=1751621847; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=YLTkg36uBQpkwu4dPNoedH3NjjOM2iYA3dGmUc2+V8Q=; b=bbR2CvfnZX03pt6TS7geVeZkmv/XX6V47lyoec1WcvKB2towl94Ker9JsK0ebed4EwiP4FvZRmoJk 18/JEb01hHTAJpLuAv1Wiw8p0t8QeRalkpxPFwyFhVMhtHK7OYBUt6lbxAL0TDM2bRWHLGvl9gjhJy /zvK8RaJxnGLU6s0RRDktipIENlgMr2XUFYtB+bR4oKkDl50YST5xwCpN0Nw3N+YdFdaqc2V8Q7ioW nCSgUj+iM5QSM59tCk2Y+18XMZHOrtJevj+vg/+NwURRo1K6nXeGCRzedyepoRHnXPt2Wuuz746R21 Ey3E3pOSlXxz89hnXsXuTvpV8nXdJtw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751017047; x=1751621847; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=YLTkg36uBQpkwu4dPNoedH3NjjOM2iYA3dGmUc2+V8Q=; b=ktnaALU5vYXLMP1jB54PdNcxAZ53drm9XGkg73yZFAnmijCkKfVt1IQn8qxQQL5XT5D3xpHFyz+az FbFjmKyCQ== X-HalOne-ID: 54a061ad-533a-11f0-95e0-494313b7f784 Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay6.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 54a061ad-533a-11f0-95e0-494313b7f784; Fri, 27 Jun 2025 09:37:25 +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 2/4] mm/slub: allow to set node and align in k[v]realloc Date: Fri, 27 Jun 2025 11:37:14 +0200 Message-Id: <20250627093714.402989-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250627092901.356909-1-vitaly.wool@konsulko.se> References: <20250627092901.356909-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, the following rules are honored: * kmalloc/kzalloc/krealloc remain unchanged * kvmalloc/kvrealloc/kvcalloc remain unchanged * kvrealloc remains unchanged * kvrealloc_node is implemented as a new function taking align and NUMA id as extra parameters compared to kvrealloc. * krealloc_node is implemented as a new function taking NUMA id as an extra parameter compared to krealloc * kvmalloc_node/kvzalloc_node/kvcalloc_node get an extra parameter (alignment) The users of functions that changed their interfaces are updated accordingly. 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 --- drivers/infiniband/hw/hfi1/ipoib_tx.c | 2 +- drivers/infiniband/hw/hfi1/sdma.c | 2 +- drivers/md/dm-stats.c | 2 +- drivers/md/dm.c | 2 +- .../net/ethernet/fungible/funcore/fun_queue.c | 2 +- .../net/ethernet/fungible/funeth/funeth_rx.c | 2 +- drivers/net/ethernet/intel/libeth/rx.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en/ptp.c | 10 ++-- .../net/ethernet/mellanox/mlx5/core/en/trap.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_dim.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 30 +++++----- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 4 +- .../net/ethernet/mellanox/mlx5/core/pci_irq.c | 2 +- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 4 +- include/linux/slab.h | 42 +++++++------ lib/rhashtable.c | 2 +- lib/sbitmap.c | 2 +- lib/tests/fortify_kunit.c | 4 +- lib/tests/overflow_kunit.c | 55 +++++++++-------- mm/shrinker.c | 4 +- mm/slub.c | 60 +++++++++++++------ net/netfilter/x_tables.c | 2 +- net/rds/ib_cm.c | 4 +- net/sched/sch_fq.c | 3 +- 26 files changed, 142 insertions(+), 108 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/= hfi1/ipoib_tx.c index 8b9cc55db59d..3d80571200ff 100644 --- a/drivers/infiniband/hw/hfi1/ipoib_tx.c +++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c @@ -729,7 +729,7 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *p= riv) priv->dd->node); =20 txq->tx_ring.items =3D - kvzalloc_node(array_size(tx_ring_size, tx_item_size), + kvzalloc_node(array_size(tx_ring_size, tx_item_size), 1, GFP_KERNEL, priv->dd->node); if (!txq->tx_ring.items) goto free_txqs; diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1= /sdma.c index 719b7c34e238..51c9740bea23 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1436,7 +1436,7 @@ int sdma_init(struct hfi1_devdata *dd, u8 port) sde->tx_ring =3D kvzalloc_node(array_size(descq_cnt, sizeof(struct sdma_txreq *)), - GFP_KERNEL, dd->node); + 1, GFP_KERNEL, dd->node); if (!sde->tx_ring) goto bail; } diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c index 1e5d988f44da..88e29a30fd17 100644 --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -150,7 +150,7 @@ static void *dm_kvzalloc(size_t alloc_size, int node) if (!claim_shared_memory(alloc_size)) return NULL; =20 - p =3D kvzalloc_node(alloc_size, GFP_KERNEL | __GFP_NOMEMALLOC, node); + p =3D kvzalloc_node(alloc_size, 1, GFP_KERNEL | __GFP_NOMEMALLOC, node); if (p) return p; =20 diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 4b9415f718e3..d2fcbf63c137 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2249,7 +2249,7 @@ static struct mapped_device *alloc_dev(int minor) struct mapped_device *md; void *old_md; =20 - md =3D kvzalloc_node(sizeof(*md), GFP_KERNEL, numa_node_id); + md =3D kvzalloc_node(sizeof(*md), 1, GFP_KERNEL, numa_node_id); if (!md) { DMERR("unable to allocate device, out of memory."); return NULL; diff --git a/drivers/net/ethernet/fungible/funcore/fun_queue.c b/drivers/ne= t/ethernet/fungible/funcore/fun_queue.c index d07ee3e4f52a..c65dfcc31117 100644 --- a/drivers/net/ethernet/fungible/funcore/fun_queue.c +++ b/drivers/net/ethernet/fungible/funcore/fun_queue.c @@ -40,7 +40,7 @@ void *fun_alloc_ring_mem(struct device *dma_dev, size_t d= epth, return NULL; =20 if (sw_desc_sz) { - *sw_va =3D kvzalloc_node(sw_desc_sz * depth, GFP_KERNEL, + *sw_va =3D kvzalloc_node(sw_desc_sz * depth, 1, GFP_KERNEL, numa_node); if (!*sw_va) { dma_free_coherent(dma_dev, dma_sz, va, *dma_addr); diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net= /ethernet/fungible/funeth/funeth_rx.c index 7e2584895de3..c27788e59934 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c @@ -567,7 +567,7 @@ static int fun_rxq_init_cache(struct funeth_rx_cache *c= , unsigned int depth, int node) { c->mask =3D depth - 1; - c->bufs =3D kvzalloc_node(depth * sizeof(*c->bufs), GFP_KERNEL, node); + c->bufs =3D kvzalloc_node(depth * sizeof(*c->bufs), 1, GFP_KERNEL, node); return c->bufs ? 0 : -ENOMEM; } =20 diff --git a/drivers/net/ethernet/intel/libeth/rx.c b/drivers/net/ethernet/= intel/libeth/rx.c index 66d1d23b8ad2..272acdf540d8 100644 --- a/drivers/net/ethernet/intel/libeth/rx.c +++ b/drivers/net/ethernet/intel/libeth/rx.c @@ -172,7 +172,7 @@ int libeth_rx_fq_create(struct libeth_fq *fq, struct na= pi_struct *napi) if (IS_ERR(pool)) return PTR_ERR(pool); =20 - fqes =3D kvcalloc_node(fq->count, sizeof(*fqes), GFP_KERNEL, fq->nid); + fqes =3D kvcalloc_node(fq->count, sizeof(*fqes), 1, GFP_KERNEL, fq->nid); if (!fqes) goto err_buf; =20 diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ether= net/mellanox/mlx4/en_rx.c index b33285d755b9..b011ff2f6e33 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -280,7 +280,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, =20 tmp =3D size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS * sizeof(struct mlx4_en_rx_alloc)); - ring->rx_info =3D kvzalloc_node(tmp, GFP_KERNEL, node); + ring->rx_info =3D kvzalloc_node(tmp, 1, GFP_KERNEL, node); if (!ring->rx_info) { err =3D -ENOMEM; goto err_xdp_info; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ether= net/mellanox/mlx4/en_tx.c index 87f35bcbeff8..c7a63613914b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -69,7 +69,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, ring->full_size =3D ring->size - HEADROOM - MLX4_MAX_DESC_TXBBS; =20 tmp =3D size * sizeof(struct mlx4_en_tx_info); - ring->tx_info =3D kvmalloc_node(tmp, GFP_KERNEL, node); + ring->tx_info =3D kvmalloc_node(tmp, 1, GFP_KERNEL, node); if (!ring->tx_info) { err =3D -ENOMEM; goto err_ring; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net= /ethernet/mellanox/mlx5/core/en/ptp.c index 5d0014129a7e..45df50efbc17 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -378,7 +378,7 @@ static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptps= q *ptpsq, int numa) int db_sz; int md; =20 - cqe_list =3D kvzalloc_node(sizeof(*ptpsq->ts_cqe_pending_list), GFP_KERNE= L, numa); + cqe_list =3D kvzalloc_node(sizeof(*ptpsq->ts_cqe_pending_list), 1, GFP_KE= RNEL, numa); if (!cqe_list) return -ENOMEM; ptpsq->ts_cqe_pending_list =3D cqe_list; @@ -388,7 +388,7 @@ static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptps= q *ptpsq, int numa) ts_cqe_metadata_size2wqe_counter)); ptpsq->ts_cqe_ctr_mask =3D db_sz - 1; =20 - cqe_list->nodes =3D kvzalloc_node(array_size(db_sz, sizeof(*cqe_list->nod= es)), + cqe_list->nodes =3D kvzalloc_node(array_size(db_sz, sizeof(*cqe_list->nod= es)), 1, GFP_KERNEL, numa); if (!cqe_list->nodes) goto free_cqe_list; @@ -396,7 +396,7 @@ static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptps= q *ptpsq, int numa) spin_lock_init(&cqe_list->tracker_list_lock); =20 metadata_freelist->data =3D - kvzalloc_node(array_size(db_sz, sizeof(*metadata_freelist->data)), + kvzalloc_node(array_size(db_sz, sizeof(*metadata_freelist->data)), 1, GFP_KERNEL, numa); if (!metadata_freelist->data) goto free_cqe_list_nodes; @@ -409,7 +409,7 @@ static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptps= q *ptpsq, int numa) metadata_freelist->pc =3D db_sz; =20 metadata_map->data =3D - kvzalloc_node(array_size(db_sz, sizeof(*metadata_map->data)), + kvzalloc_node(array_size(db_sz, sizeof(*metadata_map->data)), 1, GFP_KERNEL, numa); if (!metadata_map->data) goto free_metadata_freelist; @@ -886,7 +886,7 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5= e_params *params, int err; =20 =20 - c =3D kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev= (mdev))); + c =3D kvzalloc_node(sizeof(*c), 1, GFP_KERNEL, dev_to_node(mlx5_core_dma_= dev(mdev))); cparams =3D kvzalloc(sizeof(*cparams), GFP_KERNEL); if (!c || !cparams) { err =3D -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c b/drivers/ne= t/ethernet/mellanox/mlx5/core/en/trap.c index b5c19396e096..eca14b387b48 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c @@ -135,7 +135,7 @@ static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_= priv *priv) struct mlx5e_trap *t; int err; =20 - t =3D kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu)); + t =3D kvzalloc_node(sizeof(*t), 1, GFP_KERNEL, cpu_to_node(cpu)); if (!t) return ERR_PTR(-ENOMEM); =20 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c b/drivers/net= /ethernet/mellanox/mlx5/core/en_dim.c index 298bb74ec5e9..635b2e7e163f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c @@ -70,7 +70,7 @@ static struct dim *mlx5e_dim_enable(struct mlx5_core_dev = *mdev, struct dim *dim; int err; =20 - dim =3D kvzalloc_node(sizeof(*dim), GFP_KERNEL, cpu_to_node(cpu)); + dim =3D kvzalloc_node(sizeof(*dim), 1, GFP_KERNEL, cpu_to_node(cpu)); if (!dim) return ERR_PTR(-ENOMEM); =20 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/ne= t/ethernet/mellanox/mlx5/core/en_main.c index ea822c69d137..a5a1bed18604 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -333,7 +333,7 @@ static inline void mlx5e_build_umr_wqe(struct mlx5e_rq = *rq, =20 static int mlx5e_rq_shampo_hd_alloc(struct mlx5e_rq *rq, int node) { - rq->mpwqe.shampo =3D kvzalloc_node(sizeof(*rq->mpwqe.shampo), + rq->mpwqe.shampo =3D kvzalloc_node(sizeof(*rq->mpwqe.shampo), 1, GFP_KERNEL, node); if (!rq->mpwqe.shampo) return -ENOMEM; @@ -353,7 +353,7 @@ static int mlx5e_rq_shampo_hd_info_alloc(struct mlx5e_r= q *rq, int node) node); shampo->pages =3D kvzalloc_node(array_size(shampo->hd_per_wq, sizeof(*shampo->pages)), - GFP_KERNEL, node); + 1, GFP_KERNEL, node); if (!shampo->bitmap || !shampo->pages) goto err_nomem; =20 @@ -381,7 +381,7 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *r= q, int node) alloc_units.frag_pages, rq->mpwqe.pages_per_wqe)); =20 - rq->mpwqe.info =3D kvzalloc_node(alloc_size, GFP_KERNEL, node); + rq->mpwqe.info =3D kvzalloc_node(alloc_size, 1, GFP_KERNEL, node); if (!rq->mpwqe.info) return -ENOMEM; =20 @@ -673,11 +673,11 @@ static int mlx5e_init_wqe_alloc_info(struct mlx5e_rq = *rq, int node) else aus_sz =3D sizeof(*aus->frag_pages); =20 - aus =3D kvzalloc_node(array_size(len, aus_sz), GFP_KERNEL, node); + aus =3D kvzalloc_node(array_size(len, aus_sz), 1, GFP_KERNEL, node); if (!aus) return -ENOMEM; =20 - frags =3D kvzalloc_node(array_size(len, sizeof(*frags)), GFP_KERNEL, node= ); + frags =3D kvzalloc_node(array_size(len, sizeof(*frags)), 1, GFP_KERNEL, n= ode); if (!frags) { kvfree(aus); return -ENOMEM; @@ -780,7 +780,7 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *m= dev, err =3D mlx5e_rq_shampo_hd_info_alloc(rq, node); if (err) goto err_shampo_info; - rq->hw_gro_data =3D kvzalloc_node(sizeof(*rq->hw_gro_data), GFP_KERNEL, n= ode); + rq->hw_gro_data =3D kvzalloc_node(sizeof(*rq->hw_gro_data), 1, GFP_KERNEL= , node); if (!rq->hw_gro_data) { err =3D -ENOMEM; goto err_hw_gro_data; @@ -1409,7 +1409,7 @@ static int mlx5e_alloc_xdpsq_fifo(struct mlx5e_xdpsq = *sq, int numa) MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO); =20 size =3D array_size(sizeof(*xdpi_fifo->xi), entries); - xdpi_fifo->xi =3D kvzalloc_node(size, GFP_KERNEL, numa); + xdpi_fifo->xi =3D kvzalloc_node(size, 1, GFP_KERNEL, numa); if (!xdpi_fifo->xi) return -ENOMEM; =20 @@ -1427,7 +1427,7 @@ static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *s= q, int numa) int err; =20 size =3D array_size(sizeof(*sq->db.wqe_info), wq_sz); - sq->db.wqe_info =3D kvzalloc_node(size, GFP_KERNEL, numa); + sq->db.wqe_info =3D kvzalloc_node(size, 1, GFP_KERNEL, numa); if (!sq->db.wqe_info) return -ENOMEM; =20 @@ -1504,7 +1504,7 @@ static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *s= q, int numa) size_t size; =20 size =3D array_size(wq_sz, sizeof(*sq->db.wqe_info)); - sq->db.wqe_info =3D kvzalloc_node(size, GFP_KERNEL, numa); + sq->db.wqe_info =3D kvzalloc_node(size, 1, GFP_KERNEL, numa); if (!sq->db.wqe_info) return -ENOMEM; =20 @@ -1583,13 +1583,13 @@ int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, in= t numa) =20 sq->db.dma_fifo =3D kvzalloc_node(array_size(df_sz, sizeof(*sq->db.dma_fifo)), - GFP_KERNEL, numa); + 1, GFP_KERNEL, numa); sq->db.skb_fifo.fifo =3D kvzalloc_node(array_size(df_sz, sizeof(*sq->db.skb_fifo.fifo)), - GFP_KERNEL, numa); + 1, GFP_KERNEL, numa); sq->db.wqe_info =3D kvzalloc_node(array_size(wq_sz, sizeof(*sq->db.wqe_info)), - GFP_KERNEL, numa); + 1, GFP_KERNEL, numa); if (!sq->db.dma_fifo || !sq->db.skb_fifo.fifo || !sq->db.wqe_info) { mlx5e_free_txqsq_db(sq); return -ENOMEM; @@ -2074,7 +2074,7 @@ static struct mlx5e_xdpsq *mlx5e_open_xdpredirect_sq(= struct mlx5e_channel *c, struct mlx5e_xdpsq *xdpsq; int err; =20 - xdpsq =3D kvzalloc_node(sizeof(*xdpsq), GFP_KERNEL, cpu_to_node(c->cpu)); + xdpsq =3D kvzalloc_node(sizeof(*xdpsq), 1, GFP_KERNEL, cpu_to_node(c->cpu= )); if (!xdpsq) return ERR_PTR(-ENOMEM); =20 @@ -2643,7 +2643,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_pri= v *priv, int ix, int cpu) */ netdev_dbg(priv->netdev, "Creating channel stats %d\n", ix); priv->channel_stats[ix] =3D kvzalloc_node(sizeof(**priv->channel_stats), - GFP_KERNEL, cpu_to_node(cpu)); + 1, GFP_KERNEL, cpu_to_node(cpu)); if (!priv->channel_stats[ix]) return -ENOMEM; priv->stats_nch++; @@ -2692,7 +2692,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv= , int ix, if (err) return err; =20 - c =3D kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu)); + c =3D kvzalloc_node(sizeof(*c), 1, GFP_KERNEL, cpu_to_node(cpu)); cparam =3D kvzalloc(sizeof(*cparam), GFP_KERNEL); if (!c || !cparam) { err =3D -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/eth= ernet/mellanox/mlx5/core/eq.c index dfb079e59d85..4e47ed58dee9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -432,7 +432,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) struct mlx5_eq_table *eq_table; int i; =20 - eq_table =3D kvzalloc_node(sizeof(*eq_table), GFP_KERNEL, + eq_table =3D kvzalloc_node(sizeof(*eq_table), 1, GFP_KERNEL, dev->priv.numa_node); if (!eq_table) return -ENOMEM; @@ -746,7 +746,7 @@ struct mlx5_eq * mlx5_eq_create_generic(struct mlx5_core_dev *dev, struct mlx5_eq_param *param) { - struct mlx5_eq *eq =3D kvzalloc_node(sizeof(*eq), GFP_KERNEL, + struct mlx5_eq *eq =3D kvzalloc_node(sizeof(*eq), 1, GFP_KERNEL, dev->priv.numa_node); int err; =20 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/ne= t/ethernet/mellanox/mlx5/core/pci_irq.c index 40024cfa3099..1cfc664fd78a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -706,7 +706,7 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev) if (mlx5_core_is_sf(dev)) return 0; =20 - irq_table =3D kvzalloc_node(sizeof(*irq_table), GFP_KERNEL, + irq_table =3D kvzalloc_node(sizeof(*irq_table), GFP_KERNEL, 1, dev->priv.numa_node); if (!irq_table) return -ENOMEM; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethe= rnet/wangxun/libwx/wx_lib.c index 7f2e6cddfeb1..c35a608c3ac1 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -2658,7 +2658,7 @@ static int wx_setup_rx_resources(struct wx_ring *rx_r= ing) if (rx_ring->q_vector) numa_node =3D rx_ring->q_vector->numa_node; =20 - rx_ring->rx_buffer_info =3D kvmalloc_node(size, GFP_KERNEL, numa_node); + rx_ring->rx_buffer_info =3D kvmalloc_node(size, 1, GFP_KERNEL, numa_node); if (!rx_ring->rx_buffer_info) rx_ring->rx_buffer_info =3D kvmalloc(size, GFP_KERNEL); if (!rx_ring->rx_buffer_info) @@ -2749,7 +2749,7 @@ static int wx_setup_tx_resources(struct wx_ring *tx_r= ing) if (tx_ring->q_vector) numa_node =3D tx_ring->q_vector->numa_node; =20 - tx_ring->tx_buffer_info =3D kvmalloc_node(size, GFP_KERNEL, numa_node); + tx_ring->tx_buffer_info =3D kvmalloc_node(size, 1, GFP_KERNEL, numa_node); if (!tx_ring->tx_buffer_info) tx_ring->tx_buffer_info =3D kvmalloc(size, GFP_KERNEL); if (!tx_ring->tx_buffer_info) diff --git a/include/linux/slab.h b/include/linux/slab.h index d5a8ab98035c..1eaf6c7b2754 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -465,9 +465,12 @@ 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_noprof(const void *objp, size_t new_size, + unsigned long align, + gfp_t flags, int nid) __realloc_size(2); +#define krealloc_node(...) alloc_hooks(krealloc_node_noprof(__VA_ARGS__)) +#define krealloc_noprof(_p, _s, _f) krealloc_node_noprof(_p, _s, 1, _f, NU= MA_NO_NODE) +#define krealloc(...) alloc_hooks(krealloc_noprof(__VA_ARGS__)) =20 void kfree(const void *objp); void kfree_sensitive(const void *objp); @@ -1041,40 +1044,45 @@ 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_noprof(size, align, flags, node) \ + __kvmalloc_node_noprof(PASS_BUCKET_PARAMS(size, NULL), align, flags, node) #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(_size, _flags) kvmalloc_node(_size, 1, _flags, NUMA_NO_= NODE) +#define kvmalloc_noprof(_size, _flags) kvmalloc_node_noprof(_size, 1, _fl= ags, NUMA_NO_NODE) #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, _a, _f, _n) kvmalloc_node(_s, _a, (_f)|__GFP_ZE= RO, _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) +kvmalloc_array_node_noprof(size_t n, size_t size, unsigned long align, gfp= _t flags, int node) { size_t bytes; =20 if (unlikely(check_mul_overflow(n, size, &bytes))) return NULL; =20 - return kvmalloc_node_noprof(bytes, flags, node); + return kvmalloc_node_noprof(bytes, align, flags, node); } =20 -#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_noprof(_n, _s, _f) \ + kvmalloc_array_node_noprof(_n, _s, 1, _f, NUMA_NO_NODE) +#define kvcalloc_node_noprof(_n, _s, _a, _f, _node) \ + kvmalloc_array_node_noprof(_n, _s, _a, (_f) | __GFP_ZERO, _node) +#define kvcalloc_noprof(_n, _s, _f) kvcalloc_node_noprof(_n, _s, 1, _f, N= UMA_NO_NODE) =20 #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_noprof(const void *p, size_t size, unsigned long alig= n, + gfp_t flags, int nid) __realloc_size(2); +#define kvrealloc_node(...) alloc_hooks(kvrealloc_node_noprof(__VA_ARGS_= _)) +#define kvrealloc_noprof(_p, _s, _f) kvrealloc_node_noprof(_p, _s, 1, _f,= NUMA_NO_NODE) #define kvrealloc(...) alloc_hooks(kvrealloc_noprof(__VA_ARGS__)) =20 extern void kvfree(const void *addr); diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 3e555d012ed6..89a9fee5231d 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -184,7 +184,7 @@ static struct bucket_table *bucket_table_alloc(struct r= hashtable *ht, static struct lock_class_key __key; =20 tbl =3D alloc_hooks_tag(ht->alloc_tag, - kvmalloc_node_noprof(struct_size(tbl, buckets, nbuckets), + kvmalloc_node_noprof(struct_size(tbl, buckets, nbuckets), 1, gfp|__GFP_ZERO, NUMA_NO_NODE)); =20 size =3D nbuckets; diff --git a/lib/sbitmap.c b/lib/sbitmap.c index d3412984170c..52a7a2f938f2 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -129,7 +129,7 @@ int sbitmap_init_node(struct sbitmap *sb, unsigned int = depth, int shift, sb->alloc_hint =3D NULL; } =20 - sb->map =3D kvzalloc_node(sb->map_nr * sizeof(*sb->map), flags, node); + sb->map =3D kvzalloc_node(sb->map_nr * sizeof(*sb->map), 1, flags, node); if (!sb->map) { free_percpu(sb->alloc_hint); return -ENOMEM; diff --git a/lib/tests/fortify_kunit.c b/lib/tests/fortify_kunit.c index 29ffc62a71e3..9a583c51cc16 100644 --- a/lib/tests/fortify_kunit.c +++ b/lib/tests/fortify_kunit.c @@ -298,13 +298,13 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(vmalloc) kvmalloc((alloc_pages) * PAGE_SIZE, gfp), \ kvfree(p)); \ checker((expected_pages) * PAGE_SIZE, \ - kvmalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \ + kvmalloc_node((alloc_pages) * PAGE_SIZE, 1, gfp, NUMA_NO_NODE), \ kvfree(p)); \ checker((expected_pages) * PAGE_SIZE, \ kvzalloc((alloc_pages) * PAGE_SIZE, gfp), \ kvfree(p)); \ checker((expected_pages) * PAGE_SIZE, \ - kvzalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \ + kvzalloc_node((alloc_pages) * PAGE_SIZE, 1, gfp, NUMA_NO_NODE), \ kvfree(p)); \ checker((expected_pages) * PAGE_SIZE, \ kvcalloc(1, (alloc_pages) * PAGE_SIZE, gfp), \ diff --git a/lib/tests/overflow_kunit.c b/lib/tests/overflow_kunit.c index 19cb03b25dc5..3eede04baa08 100644 --- a/lib/tests/overflow_kunit.c +++ b/lib/tests/overflow_kunit.c @@ -608,18 +608,19 @@ static void shift_nonsense_test(struct kunit *test) * the DEFINE_TEST_ALLOC() instances for mapping of the "bits". */ #define alloc_GFP (GFP_KERNEL | __GFP_NOWARN) -#define alloc010(alloc, arg, sz) alloc(sz, alloc_GFP) -#define alloc011(alloc, arg, sz) alloc(sz, alloc_GFP, NUMA_NO_NODE) -#define alloc000(alloc, arg, sz) alloc(sz) -#define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) -#define alloc110(alloc, arg, sz) alloc(arg, sz, alloc_GFP) +#define alloc0010(alloc, arg, sz) alloc(sz, alloc_GFP) +#define alloc0011(alloc, arg, sz) alloc(sz, alloc_GFP, NUMA_NO_NODE) +#define alloc0000(alloc, arg, sz) alloc(sz) +#define alloc0111(alloc, arg, sz) alloc(sz, 1, alloc_GFP, NUMA_NO_NODE) +#define alloc0001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) +#define alloc1010(alloc, arg, sz) alloc(arg, sz, alloc_GFP) #define free0(free, arg, ptr) free(ptr) #define free1(free, arg, ptr) free(arg, ptr) =20 /* Wrap around to 16K */ #define TEST_SIZE (5 * 4096) =20 -#define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ +#define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_align, want_gfp,= want_node)\ static void test_ ## func (struct kunit *test, void *arg) \ { \ volatile size_t a =3D TEST_SIZE; \ @@ -627,21 +628,22 @@ static void test_ ## func (struct kunit *test, void *= arg) \ void *ptr; \ \ /* Tiny allocation test. */ \ - ptr =3D alloc ## want_arg ## want_gfp ## want_node (func, arg, 1);\ + ptr =3D alloc ## want_arg ## want_align ## want_gfp ## \ + want_node(func, arg, 1); \ KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, \ #func " failed regular allocation?!\n"); \ free ## want_arg (free_func, arg, ptr); \ \ /* Wrapped allocation test. */ \ - ptr =3D alloc ## want_arg ## want_gfp ## want_node (func, arg, \ - a * b); \ + ptr =3D alloc ## want_arg ## want_align ## want_gfp ## \ + want_node(func, arg, a * b); \ KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, \ #func " unexpectedly failed bad wrapping?!\n"); \ free ## want_arg (free_func, arg, ptr); \ \ /* Saturated allocation test. */ \ - ptr =3D alloc ## want_arg ## want_gfp ## want_node (func, arg, \ - array_size(a, b)); \ + ptr =3D alloc ## want_arg ## want_align ## want_gfp ## \ + want_node(func, arg, array_size(a, b)); \ if (ptr) { \ KUNIT_FAIL(test, #func " missed saturation!\n"); \ free ## want_arg (free_func, arg, ptr); \ @@ -649,22 +651,23 @@ static void test_ ## func (struct kunit *test, void *= arg) \ } =20 /* - * Allocator uses a trailing node argument --------+ (e.g. kmalloc_node()) - * Allocator uses the gfp_t argument -----------+ | (e.g. kmalloc()) - * Allocator uses a special leading argument + | | (e.g. devm_kmalloc()) - * | | | + * Allocator uses a trailing node argument -----------+ (e.g. kmalloc_nod= e()) + * Allocator uses the gfp_t argument --------------+ | (e.g. kmalloc()) + * Allocator uses align argument ---------------+ | | (e.g. kvmalloc_no= de()) + * Allocator uses a special leading argument + | | | (e.g. devm_kmallo= c()) + * | | | | */ -DEFINE_TEST_ALLOC(kmalloc, kfree, 0, 1, 0); -DEFINE_TEST_ALLOC(kmalloc_node, kfree, 0, 1, 1); -DEFINE_TEST_ALLOC(kzalloc, kfree, 0, 1, 0); -DEFINE_TEST_ALLOC(kzalloc_node, kfree, 0, 1, 1); -DEFINE_TEST_ALLOC(__vmalloc, vfree, 0, 1, 0); -DEFINE_TEST_ALLOC(kvmalloc, kvfree, 0, 1, 0); -DEFINE_TEST_ALLOC(kvmalloc_node, kvfree, 0, 1, 1); -DEFINE_TEST_ALLOC(kvzalloc, kvfree, 0, 1, 0); -DEFINE_TEST_ALLOC(kvzalloc_node, kvfree, 0, 1, 1); -DEFINE_TEST_ALLOC(devm_kmalloc, devm_kfree, 1, 1, 0); -DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 1, 0); +DEFINE_TEST_ALLOC(kmalloc, kfree, 0, 0, 1, 0); +DEFINE_TEST_ALLOC(kmalloc_node, kfree, 0, 0, 1, 1); +DEFINE_TEST_ALLOC(kzalloc, kfree, 0, 0, 1, 0); +DEFINE_TEST_ALLOC(kzalloc_node, kfree, 0, 0, 1, 1); +DEFINE_TEST_ALLOC(__vmalloc, vfree, 0, 0, 1, 0); +DEFINE_TEST_ALLOC(kvmalloc, kvfree, 0, 0, 1, 0); +DEFINE_TEST_ALLOC(kvmalloc_node, kvfree, 0, 1, 1, 1); +DEFINE_TEST_ALLOC(kvzalloc, kvfree, 0, 0, 1, 0); +DEFINE_TEST_ALLOC(kvzalloc_node, kvfree, 0, 1, 1, 1); +DEFINE_TEST_ALLOC(devm_kmalloc, devm_kfree, 1, 0, 1, 0); +DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 0, 1, 0); =20 static void overflow_allocation_test(struct kunit *test) { diff --git a/mm/shrinker.c b/mm/shrinker.c index 4a93fd433689..10b5913f0583 100644 --- a/mm/shrinker.c +++ b/mm/shrinker.c @@ -82,7 +82,7 @@ int alloc_shrinker_info(struct mem_cgroup *memcg) mutex_lock(&shrinker_mutex); array_size =3D shrinker_unit_size(shrinker_nr_max); for_each_node(nid) { - struct shrinker_info *info =3D kvzalloc_node(sizeof(*info) + array_size, + struct shrinker_info *info =3D kvzalloc_node(sizeof(*info) + array_size,= 1, GFP_KERNEL, nid); if (!info) goto err; @@ -128,7 +128,7 @@ static int expand_one_shrinker_info(struct mem_cgroup *= memcg, int new_size, if (new_nr_max <=3D old->map_nr_max) continue; =20 - new =3D kvzalloc_node(sizeof(*new) + new_size, GFP_KERNEL, nid); + new =3D kvzalloc_node(sizeof(*new) + new_size, 1, GFP_KERNEL, nid); if (!new) return -ENOMEM; =20 diff --git a/mm/slub.c b/mm/slub.c index c4b64821e680..733395642f06 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(); @@ -4918,7 +4931,9 @@ __do_krealloc(const void *p, size_t new_size, gfp_t f= lags) * krealloc - reallocate memory. The contents will remain unchanged. * @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_noprof(const void *p, size_t new_size, unsigned long a= lign, + 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_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 - 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,17 @@ 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_noprof(const void *p, size_t size, unsigned long alig= n, gfp_t flags, int nid) { void *n; =20 if (is_vmalloc_addr(p)) - return vrealloc_noprof(p, size, flags); + return vrealloc_node_noprof(p, size, align, flags, nid); =20 - n =3D krealloc_noprof(p, size, kmalloc_gfp_adjust(flags, size)); + n =3D krealloc_node_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_noprof(size, align, flags, nid); if (!n) return NULL; =20 @@ -5126,7 +5148,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_noprof); =20 struct detached_freelist { struct slab *slab; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 709840612f0d..69d06fc5637a 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1352,7 +1352,7 @@ static int xt_jumpstack_alloc(struct xt_table_info *i) */ size =3D sizeof(void *) * i->stacksize * 2u; for_each_possible_cpu(cpu) { - i->jumpstack[cpu] =3D kvmalloc_node(size, GFP_KERNEL, + i->jumpstack[cpu] =3D kvmalloc_node(size, 1, GFP_KERNEL, cpu_to_node(cpu)); if (i->jumpstack[cpu] =3D=3D NULL) /* diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 26b069e1999d..e46759b5ba4e 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -471,12 +471,12 @@ static struct rds_header **rds_dma_hdrs_alloc(struct = rds_ib_device *dev, dma_addr_t *hdr_daddrs; u32 i; =20 - hdrs =3D kvmalloc_node(sizeof(*hdrs) * num_hdrs, GFP_KERNEL, + hdrs =3D kvmalloc_node(sizeof(*hdrs) * num_hdrs, 1, GFP_KERNEL, ibdev_to_node(dev->dev)); if (!hdrs) return NULL; =20 - hdr_daddrs =3D kvmalloc_node(sizeof(*hdr_daddrs) * num_hdrs, GFP_KERNEL, + hdr_daddrs =3D kvmalloc_node(sizeof(*hdr_daddrs) * num_hdrs, 1, GFP_KERNE= L, ibdev_to_node(dev->dev)); if (!hdr_daddrs) { kvfree(hdrs); diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 902ff5470607..0e5f38a899b3 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -894,7 +894,8 @@ static int fq_resize(struct Qdisc *sch, u32 log) return 0; =20 /* If XPS was setup, we can allocate memory on right NUMA node */ - array =3D kvmalloc_node(sizeof(struct rb_root) << log, GFP_KERNEL | __GFP= _RETRY_MAYFAIL, + array =3D kvmalloc_node(sizeof(struct rb_root) << log, 1, + GFP_KERNEL | __GFP_RETRY_MAYFAIL, netdev_queue_numa_node_read(sch->dev_queue)); if (!array) return -ENOMEM; --=20 2.39.2 From nobody Wed Oct 8 13:25:00 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 08DB4271464 for ; Fri, 27 Jun 2025 09:39:04 +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=1751017146; cv=none; b=HooLCH2UPBJ2BUWZRE5cFEW3/kEOWPrXRC9YlDoaMHOMnpUzwbz96aCqizLhBkz5HeUBI/0yjkCJZVcf6YLM32VLMWNWvXaMA4KImX/klmE9YhPdE7H8ZDjZjJ9fcNWD6x9XqS5KRTxddCf6qSPQsYfl6AVqzBpGIj1kkV6DJlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751017146; c=relaxed/simple; bh=vTj9sdyfg8G0yoI82Xzj73+oAGnxEL+xm6ZGeVSNewc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=O2mu0JjWqpElcWe7Hwg8K4kqZmq2g1wv0HcRx2dZ96qaq9zvDypXmBQIqCHC2Toaibj9eJ6TiideWD/fji5lGvqLysz2r6Lx2x0jzsAaucHHrK83A0G/M++Hd4Pxm0vHnbn+yVLOIarCqVZLeKgK9XTy0+ynb+ZgIHJ8wrsdmJo= 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=SLC8WGqY; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=XIuLFsgY; 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="SLC8WGqY"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="XIuLFsgY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751017143; x=1751621943; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=Zx3LglPu0mTTlfXiukstk1SD/1VGL40wbfi6XAP+H6c=; b=SLC8WGqYSlOuExKlSLNnuwYPyRqCrtKmjCo9cjzxxalOzpHfwynKd2FQ2lKRiaUD2nfleTlQFiBzB znNqjffyPyFMoziA0lGrMWUAzNvJeexYr0li0pNn9oYprRygXhBIkVnUvl1PfLso+oW3DcJ+Xxz3yd 70SyL21vuMpIbXhaVNE2qLqNYLoARkhwvxcVkf7ngVbKh7Vo/KM7XhgdBV+DB/26FjUNkjKBGQLebM eU7764KD5weZ7miuSeMGJBn3MnTzrQcBGHH5yuUX5swX4DJgWWEy+McK3L4dDwEbStW11tO93pyiZH YqPYIwsyzZ1RVpgX4Qs2Q0owUqwYjwA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751017143; x=1751621943; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=Zx3LglPu0mTTlfXiukstk1SD/1VGL40wbfi6XAP+H6c=; b=XIuLFsgYciRqdOrFWVTDTZ2QHucN29Inmmd4QCdcnzLjTC2FfY7gG8Ec7G87pVKgTiIuuNhIwsiZz Y62j114DA== X-HalOne-ID: 8e647328-533a-11f0-b070-4f541c8bf1cc Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay3.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 8e647328-533a-11f0-b070-4f541c8bf1cc; Fri, 27 Jun 2025 09:39:02 +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 v5 3/4] rust: add support for NUMA ids in allocations Date: Fri, 27 Jun 2025 11:38:58 +0200 Message-Id: <20250627093858.413855-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250627092901.356909-1-vitaly.wool@konsulko.se> References: <20250627092901.356909-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 specifying NUMA ids in Rust allocators as an Option (i. e. providing `None` as nid corresponds to NUMA_NO_NODE). To do this, modify ReallocFunc to use the new extended realloc primitives from the C side of the kernel (i. e. k[v]realloc_node/vrealloc_node) 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 | 13 +++++++++++++ rust/helpers/vmalloc.c | 6 ++++++ rust/kernel/alloc.rs | 28 ++++++++++++++++++++++++++-- rust/kernel/alloc/allocator.rs | 33 ++++++++++++++++++++++----------- rust/kernel/alloc/kvec.rs | 3 ++- 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/rust/helpers/slab.c b/rust/helpers/slab.c index a842bfbddcba..5db9450e9348 100644 --- a/rust/helpers/slab.c +++ b/rust/helpers/slab.c @@ -13,3 +13,16 @@ rust_helper_kvrealloc(const void *p, size_t size, gfp_t = flags) { return kvrealloc(p, size, flags); } + +void * __must_check __realloc_size(2) +rust_helper_krealloc_node(const void *objp, size_t new_size, unsigned long= align, + gfp_t flags, int node) +{ + return krealloc_node(objp, new_size, align, flags, node); +} + +void * __must_check __realloc_size(2) +rust_helper_kvrealloc_node(const void *p, size_t size, unsigned long align= , gfp_t flags, int node) +{ + return kvrealloc_node(p, size, align, flags, node); +} diff --git a/rust/helpers/vmalloc.c b/rust/helpers/vmalloc.c index 80d34501bbc0..7a71427a1e78 100644 --- a/rust/helpers/vmalloc.c +++ b/rust/helpers/vmalloc.c @@ -7,3 +7,9 @@ rust_helper_vrealloc(const void *p, size_t size, gfp_t flag= s) { return vrealloc(p, size, flags); } + +void * __must_check __realloc_size(2) +rust_helper_vrealloc_node(const void *p, size_t size, unsigned long align,= gfp_t flags, int node) +{ + return vrealloc_node(p, size, align, flags, node); +} diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index a2c49e5494d3..1e26c2a7f47c 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -156,7 +156,30 @@ pub unsafe trait Allocator { fn alloc(layout: Layout, flags: Flags) -> Result, AllocE= rror> { // SAFETY: Passing `None` to `realloc` is valid by its safety requ= irements and asks for a // new memory allocation. - unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags) } + unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags, N= one) } + } + + /// 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` when called with `None`. + /// + /// # Guarantees + /// + /// When the return value is `Ok(ptr)`, then `ptr` is + /// - valid for reads and writes for `layout.size()` bytes, until it i= s passed to + /// [`Allocator::free`] or [`Allocator::realloc`], + /// - aligned to `layout.align()`, + /// + /// Additionally, `Flags` are honored as documented in + /// . + fn alloc_node(layout: Layout, flags: Flags, nid: Option) + -> Result, AllocError> { + // SAFETY: Passing `None` to `realloc` is valid by its safety requ= irements and asks for a + // new memory allocation. + unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags, n= id) } } =20 /// Re-allocate an existing memory allocation to satisfy the requested= `layout`. @@ -196,6 +219,7 @@ unsafe fn realloc( layout: Layout, old_layout: Layout, flags: Flags, + nid: Option, ) -> Result, AllocError>; =20 /// Free an existing memory allocation. @@ -211,7 +235,7 @@ unsafe fn free(ptr: NonNull, layout: Layout) { // SAFETY: The caller guarantees that `ptr` points at a valid allo= cation created by this // allocator. We are passing a `Layout` with the smallest possible= alignment, so it is // smaller than or equal to the alignment previously used with thi= s allocation. - let _ =3D unsafe { Self::realloc(Some(ptr), Layout::new::<()>(), l= ayout, Flags(0)) }; + let _ =3D unsafe { Self::realloc(Some(ptr), Layout::new::<()>(), l= ayout, Flags(0), None) }; } } =20 diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index aa2dfa9dca4c..4f0fe2b67593 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -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, crate::ffi::c_u= long, 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_NODE: 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_NODE: 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_NODE: Self =3D Self(bindings::kvrealloc_node); =20 /// # Safety /// @@ -87,6 +89,7 @@ unsafe fn call( layout: Layout, old_layout: Layout, flags: Flags, + nid: Option, ) -> Result, AllocError> { let size =3D aligned_size(layout); let ptr =3D match ptr { @@ -100,6 +103,11 @@ unsafe fn call( None =3D> ptr::null(), }; =20 + let c_nid =3D match nid { + None =3D> bindings::NUMA_NO_NODE, + Some(n) =3D> n, + }; + // SAFETY: // - `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc` and th= us only requires that // `ptr` is NULL or valid. @@ -110,7 +118,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, 1, flags.0, c_nid).cast() }; =20 let ptr =3D if size =3D=3D 0 { @@ -134,9 +142,10 @@ unsafe fn realloc( layout: Layout, old_layout: Layout, flags: Flags, + nid: Option, ) -> 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_NODE.call(ptr, layout, old_layout, = flags, nid) } } } =20 @@ -151,6 +160,7 @@ unsafe fn realloc( layout: Layout, old_layout: Layout, flags: Flags, + nid: Option, ) -> Result, AllocError> { // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { @@ -160,7 +170,7 @@ 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_NODE.call(ptr, layout, old_layout, = flags, nid) } } } =20 @@ -175,6 +185,7 @@ unsafe fn realloc( layout: Layout, old_layout: Layout, flags: Flags, + nid: Option, ) -> Result, AllocError> { // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { @@ -184,6 +195,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_NODE.call(ptr, layout, old_layout,= flags, nid) } } } diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index 1a0dd852a468..ef4f977ba012 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -633,6 +633,7 @@ pub fn reserve(&mut self, additional: usize, flags: Fla= gs) -> Result<(), AllocEr layout.into(), self.layout.into(), flags, + None, )? }; =20 @@ -1058,7 +1059,7 @@ pub fn collect(self, flags: Flags) -> Vec { // the type invariant to be smaller than `cap`. Depending on `= realloc` this operation // may shrink the buffer or leave it as it is. ptr =3D match unsafe { - A::realloc(Some(buf.cast()), layout.into(), old_layout.int= o(), flags) + A::realloc(Some(buf.cast()), layout.into(), old_layout.int= o(), flags, None) } { // If we fail to shrink, which likely can't even happen, c= ontinue with the existing // buffer. --=20 2.39.2 From nobody Wed Oct 8 13:25:00 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 1533B293C6E for ; Fri, 27 Jun 2025 09:39:23 +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=1751017165; cv=none; b=eF7aRPIwAZ7h8Joi3J4xGvXIJMd+EohsDuahJ5cELlvsT4cuFdH4yk3+MWwmZLByDcKy5IOMyXC9KBKy2OMckST1vc0CioIWpesvtBUuckBFkdxtngBCcyl7Wz6e3ACWp1Ciqv2WfZijj9QkkMSic/8ZstcyW6215XeJ0BfFzsk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751017165; c=relaxed/simple; bh=cMBPS7UL7Z9M3GsM6vxgAs14SnbamdvW0l1fLWM1wYo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NyxYTA+w/q8JpIa4RW9xKCekbiaSuSX9p1WH2/P4WlXE+uVL5/LQHzrPK0jOfYc/3c/shQz03X3M4aUeJ+ZwQlYCbMu083Tc6KgXCtiu7Trpgcul4s1gjzgoeYtcUGNXxHZKU8iKuH90O4yxTzvmCey5qmbLG5RYDfPN9Nw/TiQ= 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=5M0z4Bkc; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b=Mriq9ZxF; 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="5M0z4Bkc"; dkim=permerror (0-bit key) header.d=konsulko.se header.i=@konsulko.se header.b="Mriq9ZxF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1751017162; x=1751621962; d=konsulko.se; s=rsa1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=iZmlSFy4KF+5xgzlYCUJvQ/v8BY1pzWF9k3tLUMOd/w=; b=5M0z4BkcQJPtMNSk1YM1oSuYfov1jWqF/cQNd3w52dHdjZN3zMOcG0YoYxwbfioEKKKkMNEDH61Bz fAxfevYEfbeAqjnpwSDp9AW7seGmpjAcjVQZfuz2MMHxNcq7TGqmAQHOyjY7OtaQOtZ/9ulLtcFZ0I vZEE9Wojt1jL8BWhyPUPi0+WvcIvVszByrgXgzNrLb4raBgADaxMiBKoavMdJdCr9gmBlNHcgjoGco RF8ySaydBmQyXNhhY3WgTaS4J5AAxO/Pjn1HcrI3nvzn0Kp+IyHxtcNk8Y2+VeOl3Sl5+BEslLI4i5 YbefVxx8caSXYJc4sPCC5/A4DbkvaWQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1751017162; x=1751621962; d=konsulko.se; s=ed1; h=content-transfer-encoding:mime-version:references:in-reply-to:message-id:date: subject:cc:to:from:from; bh=iZmlSFy4KF+5xgzlYCUJvQ/v8BY1pzWF9k3tLUMOd/w=; b=Mriq9ZxFe+umxklzgZa0m3XrQgsem7CIrFuK4VBWmaIwDf/1rqvhYlj9gO3ioVs2z8KAwqx77XOIz M6hhnyqDw== X-HalOne-ID: 9a50b852-533a-11f0-83cc-e90f2b8e16ca Received: from slottsdator.home (host-90-238-19-233.mobileonline.telia.com [90.238.19.233]) by mailrelay2.pub.mailoutpod2-cph3.one.com (Halon) with ESMTPSA id 9a50b852-533a-11f0-83cc-e90f2b8e16ca; Fri, 27 Jun 2025 09:39:22 +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 v5 4/4] rust: support large alignments in allocations Date: Fri, 27 Jun 2025 11:39:18 +0200 Message-Id: <20250627093918.415888-1-vitaly.wool@konsulko.se> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250627092901.356909-1-vitaly.wool@konsulko.se> References: <20250627092901.356909-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. With _NODE primitives introduced in the previous patch, we actually have all the infractructure in place so let's just start using it. Signed-off-by: Vitaly Wool --- rust/kernel/alloc/allocator.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 4f0fe2b67593..75c9e4220ac3 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -118,7 +118,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, 1, flags.0, c_nid).cast() + self.0(ptr.cast(), size, layout.align(), flags.0, c_nid).cast() }; =20 let ptr =3D if size =3D=3D 0 { @@ -162,12 +162,6 @@ unsafe fn realloc( flags: Flags, nid: Option, ) -> 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_NODE.call(ptr, layout, old_layout, = flags, nid) } @@ -187,12 +181,6 @@ unsafe fn realloc( flags: Flags, nid: Option, ) -> 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_NODE.call(ptr, layout, old_layout,= flags, nid) } --=20 2.39.2