From: Alexander Lobakin <aleksander.lobakin@intel.com>
To: Jesper Dangaard Brouer <hawk@kernel.org>, Christoph Hellwig <hch@lst.de>
Cc: Vlastimil Babka <vbabka@kernel.org>, Harry Yoo <harry@kernel.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
Hao Li <hao.li@linux.dev>, "Christoph Lameter" <cl@gentwo.org>,
David Rientjes <rientjes@google.com>,
Roman Gushchin <roman.gushchin@linux.dev>,
<linux-arm-msm@vger.kernel.org>,
<dri-devel@lists.freedesktop.org>,
<freedreno@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>,
<linux-mm@kvack.org>, <io-uring@vger.kernel.org>,
<kasan-dev@googlegroups.com>, <bpf@vger.kernel.org>,
<netdev@vger.kernel.org>, Matt Fleming <mfleming@cloudflare.com>,
kernel-team <kernel-team@cloudflare.com>
Subject: Re: [PATCH] mm/slab: improve kmem_cache_alloc_bulk
Date: Wed, 27 May 2026 15:56:38 +0200 [thread overview]
Message-ID: <777c7229-4285-4c7c-9340-dfaebd2ab291@intel.com> (raw)
In-Reply-To: <e4dcfbc8-2666-452c-90b2-25c4b2c50c9f@kernel.org>
From: Jesper Dangaard Brouer <hawk@kernel.org>
Date: Wed, 27 May 2026 10:51:42 +0200
>
>
> On 27/05/2026 09.02, Christoph Hellwig wrote:
>> The kmem_cache_alloc_bulk return value is weird. It returns the number
>> of allocated objects, but that must always be 0 or the requested number
>> based on the implementations and the handling in the callers, but that
>> assumption is not actually documented anywhere, which confuses automated
>> review tools.
>>
>
> I remember, this API behavior was requested by AKPM when I developed
> kmem_cache_alloc_bulk. I trusted AKPM's decision, but I cannot explain
> why this choice was made.
I sorta remember that when I was reading this function, I also noticed
that it always returns only 2 possible values (0 or the requested
number), but didn't pay enough attention or it was already after I
introduced napi_skb_cache_get_bulk().
>
> I kept the netdev code usage below. The current napi_skb_cache_get_bulk
> have a retry logic that assumes that a partial bulk number can be
> returned (which it cannot as Hellwig explains). Cc Alex/Olek please
> review the changes below as you added this retry logic.
As far as I can see, the diff below doesn't introduce any functional
changes (but allows for a bit better compiler optimization). The logic
is still the same:
1) try to allocate non-zeroed skbs into the cache
2) if not enough, try to allocate zeroed skbs directly
3) if still not enough, return less than requested
The logic is still valid even if kmem_cache_alloc_bulk() return bool --
we might have some skbs in the cache (but less than requested) and then
the first allocation try may fail, but the second one succeed (as it
allocates from a different (the zeroed) zone).
>
>
>> Fix this by returning a bool if the allocation succeeded and adding a
>> kerneldoc comment explaining the API.
>>
>> Signed-off-by: Christoph Hellwig <hch@lst.de>
>> ---
>> drivers/gpu/drm/msm/msm_iommu.c | 6 +--
>> drivers/gpu/drm/panthor/panthor_mmu.c | 12 +++---
>> include/linux/slab.h | 6 ++-
>> io_uring/io_uring.c | 23 +++++------
>> lib/test_meminit.c | 19 +++++----
>> mm/kasan/kasan_test_c.c | 5 +--
>> mm/kfence/kfence_test.c | 9 +++--
>> mm/slub.c | 58 +++++++++++++++------------
>> net/bpf/test_run.c | 7 ++--
>> net/core/skbuff.c | 24 ++++++-----
>> tools/include/linux/slab.h | 2 +-
>> tools/testing/shared/linux.c | 19 ++++-----
>> 12 files changed, 93 insertions(+), 97 deletions(-)
>>
>
> [...]
>
>> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
>> index 44ac121cfccb..73045b688385 100644
>> --- a/net/core/skbuff.c
>> +++ b/net/core/skbuff.c
>> @@ -288,11 +288,11 @@ static inline struct sk_buff
>> *napi_skb_cache_get(bool alloc)
>> local_lock_nested_bh(&napi_alloc_cache.bh_lock);
>> if (unlikely(!nc->skb_count)) {
>> - if (alloc)
>> - nc->skb_count =
>> kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> - GFP_ATOMIC | __GFP_NOWARN,
>> - NAPI_SKB_CACHE_BULK,
>> - nc->skb_cache);
>> + if (alloc && kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> + GFP_ATOMIC | __GFP_NOWARN,
>> + NAPI_SKB_CACHE_BULK,
>> + nc->skb_cache))
>> + nc->skb_count = NAPI_SKB_CACHE_BULK;
>> if (unlikely(!nc->skb_count)) {
>> local_unlock_nested_bh(&napi_alloc_cache.bh_lock);
>> return NULL;
>> @@ -353,16 +353,18 @@ u32 napi_skb_cache_get_bulk(void **skbs, u32 n)
>> /* No enough cached skbs. Try refilling the cache first */
>> bulk = min(NAPI_SKB_CACHE_SIZE - nc->skb_count,
>> NAPI_SKB_CACHE_BULK);
>> - nc->skb_count += kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> - GFP_ATOMIC | __GFP_NOWARN, bulk,
>> - &nc->skb_cache[nc->skb_count]);
>> + if (kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> + GFP_ATOMIC | __GFP_NOWARN, bulk,
>> + &nc->skb_cache[nc->skb_count]))
>> + nc->skb_count += bulk;
>> if (likely(nc->skb_count >= n))
>> goto get;
>> /* Still not enough. Bulk-allocate the missing part directly,
>> zeroed */
>> - n -= kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> - GFP_ATOMIC | __GFP_ZERO | __GFP_NOWARN,
>> - n - nc->skb_count, &skbs[nc->skb_count]);
>> + if (kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
>> + GFP_ATOMIC | __GFP_ZERO | __GFP_NOWARN,
>> + n - nc->skb_count, &skbs[nc->skb_count]))
>> + n = nc->skb_count;
kmem_cache_alloc_bulk() allocates `n - nc->skb_count`, but here you
assign `nc->skb_count` to n.
Ah wait,
n -= n - nc->skb_count
n = n - (n - nc->skb_count)
n = n - n + nc->skb_count
n = nc->skb_count
Correct :D
>> if (likely(nc->skb_count >= n))
>> goto get;
Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> # skbuff
Thanks,
Olek
next prev parent reply other threads:[~2026-05-27 13:57 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 7:02 improve the kmem_cache_alloc_bulk API Christoph Hellwig
2026-05-27 7:02 ` [PATCH] mm/slab: improve kmem_cache_alloc_bulk Christoph Hellwig
2026-05-27 7:53 ` bot+bpf-ci
2026-05-27 8:51 ` Jesper Dangaard Brouer
2026-05-27 13:56 ` Alexander Lobakin [this message]
2026-05-27 14:07 ` Christoph Hellwig
2026-05-27 9:38 ` Vlastimil Babka (SUSE)
2026-05-27 12:20 ` Christoph Hellwig
2026-05-27 9:11 ` improve the kmem_cache_alloc_bulk API Vlastimil Babka (SUSE)
2026-05-27 12:21 ` Christoph Hellwig
2026-05-27 14:07 ` Vlastimil Babka (SUSE)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=777c7229-4285-4c7c-9340-dfaebd2ab291@intel.com \
--to=aleksander.lobakin@intel.com \
--cc=akpm@linux-foundation.org \
--cc=bpf@vger.kernel.org \
--cc=cl@gentwo.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=hao.li@linux.dev \
--cc=harry@kernel.org \
--cc=hawk@kernel.org \
--cc=hch@lst.de \
--cc=io-uring@vger.kernel.org \
--cc=kasan-dev@googlegroups.com \
--cc=kernel-team@cloudflare.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mfleming@cloudflare.com \
--cc=netdev@vger.kernel.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox