mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 22:37:45 -04:00
mptcp: fix unblocking connect()
Currently unblocking connect() on MPTCP sockets fails frequently.
If mptcp_stream_connect() is invoked to complete a previously
attempted unblocking connection, it will still try to create
the first subflow via __mptcp_socket_create(). If the 3whs is
completed and the 'can_ack' flag is already set, the latter
will fail with -EINVAL.
This change addresses the issue checking for pending connect and
delegating the completion to the first subflow. Additionally
do msk addresses and sk_state changes only when needed.
Fixes: 2303f994b3 ("mptcp: Associate MPTCP context with TCP socket")
Signed-off-by: Paolo Abeni <[email protected]>
Reviewed-by: Mat Martineau <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
1 parent
05aa69e5cb
commit
41be81a8d3
1 file changed
+18
-2
+18
-2
@@ -1712,6 +1712,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 +1734,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));
|
||||
mptcp_copy_inaddrs(sock->sk, 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);
|
||||
|
||||
Reference in new issue
Block a user