summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc.c
diff options
context:
space:
mode:
authorTrond Myklebust2015-06-04 21:37:10 +0200
committerTrond Myklebust2015-06-05 17:15:43 +0200
commit0d2a970d0ae55086520e1e58e572a7acd519429c (patch)
treeb91159e4d38c5c9599cfb7500395729ced35a245 /net/sunrpc/svc.c
parentSUNRPC: Clean up allocation and freeing of back channel requests (diff)
downloadkernel-qcow2-linux-0d2a970d0ae55086520e1e58e572a7acd519429c.tar.gz
kernel-qcow2-linux-0d2a970d0ae55086520e1e58e572a7acd519429c.tar.xz
kernel-qcow2-linux-0d2a970d0ae55086520e1e58e572a7acd519429c.zip
SUNRPC: Fix a backchannel race
We need to allow the server to send a new request immediately after we've replied to the previous one. Right now, there is a window between the send and the release of the old request in rpc_put_task(), where the server could send us a new backchannel RPC call, and we have no request to service it. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r--net/sunrpc/svc.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 51c8cad5e765..b47f02f60b9c 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1351,6 +1351,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
struct rpc_task *task;
+ int proc_error;
int error;
dprintk("svc: %s(%p)\n", __func__, req);
@@ -1382,7 +1383,10 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
svc_getnl(argv); /* CALLDIR */
/* Parse and execute the bc call */
- if (!svc_process_common(rqstp, argv, resv)) {
+ proc_error = svc_process_common(rqstp, argv, resv);
+
+ atomic_inc(&req->rq_xprt->bc_free_slots);
+ if (!proc_error) {
/* Processing error: drop the request */
xprt_free_bc_request(req);
return 0;