summaryrefslogtreecommitdiff
path: root/net/mptcp/protocol.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2021-04-16 02:44:53 +0300
committerDavid S. Miller <davem@davemloft.net>2021-04-17 01:23:10 +0300
commit7896248983ef4eec18c8bd301a81d8672dbc9955 (patch)
treefcc0d5d4b4666741dd9a956bffdb9a1eef482d15 /net/mptcp/protocol.c
parentd9e4c129181004ec94b315b0c9db5eeb09da75e6 (diff)
downloadlinux-7896248983ef4eec18c8bd301a81d8672dbc9955.tar.xz
mptcp: add skeleton to sync msk socket options to subflows
Handle following cases: 1. setsockopt is called with multiple subflows. Change might have to be mirrored to all of them. This is done directly in process context/setsockopt call. 2. Outgoing subflow is created after one or several setsockopt() calls have been made. Old setsockopt changes should be synced to the new socket. 3. Incoming subflow, after setsockopt call(s). Cases 2 and 3 are handled right after the join list is spliced to the conn list. Not all sockopt values can be just be copied by value, some require helper calls. Those can acquire socket lock (which can sleep). If the join->conn list splicing is done from preemptible context, synchronization can be done right away, otherwise its deferred to work queue. Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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);