SUNRPC: Don't wake tasks during connection abort
[platform/adaptation/renesas_rcar/renesas_kernel.git] / net / sunrpc / xprtsock.c
index 817a1e5..41c2f9d 100644 (file)
@@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct sock *sk = transport->inet;
        int ret = -EAGAIN;
 
        dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
@@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task)
                         * window size
                         */
                        set_bit(SOCK_NOSPACE, &transport->sock->flags);
-                       transport->inet->sk_write_pending++;
+                       sk->sk_write_pending++;
                        /* ...and wait for more buffer space */
                        xprt_wait_for_buffer_space(task, xs_nospace_callback);
                }
@@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task)
        }
 
        spin_unlock_bh(&xprt->transport_lock);
+
+       /* Race breaker in case memory is freed before above code is called */
+       sk->sk_write_space(sk);
        return ret;
 }
 
@@ -838,6 +842,8 @@ static void xs_error_report(struct sock *sk)
        dprintk("RPC:       xs_error_report client %p, error=%d...\n",
                        xprt, -err);
        trace_rpc_socket_error(xprt, sk->sk_socket, err);
+       if (test_bit(XPRT_CONNECTION_REUSE, &xprt->state))
+               goto out;
        xprt_wake_pending_tasks(xprt, err);
  out:
        read_unlock_bh(&sk->sk_callback_lock);
@@ -2247,7 +2253,9 @@ static void xs_tcp_setup_socket(struct work_struct *work)
                abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT,
                                &xprt->state);
                /* "close" the socket, preserving the local port */
+               set_bit(XPRT_CONNECTION_REUSE, &xprt->state);
                xs_tcp_reuse_connection(transport);
+               clear_bit(XPRT_CONNECTION_REUSE, &xprt->state);
 
                if (abort_and_exit)
                        goto out_eagain;