Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+175 -50
+5 -4
fs/nfs/callback_proc.c
··· 8 8 #include <linux/nfs4.h> 9 9 #include <linux/nfs_fs.h> 10 10 #include <linux/slab.h> 11 + #include <linux/rcupdate.h> 11 12 #include "nfs4_fs.h" 12 13 #include "callback.h" 13 14 #include "delegation.h" ··· 34 33 res->bitmap[0] = res->bitmap[1] = 0; 35 34 res->status = htonl(NFS4ERR_BADHANDLE); 36 35 37 - dprintk("NFS: GETATTR callback request from %s\n", 36 + dprintk_rcu("NFS: GETATTR callback request from %s\n", 38 37 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 39 38 40 39 inode = nfs_delegation_find_inode(cps->clp, &args->fh); ··· 74 73 if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */ 75 74 goto out; 76 75 77 - dprintk("NFS: RECALL callback request from %s\n", 76 + dprintk_rcu("NFS: RECALL callback request from %s\n", 78 77 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 79 78 80 79 res = htonl(NFS4ERR_BADHANDLE); ··· 534 533 if (!cps->clp) /* set in cb_sequence */ 535 534 goto out; 536 535 537 - dprintk("NFS: RECALL_ANY callback request from %s\n", 536 + dprintk_rcu("NFS: RECALL_ANY callback request from %s\n", 538 537 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 539 538 540 539 status = cpu_to_be32(NFS4ERR_INVAL); ··· 569 568 if (!cps->clp) /* set in cb_sequence */ 570 569 goto out; 571 570 572 - dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", 571 + dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", 573 572 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), 574 573 args->crsa_target_max_slots); 575 574
+11 -5
fs/nfs/client.c
··· 1284 1284 int error; 1285 1285 1286 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 1291 if (nfs4_has_session(clp)) { 1288 - error = xprt_setup_backchannel( 1289 - clp->cl_rpcclient->cl_xprt, 1292 + error = xprt_setup_backchannel(xprt, 1290 1293 NFS41_BC_MIN_CALLBACKS); 1291 1294 if (error < 0) 1292 1295 return error; 1293 1296 } 1294 1297 1295 - error = nfs_callback_up(clp->cl_mvops->minor_version, 1296 - clp->cl_rpcclient->cl_xprt); 1298 + error = nfs_callback_up(clp->cl_mvops->minor_version, xprt); 1297 1299 if (error < 0) { 1298 1300 dprintk("%s: failed to start callback. Error = %d\n", 1299 1301 __func__, error); ··· 1680 1678 data->addrlen, 1681 1679 parent_client->cl_ipaddr, 1682 1680 data->authflavor, 1683 - parent_server->client->cl_xprt->prot, 1681 + rpc_protocol(parent_server->client), 1684 1682 parent_server->client->cl_timeout, 1685 1683 parent_client->cl_mvops->minor_version, 1686 1684 parent_client->net); ··· 1907 1905 if (clp->cl_cons_state != NFS_CS_READY) 1908 1906 return 0; 1909 1907 1908 + rcu_read_lock(); 1910 1909 seq_printf(m, "v%u %s %s %3d %s\n", 1911 1910 clp->rpc_ops->version, 1912 1911 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), 1913 1912 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), 1914 1913 atomic_read(&clp->cl_count), 1915 1914 clp->cl_hostname); 1915 + rcu_read_unlock(); 1916 1916 1917 1917 return 0; 1918 1918 } ··· 1997 1993 (unsigned long long) server->fsid.major, 1998 1994 (unsigned long long) server->fsid.minor); 1999 1995 1996 + rcu_read_lock(); 2000 1997 seq_printf(m, "v%u %s %s %-7s %-17s %s\n", 2001 1998 clp->rpc_ops->version, 2002 1999 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), ··· 2005 2000 dev, 2006 2001 fsid, 2007 2002 nfs_server_fscache_state(server)); 2003 + rcu_read_unlock(); 2008 2004 2009 2005 return 0; 2010 2006 }
+1 -1
fs/nfs/nfs4namespace.c
··· 96 96 static size_t nfs_parse_server_name(char *string, size_t len, 97 97 struct sockaddr *sa, size_t salen, struct nfs_server *server) 98 98 { 99 + struct net *net = rpc_net_ns(server->client); 99 100 ssize_t ret; 100 - struct net *net = server->client->cl_xprt->xprt_net; 101 101 102 102 ret = rpc_pton(net, string, len, sa, salen); 103 103 if (ret == 0) {
+10 -3
fs/nfs/nfs4proc.c
··· 3833 3833 *p = htonl((u32)clp->cl_boot_time.tv_nsec); 3834 3834 3835 3835 for(;;) { 3836 + rcu_read_lock(); 3836 3837 setclientid.sc_name_len = scnprintf(setclientid.sc_name, 3837 3838 sizeof(setclientid.sc_name), "%s/%s %s %s %u", 3838 3839 clp->cl_ipaddr, ··· 3850 3849 setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, 3851 3850 sizeof(setclientid.sc_uaddr), "%s.%u.%u", 3852 3851 clp->cl_ipaddr, port >> 8, port & 255); 3852 + rcu_read_unlock(); 3853 3853 3854 3854 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); 3855 3855 if (status != -NFS4ERR_CLID_INUSE) ··· 5246 5244 5247 5245 void nfs4_destroy_session(struct nfs4_session *session) 5248 5246 { 5247 + struct rpc_xprt *xprt; 5248 + 5249 5249 nfs4_proc_destroy_session(session); 5250 + 5251 + rcu_read_lock(); 5252 + xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); 5253 + rcu_read_unlock(); 5250 5254 dprintk("%s Destroy backchannel for xprt %p\n", 5251 - __func__, session->clp->cl_rpcclient->cl_xprt); 5252 - xprt_destroy_backchannel(session->clp->cl_rpcclient->cl_xprt, 5253 - NFS41_BC_MIN_CALLBACKS); 5255 + __func__, xprt); 5256 + xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); 5254 5257 nfs4_destroy_slot_tables(session); 5255 5258 kfree(session); 5256 5259 }
+17 -8
fs/nfs/nfs4state.c
··· 1037 1037 void nfs4_schedule_state_manager(struct nfs_client *clp) 1038 1038 { 1039 1039 struct task_struct *task; 1040 + char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; 1040 1041 1041 1042 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) 1042 1043 return; 1043 1044 __module_get(THIS_MODULE); 1044 1045 atomic_inc(&clp->cl_count); 1045 - task = kthread_run(nfs4_run_state_manager, clp, "%s-manager", 1046 - rpc_peeraddr2str(clp->cl_rpcclient, 1047 - RPC_DISPLAY_ADDR)); 1048 - if (!IS_ERR(task)) 1049 - return; 1050 - nfs4_clear_state_manager_bit(clp); 1051 - nfs_put_client(clp); 1052 - module_put(THIS_MODULE); 1046 + 1047 + /* The rcu_read_lock() is not strictly necessary, as the state 1048 + * manager is the only thread that ever changes the rpc_xprt 1049 + * after it's initialized. At this point, we're single threaded. */ 1050 + rcu_read_lock(); 1051 + snprintf(buf, sizeof(buf), "%s-manager", 1052 + rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 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 /*
+5
fs/nfs/super.c
··· 53 53 #include <linux/magic.h> 54 54 #include <linux/parser.h> 55 55 #include <linux/nsproxy.h> 56 + #include <linux/rcupdate.h> 56 57 57 58 #include <asm/system.h> 58 59 #include <asm/uaccess.h> ··· 702 701 else 703 702 seq_puts(m, nfs_infop->nostr); 704 703 } 704 + rcu_read_lock(); 705 705 seq_printf(m, ",proto=%s", 706 706 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID)); 707 + rcu_read_unlock(); 707 708 if (version == 4) { 708 709 if (nfss->port != NFS_PORT) 709 710 seq_printf(m, ",port=%u", nfss->port); ··· 754 751 755 752 nfs_show_mount_options(m, nfss, 0); 756 753 754 + rcu_read_lock(); 757 755 seq_printf(m, ",addr=%s", 758 756 rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient, 759 757 RPC_DISPLAY_ADDR)); 758 + rcu_read_unlock(); 760 759 761 760 return 0; 762 761 }
+3 -1
include/linux/sunrpc/clnt.h
··· 35 35 struct list_head cl_clients; /* Global list of clients */ 36 36 struct list_head cl_tasks; /* List of tasks */ 37 37 spinlock_t cl_lock; /* spinlock */ 38 - struct rpc_xprt * cl_xprt; /* transport */ 38 + struct rpc_xprt __rcu * cl_xprt; /* transport */ 39 39 struct rpc_procinfo * cl_procinfo; /* procedure info */ 40 40 u32 cl_prog, /* RPC program number */ 41 41 cl_vers, /* RPC version number */ ··· 156 156 int rpc_restart_call_prepare(struct rpc_task *); 157 157 int rpc_restart_call(struct rpc_task *); 158 158 void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); 159 + int rpc_protocol(struct rpc_clnt *); 160 + struct net * rpc_net_ns(struct rpc_clnt *); 159 161 size_t rpc_max_payload(struct rpc_clnt *); 160 162 void rpc_force_rebind(struct rpc_clnt *); 161 163 size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
+13
include/linux/sunrpc/debug.h
··· 50 50 #endif 51 51 52 52 #define dprintk(args...) dfprintk(FACILITY, ## args) 53 + #define dprintk_rcu(args...) dfprintk_rcu(FACILITY, ## args) 53 54 54 55 #undef ifdebug 55 56 #ifdef RPC_DEBUG 56 57 # define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac)) 58 + 57 59 # define dfprintk(fac, args...) \ 58 60 do { \ 59 61 ifdebug(fac) \ 60 62 printk(KERN_DEFAULT args); \ 61 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 74 # define RPC_IFDEBUG(x) x 63 75 #else 64 76 # define ifdebug(fac) if (0) 65 77 # define dfprintk(fac, args...) do ; while (0) 78 + # define dfprintk_rcu(fac, args...) do ; while (0) 66 79 # define RPC_IFDEBUG(x) 67 80 #endif 68 81
+2 -2
net/sunrpc/auth_gss/auth_gss.c
··· 799 799 static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, 800 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 803 struct super_block *sb; 804 804 805 805 sb = rpc_get_sb_net(net); ··· 813 813 static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, 814 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 817 struct super_block *sb; 818 818 int err = 0; 819 819
+89 -21
net/sunrpc/clnt.c
··· 31 31 #include <linux/in.h> 32 32 #include <linux/in6.h> 33 33 #include <linux/un.h> 34 + #include <linux/rcupdate.h> 34 35 35 36 #include <linux/sunrpc/clnt.h> 36 37 #include <linux/sunrpc/rpc_pipe_fs.h> ··· 82 81 83 82 static void rpc_register_client(struct rpc_clnt *clnt) 84 83 { 85 - struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); 84 + struct net *net = rpc_net_ns(clnt); 85 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 86 86 87 87 spin_lock(&sn->rpc_client_lock); 88 88 list_add(&clnt->cl_clients, &sn->all_clients); ··· 92 90 93 91 static void rpc_unregister_client(struct rpc_clnt *clnt) 94 92 { 95 - struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); 93 + struct net *net = rpc_net_ns(clnt); 94 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 96 95 97 96 spin_lock(&sn->rpc_client_lock); 98 97 list_del(&clnt->cl_clients); ··· 112 109 113 110 static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) 114 111 { 112 + struct net *net = rpc_net_ns(clnt); 115 113 struct super_block *pipefs_sb; 116 114 117 - pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); 115 + pipefs_sb = rpc_get_sb_net(net); 118 116 if (pipefs_sb) { 119 117 __rpc_clnt_remove_pipedir(clnt); 120 - rpc_put_sb_net(clnt->cl_xprt->xprt_net); 118 + rpc_put_sb_net(net); 121 119 } 122 120 } 123 121 ··· 159 155 static int 160 156 rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) 161 157 { 158 + struct net *net = rpc_net_ns(clnt); 162 159 struct super_block *pipefs_sb; 163 160 struct dentry *dentry; 164 161 165 162 clnt->cl_dentry = NULL; 166 163 if (dir_name == NULL) 167 164 return 0; 168 - pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); 165 + pipefs_sb = rpc_get_sb_net(net); 169 166 if (!pipefs_sb) 170 167 return 0; 171 168 dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); 172 - rpc_put_sb_net(clnt->cl_xprt->xprt_net); 169 + rpc_put_sb_net(net); 173 170 if (IS_ERR(dentry)) 174 171 return PTR_ERR(dentry); 175 172 clnt->cl_dentry = dentry; ··· 300 295 if (clnt->cl_server == NULL) 301 296 goto out_no_server; 302 297 303 - clnt->cl_xprt = xprt; 298 + rcu_assign_pointer(clnt->cl_xprt, xprt); 304 299 clnt->cl_procinfo = version->procs; 305 300 clnt->cl_maxproc = version->nrprocs; 306 301 clnt->cl_protname = program->name; ··· 315 310 INIT_LIST_HEAD(&clnt->cl_tasks); 316 311 spin_lock_init(&clnt->cl_lock); 317 312 318 - if (!xprt_bound(clnt->cl_xprt)) 313 + if (!xprt_bound(xprt)) 319 314 clnt->cl_autobind = 1; 320 315 321 316 clnt->cl_timeout = xprt->timeout; ··· 482 477 rpc_clone_client(struct rpc_clnt *clnt) 483 478 { 484 479 struct rpc_clnt *new; 480 + struct rpc_xprt *xprt; 485 481 int err = -ENOMEM; 486 482 487 483 new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); ··· 505 499 if (new->cl_principal == NULL) 506 500 goto out_no_principal; 507 501 } 502 + rcu_read_lock(); 503 + xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); 504 + rcu_read_unlock(); 505 + if (xprt == NULL) 506 + goto out_no_transport; 507 + rcu_assign_pointer(new->cl_xprt, xprt); 508 508 atomic_set(&new->cl_count, 1); 509 509 err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); 510 510 if (err != 0) 511 511 goto out_no_path; 512 512 if (new->cl_auth) 513 513 atomic_inc(&new->cl_auth->au_count); 514 - xprt_get(clnt->cl_xprt); 515 514 atomic_inc(&clnt->cl_count); 516 515 rpc_register_client(new); 517 516 rpciod_up(); 518 517 return new; 519 518 out_no_path: 519 + xprt_put(xprt); 520 + out_no_transport: 520 521 kfree(new->cl_principal); 521 522 out_no_principal: 522 523 rpc_free_iostats(new->cl_metrics); ··· 603 590 rpc_free_iostats(clnt->cl_metrics); 604 591 kfree(clnt->cl_principal); 605 592 clnt->cl_metrics = NULL; 606 - xprt_put(clnt->cl_xprt); 593 + xprt_put(rcu_dereference_raw(clnt->cl_xprt)); 607 594 rpciod_down(); 608 595 kfree(clnt); 609 596 } ··· 892 879 size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) 893 880 { 894 881 size_t bytes; 895 - struct rpc_xprt *xprt = clnt->cl_xprt; 882 + struct rpc_xprt *xprt; 896 883 897 - bytes = sizeof(xprt->addr); 884 + rcu_read_lock(); 885 + xprt = rcu_dereference(clnt->cl_xprt); 886 + 887 + bytes = xprt->addrlen; 898 888 if (bytes > bufsize) 899 889 bytes = bufsize; 900 - memcpy(buf, &clnt->cl_xprt->addr, bytes); 901 - return xprt->addrlen; 890 + memcpy(buf, &xprt->addr, bytes); 891 + rcu_read_unlock(); 892 + 893 + return bytes; 902 894 } 903 895 EXPORT_SYMBOL_GPL(rpc_peeraddr); 904 896 ··· 912 894 * @clnt: RPC client structure 913 895 * @format: address format 914 896 * 897 + * NB: the lifetime of the memory referenced by the returned pointer is 898 + * the same as the rpc_xprt itself. As long as the caller uses this 899 + * pointer, it must hold the RCU read lock. 915 900 */ 916 901 const char *rpc_peeraddr2str(struct rpc_clnt *clnt, 917 902 enum rpc_display_format_t format) 918 903 { 919 - struct rpc_xprt *xprt = clnt->cl_xprt; 904 + struct rpc_xprt *xprt; 905 + 906 + xprt = rcu_dereference(clnt->cl_xprt); 920 907 921 908 if (xprt->address_strings[format] != NULL) 922 909 return xprt->address_strings[format]; ··· 933 910 void 934 911 rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) 935 912 { 936 - struct rpc_xprt *xprt = clnt->cl_xprt; 913 + struct rpc_xprt *xprt; 914 + 915 + rcu_read_lock(); 916 + xprt = rcu_dereference(clnt->cl_xprt); 937 917 if (xprt->ops->set_buffer_size) 938 918 xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); 919 + rcu_read_unlock(); 939 920 } 940 921 EXPORT_SYMBOL_GPL(rpc_setbufsize); 941 922 942 - /* 943 - * Return size of largest payload RPC client can support, in bytes 923 + /** 924 + * rpc_protocol - Get transport protocol number for an RPC client 925 + * @clnt: RPC client to query 926 + * 927 + */ 928 + int rpc_protocol(struct rpc_clnt *clnt) 929 + { 930 + int protocol; 931 + 932 + rcu_read_lock(); 933 + protocol = rcu_dereference(clnt->cl_xprt)->prot; 934 + rcu_read_unlock(); 935 + return protocol; 936 + } 937 + EXPORT_SYMBOL_GPL(rpc_protocol); 938 + 939 + /** 940 + * rpc_net_ns - Get the network namespace for this RPC client 941 + * @clnt: RPC client to query 942 + * 943 + */ 944 + struct net *rpc_net_ns(struct rpc_clnt *clnt) 945 + { 946 + struct net *ret; 947 + 948 + rcu_read_lock(); 949 + ret = rcu_dereference(clnt->cl_xprt)->xprt_net; 950 + rcu_read_unlock(); 951 + return ret; 952 + } 953 + EXPORT_SYMBOL_GPL(rpc_net_ns); 954 + 955 + /** 956 + * rpc_max_payload - Get maximum payload size for a transport, in bytes 957 + * @clnt: RPC client to query 944 958 * 945 959 * For stream transports, this is one RPC record fragment (see RFC 946 960 * 1831), as we don't support multi-record requests yet. For datagram ··· 986 926 */ 987 927 size_t rpc_max_payload(struct rpc_clnt *clnt) 988 928 { 989 - return clnt->cl_xprt->max_payload; 929 + size_t ret; 930 + 931 + rcu_read_lock(); 932 + ret = rcu_dereference(clnt->cl_xprt)->max_payload; 933 + rcu_read_unlock(); 934 + return ret; 990 935 } 991 936 EXPORT_SYMBOL_GPL(rpc_max_payload); 992 937 ··· 1002 937 */ 1003 938 void rpc_force_rebind(struct rpc_clnt *clnt) 1004 939 { 1005 - if (clnt->cl_autobind) 1006 - xprt_clear_bound(clnt->cl_xprt); 940 + if (clnt->cl_autobind) { 941 + rcu_read_lock(); 942 + xprt_clear_bound(rcu_dereference(clnt->cl_xprt)); 943 + rcu_read_unlock(); 944 + } 1007 945 } 1008 946 EXPORT_SYMBOL_GPL(rpc_force_rebind); 1009 947
+3
net/sunrpc/rpc_pipe.c
··· 16 16 #include <linux/namei.h> 17 17 #include <linux/fsnotify.h> 18 18 #include <linux/kernel.h> 19 + #include <linux/rcupdate.h> 19 20 20 21 #include <asm/ioctls.h> 21 22 #include <linux/poll.h> ··· 403 402 { 404 403 struct rpc_clnt *clnt = m->private; 405 404 405 + rcu_read_lock(); 406 406 seq_printf(m, "RPC server: %s\n", clnt->cl_server); 407 407 seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, 408 408 clnt->cl_prog, clnt->cl_vers); 409 409 seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); 410 410 seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); 411 411 seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); 412 + rcu_read_unlock(); 412 413 return 0; 413 414 } 414 415
+11 -4
net/sunrpc/rpcb_clnt.c
··· 620 620 static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) 621 621 { 622 622 struct rpc_clnt *parent = clnt->cl_parent; 623 + struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt); 623 624 624 625 while (parent != clnt) { 625 - if (parent->cl_xprt != clnt->cl_xprt) 626 + if (rcu_dereference(parent->cl_xprt) != xprt) 626 627 break; 627 628 if (clnt->cl_autobind) 628 629 break; ··· 654 653 size_t salen; 655 654 int status; 656 655 657 - clnt = rpcb_find_transport_owner(task->tk_client); 658 - xprt = clnt->cl_xprt; 656 + rcu_read_lock(); 657 + do { 658 + clnt = rpcb_find_transport_owner(task->tk_client); 659 + xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); 660 + } while (xprt == NULL); 661 + rcu_read_unlock(); 659 662 660 663 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", 661 664 task->tk_pid, __func__, ··· 672 667 if (xprt_test_and_set_binding(xprt)) { 673 668 dprintk("RPC: %5u %s: waiting for another binder\n", 674 669 task->tk_pid, __func__); 670 + xprt_put(xprt); 675 671 return; 676 672 } 677 673 ··· 740 734 switch (bind_version) { 741 735 case RPCBVERS_4: 742 736 case RPCBVERS_3: 743 - map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); 737 + map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID]; 744 738 map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); 745 739 map->r_owner = ""; 746 740 break; ··· 769 763 bailout_nofree: 770 764 rpcb_wake_rpcbind_waiters(xprt, status); 771 765 task->tk_status = status; 766 + xprt_put(xprt); 772 767 } 773 768 EXPORT_SYMBOL_GPL(rpcb_getport_async); 774 769
+5 -1
net/sunrpc/stats.c
··· 22 22 #include <linux/sunrpc/clnt.h> 23 23 #include <linux/sunrpc/svcsock.h> 24 24 #include <linux/sunrpc/metrics.h> 25 + #include <linux/rcupdate.h> 25 26 26 27 #include "netns.h" 27 28 ··· 180 179 void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) 181 180 { 182 181 struct rpc_iostats *stats = clnt->cl_metrics; 183 - struct rpc_xprt *xprt = clnt->cl_xprt; 182 + struct rpc_xprt *xprt; 184 183 unsigned int op, maxproc = clnt->cl_maxproc; 185 184 186 185 if (!stats) ··· 190 189 seq_printf(seq, "p/v: %u/%u (%s)\n", 191 190 clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); 192 191 192 + rcu_read_lock(); 193 + xprt = rcu_dereference(clnt->cl_xprt); 193 194 if (xprt) 194 195 xprt->ops->print_stats(xprt, seq); 196 + rcu_read_unlock(); 195 197 196 198 seq_printf(seq, "\tper-op statistics\n"); 197 199 for (op = 0; op < maxproc; op++) {