summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-01 17:00:56 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-02 15:36:38 -0500
commit2446ab6070861aba2dd9229463ffbc40016a9f33 (patch)
tree2e366c3236788936b9f4f58c0787ae01c265f4a4 /net
parenta3ca5651cb5eebe2e56e510bbf5cd60abc301c9f (diff)
SUNRPC: Use RCU to dereference the rpc_clnt.cl_xprt field
A migration event will replace the rpc_xprt used by an rpc_clnt. To ensure this can be done safely, all references to cl_xprt must now use a form of rcu_dereference(). Special care is taken with rpc_peeraddr2str(), which returns a pointer to memory whose lifetime is the same as the rpc_xprt. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> [ cel: fix lockdep splats and layering violations ] [ cel: forward ported to 3.4 ] [ cel: remove rpc_max_reqs(), add rpc_net_ns() ] Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c4
-rw-r--r--net/sunrpc/clnt.c110
-rw-r--r--net/sunrpc/rpc_pipe.c3
-rw-r--r--net/sunrpc/rpcb_clnt.c15
-rw-r--r--net/sunrpc/stats.c6
5 files changed, 110 insertions, 28 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index cb2e56452748..d3ad81f8da5b 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -799,7 +799,7 @@ err_unlink_pipe_1:
799static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, 799static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt,
800 struct rpc_auth *auth) 800 struct rpc_auth *auth)
801{ 801{
802 struct net *net = clnt->cl_xprt->xprt_net; 802 struct net *net = rpc_net_ns(clnt);
803 struct super_block *sb; 803 struct super_block *sb;
804 804
805 sb = rpc_get_sb_net(net); 805 sb = rpc_get_sb_net(net);
@@ -813,7 +813,7 @@ static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt,
813static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, 813static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt,
814 struct rpc_auth *auth) 814 struct rpc_auth *auth)
815{ 815{
816 struct net *net = clnt->cl_xprt->xprt_net; 816 struct net *net = rpc_net_ns(clnt);
817 struct super_block *sb; 817 struct super_block *sb;
818 int err = 0; 818 int err = 0;
819 819
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 25c3da53fb69..7783fc0e7263 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -31,6 +31,7 @@
31#include <linux/in.h> 31#include <linux/in.h>
32#include <linux/in6.h> 32#include <linux/in6.h>
33#include <linux/un.h> 33#include <linux/un.h>
34#include <linux/rcupdate.h>
34 35
35#include <linux/sunrpc/clnt.h> 36#include <linux/sunrpc/clnt.h>
36#include <linux/sunrpc/rpc_pipe_fs.h> 37#include <linux/sunrpc/rpc_pipe_fs.h>
@@ -81,7 +82,8 @@ static int rpc_ping(struct rpc_clnt *clnt);
81 82
82static void rpc_register_client(struct rpc_clnt *clnt) 83static void rpc_register_client(struct rpc_clnt *clnt)
83{ 84{
84 struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); 85 struct net *net = rpc_net_ns(clnt);
86 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
85 87
86 spin_lock(&sn->rpc_client_lock); 88 spin_lock(&sn->rpc_client_lock);
87 list_add(&clnt->cl_clients, &sn->all_clients); 89 list_add(&clnt->cl_clients, &sn->all_clients);
@@ -90,7 +92,8 @@ static void rpc_register_client(struct rpc_clnt *clnt)
90 92
91static void rpc_unregister_client(struct rpc_clnt *clnt) 93static void rpc_unregister_client(struct rpc_clnt *clnt)
92{ 94{
93 struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); 95 struct net *net = rpc_net_ns(clnt);
96 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
94 97
95 spin_lock(&sn->rpc_client_lock); 98 spin_lock(&sn->rpc_client_lock);
96 list_del(&clnt->cl_clients); 99 list_del(&clnt->cl_clients);
@@ -109,12 +112,13 @@ static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
109 112
110static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) 113static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
111{ 114{
115 struct net *net = rpc_net_ns(clnt);
112 struct super_block *pipefs_sb; 116 struct super_block *pipefs_sb;
113 117
114 pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); 118 pipefs_sb = rpc_get_sb_net(net);
115 if (pipefs_sb) { 119 if (pipefs_sb) {
116 __rpc_clnt_remove_pipedir(clnt); 120 __rpc_clnt_remove_pipedir(clnt);
117 rpc_put_sb_net(clnt->cl_xprt->xprt_net); 121 rpc_put_sb_net(net);
118 } 122 }
119} 123}
120 124
@@ -155,17 +159,18 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
155static int 159static int
156rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) 160rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name)
157{ 161{
162 struct net *net = rpc_net_ns(clnt);
158 struct super_block *pipefs_sb; 163 struct super_block *pipefs_sb;
159 struct dentry *dentry; 164 struct dentry *dentry;
160 165
161 clnt->cl_dentry = NULL; 166 clnt->cl_dentry = NULL;
162 if (dir_name == NULL) 167 if (dir_name == NULL)
163 return 0; 168 return 0;
164 pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); 169 pipefs_sb = rpc_get_sb_net(net);
165 if (!pipefs_sb) 170 if (!pipefs_sb)
166 return 0; 171 return 0;
167 dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); 172 dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
168 rpc_put_sb_net(clnt->cl_xprt->xprt_net); 173 rpc_put_sb_net(net);
169 if (IS_ERR(dentry)) 174 if (IS_ERR(dentry))
170 return PTR_ERR(dentry); 175 return PTR_ERR(dentry);
171 clnt->cl_dentry = dentry; 176 clnt->cl_dentry = dentry;
@@ -295,7 +300,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
295 if (clnt->cl_server == NULL) 300 if (clnt->cl_server == NULL)
296 goto out_no_server; 301 goto out_no_server;
297 302
298 clnt->cl_xprt = xprt; 303 rcu_assign_pointer(clnt->cl_xprt, xprt);
299 clnt->cl_procinfo = version->procs; 304 clnt->cl_procinfo = version->procs;
300 clnt->cl_maxproc = version->nrprocs; 305 clnt->cl_maxproc = version->nrprocs;
301 clnt->cl_protname = program->name; 306 clnt->cl_protname = program->name;
@@ -310,7 +315,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
310 INIT_LIST_HEAD(&clnt->cl_tasks); 315 INIT_LIST_HEAD(&clnt->cl_tasks);
311 spin_lock_init(&clnt->cl_lock); 316 spin_lock_init(&clnt->cl_lock);
312 317
313 if (!xprt_bound(clnt->cl_xprt)) 318 if (!xprt_bound(xprt))
314 clnt->cl_autobind = 1; 319 clnt->cl_autobind = 1;
315 320
316 clnt->cl_timeout = xprt->timeout; 321 clnt->cl_timeout = xprt->timeout;
@@ -477,6 +482,7 @@ struct rpc_clnt *
477rpc_clone_client(struct rpc_clnt *clnt) 482rpc_clone_client(struct rpc_clnt *clnt)
478{ 483{
479 struct rpc_clnt *new; 484 struct rpc_clnt *new;
485 struct rpc_xprt *xprt;
480 int err = -ENOMEM; 486 int err = -ENOMEM;
481 487
482 new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); 488 new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
@@ -499,18 +505,25 @@ rpc_clone_client(struct rpc_clnt *clnt)
499 if (new->cl_principal == NULL) 505 if (new->cl_principal == NULL)
500 goto out_no_principal; 506 goto out_no_principal;
501 } 507 }
508 rcu_read_lock();
509 xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
510 rcu_read_unlock();
511 if (xprt == NULL)
512 goto out_no_transport;
513 rcu_assign_pointer(new->cl_xprt, xprt);
502 atomic_set(&new->cl_count, 1); 514 atomic_set(&new->cl_count, 1);
503 err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); 515 err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
504 if (err != 0) 516 if (err != 0)
505 goto out_no_path; 517 goto out_no_path;
506 if (new->cl_auth) 518 if (new->cl_auth)
507 atomic_inc(&new->cl_auth->au_count); 519 atomic_inc(&new->cl_auth->au_count);
508 xprt_get(clnt->cl_xprt);
509 atomic_inc(&clnt->cl_count); 520 atomic_inc(&clnt->cl_count);
510 rpc_register_client(new); 521 rpc_register_client(new);
511 rpciod_up(); 522 rpciod_up();
512 return new; 523 return new;
513out_no_path: 524out_no_path:
525 xprt_put(xprt);
526out_no_transport:
514 kfree(new->cl_principal); 527 kfree(new->cl_principal);
515out_no_principal: 528out_no_principal:
516 rpc_free_iostats(new->cl_metrics); 529 rpc_free_iostats(new->cl_metrics);
@@ -590,7 +603,7 @@ rpc_free_client(struct rpc_clnt *clnt)
590 rpc_free_iostats(clnt->cl_metrics); 603 rpc_free_iostats(clnt->cl_metrics);
591 kfree(clnt->cl_principal); 604 kfree(clnt->cl_principal);
592 clnt->cl_metrics = NULL; 605 clnt->cl_metrics = NULL;
593 xprt_put(clnt->cl_xprt); 606 xprt_put(rcu_dereference_raw(clnt->cl_xprt));
594 rpciod_down(); 607 rpciod_down();
595 kfree(clnt); 608 kfree(clnt);
596} 609}
@@ -879,13 +892,18 @@ EXPORT_SYMBOL_GPL(rpc_call_start);
879size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) 892size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize)
880{ 893{
881 size_t bytes; 894 size_t bytes;
882 struct rpc_xprt *xprt = clnt->cl_xprt; 895 struct rpc_xprt *xprt;
896
897 rcu_read_lock();
898 xprt = rcu_dereference(clnt->cl_xprt);
883 899
884 bytes = sizeof(xprt->addr); 900 bytes = xprt->addrlen;
885 if (bytes > bufsize) 901 if (bytes > bufsize)
886 bytes = bufsize; 902 bytes = bufsize;
887 memcpy(buf, &clnt->cl_xprt->addr, bytes); 903 memcpy(buf, &xprt->addr, bytes);
888 return xprt->addrlen; 904 rcu_read_unlock();
905
906 return bytes;
889} 907}
890EXPORT_SYMBOL_GPL(rpc_peeraddr); 908EXPORT_SYMBOL_GPL(rpc_peeraddr);
891 909
@@ -894,11 +912,16 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr);
894 * @clnt: RPC client structure 912 * @clnt: RPC client structure
895 * @format: address format 913 * @format: address format
896 * 914 *
915 * NB: the lifetime of the memory referenced by the returned pointer is
916 * the same as the rpc_xprt itself. As long as the caller uses this
917 * pointer, it must hold the RCU read lock.
897 */ 918 */
898const char *rpc_peeraddr2str(struct rpc_clnt *clnt, 919const char *rpc_peeraddr2str(struct rpc_clnt *clnt,
899 enum rpc_display_format_t format) 920 enum rpc_display_format_t format)
900{ 921{
901 struct rpc_xprt *xprt = clnt->cl_xprt; 922 struct rpc_xprt *xprt;
923
924 xprt = rcu_dereference(clnt->cl_xprt);
902 925
903 if (xprt->address_strings[format] != NULL) 926 if (xprt->address_strings[format] != NULL)
904 return xprt->address_strings[format]; 927 return xprt->address_strings[format];
@@ -910,14 +933,51 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr2str);
910void 933void
911rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) 934rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
912{ 935{
913 struct rpc_xprt *xprt = clnt->cl_xprt; 936 struct rpc_xprt *xprt;
937
938 rcu_read_lock();
939 xprt = rcu_dereference(clnt->cl_xprt);
914 if (xprt->ops->set_buffer_size) 940 if (xprt->ops->set_buffer_size)
915 xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); 941 xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
942 rcu_read_unlock();
916} 943}
917EXPORT_SYMBOL_GPL(rpc_setbufsize); 944EXPORT_SYMBOL_GPL(rpc_setbufsize);
918 945
919/* 946/**
920 * Return size of largest payload RPC client can support, in bytes 947 * rpc_protocol - Get transport protocol number for an RPC client
948 * @clnt: RPC client to query
949 *
950 */
951int rpc_protocol(struct rpc_clnt *clnt)
952{
953 int protocol;
954
955 rcu_read_lock();
956 protocol = rcu_dereference(clnt->cl_xprt)->prot;
957 rcu_read_unlock();
958 return protocol;
959}
960EXPORT_SYMBOL_GPL(rpc_protocol);
961
962/**
963 * rpc_net_ns - Get the network namespace for this RPC client
964 * @clnt: RPC client to query
965 *
966 */
967struct net *rpc_net_ns(struct rpc_clnt *clnt)
968{
969 struct net *ret;
970
971 rcu_read_lock();
972 ret = rcu_dereference(clnt->cl_xprt)->xprt_net;
973 rcu_read_unlock();
974 return ret;
975}
976EXPORT_SYMBOL_GPL(rpc_net_ns);
977
978/**
979 * rpc_max_payload - Get maximum payload size for a transport, in bytes
980 * @clnt: RPC client to query
921 * 981 *
922 * For stream transports, this is one RPC record fragment (see RFC 982 * For stream transports, this is one RPC record fragment (see RFC
923 * 1831), as we don't support multi-record requests yet. For datagram 983 * 1831), as we don't support multi-record requests yet. For datagram
@@ -926,7 +986,12 @@ EXPORT_SYMBOL_GPL(rpc_setbufsize);
926 */ 986 */
927size_t rpc_max_payload(struct rpc_clnt *clnt) 987size_t rpc_max_payload(struct rpc_clnt *clnt)
928{ 988{
929 return clnt->cl_xprt->max_payload; 989 size_t ret;
990
991 rcu_read_lock();
992 ret = rcu_dereference(clnt->cl_xprt)->max_payload;
993 rcu_read_unlock();
994 return ret;
930} 995}
931EXPORT_SYMBOL_GPL(rpc_max_payload); 996EXPORT_SYMBOL_GPL(rpc_max_payload);
932 997
@@ -937,8 +1002,11 @@ EXPORT_SYMBOL_GPL(rpc_max_payload);
937 */ 1002 */
938void rpc_force_rebind(struct rpc_clnt *clnt) 1003void rpc_force_rebind(struct rpc_clnt *clnt)
939{ 1004{
940 if (clnt->cl_autobind) 1005 if (clnt->cl_autobind) {
941 xprt_clear_bound(clnt->cl_xprt); 1006 rcu_read_lock();
1007 xprt_clear_bound(rcu_dereference(clnt->cl_xprt));
1008 rcu_read_unlock();
1009 }
942} 1010}
943EXPORT_SYMBOL_GPL(rpc_force_rebind); 1011EXPORT_SYMBOL_GPL(rpc_force_rebind);
944 1012
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ac9ee1590739..3d30943ed6db 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -16,6 +16,7 @@
16#include <linux/namei.h> 16#include <linux/namei.h>
17#include <linux/fsnotify.h> 17#include <linux/fsnotify.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/rcupdate.h>
19 20
20#include <asm/ioctls.h> 21#include <asm/ioctls.h>
21#include <linux/poll.h> 22#include <linux/poll.h>
@@ -402,12 +403,14 @@ rpc_show_info(struct seq_file *m, void *v)
402{ 403{
403 struct rpc_clnt *clnt = m->private; 404 struct rpc_clnt *clnt = m->private;
404 405
406 rcu_read_lock();
405 seq_printf(m, "RPC server: %s\n", clnt->cl_server); 407 seq_printf(m, "RPC server: %s\n", clnt->cl_server);
406 seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, 408 seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname,
407 clnt->cl_prog, clnt->cl_vers); 409 clnt->cl_prog, clnt->cl_vers);
408 seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); 410 seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
409 seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); 411 seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO));
410 seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); 412 seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT));
413 rcu_read_unlock();
411 return 0; 414 return 0;
412} 415}
413 416
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index b1f08bd67883..4f8af63798a2 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -620,9 +620,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
620static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) 620static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
621{ 621{
622 struct rpc_clnt *parent = clnt->cl_parent; 622 struct rpc_clnt *parent = clnt->cl_parent;
623 struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt);
623 624
624 while (parent != clnt) { 625 while (parent != clnt) {
625 if (parent->cl_xprt != clnt->cl_xprt) 626 if (rcu_dereference(parent->cl_xprt) != xprt)
626 break; 627 break;
627 if (clnt->cl_autobind) 628 if (clnt->cl_autobind)
628 break; 629 break;
@@ -653,8 +654,12 @@ void rpcb_getport_async(struct rpc_task *task)
653 size_t salen; 654 size_t salen;
654 int status; 655 int status;
655 656
656 clnt = rpcb_find_transport_owner(task->tk_client); 657 rcu_read_lock();
657 xprt = clnt->cl_xprt; 658 do {
659 clnt = rpcb_find_transport_owner(task->tk_client);
660 xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
661 } while (xprt == NULL);
662 rcu_read_unlock();
658 663
659 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", 664 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
660 task->tk_pid, __func__, 665 task->tk_pid, __func__,
@@ -667,6 +672,7 @@ void rpcb_getport_async(struct rpc_task *task)
667 if (xprt_test_and_set_binding(xprt)) { 672 if (xprt_test_and_set_binding(xprt)) {
668 dprintk("RPC: %5u %s: waiting for another binder\n", 673 dprintk("RPC: %5u %s: waiting for another binder\n",
669 task->tk_pid, __func__); 674 task->tk_pid, __func__);
675 xprt_put(xprt);
670 return; 676 return;
671 } 677 }
672 678
@@ -734,7 +740,7 @@ void rpcb_getport_async(struct rpc_task *task)
734 switch (bind_version) { 740 switch (bind_version) {
735 case RPCBVERS_4: 741 case RPCBVERS_4:
736 case RPCBVERS_3: 742 case RPCBVERS_3:
737 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); 743 map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID];
738 map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); 744 map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC);
739 map->r_owner = ""; 745 map->r_owner = "";
740 break; 746 break;
@@ -763,6 +769,7 @@ bailout_release_client:
763bailout_nofree: 769bailout_nofree:
764 rpcb_wake_rpcbind_waiters(xprt, status); 770 rpcb_wake_rpcbind_waiters(xprt, status);
765 task->tk_status = status; 771 task->tk_status = status;
772 xprt_put(xprt);
766} 773}
767EXPORT_SYMBOL_GPL(rpcb_getport_async); 774EXPORT_SYMBOL_GPL(rpcb_getport_async);
768 775
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 1eb3304bc105..bc2068ee795b 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -22,6 +22,7 @@
22#include <linux/sunrpc/clnt.h> 22#include <linux/sunrpc/clnt.h>
23#include <linux/sunrpc/svcsock.h> 23#include <linux/sunrpc/svcsock.h>
24#include <linux/sunrpc/metrics.h> 24#include <linux/sunrpc/metrics.h>
25#include <linux/rcupdate.h>
25 26
26#include "netns.h" 27#include "netns.h"
27 28
@@ -179,7 +180,7 @@ static void _print_name(struct seq_file *seq, unsigned int op,
179void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) 180void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
180{ 181{
181 struct rpc_iostats *stats = clnt->cl_metrics; 182 struct rpc_iostats *stats = clnt->cl_metrics;
182 struct rpc_xprt *xprt = clnt->cl_xprt; 183 struct rpc_xprt *xprt;
183 unsigned int op, maxproc = clnt->cl_maxproc; 184 unsigned int op, maxproc = clnt->cl_maxproc;
184 185
185 if (!stats) 186 if (!stats)
@@ -189,8 +190,11 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
189 seq_printf(seq, "p/v: %u/%u (%s)\n", 190 seq_printf(seq, "p/v: %u/%u (%s)\n",
190 clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); 191 clnt->cl_prog, clnt->cl_vers, clnt->cl_protname);
191 192
193 rcu_read_lock();
194 xprt = rcu_dereference(clnt->cl_xprt);
192 if (xprt) 195 if (xprt)
193 xprt->ops->print_stats(xprt, seq); 196 xprt->ops->print_stats(xprt, seq);
197 rcu_read_unlock();
194 198
195 seq_printf(seq, "\tper-op statistics\n"); 199 seq_printf(seq, "\tper-op statistics\n");
196 for (op = 0; op < maxproc; op++) { 200 for (op = 0; op < maxproc; op++) {