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: 17+ 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
2026-07-29 14:14 ` [PATCH v5 0/8] mm/slab: introduce kfree_rcu_nolock() and improve slub_kunit coverage 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=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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.