summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2019-07-11 16:33:12 -0400
committerTrond Myklebust <trond.myklebust@hammerspace.com>2019-07-12 13:14:54 -0400
commita101b043c44dfcb63bed7f29a675e9fa0259005e (patch)
treefee002167b713916d0eb068551a25911891660e6
parent347543e64082782379627cb21162cb859590f3c7 (diff)
SUNRPC: Fix transport accounting when caller specifies an rpc_xprt
Ensure that we do the required accounting for the round robin queue when the caller to rpc_init_task() has passed in a transport to be used. Reported-by: Olga Kornievskaia <aglo@umich.edu> Reported-by: Neil Brown <neilb@suse.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--net/sunrpc/clnt.c42
-rw-r--r--net/sunrpc/sched.c3
3 files changed, 24 insertions, 23 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 4619098affa3..4e070e00c143 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -164,6 +164,8 @@ void rpc_shutdown_client(struct rpc_clnt *);
164void rpc_release_client(struct rpc_clnt *); 164void rpc_release_client(struct rpc_clnt *);
165void rpc_task_release_transport(struct rpc_task *); 165void rpc_task_release_transport(struct rpc_task *);
166void rpc_task_release_client(struct rpc_task *); 166void rpc_task_release_client(struct rpc_task *);
167struct rpc_xprt *rpc_task_get_xprt(struct rpc_clnt *clnt,
168 struct rpc_xprt *xprt);
167 169
168int rpcb_create_local(struct net *); 170int rpcb_create_local(struct net *);
169void rpcb_put_local(struct net *); 171void rpcb_put_local(struct net *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d599fab8adcb..383555d2b522 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -978,11 +978,10 @@ out:
978} 978}
979EXPORT_SYMBOL_GPL(rpc_bind_new_program); 979EXPORT_SYMBOL_GPL(rpc_bind_new_program);
980 980
981static struct rpc_xprt * 981struct rpc_xprt *
982rpc_task_get_xprt(struct rpc_clnt *clnt) 982rpc_task_get_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
983{ 983{
984 struct rpc_xprt_switch *xps; 984 struct rpc_xprt_switch *xps;
985 struct rpc_xprt *xprt= xprt_iter_get_next(&clnt->cl_xpi);
986 985
987 if (!xprt) 986 if (!xprt)
988 return NULL; 987 return NULL;
@@ -995,24 +994,6 @@ rpc_task_get_xprt(struct rpc_clnt *clnt)
995 return xprt; 994 return xprt;
996} 995}
997 996
998static struct rpc_xprt *
999rpc_task_get_first_xprt(struct rpc_clnt *clnt)
1000{
1001 struct rpc_xprt_switch *xps;
1002 struct rpc_xprt *xprt;
1003
1004 rcu_read_lock();
1005 xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
1006 if (xprt) {
1007 atomic_long_inc(&xprt->queuelen);
1008 xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
1009 atomic_long_inc(&xps->xps_queuelen);
1010 }
1011 rcu_read_unlock();
1012
1013 return xprt;
1014}
1015
1016static void 997static void
1017rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt) 998rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
1018{ 999{
@@ -1057,6 +1038,23 @@ void rpc_task_release_client(struct rpc_task *task)
1057 } 1038 }
1058} 1039}
1059 1040
1041static struct rpc_xprt *
1042rpc_task_get_first_xprt(struct rpc_clnt *clnt)
1043{
1044 struct rpc_xprt *xprt;
1045
1046 rcu_read_lock();
1047 xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
1048 rcu_read_unlock();
1049 return rpc_task_get_xprt(clnt, xprt);
1050}
1051
1052static struct rpc_xprt *
1053rpc_task_get_next_xprt(struct rpc_clnt *clnt)
1054{
1055 return rpc_task_get_xprt(clnt, xprt_iter_get_next(&clnt->cl_xpi));
1056}
1057
1060static 1058static
1061void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt) 1059void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
1062{ 1060{
@@ -1065,7 +1063,7 @@ void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
1065 if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN) 1063 if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
1066 task->tk_xprt = rpc_task_get_first_xprt(clnt); 1064 task->tk_xprt = rpc_task_get_first_xprt(clnt);
1067 else 1065 else
1068 task->tk_xprt = rpc_task_get_xprt(clnt); 1066 task->tk_xprt = rpc_task_get_next_xprt(clnt);
1069} 1067}
1070 1068
1071static 1069static
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 8a0779e963f9..1f275aba786f 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -1092,7 +1092,8 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
1092 /* Initialize workqueue for async tasks */ 1092 /* Initialize workqueue for async tasks */
1093 task->tk_workqueue = task_setup_data->workqueue; 1093 task->tk_workqueue = task_setup_data->workqueue;
1094 1094
1095 task->tk_xprt = xprt_get(task_setup_data->rpc_xprt); 1095 task->tk_xprt = rpc_task_get_xprt(task_setup_data->rpc_client,
1096 xprt_get(task_setup_data->rpc_xprt));
1096 1097
1097 task->tk_op_cred = get_rpccred(task_setup_data->rpc_op_cred); 1098 task->tk_op_cred = get_rpccred(task_setup_data->rpc_op_cred);
1098 1099