summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/nfs/callback_proc.c9
-rw-r--r--fs/nfs/client.c16
-rw-r--r--fs/nfs/nfs4namespace.c2
-rw-r--r--fs/nfs/nfs4proc.c13
-rw-r--r--fs/nfs/nfs4state.c25
-rw-r--r--fs/nfs/super.c5
-rw-r--r--include/linux/sunrpc/clnt.h4
-rw-r--r--include/linux/sunrpc/debug.h13
-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
13 files changed, 175 insertions, 50 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 0e0865e38065..1bb297243624 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -8,6 +8,7 @@
8#include <linux/nfs4.h> 8#include <linux/nfs4.h>
9#include <linux/nfs_fs.h> 9#include <linux/nfs_fs.h>
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/rcupdate.h>
11#include "nfs4_fs.h" 12#include "nfs4_fs.h"
12#include "callback.h" 13#include "callback.h"
13#include "delegation.h" 14#include "delegation.h"
@@ -33,7 +34,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
33 res->bitmap[0] = res->bitmap[1] = 0; 34 res->bitmap[0] = res->bitmap[1] = 0;
34 res->status = htonl(NFS4ERR_BADHANDLE); 35 res->status = htonl(NFS4ERR_BADHANDLE);
35 36
36 dprintk("NFS: GETATTR callback request from %s\n", 37 dprintk_rcu("NFS: GETATTR callback request from %s\n",
37 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 38 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
38 39
39 inode = nfs_delegation_find_inode(cps->clp, &args->fh); 40 inode = nfs_delegation_find_inode(cps->clp, &args->fh);
@@ -73,7 +74,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
73 if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */ 74 if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
74 goto out; 75 goto out;
75 76
76 dprintk("NFS: RECALL callback request from %s\n", 77 dprintk_rcu("NFS: RECALL callback request from %s\n",
77 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 78 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
78 79
79 res = htonl(NFS4ERR_BADHANDLE); 80 res = htonl(NFS4ERR_BADHANDLE);
@@ -533,7 +534,7 @@ __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy,
533 if (!cps->clp) /* set in cb_sequence */ 534 if (!cps->clp) /* set in cb_sequence */
534 goto out; 535 goto out;
535 536
536 dprintk("NFS: RECALL_ANY callback request from %s\n", 537 dprintk_rcu("NFS: RECALL_ANY callback request from %s\n",
537 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 538 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
538 539
539 status = cpu_to_be32(NFS4ERR_INVAL); 540 status = cpu_to_be32(NFS4ERR_INVAL);
@@ -568,7 +569,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
568 if (!cps->clp) /* set in cb_sequence */ 569 if (!cps->clp) /* set in cb_sequence */
569 goto out; 570 goto out;
570 571
571 dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", 572 dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
572 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), 573 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR),
573 args->crsa_target_max_slots); 574 args->crsa_target_max_slots);
574 575
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 1506adf4d4ed..d038dc5916e5 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1284,16 +1284,18 @@ static int nfs4_init_callback(struct nfs_client *clp)
1284 int error; 1284 int error;
1285 1285
1286 if (clp->rpc_ops->version == 4) { 1286 if (clp->rpc_ops->version == 4) {
1287 struct rpc_xprt *xprt;
1288
1289 xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
1290
1287 if (nfs4_has_session(clp)) { 1291 if (nfs4_has_session(clp)) {
1288 error = xprt_setup_backchannel( 1292 error = xprt_setup_backchannel(xprt,
1289 clp->cl_rpcclient->cl_xprt,
1290 NFS41_BC_MIN_CALLBACKS); 1293 NFS41_BC_MIN_CALLBACKS);
1291 if (error < 0) 1294 if (error < 0)
1292 return error; 1295 return error;
1293 } 1296 }
1294 1297
1295 error = nfs_callback_up(clp->cl_mvops->minor_version, 1298 error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
1296 clp->cl_rpcclient->cl_xprt);
1297 if (error < 0) { 1299 if (error < 0) {
1298 dprintk("%s: failed to start callback. Error = %d\n", 1300 dprintk("%s: failed to start callback. Error = %d\n",
1299 __func__, error); 1301 __func__, error);
@@ -1678,7 +1680,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1678 data->addrlen, 1680 data->addrlen,
1679 parent_client->cl_ipaddr, 1681 parent_client->cl_ipaddr,
1680 data->authflavor, 1682 data->authflavor,
1681 parent_server->client->cl_xprt->prot, 1683 rpc_protocol(parent_server->client),
1682 parent_server->client->cl_timeout, 1684 parent_server->client->cl_timeout,
1683 parent_client->cl_mvops->minor_version, 1685 parent_client->cl_mvops->minor_version,
1684 parent_client->net); 1686 parent_client->net);
@@ -1905,12 +1907,14 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
1905 if (clp->cl_cons_state != NFS_CS_READY) 1907 if (clp->cl_cons_state != NFS_CS_READY)
1906 return 0; 1908 return 0;
1907 1909
1910 rcu_read_lock();
1908 seq_printf(m, "v%u %s %s %3d %s\n", 1911 seq_printf(m, "v%u %s %s %3d %s\n",
1909 clp->rpc_ops->version, 1912 clp->rpc_ops->version,
1910 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), 1913 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
1911 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), 1914 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
1912 atomic_read(&clp->cl_count), 1915 atomic_read(&clp->cl_count),
1913 clp->cl_hostname); 1916 clp->cl_hostname);
1917 rcu_read_unlock();
1914 1918
1915 return 0; 1919 return 0;
1916} 1920}
@@ -1993,6 +1997,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
1993 (unsigned long long) server->fsid.major, 1997 (unsigned long long) server->fsid.major,
1994 (unsigned long long) server->fsid.minor); 1998 (unsigned long long) server->fsid.minor);
1995 1999
2000 rcu_read_lock();
1996 seq_printf(m, "v%u %s %s %-7s %-17s %s\n", 2001 seq_printf(m, "v%u %s %s %-7s %-17s %s\n",
1997 clp->rpc_ops->version, 2002 clp->rpc_ops->version,
1998 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), 2003 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
@@ -2000,6 +2005,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
2000 dev, 2005 dev,
2001 fsid, 2006 fsid,
2002 nfs_server_fscache_state(server)); 2007 nfs_server_fscache_state(server));
2008 rcu_read_unlock();
2003 2009
2004 return 0; 2010 return 0;
2005} 2011}
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 667ea7406fd3..9c8eca315f43 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -96,8 +96,8 @@ static int nfs4_validate_fspath(struct dentry *dentry,
96static size_t nfs_parse_server_name(char *string, size_t len, 96static size_t nfs_parse_server_name(char *string, size_t len,
97 struct sockaddr *sa, size_t salen, struct nfs_server *server) 97 struct sockaddr *sa, size_t salen, struct nfs_server *server)
98{ 98{
99 struct net *net = rpc_net_ns(server->client);
99 ssize_t ret; 100 ssize_t ret;
100 struct net *net = server->client->cl_xprt->xprt_net;
101 101
102 ret = rpc_pton(net, string, len, sa, salen); 102 ret = rpc_pton(net, string, len, sa, salen);
103 if (ret == 0) { 103 if (ret == 0) {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6c8e170e2e6b..671510cc14c0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3833,6 +3833,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3833 *p = htonl((u32)clp->cl_boot_time.tv_nsec); 3833 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
3834 3834
3835 for(;;) { 3835 for(;;) {
3836 rcu_read_lock();
3836 setclientid.sc_name_len = scnprintf(setclientid.sc_name, 3837 setclientid.sc_name_len = scnprintf(setclientid.sc_name,
3837 sizeof(setclientid.sc_name), "%s/%s %s %s %u", 3838 sizeof(setclientid.sc_name), "%s/%s %s %s %u",
3838 clp->cl_ipaddr, 3839 clp->cl_ipaddr,
@@ -3849,6 +3850,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3849 setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, 3850 setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
3850 sizeof(setclientid.sc_uaddr), "%s.%u.%u", 3851 sizeof(setclientid.sc_uaddr), "%s.%u.%u",
3851 clp->cl_ipaddr, port >> 8, port & 255); 3852 clp->cl_ipaddr, port >> 8, port & 255);
3853 rcu_read_unlock();
3852 3854
3853 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); 3855 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
3854 if (status != -NFS4ERR_CLID_INUSE) 3856 if (status != -NFS4ERR_CLID_INUSE)
@@ -5244,11 +5246,16 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
5244 5246
5245void nfs4_destroy_session(struct nfs4_session *session) 5247void nfs4_destroy_session(struct nfs4_session *session)
5246{ 5248{
5249 struct rpc_xprt *xprt;
5250
5247 nfs4_proc_destroy_session(session); 5251 nfs4_proc_destroy_session(session);
5252
5253 rcu_read_lock();
5254 xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt);
5255 rcu_read_unlock();
5248 dprintk("%s Destroy backchannel for xprt %p\n", 5256 dprintk("%s Destroy backchannel for xprt %p\n",
5249 __func__, session->clp->cl_rpcclient->cl_xprt); 5257 __func__, xprt);
5250 xprt_destroy_backchannel(session->clp->cl_rpcclient->cl_xprt, 5258 xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
5251 NFS41_BC_MIN_CALLBACKS);
5252 nfs4_destroy_slot_tables(session); 5259 nfs4_destroy_slot_tables(session);
5253 kfree(session); 5260 kfree(session);
5254} 5261}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c1111a37dc14..bae959e294cd 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1037,19 +1037,28 @@ static void nfs4_clear_state_manager_bit(struct nfs_client *clp)
1037void nfs4_schedule_state_manager(struct nfs_client *clp) 1037void nfs4_schedule_state_manager(struct nfs_client *clp)
1038{ 1038{
1039 struct task_struct *task; 1039 struct task_struct *task;
1040 char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
1040 1041
1041 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) 1042 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
1042 return; 1043 return;
1043 __module_get(THIS_MODULE); 1044 __module_get(THIS_MODULE);
1044 atomic_inc(&clp->cl_count); 1045 atomic_inc(&clp->cl_count);
1045 task = kthread_run(nfs4_run_state_manager, clp, "%s-manager", 1046
1046 rpc_peeraddr2str(clp->cl_rpcclient, 1047 /* The rcu_read_lock() is not strictly necessary, as the state
1047 RPC_DISPLAY_ADDR)); 1048 * manager is the only thread that ever changes the rpc_xprt
1048 if (!IS_ERR(task)) 1049 * after it's initialized. At this point, we're single threaded. */
1049 return; 1050 rcu_read_lock();
1050 nfs4_clear_state_manager_bit(clp); 1051 snprintf(buf, sizeof(buf), "%s-manager",
1051 nfs_put_client(clp); 1052 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
1052 module_put(THIS_MODULE); 1053 rcu_read_unlock();
1054 task = kthread_run(nfs4_run_state_manager, clp, buf);
1055 if (IS_ERR(task)) {
1056 printk(KERN_ERR "%s: kthread_run: %ld\n",
1057 __func__, PTR_ERR(task));
1058 nfs4_clear_state_manager_bit(clp);
1059 nfs_put_client(clp);
1060 module_put(THIS_MODULE);
1061 }
1053} 1062}
1054 1063
1055/* 1064/*
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f4ccdae6a0cf..7002be11d99f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -53,6 +53,7 @@
53#include <linux/magic.h> 53#include <linux/magic.h>
54#include <linux/parser.h> 54#include <linux/parser.h>
55#include <linux/nsproxy.h> 55#include <linux/nsproxy.h>
56#include <linux/rcupdate.h>
56 57
57#include <asm/system.h> 58#include <asm/system.h>
58#include <asm/uaccess.h> 59#include <asm/uaccess.h>
@@ -701,8 +702,10 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
701 else 702 else
702 seq_puts(m, nfs_infop->nostr); 703 seq_puts(m, nfs_infop->nostr);
703 } 704 }
705 rcu_read_lock();
704 seq_printf(m, ",proto=%s", 706 seq_printf(m, ",proto=%s",
705 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID)); 707 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
708 rcu_read_unlock();
706 if (version == 4) { 709 if (version == 4) {
707 if (nfss->port != NFS_PORT) 710 if (nfss->port != NFS_PORT)
708 seq_printf(m, ",port=%u", nfss->port); 711 seq_printf(m, ",port=%u", nfss->port);
@@ -751,9 +754,11 @@ static int nfs_show_options(struct seq_file *m, struct dentry *root)
751 754
752 nfs_show_mount_options(m, nfss, 0); 755 nfs_show_mount_options(m, nfss, 0);
753 756
757 rcu_read_lock();
754 seq_printf(m, ",addr=%s", 758 seq_printf(m, ",addr=%s",
755 rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient, 759 rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient,
756 RPC_DISPLAY_ADDR)); 760 RPC_DISPLAY_ADDR));
761 rcu_read_unlock();
757 762
758 return 0; 763 return 0;
759} 764}
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index a4c62e95c720..e3d12b4a0314 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -35,7 +35,7 @@ struct rpc_clnt {
35 struct list_head cl_clients; /* Global list of clients */ 35 struct list_head cl_clients; /* Global list of clients */
36 struct list_head cl_tasks; /* List of tasks */ 36 struct list_head cl_tasks; /* List of tasks */
37 spinlock_t cl_lock; /* spinlock */ 37 spinlock_t cl_lock; /* spinlock */
38 struct rpc_xprt * cl_xprt; /* transport */ 38 struct rpc_xprt __rcu * cl_xprt; /* transport */
39 struct rpc_procinfo * cl_procinfo; /* procedure info */ 39 struct rpc_procinfo * cl_procinfo; /* procedure info */
40 u32 cl_prog, /* RPC program number */ 40 u32 cl_prog, /* RPC program number */
41 cl_vers, /* RPC version number */ 41 cl_vers, /* RPC version number */
@@ -156,6 +156,8 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
156int rpc_restart_call_prepare(struct rpc_task *); 156int rpc_restart_call_prepare(struct rpc_task *);
157int rpc_restart_call(struct rpc_task *); 157int rpc_restart_call(struct rpc_task *);
158void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); 158void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
159int rpc_protocol(struct rpc_clnt *);
160struct net * rpc_net_ns(struct rpc_clnt *);
159size_t rpc_max_payload(struct rpc_clnt *); 161size_t rpc_max_payload(struct rpc_clnt *);
160void rpc_force_rebind(struct rpc_clnt *); 162void rpc_force_rebind(struct rpc_clnt *);
161size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); 163size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index b506936f4ce6..6cb2517bcf75 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -50,19 +50,32 @@ extern unsigned int nlm_debug;
50#endif 50#endif
51 51
52#define dprintk(args...) dfprintk(FACILITY, ## args) 52#define dprintk(args...) dfprintk(FACILITY, ## args)
53#define dprintk_rcu(args...) dfprintk_rcu(FACILITY, ## args)
53 54
54#undef ifdebug 55#undef ifdebug
55#ifdef RPC_DEBUG 56#ifdef RPC_DEBUG
56# define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac)) 57# define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac))
58
57# define dfprintk(fac, args...) \ 59# define dfprintk(fac, args...) \
58 do { \ 60 do { \
59 ifdebug(fac) \ 61 ifdebug(fac) \
60 printk(KERN_DEFAULT args); \ 62 printk(KERN_DEFAULT args); \
61 } while (0) 63 } while (0)
64
65# define dfprintk_rcu(fac, args...) \
66 do { \
67 ifdebug(fac) { \
68 rcu_read_lock(); \
69 printk(KERN_DEFAULT args); \
70 rcu_read_unlock(); \
71 } \
72 } while (0)
73
62# define RPC_IFDEBUG(x) x 74# define RPC_IFDEBUG(x) x
63#else 75#else
64# define ifdebug(fac) if (0) 76# define ifdebug(fac) if (0)
65# define dfprintk(fac, args...) do ; while (0) 77# define dfprintk(fac, args...) do ; while (0)
78# define dfprintk_rcu(fac, args...) do ; while (0)
66# define RPC_IFDEBUG(x) 79# define RPC_IFDEBUG(x)
67#endif 80#endif
68 81
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++) {