On Thu, 27 Oct 2022 16:34:53 -0400 Steven Rostedt <rostedt@xxxxxxxxxxx> wrote: > What about del_timer_try_shutdown(), that if it removes the timer, it sets > the function to NULL (making it equivalent to a successful shutdown), > otherwise it does nothing. Allowing the the timer to be rearmed. > > I think this would work in this case. Guenter, Can you apply this patch on top of the series, and see if it makes the warning go away? diff --git a/include/linux/timer.h b/include/linux/timer.h index d4d90149d015..e3c5f4bdd526 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -184,12 +184,23 @@ static inline int timer_pending(const struct timer_list * timer) return !hlist_unhashed_lockless(&timer->entry); } +extern int __del_timer(struct timer_list * timer, bool free); + extern void add_timer_on(struct timer_list *timer, int cpu); -extern int del_timer(struct timer_list * timer); extern int mod_timer(struct timer_list *timer, unsigned long expires); extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); extern int timer_reduce(struct timer_list *timer, unsigned long expires); +static inline int del_timer_try_shutdown(struct timer_list *timer) +{ + return __del_timer(timer, true); +} + +static inline int del_timer(struct timer_list *timer) +{ + return __del_timer(timer, false); +} + /* * The jiffies value which is added to now, when there is no timer * in the timer wheel: diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 7305c65ad0eb..073031cb3bb9 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1255,7 +1255,7 @@ EXPORT_SYMBOL_GPL(add_timer_on); * (ie. del_timer() of an inactive timer returns 0, del_timer() of an * active timer returns 1.) */ -int del_timer(struct timer_list *timer) +int __del_timer(struct timer_list *timer, bool free) { struct timer_base *base; unsigned long flags; @@ -1266,12 +1266,16 @@ int del_timer(struct timer_list *timer) if (timer_pending(timer)) { base = lock_timer_base(timer, &flags); ret = detach_if_pending(timer, base, true); + if (free && ret) { + timer->function = NULL; + debug_timer_deactivate(timer); + } raw_spin_unlock_irqrestore(&base->lock, flags); } return ret; } -EXPORT_SYMBOL(del_timer); +EXPORT_SYMBOL(__del_timer); static int __try_to_del_timer_sync(struct timer_list *timer, bool free) { diff --git a/net/core/sock.c b/net/core/sock.c index 10cc84379d75..23a97442a0a6 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -3345,7 +3345,7 @@ EXPORT_SYMBOL(sk_reset_timer); void sk_stop_timer(struct sock *sk, struct timer_list* timer) { - if (del_timer(timer)) + if (del_timer_try_shutdown(timer)) __sock_put(sk); } EXPORT_SYMBOL(sk_stop_timer);