Jakub Kicinski
2022-Oct-28 22:46 UTC
[Bridge] [RFC][PATCH v2 19/31] timers: net: Use del_timer_shutdown() before freeing timer
On Fri, 28 Oct 2022 18:31:49 -0400 Steven Rostedt wrote:> Could someone from networking confirm (or deny) that the timer being > removed in sk_stop_timer() will no longer be used even if del_timer() > returns false? > > net/core/sock.c: > > void sk_stop_timer(struct sock *sk, struct timer_list* timer) > { > if (del_timer(timer)) > __sock_put(sk); > } > > If this is the case, then I'll add the following interface: > > del_timer_sync_shutdown() // the common case which syncs > > del_timer_shutdown() // the uncommon case, that returns immediately > // used for those cases that add extra code to > // handle it, like sk_stop_timer()Sorry too many bugs at once :) FWIW Paolo was saying privately earlier today that he spotted some cases of reuse, he gave an example of ccid2_hc_tx_packet_recv() So we can't convert all cases of sk_stop_timer() in one fell swoop :(> Which has the same semantics as del_timer_sync() and del_timer() > respectively, but will prevent the timer from being rearmed again. > > This way we can convert the sk_stop_timer() to: > > void sk_stop_timer(struct sock *sk, struct timer_list* timer) > { > if (del_timer_shutdown(timer)) > __sock_put(sk); > } > > > We can also add the del_timer_shutdown() to other locations that need to > put a timer into a shutdown state before freeing, and where it's in a > context that can not call del_timer_sync_shutdown().
Paolo Abeni
2022-Oct-30 17:22 UTC
[Bridge] [RFC][PATCH v2 19/31] timers: net: Use del_timer_shutdown() before freeing timer
On Fri, 2022-10-28 at 15:46 -0700, Jakub Kicinski wrote:> On Fri, 28 Oct 2022 18:31:49 -0400 Steven Rostedt wrote: > > Could someone from networking confirm (or deny) that the timer being > > removed in sk_stop_timer() will no longer be used even if del_timer() > > returns false? > > > > net/core/sock.c: > > > > void sk_stop_timer(struct sock *sk, struct timer_list* timer) > > { > > if (del_timer(timer)) > > __sock_put(sk); > > } > > > > If this is the case, then I'll add the following interface: > > > > del_timer_sync_shutdown() // the common case which syncs > > > > del_timer_shutdown() // the uncommon case, that returns immediately > > // used for those cases that add extra code to > > // handle it, like sk_stop_timer() > > Sorry too many bugs at once :) > > FWIW Paolo was saying privately earlier today that he spotted some cases > of reuse, he gave an example of ccid2_hc_tx_packet_recv()For the records, there are other cases, e.g. after sk_stop_timer() in clear_3rdack_retransmission() (mptcp code) the timer can be-rearmed without re-initializing. I *think* there are more of such use in the in ax25/rose code.> So we can't convert all cases of sk_stop_timer() in one fell swoop :(On the positive side, I think converting the sk_stop_timer in inet_csk_clear_xmit_timers() should be safe and should cover the issue reported by Guenter Cheers, Paolo
Steven Rostedt
2022-Nov-03 21:51 UTC
[Bridge] [RFC][PATCH v2 19/31] timers: net: Use del_timer_shutdown() before freeing timer
On Sun, 30 Oct 2022 18:22:03 +0100 Paolo Abeni <pabeni at redhat.com> wrote:> On the positive side, I think converting the sk_stop_timer in > inet_csk_clear_xmit_timers() should be safe and should cover the issue > reported by GuenterWould something like this be OK? [ Note, talking with Thomas Gleixner, we agreed that we are changing the name to: time_shutdown_sync() and timer_shutdown() (no wait version). I'll be posting new patches soon. ] -- Steve diff --git a/include/net/sock.h b/include/net/sock.h index 22f8bab583dd..0ef58697d4e5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2439,6 +2439,8 @@ void sk_stop_timer(struct sock *sk, struct timer_list *timer); void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer); +void sk_shutdown_timer(struct sock *sk, struct timer_list *timer); + int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue, struct sk_buff *skb, unsigned int flags, void (*destructor)(struct sock *sk, diff --git a/net/core/sock.c b/net/core/sock.c index a3ba0358c77c..82124862b594 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -3357,6 +3357,13 @@ void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer) } EXPORT_SYMBOL(sk_stop_timer_sync); +void sk_shutdown_timer(struct sock *sk, struct timer_list* timer) +{ + if (timer_shutdown(timer)) + __sock_put(sk); +} +EXPORT_SYMBOL(sk_shutdown_timer); + void sock_init_data(struct socket *sock, struct sock *sk) { sk_init_common(sk); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 5e70228c5ae9..71f398f51958 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -722,15 +722,15 @@ void inet_csk_clear_xmit_timers(struct sock *sk) icsk->icsk_pending = icsk->icsk_ack.pending = 0; - sk_stop_timer(sk, &icsk->icsk_retransmit_timer); - sk_stop_timer(sk, &icsk->icsk_delack_timer); - sk_stop_timer(sk, &sk->sk_timer); + sk_shutdown_timer(sk, &icsk->icsk_retransmit_timer); + sk_shutdown_timer(sk, &icsk->icsk_delack_timer); + sk_shutdown_timer(sk, &sk->sk_timer); } EXPORT_SYMBOL(inet_csk_clear_xmit_timers); void inet_csk_delete_keepalive_timer(struct sock *sk) { - sk_stop_timer(sk, &sk->sk_timer); + sk_shutdown_timer(sk, &sk->sk_timer); } EXPORT_SYMBOL(inet_csk_delete_keepalive_timer);