On Tue, Jun 16, 2026 at 12:44:48AM +0800, [email protected] wrote:
> From: Wen Yang <[email protected]>
> 
> The DEFINE_WAIT_OVERRIDE_MAP() macro creates a lockdep map with
> wait_type_inner = LD_WAIT_CONFIG, which inherits the outer context's
> wait type.  When rv_react() is called from a LD_WAIT_FREE context
> (e.g., a KUnit test with busy-wait), and the reactor callback triggers
> a timer interrupt during the busy-loop, the interrupt exit path attempts
> to schedule (preempt_schedule_irq -> __schedule -> rq->__lock), which is
> LD_WAIT_SPIN.  Lockdep then reports:
> 
>     [ BUG: Invalid wait context ]
>     context-{5:5}
>     1 lock held by kunit_try_catch/209:
>      #0: rv_react_map-wait-type-override at rv_react+0x9d/0xf0

It would be nice to have the full trace here from your real-world example.

> The wait_type_override map allowed the outer LD_WAIT_FREE to propagate
> inward, but scheduling from an interrupt is LD_WAIT_SPIN, violating the
> constraint.
> 
> Fix by explicitly setting wait_type_inner = LD_WAIT_SPIN, which is the
> tightest constraint rv_react() callbacks must satisfy: they may not
> sleep (LD_WAIT_SLEEP) or use mutexes, but can use spinlocks and be
> interrupted. This matches the documented LD_WAIT_FREE constraint.

So this is not a pure fix but a change in behavior. This should be
reflected in the subject.

> Fixes: 69d8895cb9a9 ("rv: Add explicit lockdep context for reactors")
> Signed-off-by: Wen Yang <[email protected]>
> Cc: Thomas Weißschuh <[email protected]>
> ---
>  kernel/trace/rv/rv_reactors.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c
> index 460af07f7aba..423f843bbd68 100644
> --- a/kernel/trace/rv/rv_reactors.c
> +++ b/kernel/trace/rv/rv_reactors.c
> @@ -465,7 +465,13 @@ int init_rv_reactors(struct dentry *root_dir)
>  
>  void rv_react(struct rv_monitor *monitor, const char *msg, ...)
>  {
> -     static DEFINE_WAIT_OVERRIDE_MAP(rv_react_map, LD_WAIT_FREE);
> +#ifdef CONFIG_LOCKDEP
> +     static struct lockdep_map rv_react_map = {
> +             .name = "rv_react",
> +             .wait_type_outer = LD_WAIT_FREE,
> +             .wait_type_inner = LD_WAIT_SPIN,
> +     };
> +#endif

This now allows reactors to take (raw) spinlocks. The original idea was
to not allow that as a reactor can be called from LD_WAIT_FREE context.
So I am not sure this is the right fix. Not that I have a better one
available right now.

>       va_list args;
>  
>       if (!rv_reacting_on() || !monitor->react)
> -- 
> 2.25.1
> 

Reply via email to