Commit 2e52213c79c0b94aff42ba898ad9ad57546be67d
Committed by
David S. Miller
1 parent
bfae9dae44
mptcp: avoid work queue scheduling if possible
We can't lock_sock() the mptcp socket from the subflow data_ready callback, it would result in ABBA deadlock with the subflow socket lock. We can however grab the spinlock: if that succeeds and the mptcp socket is not owned at the moment, we can process the new skbs right away without deferring this to the work queue. This avoids the schedule_work and hence the small delay until the work item is processed. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 31 additions and 4 deletions Side-by-side Diff
net/mptcp/protocol.c
... | ... | @@ -201,11 +201,38 @@ |
201 | 201 | return done; |
202 | 202 | } |
203 | 203 | |
204 | -void mptcp_data_ready(struct sock *sk) | |
204 | +/* In most cases we will be able to lock the mptcp socket. If its already | |
205 | + * owned, we need to defer to the work queue to avoid ABBA deadlock. | |
206 | + */ | |
207 | +static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk) | |
205 | 208 | { |
209 | + struct sock *sk = (struct sock *)msk; | |
210 | + unsigned int moved = 0; | |
211 | + | |
212 | + if (READ_ONCE(sk->sk_lock.owned)) | |
213 | + return false; | |
214 | + | |
215 | + if (unlikely(!spin_trylock_bh(&sk->sk_lock.slock))) | |
216 | + return false; | |
217 | + | |
218 | + /* must re-check after taking the lock */ | |
219 | + if (!READ_ONCE(sk->sk_lock.owned)) | |
220 | + __mptcp_move_skbs_from_subflow(msk, ssk, &moved); | |
221 | + | |
222 | + spin_unlock_bh(&sk->sk_lock.slock); | |
223 | + | |
224 | + return moved > 0; | |
225 | +} | |
226 | + | |
227 | +void mptcp_data_ready(struct sock *sk, struct sock *ssk) | |
228 | +{ | |
206 | 229 | struct mptcp_sock *msk = mptcp_sk(sk); |
207 | 230 | |
208 | 231 | set_bit(MPTCP_DATA_READY, &msk->flags); |
232 | + | |
233 | + if (atomic_read(&sk->sk_rmem_alloc) < READ_ONCE(sk->sk_rcvbuf) && | |
234 | + move_skbs_to_msk(msk, ssk)) | |
235 | + goto wake; | |
209 | 236 | |
210 | 237 | /* don't schedule if mptcp sk is (still) over limit */ |
211 | 238 | if (atomic_read(&sk->sk_rmem_alloc) > READ_ONCE(sk->sk_rcvbuf)) |
net/mptcp/protocol.h
... | ... | @@ -195,7 +195,7 @@ |
195 | 195 | struct tcp_options_received *opt_rx); |
196 | 196 | |
197 | 197 | void mptcp_finish_connect(struct sock *sk); |
198 | -void mptcp_data_ready(struct sock *sk); | |
198 | +void mptcp_data_ready(struct sock *sk, struct sock *ssk); | |
199 | 199 | |
200 | 200 | int mptcp_token_new_request(struct request_sock *req); |
201 | 201 | void mptcp_token_destroy_request(u32 token); |
net/mptcp/subflow.c
... | ... | @@ -563,7 +563,7 @@ |
563 | 563 | } |
564 | 564 | |
565 | 565 | if (mptcp_subflow_data_available(sk)) |
566 | - mptcp_data_ready(parent); | |
566 | + mptcp_data_ready(parent, sk); | |
567 | 567 | } |
568 | 568 | |
569 | 569 | static void subflow_write_space(struct sock *sk) |
... | ... | @@ -696,7 +696,7 @@ |
696 | 696 | * the data available machinery here. |
697 | 697 | */ |
698 | 698 | if (parent && subflow->mp_capable && mptcp_subflow_data_available(sk)) |
699 | - mptcp_data_ready(parent); | |
699 | + mptcp_data_ready(parent, sk); | |
700 | 700 | |
701 | 701 | if (parent && !(parent->sk_shutdown & RCV_SHUTDOWN) && |
702 | 702 | !subflow->rx_eof && subflow_is_done(sk)) { |