summaryrefslogtreecommitdiffstats
path: root/net/mptcp/protocol.c
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2020-11-16 10:48:05 +0100
committerJakub Kicinski <kuba@kernel.org>2020-11-16 10:46:06 -0800
commitba8f48f7a4d79352b764ace585b5f602ef940be0 (patch)
tree5529c65bcb566b548f9ad99b28c5be155bc14be0 /net/mptcp/protocol.c
parent77c3c95637526f1e4330cc9a4b2065f668c2c4fe (diff)
downloadlinux-ba8f48f7a4d79352b764ace585b5f602ef940be0.tar.gz
linux-ba8f48f7a4d79352b764ace585b5f602ef940be0.tar.bz2
linux-ba8f48f7a4d79352b764ace585b5f602ef940be0.zip
mptcp: introduce mptcp_schedule_work
remove some of code duplications an allow preventing rescheduling on close. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/mptcp/protocol.c')
-rw-r--r--net/mptcp/protocol.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3c68cf912fb8..0e725f18af24 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -620,9 +620,8 @@ static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)
* this is not a good place to change state. Let the workqueue
* do it.
*/
- if (mptcp_pending_data_fin(sk, NULL) &&
- schedule_work(&msk->work))
- sock_hold(sk);
+ if (mptcp_pending_data_fin(sk, NULL))
+ mptcp_schedule_work(sk);
}
spin_unlock_bh(&sk->sk_lock.slock);
@@ -699,23 +698,32 @@ static void mptcp_reset_timer(struct sock *sk)
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + tout);
}
+bool mptcp_schedule_work(struct sock *sk)
+{
+ if (inet_sk_state_load(sk) != TCP_CLOSE &&
+ schedule_work(&mptcp_sk(sk)->work)) {
+ /* each subflow already holds a reference to the sk, and the
+ * workqueue is invoked by a subflow, so sk can't go away here.
+ */
+ sock_hold(sk);
+ return true;
+ }
+ return false;
+}
+
void mptcp_data_acked(struct sock *sk)
{
mptcp_reset_timer(sk);
if ((!test_bit(MPTCP_SEND_SPACE, &mptcp_sk(sk)->flags) ||
- (inet_sk_state_load(sk) != TCP_ESTABLISHED)) &&
- schedule_work(&mptcp_sk(sk)->work))
- sock_hold(sk);
+ (inet_sk_state_load(sk) != TCP_ESTABLISHED)))
+ mptcp_schedule_work(sk);
}
void mptcp_subflow_eof(struct sock *sk)
{
- struct mptcp_sock *msk = mptcp_sk(sk);
-
- if (!test_and_set_bit(MPTCP_WORK_EOF, &msk->flags) &&
- schedule_work(&msk->work))
- sock_hold(sk);
+ if (!test_and_set_bit(MPTCP_WORK_EOF, &mptcp_sk(sk)->flags))
+ mptcp_schedule_work(sk);
}
static void mptcp_check_for_eof(struct mptcp_sock *msk)
@@ -1620,8 +1628,7 @@ static void mptcp_retransmit_handler(struct sock *sk)
mptcp_stop_timer(sk);
} else {
set_bit(MPTCP_WORK_RTX, &msk->flags);
- if (schedule_work(&msk->work))
- sock_hold(sk);
+ mptcp_schedule_work(sk);
}
}
@@ -2334,7 +2341,8 @@ static void mptcp_release_cb(struct sock *sk)
struct sock *ssk;
ssk = mptcp_subflow_recv_lookup(msk);
- if (!ssk || !schedule_work(&msk->work))
+ if (!ssk || sk->sk_state == TCP_CLOSE ||
+ !schedule_work(&msk->work))
__sock_put(sk);
}