From a4f0835c604f80f945ab3e72ffd00547145c4b2b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2013 09:10:21 -0500 Subject: SUNRPC: Eliminate task->tk_xprt accesses that bypass rcu_dereference() tk_xprt is just a shortcut for tk_client->cl_xprt, however cl_xprt is defined as an __rcu variable. Replace dereferences of tk_xprt with non-rcu dereferences where it is safe to do so. Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/sunrpc/xprt.c') diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 33811db8788a..738ad59628cd 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -430,7 +430,9 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req) */ void xprt_release_rqst_cong(struct rpc_task *task) { - __xprt_put_cong(task->tk_xprt, task->tk_rqstp); + struct rpc_rqst *req = task->tk_rqstp; + + __xprt_put_cong(req->rq_xprt, req); } EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); -- cgit v1.2.3 From 1b092092bf0e2e8b7af1c2a03f615b4e60b05d47 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2013 09:26:49 -0500 Subject: SUNRPC: Pass a pointer to struct rpc_xprt to the connect callback Avoid another RCU dereference by passing the pointer to struct rpc_xprt from the caller. Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sunrpc/xprt.c') diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 738ad59628cd..774025109e2f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -724,7 +724,7 @@ void xprt_connect(struct rpc_task *task) if (xprt_test_and_set_connecting(xprt)) return; xprt->stat.connect_start = jiffies; - xprt->ops->connect(task); + xprt->ops->connect(xprt, task); } } -- cgit v1.2.3 From 6a24dfb645dbcb05b34d08b991d082bdaa3ff072 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2013 09:48:15 -0500 Subject: SUNRPC: Pass pointers to struct rpc_xprt to the congestion window Avoid access to task->tk_xprt Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/sunrpc/xprt.c') diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 774025109e2f..e1e439ea177f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -438,15 +438,15 @@ EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); /** * xprt_adjust_cwnd - adjust transport congestion window + * @xprt: pointer to xprt * @task: recently completed RPC request used to adjust window * @result: result code of completed RPC request * * We use a time-smoothed congestion estimator to avoid heavy oscillation. */ -void xprt_adjust_cwnd(struct rpc_task *task, int result) +void xprt_adjust_cwnd(struct rpc_xprt *xprt, struct rpc_task *task, int result) { struct rpc_rqst *req = task->tk_rqstp; - struct rpc_xprt *xprt = task->tk_xprt; unsigned long cwnd = xprt->cwnd; if (result >= 0 && cwnd <= xprt->cong) { @@ -834,7 +834,7 @@ static void xprt_timer(struct rpc_task *task) spin_lock_bh(&xprt->transport_lock); if (!req->rq_reply_bytes_recvd) { if (xprt->ops->timer) - xprt->ops->timer(task); + xprt->ops->timer(xprt, task); } else task->tk_status = 0; spin_unlock_bh(&xprt->transport_lock); -- cgit v1.2.3 From 45bc0dce9879505d6fd9ff68dcd0359fb260dfd7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2013 10:03:22 -0500 Subject: SUNRPC: Fix an RCU dereference in xprt_reserve Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/sunrpc/xprt.c') diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index e1e439ea177f..7f3a01a8cae7 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1093,7 +1093,7 @@ EXPORT_SYMBOL_GPL(xprt_free); */ void xprt_reserve(struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_xprt *xprt; task->tk_status = 0; if (task->tk_rqstp != NULL) @@ -1101,7 +1101,10 @@ void xprt_reserve(struct rpc_task *task) task->tk_timeout = 0; task->tk_status = -EAGAIN; + rcu_read_lock(); + xprt = rcu_dereference(task->tk_client->cl_xprt); xprt->ops->alloc_slot(xprt, task); + rcu_read_unlock(); } static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) -- cgit v1.2.3 From ad2368d6f5ec6467b9503176e9fb878daf999629 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 8 Jan 2013 10:08:33 -0500 Subject: SUNRPC: Avoid RCU dereferences in the transport bind and connect code Avoid an RCU dereference by removing task->tk_xprt Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/sunrpc/xprt.c') diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 7f3a01a8cae7..846c34fdee9f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -697,7 +697,7 @@ out_abort: */ void xprt_connect(struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; dprintk("RPC: %5u xprt_connect xprt %p %s connected\n", task->tk_pid, xprt, (xprt_connected(xprt) ? "is" : "is not")); @@ -730,7 +730,7 @@ void xprt_connect(struct rpc_task *task) static void xprt_connect_status(struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; if (task->tk_status == 0) { xprt->stat.connect_count++; -- cgit v1.2.3