]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sunrpc/clnt.c
Merge tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux
[linux.git] / net / sunrpc / clnt.c
index a07b516e503a0a8252d0f3876f38df65b812da0d..a3379765605d160dee186bb6743ed8e53756df07 100644 (file)
@@ -591,6 +591,9 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        xprt->resvport = 1;
        if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
                xprt->resvport = 0;
+       xprt->reuseport = 0;
+       if (args->flags & RPC_CLNT_CREATE_REUSEPORT)
+               xprt->reuseport = 1;
 
        clnt = rpc_create_xprt(args, xprt);
        if (IS_ERR(clnt) || args->nconnect <= 1)
@@ -1676,8 +1679,6 @@ call_reserveresult(struct rpc_task *task)
                        return;
                }
 
-               printk(KERN_ERR "%s: status=%d, but no request slot, exiting\n",
-                               __func__, status);
                rpc_call_rpcerror(task, -EIO);
                return;
        }
@@ -1686,11 +1687,8 @@ call_reserveresult(struct rpc_task *task)
         * Even though there was an error, we may have acquired
         * a request slot somehow.  Make sure not to leak it.
         */
-       if (task->tk_rqstp) {
-               printk(KERN_ERR "%s: status=%d, request allocated anyway\n",
-                               __func__, status);
+       if (task->tk_rqstp)
                xprt_release(task);
-       }
 
        switch (status) {
        case -ENOMEM:
@@ -1699,14 +1697,9 @@ call_reserveresult(struct rpc_task *task)
        case -EAGAIN:   /* woken up; retry */
                task->tk_action = call_retry_reserve;
                return;
-       case -EIO:      /* probably a shutdown */
-               break;
        default:
-               printk(KERN_ERR "%s: unrecognized error %d, exiting\n",
-                               __func__, status);
-               break;
+               rpc_call_rpcerror(task, status);
        }
-       rpc_call_rpcerror(task, status);
 }
 
 /*
@@ -1837,7 +1830,7 @@ call_allocate(struct rpc_task *task)
                return;
        }
 
-       rpc_exit(task, -ERESTARTSYS);
+       rpc_call_rpcerror(task, -ERESTARTSYS);
 }
 
 static int
@@ -1862,6 +1855,7 @@ rpc_xdr_encode(struct rpc_task *task)
                     req->rq_rbuffer,
                     req->rq_rcvsize);
 
+       req->rq_reply_bytes_recvd = 0;
        req->rq_snd_buf.head[0].iov_len = 0;
        xdr_init_encode(&xdr, &req->rq_snd_buf,
                        req->rq_snd_buf.head[0].iov_base, req);
@@ -1881,6 +1875,8 @@ call_encode(struct rpc_task *task)
        if (!rpc_task_need_encode(task))
                goto out;
        dprint_status(task);
+       /* Dequeue task from the receive queue while we're encoding */
+       xprt_request_dequeue_xprt(task);
        /* Encode here so that rpcsec_gss can use correct sequence number. */
        rpc_xdr_encode(task);
        /* Did the encode result in an error condition? */
@@ -2479,6 +2475,7 @@ call_decode(struct rpc_task *task)
        struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
        struct xdr_stream xdr;
+       int err;
 
        dprint_status(task);
 
@@ -2501,6 +2498,15 @@ call_decode(struct rpc_task *task)
         * before it changed req->rq_reply_bytes_recvd.
         */
        smp_rmb();
+
+       /*
+        * Did we ever call xprt_complete_rqst()? If not, we should assume
+        * the message is incomplete.
+        */
+       err = -EAGAIN;
+       if (!req->rq_reply_bytes_recvd)
+               goto out;
+
        req->rq_rcv_buf.len = req->rq_private_buf.len;
 
        /* Check that the softirq receive buffer is valid */
@@ -2509,7 +2515,9 @@ call_decode(struct rpc_task *task)
 
        xdr_init_decode(&xdr, &req->rq_rcv_buf,
                        req->rq_rcv_buf.head[0].iov_base, req);
-       switch (rpc_decode_header(task, &xdr)) {
+       err = rpc_decode_header(task, &xdr);
+out:
+       switch (err) {
        case 0:
                task->tk_action = rpc_exit_task;
                task->tk_status = rpcauth_unwrap_resp(task, &xdr);
@@ -2518,9 +2526,6 @@ call_decode(struct rpc_task *task)
                return;
        case -EAGAIN:
                task->tk_status = 0;
-               xdr_free_bvec(&req->rq_rcv_buf);
-               req->rq_reply_bytes_recvd = 0;
-               req->rq_rcv_buf.len = 0;
                if (task->tk_client->cl_discrtry)
                        xprt_conditional_disconnect(req->rq_xprt,
                                                    req->rq_connect_cookie);
@@ -2561,7 +2566,7 @@ rpc_encode_header(struct rpc_task *task, struct xdr_stream *xdr)
        return 0;
 out_fail:
        trace_rpc_bad_callhdr(task);
-       rpc_exit(task, error);
+       rpc_call_rpcerror(task, error);
        return error;
 }
 
@@ -2628,7 +2633,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
                return -EAGAIN;
        }
 out_err:
-       rpc_exit(task, error);
+       rpc_call_rpcerror(task, error);
        return error;
 
 out_unparsable:
@@ -2894,7 +2899,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
        struct rpc_xprt *xprt;
        unsigned long connect_timeout;
        unsigned long reconnect_timeout;
-       unsigned char resvport;
+       unsigned char resvport, reuseport;
        int ret = 0;
 
        rcu_read_lock();
@@ -2906,6 +2911,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
                return -EAGAIN;
        }
        resvport = xprt->resvport;
+       reuseport = xprt->reuseport;
        connect_timeout = xprt->connect_timeout;
        reconnect_timeout = xprt->max_reconnect_timeout;
        rcu_read_unlock();
@@ -2916,6 +2922,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
                goto out_put_switch;
        }
        xprt->resvport = resvport;
+       xprt->reuseport = reuseport;
        if (xprt->ops->set_connect_timeout != NULL)
                xprt->ops->set_connect_timeout(xprt,
                                connect_timeout,