Guenter Roeck
2022-Oct-27 23:13 UTC
[Bridge] [RFC][PATCH v2 19/31] timers: net: Use del_timer_shutdown() before freeing timer
On Thu, Oct 27, 2022 at 05:07:55PM -0400, Steven Rostedt wrote:> On Thu, 27 Oct 2022 16:34:53 -0400 > Steven Rostedt <rostedt at goodmis.org> 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?Applied, and started testing. Please let me know if I am missing some other patch(es) to apply. Thanks, Guenter> > 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);