Commit e237659c authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mptcp-a-bunch-of-fixes'



Paolo Abeni says:

====================
mptcp: a bunch of fixes

This patch series pulls together a few bugfixes for MPTCP bug observed while
doing stress-test with apache bench - forced to use MPTCP and multiple
subflows.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 05aa69e5 c5c79763
Loading
Loading
Loading
Loading
+46 −18
Original line number Diff line number Diff line
@@ -1263,11 +1263,14 @@ static void mptcp_close(struct sock *sk, long timeout)

	lock_sock(sk);

	mptcp_token_destroy(msk->token);
	inet_sk_state_store(sk, TCP_CLOSE);

	__mptcp_flush_join_list(msk);

	/* be sure to always acquire the join list lock, to sync vs
	 * mptcp_finish_join().
	 */
	spin_lock_bh(&msk->join_list_lock);
	list_splice_tail_init(&msk->join_list, &msk->conn_list);
	spin_unlock_bh(&msk->join_list_lock);
	list_splice_init(&msk->conn_list, &conn_list);

	data_fin_tx_seq = msk->write_seq;
@@ -1457,6 +1460,7 @@ static void mptcp_destroy(struct sock *sk)
{
	struct mptcp_sock *msk = mptcp_sk(sk);

	mptcp_token_destroy(msk->token);
	if (msk->cached_ext)
		__skb_ext_put(msk->cached_ext);

@@ -1623,22 +1627,30 @@ bool mptcp_finish_join(struct sock *sk)
	if (!msk->pm.server_side)
		return true;

	/* passive connection, attach to msk socket */
	parent_sock = READ_ONCE(parent->sk_socket);
	if (parent_sock && !sk->sk_socket)
		mptcp_sock_graft(sk, parent_sock);

	ret = mptcp_pm_allow_new_subflow(msk);
	if (ret) {
		subflow->map_seq = msk->ack_seq;
	if (!mptcp_pm_allow_new_subflow(msk))
		return false;

		/* active connections are already on conn_list */
	/* active connections are already on conn_list, and we can't acquire
	 * msk lock here.
	 * use the join list lock as synchronization point and double-check
	 * msk status to avoid racing with mptcp_close()
	 */
	spin_lock_bh(&msk->join_list_lock);
		if (!WARN_ON_ONCE(!list_empty(&subflow->node)))
	ret = inet_sk_state_load(parent) == TCP_ESTABLISHED;
	if (ret && !WARN_ON_ONCE(!list_empty(&subflow->node)))
		list_add_tail(&subflow->node, &msk->join_list);
	spin_unlock_bh(&msk->join_list_lock);
	}
	return ret;
	if (!ret)
		return false;

	/* attach to msk socket only after we are sure he will deal with us
	 * at close time
	 */
	parent_sock = READ_ONCE(parent->sk_socket);
	if (parent_sock && !sk->sk_socket)
		mptcp_sock_graft(sk, parent_sock);
	subflow->map_seq = msk->ack_seq;
	return true;
}

bool mptcp_sk_is_subflow(const struct sock *sk)
@@ -1712,6 +1724,14 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
	int err;

	lock_sock(sock->sk);
	if (sock->state != SS_UNCONNECTED && msk->subflow) {
		/* pending connection or invalid state, let existing subflow
		 * cope with that
		 */
		ssock = msk->subflow;
		goto do_connect;
	}

	ssock = __mptcp_socket_create(msk, TCP_SYN_SENT);
	if (IS_ERR(ssock)) {
		err = PTR_ERR(ssock);
@@ -1726,9 +1746,17 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
		mptcp_subflow_ctx(ssock->sk)->request_mptcp = 0;
#endif

do_connect:
	err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
	inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
	sock->state = ssock->state;

	/* on successful connect, the msk state will be moved to established by
	 * subflow_finish_connect()
	 */
	if (!err || err == EINPROGRESS)
		mptcp_copy_inaddrs(sock->sk, ssock->sk);
	else
		inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));

unlock:
	release_sock(sock->sk);