mptcp: dedicated request sock for subflow in v6
[platform/kernel/linux-rpi.git] / net / sunrpc / xprtsock.c
index 2096b26..897dfce 100644 (file)
@@ -880,7 +880,7 @@ static int xs_local_send_request(struct rpc_rqst *req)
 
        /* Close the stream if the previous transmission was incomplete */
        if (xs_send_request_was_aborted(transport, req)) {
-               xs_close(xprt);
+               xprt_force_disconnect(xprt);
                return -ENOTCONN;
        }
 
@@ -918,7 +918,7 @@ static int xs_local_send_request(struct rpc_rqst *req)
                        -status);
                fallthrough;
        case -EPIPE:
-               xs_close(xprt);
+               xprt_force_disconnect(xprt);
                status = -ENOTCONN;
        }
 
@@ -1205,6 +1205,16 @@ static void xs_reset_transport(struct sock_xprt *transport)
 
        if (sk == NULL)
                return;
+       /*
+        * Make sure we're calling this in a context from which it is safe
+        * to call __fput_sync(). In practice that means rpciod and the
+        * system workqueue.
+        */
+       if (!(current->flags & PF_WQ_WORKER)) {
+               WARN_ON_ONCE(1);
+               set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+               return;
+       }
 
        if (atomic_read(&transport->xprt.swapper))
                sk_clear_memalloc(sk);
@@ -1228,7 +1238,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
        mutex_unlock(&transport->recv_mutex);
 
        trace_rpc_socket_close(xprt, sock);
-       fput(filp);
+       __fput_sync(filp);
 
        xprt_disconnect_done(xprt);
 }
@@ -2257,6 +2267,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                fallthrough;
        case -EINPROGRESS:
                /* SYN_SENT! */
+               set_bit(XPRT_SOCK_CONNECT_SENT, &transport->sock_state);
                if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
                        xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
                break;
@@ -2282,10 +2293,14 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        struct rpc_xprt *xprt = &transport->xprt;
        int status = -EIO;
 
-       if (!sock) {
-               sock = xs_create_sock(xprt, transport,
-                               xs_addr(xprt)->sa_family, SOCK_STREAM,
-                               IPPROTO_TCP, true);
+       if (xprt_connected(xprt))
+               goto out;
+       if (test_and_clear_bit(XPRT_SOCK_CONNECT_SENT,
+                              &transport->sock_state) ||
+           !sock) {
+               xs_reset_transport(transport);
+               sock = xs_create_sock(xprt, transport, xs_addr(xprt)->sa_family,
+                                     SOCK_STREAM, IPPROTO_TCP, true);
                if (IS_ERR(sock)) {
                        status = PTR_ERR(sock);
                        goto out;
@@ -2367,11 +2382,7 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
 
        if (transport->sock != NULL) {
                dprintk("RPC:       xs_connect delayed xprt %p for %lu "
-                               "seconds\n",
-                               xprt, xprt->reestablish_timeout / HZ);
-
-               /* Start by resetting any existing state */
-               xs_reset_transport(transport);
+                       "seconds\n", xprt, xprt->reestablish_timeout / HZ);
 
                delay = xprt_reconnect_delay(xprt);
                xprt_reconnect_backoff(xprt, XS_TCP_INIT_REEST_TO);
@@ -2847,9 +2858,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
                }
                xprt_set_bound(xprt);
                xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
-               ret = ERR_PTR(xs_local_setup_socket(transport));
-               if (ret)
-                       goto out_err;
                break;
        default:
                ret = ERR_PTR(-EAFNOSUPPORT);