From: sashiko-bot@kernel.org
To: "Harry Yoo (Oracle)" <harry@kernel.org>
Cc: linux-rt-devel@lists.linux.dev, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org
Subject: Re: [PATCH v5 7/8] mm/slab: introduce kfree_rcu_nolock()
Date: Wed, 29 Jul 2026 08:41:33 +0000 [thread overview]
Message-ID: <20260729084133.868411F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260729-kfree_rcu_nolock-v5-7-a28cdcda9673@kernel.org>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] `kfree_rcu_nolock()` and `kvfree_call_rcu()` invoke `__kfree_rcu_sheaf()`, which acquires a `local_trylock()`. This triggers lockdep 'Invalid wait context' warnings and can cause deadlocks on PREEMPT_RT.
- [Medium] Missing `kasan_record_aux_stack()` in the `fallback` path of `kfree_call_rcu_nolock()` loses the original free stack trace.
- [Low] Missing struct pointer cast in the `kfree_rcu_nolock()` macro causes incompatible pointer type compilation errors when `CONFIG_KVFREE_RCU_BATCHED` is enabled.
--
--- Patch [7]: [PATCH v5 7/8] mm/slab: introduce kfree_rcu_nolock() ---
commit 34c7828edcaca9e66aa219ee881130dc05e9102d
Author: Harry Yoo (Oracle) <harry@kernel.org>
Subject: mm/slab: introduce kfree_rcu_nolock()
The commit introduces kfree_rcu_nolock() to handle freeing objects in unknown
contexts without deferred processing when possible. It relies on
__kfree_rcu_sheaf() for the fast path and falls back to defer_kfree_rcu()
which uses an irq_work.
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -1124,6 +1125,27 @@ do { \
> kvfree_call_rcu(NULL, (void *) (___p)); \
> } while (0)
>
> +/**
> + * kfree_rcu_nolock() - a version of kfree_rcu() that can be called in any context.
> + * @ptr: pointer to kfree for double-argument invocations.
> + * @kvrhf: the name of the struct kvfree_rcu_head within the type of @ptr.
> + *
> + * With KVFREE_RCU_BATCHED, kfree_rcu_nolock() tries hard to free objects
> + * without any deferred processing, but may still defer freeing.
> + * Large kmalloc and vmalloc objects are always deferred.
> + *
> + * kfree_rcu_nolock() supports 2-arg variant only.
> + */
> +#define kfree_rcu_nolock(ptr, kvrhf) \
> +do { \
> + typeof (ptr) ___p = (ptr); \
> + \
> + if (___p) { \
> + BUILD_BUG_ON(offsetof(typeof(*(ptr)), kvrhf) >= 4096); \
> + kfree_call_rcu_nolock(&((___p)->kvrhf), (void *) (___p)); \
[Severity: Low]
Is a cast to (struct kvfree_rcu_head *) needed here?
Because the caller typically embeds struct rcu_head, passing the member
address directly to kfree_call_rcu_nolock() results in an incompatible pointer
type compilation error when CONFIG_KVFREE_RCU_BATCHED is enabled.
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -1296,6 +1296,33 @@ EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
> EXPORT_TRACEPOINT_SYMBOL(kfree);
> EXPORT_TRACEPOINT_SYMBOL(kmem_cache_free);
>
> +void kfree_call_rcu_nolock(struct kvfree_rcu_head *head, void *ptr)
> +{
> + struct slab *slab;
> +
> + if (!IS_ENABLED(CONFIG_KVFREE_RCU_BATCHED))
> + goto fallback;
> +
> + if (unlikely(is_vmalloc_addr(ptr)))
> + goto fallback;
> +
> + slab = virt_to_slab(ptr);
> + if (unlikely(!slab))
> + goto fallback;
> +
> + if (unlikely(IS_ENABLED(CONFIG_NUMA) && slab_nid(slab) != numa_mem_id()))
> + goto fallback;
> +
> + if (unlikely(!__kfree_rcu_sheaf(slab->slab_cache, ptr, SLAB_FREE_NOLOCK)))
[Severity: High]
Could calling __kfree_rcu_sheaf() here violate the unknown context
requirement?
When kfree_rcu_nolock() or kvfree_call_rcu() are called in a hardirq or NMI
context, the fastpath unconditionally executes local_trylock() inside
__kfree_rcu_sheaf():
mm/slub.c:__kfree_rcu_sheaf() {
...
if (!local_trylock(&s->cpu_sheaves->lock))
goto fail;
...
}
Because a local_lock on PREEMPT_RT is a sleeping lock, acquiring it under
a raw spinlock triggers lockdep "Invalid wait context" warnings, and if
called from NMI context on PREEMPT_RT, it can unconditionally deadlock.
> + goto fallback;
> +
> + return;
> +
> +fallback:
> + defer_kfree_rcu(head);
[Severity: Medium]
Will this lose the original free stack trace if KASAN is enabled?
When the fastpath fails and execution jumps to fallback, the object is deferred
to an irq_work without calling kasan_record_aux_stack(). Later, when
kvfree_call_rcu() is finally invoked in the irq_work context, it will
record the worker's stack trace instead of the original caller that
requested the free, making KASAN Use-After-Free reports harder to debug.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260729-kfree_rcu_nolock-v5-0-a28cdcda9673@kernel.org?part=7
next prev parent reply other threads:[~2026-07-29 8:41 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-29 8:20 [PATCH v5 0/8] mm/slab: introduce kfree_rcu_nolock() and improve slub_kunit coverage Harry Yoo (Oracle)
2026-07-29 8:20 ` [PATCH v5 1/8] mm/slab, slub_kunit: register kprobe to trigger _nolock APIs Harry Yoo (Oracle)
2026-07-29 8:35 ` sashiko-bot
2026-07-29 8:20 ` [PATCH v5 2/8] mm/slab: handle the !allow_spin case in kfree_rcu_sheaf() Harry Yoo (Oracle)
2026-07-29 8:44 ` sashiko-bot
2026-07-29 8:20 ` [PATCH v5 3/8] mm/slab: use call_rcu() in unknown context if irqs are enabled Harry Yoo (Oracle)
2026-07-29 8:47 ` sashiko-bot
2026-07-29 8:20 ` [PATCH v5 4/8] mm/slab: extend deferred free mechanism to handle rcu sheaves Harry Yoo (Oracle)
2026-07-29 8:20 ` [PATCH v5 5/8] mm/slab: allow kfree_rcu_sheaf() on PREEMPT_RT Harry Yoo (Oracle)
2026-07-29 8:43 ` sashiko-bot
2026-07-29 8:20 ` [PATCH v5 6/8] mm/slab: introduce struct kvfree_rcu_head for kvfree_rcu batching Harry Yoo (Oracle)
2026-07-29 8:40 ` sashiko-bot
2026-07-29 8:20 ` [PATCH v5 7/8] mm/slab: introduce kfree_rcu_nolock() Harry Yoo (Oracle)
2026-07-29 8:41 ` sashiko-bot [this message]
2026-07-29 8:20 ` [PATCH v5 8/8] slub_kunit: extend the test for kfree_rcu_nolock() Harry Yoo (Oracle)
2026-07-29 8:39 ` sashiko-bot
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=20260729084133.868411F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=harry@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/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