summaryrefslogtreecommitdiff
path: root/net/sunrpc/xprt.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2022-09-01 00:28:13 +0300
committerTrond Myklebust <trond.myklebust@hammerspace.com>2022-09-01 17:40:37 +0300
commit17814819ac9829a437e06fbb5c7056a1f4f893da (patch)
tree5943e21a6aea0ec1fb55cd9fc21dbd287f7d7161 /net/sunrpc/xprt.c
parented06fce0b034b2e25bd93430f5c4cbb28036cc1a (diff)
downloadlinux-17814819ac9829a437e06fbb5c7056a1f4f893da.tar.xz
SUNRPC: Fix call completion races with call_decode()
We need to make sure that the req->rq_private_buf is completely up to date before we make req->rq_reply_bytes_recvd visible to the call_decode() routine in order to avoid triggering the WARN_ON(). Reported-by: Benjamin Coddington <bcodding@redhat.com> Fixes: 72691a269f0b ("SUNRPC: Don't reuse bvec on retransmission of the request") Tested-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r--net/sunrpc/xprt.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index d71eec494826..f8fae7815649 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1179,11 +1179,8 @@ xprt_request_dequeue_receive_locked(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
- if (test_and_clear_bit(RPC_TASK_NEED_RECV, &task->tk_runstate)) {
+ if (test_and_clear_bit(RPC_TASK_NEED_RECV, &task->tk_runstate))
xprt_request_rb_remove(req->rq_xprt, req);
- xdr_free_bvec(&req->rq_rcv_buf);
- req->rq_private_buf.bvec = NULL;
- }
}
/**
@@ -1221,6 +1218,8 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
xprt->stat.recvs++;
+ xdr_free_bvec(&req->rq_rcv_buf);
+ req->rq_private_buf.bvec = NULL;
req->rq_private_buf.len = copied;
/* Ensure all writes are done before we update */
/* req->rq_reply_bytes_recvd */
@@ -1453,6 +1452,7 @@ xprt_request_dequeue_xprt(struct rpc_task *task)
xprt_request_dequeue_transmit_locked(task);
xprt_request_dequeue_receive_locked(task);
spin_unlock(&xprt->queue_lock);
+ xdr_free_bvec(&req->rq_rcv_buf);
}
}