aboutsummaryrefslogtreecommitdiff
path: root/net/mptcp/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mptcp/protocol.c')
-rw-r--r--net/mptcp/protocol.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index e0b381ae99af..1399d301d47f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -730,18 +730,42 @@ wake:
sk->sk_data_ready(sk);
}
-void __mptcp_flush_join_list(struct mptcp_sock *msk)
+static bool mptcp_do_flush_join_list(struct mptcp_sock *msk)
{
struct mptcp_subflow_context *subflow;
if (likely(list_empty(&msk->join_list)))
- return;
+ return false;
spin_lock_bh(&msk->join_list_lock);
list_for_each_entry(subflow, &msk->join_list, node)
mptcp_propagate_sndbuf((struct sock *)msk, mptcp_subflow_tcp_sock(subflow));
+
list_splice_tail_init(&msk->join_list, &msk->conn_list);
spin_unlock_bh(&msk->join_list_lock);
+
+ return true;
+}
+
+void __mptcp_flush_join_list(struct mptcp_sock *msk)
+{
+ if (likely(!mptcp_do_flush_join_list(msk)))
+ return;
+
+ if (!test_and_set_bit(MPTCP_WORK_SYNC_SETSOCKOPT, &msk->flags))
+ mptcp_schedule_work((struct sock *)msk);
+}
+
+static void mptcp_flush_join_list(struct mptcp_sock *msk)
+{
+ bool sync_needed = test_and_clear_bit(MPTCP_WORK_SYNC_SETSOCKOPT, &msk->flags);
+
+ might_sleep();
+
+ if (!mptcp_do_flush_join_list(msk) && !sync_needed)
+ return;
+
+ mptcp_sockopt_sync_all(msk);
}
static bool mptcp_timer_pending(struct sock *sk)
@@ -1457,7 +1481,7 @@ static void __mptcp_push_pending(struct sock *sk, unsigned int flags)
int ret = 0;
prev_ssk = ssk;
- __mptcp_flush_join_list(msk);
+ mptcp_flush_join_list(msk);
ssk = mptcp_subflow_get_send(msk);
/* try to keep the subflow socket lock across
@@ -1883,7 +1907,7 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
unsigned int moved = 0;
bool ret, done;
- __mptcp_flush_join_list(msk);
+ mptcp_flush_join_list(msk);
do {
struct sock *ssk = mptcp_subflow_recv_lookup(msk);
bool slowpath;
@@ -2307,7 +2331,7 @@ static void mptcp_worker(struct work_struct *work)
goto unlock;
mptcp_check_data_fin_ack(sk);
- __mptcp_flush_join_list(msk);
+ mptcp_flush_join_list(msk);
mptcp_check_fastclose(msk);
@@ -2507,7 +2531,7 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
}
}
- __mptcp_flush_join_list(msk);
+ mptcp_flush_join_list(msk);
mptcp_for_each_subflow(msk, subflow) {
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
@@ -2644,7 +2668,8 @@ static int mptcp_disconnect(struct sock *sk, int flags)
struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
- __mptcp_flush_join_list(msk);
+ mptcp_do_flush_join_list(msk);
+
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
@@ -3210,7 +3235,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
/* set ssk->sk_socket of accept()ed flows to mptcp socket.
* This is needed so NOSPACE flag can be set from tcp stack.
*/
- __mptcp_flush_join_list(msk);
+ mptcp_flush_join_list(msk);
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);