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

Merge branch 'mptcp-fixes'



Paolo Abeni says:

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

This series includes a few fixes following-up the
recent code refactor for the MPTCP RX and TX paths.

Boundling them together, since the fixes are somewhat
related.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7bdddc68 d7b1bfd0
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -802,7 +802,12 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
	mptcp_subflow_fully_established(subflow, mp_opt);

fully_established:
	if (likely(subflow->pm_notified))
	/* if the subflow is not already linked into the conn_list, we can't
	 * notify the PM: this subflow is still on the listener queue
	 * and the PM possibly acquiring the subflow lock could race with
	 * the listener close
	 */
	if (likely(subflow->pm_notified) || list_empty(&subflow->node))
		return true;

	subflow->pm_notified = 1;
+7 −1
Original line number Diff line number Diff line
@@ -126,8 +126,14 @@ void mptcp_pm_fully_established(struct mptcp_sock *msk)

	spin_lock_bh(&pm->lock);

	if (READ_ONCE(pm->work_pending))
	/* mptcp_pm_fully_established() can be invoked by multiple
	 * racing paths - accept() and check_fully_established()
	 * be sure to serve this event only once.
	 */
	if (READ_ONCE(pm->work_pending) &&
	    !(msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)))
		mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
	msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED);

	spin_unlock_bh(&pm->lock);
}
+21 −2
Original line number Diff line number Diff line
@@ -701,6 +701,13 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
	int sk_rbuf, ssk_rbuf;
	bool wake;

	/* The peer can send data while we are shutting down this
	 * subflow at msk destruction time, but we must avoid enqueuing
	 * more data to the msk receive queue
	 */
	if (unlikely(subflow->disposable))
		return;

	/* move_skbs_to_msk below can legitly clear the data_avail flag,
	 * but we will need later to properly woke the reader, cache its
	 * value
@@ -2119,6 +2126,8 @@ void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
		sock_orphan(ssk);
	}

	subflow->disposable = 1;

	/* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops
	 * the ssk has been already destroyed, we just need to release the
	 * reference owned by msk;
@@ -2126,8 +2135,7 @@ void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
	if (!inet_csk(ssk)->icsk_ulp_ops) {
		kfree_rcu(subflow, rcu);
	} else {
		/* otherwise ask tcp do dispose of ssk and subflow ctx */
		subflow->disposable = 1;
		/* otherwise tcp will dispose of the ssk and subflow ctx */
		__tcp_close(ssk, 0);

		/* close acquired an extra ref */
@@ -3208,6 +3216,17 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
		bool slowpath;

		slowpath = lock_sock_fast(newsk);

		/* PM/worker can now acquire the first subflow socket
		 * lock without racing with listener queue cleanup,
		 * we can notify it, if needed.
		 */
		subflow = mptcp_subflow_ctx(msk->first);
		list_add(&subflow->node, &msk->conn_list);
		sock_hold(msk->first);
		if (mptcp_is_fully_established(newsk))
			mptcp_pm_fully_established(msk);

		mptcp_copy_inaddrs(newsk, msk->first);
		mptcp_rcv_space_init(msk, msk->first);

+1 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ enum mptcp_pm_status {
	MPTCP_PM_ADD_ADDR_SEND_ACK,
	MPTCP_PM_RM_ADDR_RECEIVED,
	MPTCP_PM_ESTABLISHED,
	MPTCP_PM_ALREADY_ESTABLISHED,	/* persistent status, set after ESTABLISHED event */
	MPTCP_PM_SUBFLOW_ESTABLISHED,
};

+13 −6
Original line number Diff line number Diff line
@@ -614,8 +614,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
			 */
			inet_sk_state_store((void *)new_msk, TCP_ESTABLISHED);

			/* link the newly created socket to the msk */
			mptcp_add_pending_subflow(mptcp_sk(new_msk), ctx);
			/* record the newly created socket as the first msk
			 * subflow, but don't link it yet into conn_list
			 */
			WRITE_ONCE(mptcp_sk(new_msk)->first, child);

			/* new mpc subflow takes ownership of the newly
@@ -1148,13 +1149,18 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
	subflow->request_bkup = !!(loc->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
	mptcp_info2sockaddr(remote, &addr);

	mptcp_add_pending_subflow(msk, subflow);
	err = kernel_connect(sf, (struct sockaddr *)&addr, addrlen, O_NONBLOCK);
	if (err && err != -EINPROGRESS)
		goto failed;
		goto failed_unlink;

	mptcp_add_pending_subflow(msk, subflow);
	return err;

failed_unlink:
	spin_lock_bh(&msk->join_list_lock);
	list_del(&subflow->node);
	spin_unlock_bh(&msk->join_list_lock);

failed:
	subflow->disposable = 1;
	sock_release(sf);
@@ -1333,9 +1339,10 @@ static void subflow_ulp_release(struct sock *ssk)
	sk = ctx->conn;
	if (sk) {
		/* if the msk has been orphaned, keep the ctx
		 * alive, will be freed by mptcp_done()
		 * alive, will be freed by __mptcp_close_ssk(),
		 * when the subflow is still unaccepted
		 */
		release = ctx->disposable;
		release = ctx->disposable || list_empty(&ctx->node);
		sock_put(sk);
	}