diff options
author | Sowmini Varadhan <sowmini.varadhan@oracle.com> | 2018-01-04 09:53:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-05 13:39:18 -0500 |
commit | 3db6e0d172c94bd9953a1347c55ffb64b1d2e74f (patch) | |
tree | 67f61aa4784da3fba56aa43e3626d3f3b6562c78 /net/rds/tcp_send.c | |
parent | c90ecbfaf50d2d7db25c531d9169be7e47435f3f (diff) |
rds: use RCU to synchronize work-enqueue with connection teardown
rds_sendmsg() can enqueue work on cp_send_w from process context, but
it should not enqueue this work if connection teardown has commenced
(else we risk enquing work after rds_conn_path_destroy() has assumed that
all work has been cancelled/flushed).
Similarly some other functions like rds_cong_queue_updates
and rds_tcp_data_ready are called in softirq context, and may end
up enqueuing work on rds_wq after rds_conn_path_destroy() has assumed
that all workqs are quiesced.
Check the RDS_DESTROY_PENDING bit and use rcu synchronization to avoid
all these races.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds/tcp_send.c')
-rw-r--r-- | net/rds/tcp_send.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index dc860d1bb608..73c74763ca72 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c | |||
@@ -202,8 +202,11 @@ void rds_tcp_write_space(struct sock *sk) | |||
202 | tc->t_last_seen_una = rds_tcp_snd_una(tc); | 202 | tc->t_last_seen_una = rds_tcp_snd_una(tc); |
203 | rds_send_path_drop_acked(cp, rds_tcp_snd_una(tc), rds_tcp_is_acked); | 203 | rds_send_path_drop_acked(cp, rds_tcp_snd_una(tc), rds_tcp_is_acked); |
204 | 204 | ||
205 | if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) | 205 | rcu_read_lock(); |
206 | if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf && | ||
207 | !test_bit(RDS_DESTROY_PENDING, &cp->cp_flags)) | ||
206 | queue_delayed_work(rds_wq, &cp->cp_send_w, 0); | 208 | queue_delayed_work(rds_wq, &cp->cp_send_w, 0); |
209 | rcu_read_unlock(); | ||
207 | 210 | ||
208 | out: | 211 | out: |
209 | read_unlock_bh(&sk->sk_callback_lock); | 212 | read_unlock_bh(&sk->sk_callback_lock); |