1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/net/sunrpc/clnt.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This file contains the high-level RPC interface.
6*4882a593Smuzhiyun * It is modeled as a finite state machine to support both synchronous
7*4882a593Smuzhiyun * and asynchronous requests.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * - RPC header generation and argument serialization.
10*4882a593Smuzhiyun * - Credential refresh.
11*4882a593Smuzhiyun * - TCP connect handling.
12*4882a593Smuzhiyun * - Retry of operation when it is suspected the operation failed because
13*4882a593Smuzhiyun * of uid squashing on the server, or when the credentials were stale
14*4882a593Smuzhiyun * and need to be refreshed, or when a packet was damaged in transit.
15*4882a593Smuzhiyun * This may be have to be moved to the VFS layer.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com>
18*4882a593Smuzhiyun * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
19*4882a593Smuzhiyun */
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <linux/module.h>
23*4882a593Smuzhiyun #include <linux/types.h>
24*4882a593Smuzhiyun #include <linux/kallsyms.h>
25*4882a593Smuzhiyun #include <linux/mm.h>
26*4882a593Smuzhiyun #include <linux/namei.h>
27*4882a593Smuzhiyun #include <linux/mount.h>
28*4882a593Smuzhiyun #include <linux/slab.h>
29*4882a593Smuzhiyun #include <linux/rcupdate.h>
30*4882a593Smuzhiyun #include <linux/utsname.h>
31*4882a593Smuzhiyun #include <linux/workqueue.h>
32*4882a593Smuzhiyun #include <linux/in.h>
33*4882a593Smuzhiyun #include <linux/in6.h>
34*4882a593Smuzhiyun #include <linux/un.h>
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <linux/sunrpc/clnt.h>
37*4882a593Smuzhiyun #include <linux/sunrpc/addr.h>
38*4882a593Smuzhiyun #include <linux/sunrpc/rpc_pipe_fs.h>
39*4882a593Smuzhiyun #include <linux/sunrpc/metrics.h>
40*4882a593Smuzhiyun #include <linux/sunrpc/bc_xprt.h>
41*4882a593Smuzhiyun #include <trace/events/sunrpc.h>
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #include "sunrpc.h"
44*4882a593Smuzhiyun #include "netns.h"
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
47*4882a593Smuzhiyun # define RPCDBG_FACILITY RPCDBG_CALL
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * All RPC clients are linked into this list
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun static void call_start(struct rpc_task *task);
58*4882a593Smuzhiyun static void call_reserve(struct rpc_task *task);
59*4882a593Smuzhiyun static void call_reserveresult(struct rpc_task *task);
60*4882a593Smuzhiyun static void call_allocate(struct rpc_task *task);
61*4882a593Smuzhiyun static void call_encode(struct rpc_task *task);
62*4882a593Smuzhiyun static void call_decode(struct rpc_task *task);
63*4882a593Smuzhiyun static void call_bind(struct rpc_task *task);
64*4882a593Smuzhiyun static void call_bind_status(struct rpc_task *task);
65*4882a593Smuzhiyun static void call_transmit(struct rpc_task *task);
66*4882a593Smuzhiyun static void call_status(struct rpc_task *task);
67*4882a593Smuzhiyun static void call_transmit_status(struct rpc_task *task);
68*4882a593Smuzhiyun static void call_refresh(struct rpc_task *task);
69*4882a593Smuzhiyun static void call_refreshresult(struct rpc_task *task);
70*4882a593Smuzhiyun static void call_connect(struct rpc_task *task);
71*4882a593Smuzhiyun static void call_connect_status(struct rpc_task *task);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static int rpc_encode_header(struct rpc_task *task,
74*4882a593Smuzhiyun struct xdr_stream *xdr);
75*4882a593Smuzhiyun static int rpc_decode_header(struct rpc_task *task,
76*4882a593Smuzhiyun struct xdr_stream *xdr);
77*4882a593Smuzhiyun static int rpc_ping(struct rpc_clnt *clnt);
78*4882a593Smuzhiyun static void rpc_check_timeout(struct rpc_task *task);
79*4882a593Smuzhiyun
rpc_register_client(struct rpc_clnt * clnt)80*4882a593Smuzhiyun static void rpc_register_client(struct rpc_clnt *clnt)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun struct net *net = rpc_net_ns(clnt);
83*4882a593Smuzhiyun struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun spin_lock(&sn->rpc_client_lock);
86*4882a593Smuzhiyun list_add(&clnt->cl_clients, &sn->all_clients);
87*4882a593Smuzhiyun spin_unlock(&sn->rpc_client_lock);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
rpc_unregister_client(struct rpc_clnt * clnt)90*4882a593Smuzhiyun static void rpc_unregister_client(struct rpc_clnt *clnt)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun struct net *net = rpc_net_ns(clnt);
93*4882a593Smuzhiyun struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun spin_lock(&sn->rpc_client_lock);
96*4882a593Smuzhiyun list_del(&clnt->cl_clients);
97*4882a593Smuzhiyun spin_unlock(&sn->rpc_client_lock);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
__rpc_clnt_remove_pipedir(struct rpc_clnt * clnt)100*4882a593Smuzhiyun static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun rpc_remove_client_dir(clnt);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
rpc_clnt_remove_pipedir(struct rpc_clnt * clnt)105*4882a593Smuzhiyun static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct net *net = rpc_net_ns(clnt);
108*4882a593Smuzhiyun struct super_block *pipefs_sb;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun pipefs_sb = rpc_get_sb_net(net);
111*4882a593Smuzhiyun if (pipefs_sb) {
112*4882a593Smuzhiyun __rpc_clnt_remove_pipedir(clnt);
113*4882a593Smuzhiyun rpc_put_sb_net(net);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
rpc_setup_pipedir_sb(struct super_block * sb,struct rpc_clnt * clnt)117*4882a593Smuzhiyun static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
118*4882a593Smuzhiyun struct rpc_clnt *clnt)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun static uint32_t clntid;
121*4882a593Smuzhiyun const char *dir_name = clnt->cl_program->pipe_dir_name;
122*4882a593Smuzhiyun char name[15];
123*4882a593Smuzhiyun struct dentry *dir, *dentry;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun dir = rpc_d_lookup_sb(sb, dir_name);
126*4882a593Smuzhiyun if (dir == NULL) {
127*4882a593Smuzhiyun pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name);
128*4882a593Smuzhiyun return dir;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun for (;;) {
131*4882a593Smuzhiyun snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
132*4882a593Smuzhiyun name[sizeof(name) - 1] = '\0';
133*4882a593Smuzhiyun dentry = rpc_create_client_dir(dir, name, clnt);
134*4882a593Smuzhiyun if (!IS_ERR(dentry))
135*4882a593Smuzhiyun break;
136*4882a593Smuzhiyun if (dentry == ERR_PTR(-EEXIST))
137*4882a593Smuzhiyun continue;
138*4882a593Smuzhiyun printk(KERN_INFO "RPC: Couldn't create pipefs entry"
139*4882a593Smuzhiyun " %s/%s, error %ld\n",
140*4882a593Smuzhiyun dir_name, name, PTR_ERR(dentry));
141*4882a593Smuzhiyun break;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun dput(dir);
144*4882a593Smuzhiyun return dentry;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun static int
rpc_setup_pipedir(struct super_block * pipefs_sb,struct rpc_clnt * clnt)148*4882a593Smuzhiyun rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct dentry *dentry;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (clnt->cl_program->pipe_dir_name != NULL) {
153*4882a593Smuzhiyun dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt);
154*4882a593Smuzhiyun if (IS_ERR(dentry))
155*4882a593Smuzhiyun return PTR_ERR(dentry);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
rpc_clnt_skip_event(struct rpc_clnt * clnt,unsigned long event)160*4882a593Smuzhiyun static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun if (clnt->cl_program->pipe_dir_name == NULL)
163*4882a593Smuzhiyun return 1;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun switch (event) {
166*4882a593Smuzhiyun case RPC_PIPEFS_MOUNT:
167*4882a593Smuzhiyun if (clnt->cl_pipedir_objects.pdh_dentry != NULL)
168*4882a593Smuzhiyun return 1;
169*4882a593Smuzhiyun if (atomic_read(&clnt->cl_count) == 0)
170*4882a593Smuzhiyun return 1;
171*4882a593Smuzhiyun break;
172*4882a593Smuzhiyun case RPC_PIPEFS_UMOUNT:
173*4882a593Smuzhiyun if (clnt->cl_pipedir_objects.pdh_dentry == NULL)
174*4882a593Smuzhiyun return 1;
175*4882a593Smuzhiyun break;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun return 0;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
__rpc_clnt_handle_event(struct rpc_clnt * clnt,unsigned long event,struct super_block * sb)180*4882a593Smuzhiyun static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
181*4882a593Smuzhiyun struct super_block *sb)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun struct dentry *dentry;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun switch (event) {
186*4882a593Smuzhiyun case RPC_PIPEFS_MOUNT:
187*4882a593Smuzhiyun dentry = rpc_setup_pipedir_sb(sb, clnt);
188*4882a593Smuzhiyun if (!dentry)
189*4882a593Smuzhiyun return -ENOENT;
190*4882a593Smuzhiyun if (IS_ERR(dentry))
191*4882a593Smuzhiyun return PTR_ERR(dentry);
192*4882a593Smuzhiyun break;
193*4882a593Smuzhiyun case RPC_PIPEFS_UMOUNT:
194*4882a593Smuzhiyun __rpc_clnt_remove_pipedir(clnt);
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun default:
197*4882a593Smuzhiyun printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event);
198*4882a593Smuzhiyun return -ENOTSUPP;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
__rpc_pipefs_event(struct rpc_clnt * clnt,unsigned long event,struct super_block * sb)203*4882a593Smuzhiyun static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
204*4882a593Smuzhiyun struct super_block *sb)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun int error = 0;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun for (;; clnt = clnt->cl_parent) {
209*4882a593Smuzhiyun if (!rpc_clnt_skip_event(clnt, event))
210*4882a593Smuzhiyun error = __rpc_clnt_handle_event(clnt, event, sb);
211*4882a593Smuzhiyun if (error || clnt == clnt->cl_parent)
212*4882a593Smuzhiyun break;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun return error;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
rpc_get_client_for_event(struct net * net,int event)217*4882a593Smuzhiyun static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
220*4882a593Smuzhiyun struct rpc_clnt *clnt;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun spin_lock(&sn->rpc_client_lock);
223*4882a593Smuzhiyun list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
224*4882a593Smuzhiyun if (rpc_clnt_skip_event(clnt, event))
225*4882a593Smuzhiyun continue;
226*4882a593Smuzhiyun spin_unlock(&sn->rpc_client_lock);
227*4882a593Smuzhiyun return clnt;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun spin_unlock(&sn->rpc_client_lock);
230*4882a593Smuzhiyun return NULL;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
rpc_pipefs_event(struct notifier_block * nb,unsigned long event,void * ptr)233*4882a593Smuzhiyun static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
234*4882a593Smuzhiyun void *ptr)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct super_block *sb = ptr;
237*4882a593Smuzhiyun struct rpc_clnt *clnt;
238*4882a593Smuzhiyun int error = 0;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) {
241*4882a593Smuzhiyun error = __rpc_pipefs_event(clnt, event, sb);
242*4882a593Smuzhiyun if (error)
243*4882a593Smuzhiyun break;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun return error;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun static struct notifier_block rpc_clients_block = {
249*4882a593Smuzhiyun .notifier_call = rpc_pipefs_event,
250*4882a593Smuzhiyun .priority = SUNRPC_PIPEFS_RPC_PRIO,
251*4882a593Smuzhiyun };
252*4882a593Smuzhiyun
rpc_clients_notifier_register(void)253*4882a593Smuzhiyun int rpc_clients_notifier_register(void)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun return rpc_pipefs_notifier_register(&rpc_clients_block);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
rpc_clients_notifier_unregister(void)258*4882a593Smuzhiyun void rpc_clients_notifier_unregister(void)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun return rpc_pipefs_notifier_unregister(&rpc_clients_block);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
rpc_clnt_set_transport(struct rpc_clnt * clnt,struct rpc_xprt * xprt,const struct rpc_timeout * timeout)263*4882a593Smuzhiyun static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
264*4882a593Smuzhiyun struct rpc_xprt *xprt,
265*4882a593Smuzhiyun const struct rpc_timeout *timeout)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun struct rpc_xprt *old;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun spin_lock(&clnt->cl_lock);
270*4882a593Smuzhiyun old = rcu_dereference_protected(clnt->cl_xprt,
271*4882a593Smuzhiyun lockdep_is_held(&clnt->cl_lock));
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun if (!xprt_bound(xprt))
274*4882a593Smuzhiyun clnt->cl_autobind = 1;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun clnt->cl_timeout = timeout;
277*4882a593Smuzhiyun rcu_assign_pointer(clnt->cl_xprt, xprt);
278*4882a593Smuzhiyun spin_unlock(&clnt->cl_lock);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return old;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
rpc_clnt_set_nodename(struct rpc_clnt * clnt,const char * nodename)283*4882a593Smuzhiyun static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
286*4882a593Smuzhiyun nodename, sizeof(clnt->cl_nodename));
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
rpc_client_register(struct rpc_clnt * clnt,rpc_authflavor_t pseudoflavor,const char * client_name)289*4882a593Smuzhiyun static int rpc_client_register(struct rpc_clnt *clnt,
290*4882a593Smuzhiyun rpc_authflavor_t pseudoflavor,
291*4882a593Smuzhiyun const char *client_name)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun struct rpc_auth_create_args auth_args = {
294*4882a593Smuzhiyun .pseudoflavor = pseudoflavor,
295*4882a593Smuzhiyun .target_name = client_name,
296*4882a593Smuzhiyun };
297*4882a593Smuzhiyun struct rpc_auth *auth;
298*4882a593Smuzhiyun struct net *net = rpc_net_ns(clnt);
299*4882a593Smuzhiyun struct super_block *pipefs_sb;
300*4882a593Smuzhiyun int err;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun rpc_clnt_debugfs_register(clnt);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun pipefs_sb = rpc_get_sb_net(net);
305*4882a593Smuzhiyun if (pipefs_sb) {
306*4882a593Smuzhiyun err = rpc_setup_pipedir(pipefs_sb, clnt);
307*4882a593Smuzhiyun if (err)
308*4882a593Smuzhiyun goto out;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun rpc_register_client(clnt);
312*4882a593Smuzhiyun if (pipefs_sb)
313*4882a593Smuzhiyun rpc_put_sb_net(net);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun auth = rpcauth_create(&auth_args, clnt);
316*4882a593Smuzhiyun if (IS_ERR(auth)) {
317*4882a593Smuzhiyun dprintk("RPC: Couldn't create auth handle (flavor %u)\n",
318*4882a593Smuzhiyun pseudoflavor);
319*4882a593Smuzhiyun err = PTR_ERR(auth);
320*4882a593Smuzhiyun goto err_auth;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun return 0;
323*4882a593Smuzhiyun err_auth:
324*4882a593Smuzhiyun pipefs_sb = rpc_get_sb_net(net);
325*4882a593Smuzhiyun rpc_unregister_client(clnt);
326*4882a593Smuzhiyun __rpc_clnt_remove_pipedir(clnt);
327*4882a593Smuzhiyun out:
328*4882a593Smuzhiyun if (pipefs_sb)
329*4882a593Smuzhiyun rpc_put_sb_net(net);
330*4882a593Smuzhiyun rpc_clnt_debugfs_unregister(clnt);
331*4882a593Smuzhiyun return err;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun static DEFINE_IDA(rpc_clids);
335*4882a593Smuzhiyun
rpc_cleanup_clids(void)336*4882a593Smuzhiyun void rpc_cleanup_clids(void)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun ida_destroy(&rpc_clids);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
rpc_alloc_clid(struct rpc_clnt * clnt)341*4882a593Smuzhiyun static int rpc_alloc_clid(struct rpc_clnt *clnt)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun int clid;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun clid = ida_simple_get(&rpc_clids, 0, 0, GFP_KERNEL);
346*4882a593Smuzhiyun if (clid < 0)
347*4882a593Smuzhiyun return clid;
348*4882a593Smuzhiyun clnt->cl_clid = clid;
349*4882a593Smuzhiyun return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
rpc_free_clid(struct rpc_clnt * clnt)352*4882a593Smuzhiyun static void rpc_free_clid(struct rpc_clnt *clnt)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun ida_simple_remove(&rpc_clids, clnt->cl_clid);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
rpc_new_client(const struct rpc_create_args * args,struct rpc_xprt_switch * xps,struct rpc_xprt * xprt,struct rpc_clnt * parent)357*4882a593Smuzhiyun static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
358*4882a593Smuzhiyun struct rpc_xprt_switch *xps,
359*4882a593Smuzhiyun struct rpc_xprt *xprt,
360*4882a593Smuzhiyun struct rpc_clnt *parent)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun const struct rpc_program *program = args->program;
363*4882a593Smuzhiyun const struct rpc_version *version;
364*4882a593Smuzhiyun struct rpc_clnt *clnt = NULL;
365*4882a593Smuzhiyun const struct rpc_timeout *timeout;
366*4882a593Smuzhiyun const char *nodename = args->nodename;
367*4882a593Smuzhiyun int err;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun err = rpciod_up();
370*4882a593Smuzhiyun if (err)
371*4882a593Smuzhiyun goto out_no_rpciod;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun err = -EINVAL;
374*4882a593Smuzhiyun if (args->version >= program->nrvers)
375*4882a593Smuzhiyun goto out_err;
376*4882a593Smuzhiyun version = program->version[args->version];
377*4882a593Smuzhiyun if (version == NULL)
378*4882a593Smuzhiyun goto out_err;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun err = -ENOMEM;
381*4882a593Smuzhiyun clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
382*4882a593Smuzhiyun if (!clnt)
383*4882a593Smuzhiyun goto out_err;
384*4882a593Smuzhiyun clnt->cl_parent = parent ? : clnt;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun err = rpc_alloc_clid(clnt);
387*4882a593Smuzhiyun if (err)
388*4882a593Smuzhiyun goto out_no_clid;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun clnt->cl_cred = get_cred(args->cred);
391*4882a593Smuzhiyun clnt->cl_procinfo = version->procs;
392*4882a593Smuzhiyun clnt->cl_maxproc = version->nrprocs;
393*4882a593Smuzhiyun clnt->cl_prog = args->prognumber ? : program->number;
394*4882a593Smuzhiyun clnt->cl_vers = version->number;
395*4882a593Smuzhiyun clnt->cl_stats = program->stats;
396*4882a593Smuzhiyun clnt->cl_metrics = rpc_alloc_iostats(clnt);
397*4882a593Smuzhiyun rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
398*4882a593Smuzhiyun err = -ENOMEM;
399*4882a593Smuzhiyun if (clnt->cl_metrics == NULL)
400*4882a593Smuzhiyun goto out_no_stats;
401*4882a593Smuzhiyun clnt->cl_program = program;
402*4882a593Smuzhiyun INIT_LIST_HEAD(&clnt->cl_tasks);
403*4882a593Smuzhiyun spin_lock_init(&clnt->cl_lock);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun timeout = xprt->timeout;
406*4882a593Smuzhiyun if (args->timeout != NULL) {
407*4882a593Smuzhiyun memcpy(&clnt->cl_timeout_default, args->timeout,
408*4882a593Smuzhiyun sizeof(clnt->cl_timeout_default));
409*4882a593Smuzhiyun timeout = &clnt->cl_timeout_default;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun rpc_clnt_set_transport(clnt, xprt, timeout);
413*4882a593Smuzhiyun xprt_iter_init(&clnt->cl_xpi, xps);
414*4882a593Smuzhiyun xprt_switch_put(xps);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun clnt->cl_rtt = &clnt->cl_rtt_default;
417*4882a593Smuzhiyun rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun atomic_set(&clnt->cl_count, 1);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (nodename == NULL)
422*4882a593Smuzhiyun nodename = utsname()->nodename;
423*4882a593Smuzhiyun /* save the nodename */
424*4882a593Smuzhiyun rpc_clnt_set_nodename(clnt, nodename);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun err = rpc_client_register(clnt, args->authflavor, args->client_name);
427*4882a593Smuzhiyun if (err)
428*4882a593Smuzhiyun goto out_no_path;
429*4882a593Smuzhiyun if (parent)
430*4882a593Smuzhiyun atomic_inc(&parent->cl_count);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun trace_rpc_clnt_new(clnt, xprt, program->name, args->servername);
433*4882a593Smuzhiyun return clnt;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun out_no_path:
436*4882a593Smuzhiyun rpc_free_iostats(clnt->cl_metrics);
437*4882a593Smuzhiyun out_no_stats:
438*4882a593Smuzhiyun put_cred(clnt->cl_cred);
439*4882a593Smuzhiyun rpc_free_clid(clnt);
440*4882a593Smuzhiyun out_no_clid:
441*4882a593Smuzhiyun kfree(clnt);
442*4882a593Smuzhiyun out_err:
443*4882a593Smuzhiyun rpciod_down();
444*4882a593Smuzhiyun out_no_rpciod:
445*4882a593Smuzhiyun xprt_switch_put(xps);
446*4882a593Smuzhiyun xprt_put(xprt);
447*4882a593Smuzhiyun trace_rpc_clnt_new_err(program->name, args->servername, err);
448*4882a593Smuzhiyun return ERR_PTR(err);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
rpc_create_xprt(struct rpc_create_args * args,struct rpc_xprt * xprt)451*4882a593Smuzhiyun static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
452*4882a593Smuzhiyun struct rpc_xprt *xprt)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun struct rpc_clnt *clnt = NULL;
455*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) {
458*4882a593Smuzhiyun WARN_ON_ONCE(!(args->protocol & XPRT_TRANSPORT_BC));
459*4882a593Smuzhiyun xps = args->bc_xprt->xpt_bc_xps;
460*4882a593Smuzhiyun xprt_switch_get(xps);
461*4882a593Smuzhiyun } else {
462*4882a593Smuzhiyun xps = xprt_switch_alloc(xprt, GFP_KERNEL);
463*4882a593Smuzhiyun if (xps == NULL) {
464*4882a593Smuzhiyun xprt_put(xprt);
465*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun if (xprt->bc_xprt) {
468*4882a593Smuzhiyun xprt_switch_get(xps);
469*4882a593Smuzhiyun xprt->bc_xprt->xpt_bc_xps = xps;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun clnt = rpc_new_client(args, xps, xprt, NULL);
473*4882a593Smuzhiyun if (IS_ERR(clnt))
474*4882a593Smuzhiyun return clnt;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
477*4882a593Smuzhiyun int err = rpc_ping(clnt);
478*4882a593Smuzhiyun if (err != 0) {
479*4882a593Smuzhiyun rpc_shutdown_client(clnt);
480*4882a593Smuzhiyun return ERR_PTR(err);
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun clnt->cl_softrtry = 1;
485*4882a593Smuzhiyun if (args->flags & (RPC_CLNT_CREATE_HARDRTRY|RPC_CLNT_CREATE_SOFTERR)) {
486*4882a593Smuzhiyun clnt->cl_softrtry = 0;
487*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_SOFTERR)
488*4882a593Smuzhiyun clnt->cl_softerr = 1;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
492*4882a593Smuzhiyun clnt->cl_autobind = 1;
493*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT)
494*4882a593Smuzhiyun clnt->cl_noretranstimeo = 1;
495*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
496*4882a593Smuzhiyun clnt->cl_discrtry = 1;
497*4882a593Smuzhiyun if (!(args->flags & RPC_CLNT_CREATE_QUIET))
498*4882a593Smuzhiyun clnt->cl_chatty = 1;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun return clnt;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /**
504*4882a593Smuzhiyun * rpc_create - create an RPC client and transport with one call
505*4882a593Smuzhiyun * @args: rpc_clnt create argument structure
506*4882a593Smuzhiyun *
507*4882a593Smuzhiyun * Creates and initializes an RPC transport and an RPC client.
508*4882a593Smuzhiyun *
509*4882a593Smuzhiyun * It can ping the server in order to determine if it is up, and to see if
510*4882a593Smuzhiyun * it supports this program and version. RPC_CLNT_CREATE_NOPING disables
511*4882a593Smuzhiyun * this behavior so asynchronous tasks can also use rpc_create.
512*4882a593Smuzhiyun */
rpc_create(struct rpc_create_args * args)513*4882a593Smuzhiyun struct rpc_clnt *rpc_create(struct rpc_create_args *args)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun struct rpc_xprt *xprt;
516*4882a593Smuzhiyun struct xprt_create xprtargs = {
517*4882a593Smuzhiyun .net = args->net,
518*4882a593Smuzhiyun .ident = args->protocol,
519*4882a593Smuzhiyun .srcaddr = args->saddress,
520*4882a593Smuzhiyun .dstaddr = args->address,
521*4882a593Smuzhiyun .addrlen = args->addrsize,
522*4882a593Smuzhiyun .servername = args->servername,
523*4882a593Smuzhiyun .bc_xprt = args->bc_xprt,
524*4882a593Smuzhiyun };
525*4882a593Smuzhiyun char servername[48];
526*4882a593Smuzhiyun struct rpc_clnt *clnt;
527*4882a593Smuzhiyun int i;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (args->bc_xprt) {
530*4882a593Smuzhiyun WARN_ON_ONCE(!(args->protocol & XPRT_TRANSPORT_BC));
531*4882a593Smuzhiyun xprt = args->bc_xprt->xpt_bc_xprt;
532*4882a593Smuzhiyun if (xprt) {
533*4882a593Smuzhiyun xprt_get(xprt);
534*4882a593Smuzhiyun return rpc_create_xprt(args, xprt);
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
539*4882a593Smuzhiyun xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
540*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
541*4882a593Smuzhiyun xprtargs.flags |= XPRT_CREATE_NO_IDLE_TIMEOUT;
542*4882a593Smuzhiyun /*
543*4882a593Smuzhiyun * If the caller chooses not to specify a hostname, whip
544*4882a593Smuzhiyun * up a string representation of the passed-in address.
545*4882a593Smuzhiyun */
546*4882a593Smuzhiyun if (xprtargs.servername == NULL) {
547*4882a593Smuzhiyun struct sockaddr_un *sun =
548*4882a593Smuzhiyun (struct sockaddr_un *)args->address;
549*4882a593Smuzhiyun struct sockaddr_in *sin =
550*4882a593Smuzhiyun (struct sockaddr_in *)args->address;
551*4882a593Smuzhiyun struct sockaddr_in6 *sin6 =
552*4882a593Smuzhiyun (struct sockaddr_in6 *)args->address;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun servername[0] = '\0';
555*4882a593Smuzhiyun switch (args->address->sa_family) {
556*4882a593Smuzhiyun case AF_LOCAL:
557*4882a593Smuzhiyun snprintf(servername, sizeof(servername), "%s",
558*4882a593Smuzhiyun sun->sun_path);
559*4882a593Smuzhiyun break;
560*4882a593Smuzhiyun case AF_INET:
561*4882a593Smuzhiyun snprintf(servername, sizeof(servername), "%pI4",
562*4882a593Smuzhiyun &sin->sin_addr.s_addr);
563*4882a593Smuzhiyun break;
564*4882a593Smuzhiyun case AF_INET6:
565*4882a593Smuzhiyun snprintf(servername, sizeof(servername), "%pI6",
566*4882a593Smuzhiyun &sin6->sin6_addr);
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun default:
569*4882a593Smuzhiyun /* caller wants default server name, but
570*4882a593Smuzhiyun * address family isn't recognized. */
571*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun xprtargs.servername = servername;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun xprt = xprt_create_transport(&xprtargs);
577*4882a593Smuzhiyun if (IS_ERR(xprt))
578*4882a593Smuzhiyun return (struct rpc_clnt *)xprt;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /*
581*4882a593Smuzhiyun * By default, kernel RPC client connects from a reserved port.
582*4882a593Smuzhiyun * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
583*4882a593Smuzhiyun * but it is always enabled for rpciod, which handles the connect
584*4882a593Smuzhiyun * operation.
585*4882a593Smuzhiyun */
586*4882a593Smuzhiyun xprt->resvport = 1;
587*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
588*4882a593Smuzhiyun xprt->resvport = 0;
589*4882a593Smuzhiyun xprt->reuseport = 0;
590*4882a593Smuzhiyun if (args->flags & RPC_CLNT_CREATE_REUSEPORT)
591*4882a593Smuzhiyun xprt->reuseport = 1;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun clnt = rpc_create_xprt(args, xprt);
594*4882a593Smuzhiyun if (IS_ERR(clnt) || args->nconnect <= 1)
595*4882a593Smuzhiyun return clnt;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun for (i = 0; i < args->nconnect - 1; i++) {
598*4882a593Smuzhiyun if (rpc_clnt_add_xprt(clnt, &xprtargs, NULL, NULL) < 0)
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun return clnt;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_create);
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun /*
606*4882a593Smuzhiyun * This function clones the RPC client structure. It allows us to share the
607*4882a593Smuzhiyun * same transport while varying parameters such as the authentication
608*4882a593Smuzhiyun * flavour.
609*4882a593Smuzhiyun */
__rpc_clone_client(struct rpc_create_args * args,struct rpc_clnt * clnt)610*4882a593Smuzhiyun static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
611*4882a593Smuzhiyun struct rpc_clnt *clnt)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
614*4882a593Smuzhiyun struct rpc_xprt *xprt;
615*4882a593Smuzhiyun struct rpc_clnt *new;
616*4882a593Smuzhiyun int err;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun err = -ENOMEM;
619*4882a593Smuzhiyun rcu_read_lock();
620*4882a593Smuzhiyun xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
621*4882a593Smuzhiyun xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
622*4882a593Smuzhiyun rcu_read_unlock();
623*4882a593Smuzhiyun if (xprt == NULL || xps == NULL) {
624*4882a593Smuzhiyun xprt_put(xprt);
625*4882a593Smuzhiyun xprt_switch_put(xps);
626*4882a593Smuzhiyun goto out_err;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun args->servername = xprt->servername;
629*4882a593Smuzhiyun args->nodename = clnt->cl_nodename;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun new = rpc_new_client(args, xps, xprt, clnt);
632*4882a593Smuzhiyun if (IS_ERR(new))
633*4882a593Smuzhiyun return new;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /* Turn off autobind on clones */
636*4882a593Smuzhiyun new->cl_autobind = 0;
637*4882a593Smuzhiyun new->cl_softrtry = clnt->cl_softrtry;
638*4882a593Smuzhiyun new->cl_softerr = clnt->cl_softerr;
639*4882a593Smuzhiyun new->cl_noretranstimeo = clnt->cl_noretranstimeo;
640*4882a593Smuzhiyun new->cl_discrtry = clnt->cl_discrtry;
641*4882a593Smuzhiyun new->cl_chatty = clnt->cl_chatty;
642*4882a593Smuzhiyun new->cl_principal = clnt->cl_principal;
643*4882a593Smuzhiyun return new;
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun out_err:
646*4882a593Smuzhiyun trace_rpc_clnt_clone_err(clnt, err);
647*4882a593Smuzhiyun return ERR_PTR(err);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun /**
651*4882a593Smuzhiyun * rpc_clone_client - Clone an RPC client structure
652*4882a593Smuzhiyun *
653*4882a593Smuzhiyun * @clnt: RPC client whose parameters are copied
654*4882a593Smuzhiyun *
655*4882a593Smuzhiyun * Returns a fresh RPC client or an ERR_PTR.
656*4882a593Smuzhiyun */
rpc_clone_client(struct rpc_clnt * clnt)657*4882a593Smuzhiyun struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun struct rpc_create_args args = {
660*4882a593Smuzhiyun .program = clnt->cl_program,
661*4882a593Smuzhiyun .prognumber = clnt->cl_prog,
662*4882a593Smuzhiyun .version = clnt->cl_vers,
663*4882a593Smuzhiyun .authflavor = clnt->cl_auth->au_flavor,
664*4882a593Smuzhiyun .cred = clnt->cl_cred,
665*4882a593Smuzhiyun };
666*4882a593Smuzhiyun return __rpc_clone_client(&args, clnt);
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clone_client);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun /**
671*4882a593Smuzhiyun * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
672*4882a593Smuzhiyun *
673*4882a593Smuzhiyun * @clnt: RPC client whose parameters are copied
674*4882a593Smuzhiyun * @flavor: security flavor for new client
675*4882a593Smuzhiyun *
676*4882a593Smuzhiyun * Returns a fresh RPC client or an ERR_PTR.
677*4882a593Smuzhiyun */
678*4882a593Smuzhiyun struct rpc_clnt *
rpc_clone_client_set_auth(struct rpc_clnt * clnt,rpc_authflavor_t flavor)679*4882a593Smuzhiyun rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun struct rpc_create_args args = {
682*4882a593Smuzhiyun .program = clnt->cl_program,
683*4882a593Smuzhiyun .prognumber = clnt->cl_prog,
684*4882a593Smuzhiyun .version = clnt->cl_vers,
685*4882a593Smuzhiyun .authflavor = flavor,
686*4882a593Smuzhiyun .cred = clnt->cl_cred,
687*4882a593Smuzhiyun };
688*4882a593Smuzhiyun return __rpc_clone_client(&args, clnt);
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun /**
693*4882a593Smuzhiyun * rpc_switch_client_transport: switch the RPC transport on the fly
694*4882a593Smuzhiyun * @clnt: pointer to a struct rpc_clnt
695*4882a593Smuzhiyun * @args: pointer to the new transport arguments
696*4882a593Smuzhiyun * @timeout: pointer to the new timeout parameters
697*4882a593Smuzhiyun *
698*4882a593Smuzhiyun * This function allows the caller to switch the RPC transport for the
699*4882a593Smuzhiyun * rpc_clnt structure 'clnt' to allow it to connect to a mirrored NFS
700*4882a593Smuzhiyun * server, for instance. It assumes that the caller has ensured that
701*4882a593Smuzhiyun * there are no active RPC tasks by using some form of locking.
702*4882a593Smuzhiyun *
703*4882a593Smuzhiyun * Returns zero if "clnt" is now using the new xprt. Otherwise a
704*4882a593Smuzhiyun * negative errno is returned, and "clnt" continues to use the old
705*4882a593Smuzhiyun * xprt.
706*4882a593Smuzhiyun */
rpc_switch_client_transport(struct rpc_clnt * clnt,struct xprt_create * args,const struct rpc_timeout * timeout)707*4882a593Smuzhiyun int rpc_switch_client_transport(struct rpc_clnt *clnt,
708*4882a593Smuzhiyun struct xprt_create *args,
709*4882a593Smuzhiyun const struct rpc_timeout *timeout)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun const struct rpc_timeout *old_timeo;
712*4882a593Smuzhiyun rpc_authflavor_t pseudoflavor;
713*4882a593Smuzhiyun struct rpc_xprt_switch *xps, *oldxps;
714*4882a593Smuzhiyun struct rpc_xprt *xprt, *old;
715*4882a593Smuzhiyun struct rpc_clnt *parent;
716*4882a593Smuzhiyun int err;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun xprt = xprt_create_transport(args);
719*4882a593Smuzhiyun if (IS_ERR(xprt))
720*4882a593Smuzhiyun return PTR_ERR(xprt);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun xps = xprt_switch_alloc(xprt, GFP_KERNEL);
723*4882a593Smuzhiyun if (xps == NULL) {
724*4882a593Smuzhiyun xprt_put(xprt);
725*4882a593Smuzhiyun return -ENOMEM;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun pseudoflavor = clnt->cl_auth->au_flavor;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun old_timeo = clnt->cl_timeout;
731*4882a593Smuzhiyun old = rpc_clnt_set_transport(clnt, xprt, timeout);
732*4882a593Smuzhiyun oldxps = xprt_iter_xchg_switch(&clnt->cl_xpi, xps);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun rpc_unregister_client(clnt);
735*4882a593Smuzhiyun __rpc_clnt_remove_pipedir(clnt);
736*4882a593Smuzhiyun rpc_clnt_debugfs_unregister(clnt);
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun /*
739*4882a593Smuzhiyun * A new transport was created. "clnt" therefore
740*4882a593Smuzhiyun * becomes the root of a new cl_parent tree. clnt's
741*4882a593Smuzhiyun * children, if it has any, still point to the old xprt.
742*4882a593Smuzhiyun */
743*4882a593Smuzhiyun parent = clnt->cl_parent;
744*4882a593Smuzhiyun clnt->cl_parent = clnt;
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun /*
747*4882a593Smuzhiyun * The old rpc_auth cache cannot be re-used. GSS
748*4882a593Smuzhiyun * contexts in particular are between a single
749*4882a593Smuzhiyun * client and server.
750*4882a593Smuzhiyun */
751*4882a593Smuzhiyun err = rpc_client_register(clnt, pseudoflavor, NULL);
752*4882a593Smuzhiyun if (err)
753*4882a593Smuzhiyun goto out_revert;
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun synchronize_rcu();
756*4882a593Smuzhiyun if (parent != clnt)
757*4882a593Smuzhiyun rpc_release_client(parent);
758*4882a593Smuzhiyun xprt_switch_put(oldxps);
759*4882a593Smuzhiyun xprt_put(old);
760*4882a593Smuzhiyun trace_rpc_clnt_replace_xprt(clnt);
761*4882a593Smuzhiyun return 0;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun out_revert:
764*4882a593Smuzhiyun xps = xprt_iter_xchg_switch(&clnt->cl_xpi, oldxps);
765*4882a593Smuzhiyun rpc_clnt_set_transport(clnt, old, old_timeo);
766*4882a593Smuzhiyun clnt->cl_parent = parent;
767*4882a593Smuzhiyun rpc_client_register(clnt, pseudoflavor, NULL);
768*4882a593Smuzhiyun xprt_switch_put(xps);
769*4882a593Smuzhiyun xprt_put(xprt);
770*4882a593Smuzhiyun trace_rpc_clnt_replace_xprt_err(clnt);
771*4882a593Smuzhiyun return err;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_switch_client_transport);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun static
rpc_clnt_xprt_iter_init(struct rpc_clnt * clnt,struct rpc_xprt_iter * xpi)776*4882a593Smuzhiyun int rpc_clnt_xprt_iter_init(struct rpc_clnt *clnt, struct rpc_xprt_iter *xpi)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun rcu_read_lock();
781*4882a593Smuzhiyun xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
782*4882a593Smuzhiyun rcu_read_unlock();
783*4882a593Smuzhiyun if (xps == NULL)
784*4882a593Smuzhiyun return -EAGAIN;
785*4882a593Smuzhiyun xprt_iter_init_listall(xpi, xps);
786*4882a593Smuzhiyun xprt_switch_put(xps);
787*4882a593Smuzhiyun return 0;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun /**
791*4882a593Smuzhiyun * rpc_clnt_iterate_for_each_xprt - Apply a function to all transports
792*4882a593Smuzhiyun * @clnt: pointer to client
793*4882a593Smuzhiyun * @fn: function to apply
794*4882a593Smuzhiyun * @data: void pointer to function data
795*4882a593Smuzhiyun *
796*4882a593Smuzhiyun * Iterates through the list of RPC transports currently attached to the
797*4882a593Smuzhiyun * client and applies the function fn(clnt, xprt, data).
798*4882a593Smuzhiyun *
799*4882a593Smuzhiyun * On error, the iteration stops, and the function returns the error value.
800*4882a593Smuzhiyun */
rpc_clnt_iterate_for_each_xprt(struct rpc_clnt * clnt,int (* fn)(struct rpc_clnt *,struct rpc_xprt *,void *),void * data)801*4882a593Smuzhiyun int rpc_clnt_iterate_for_each_xprt(struct rpc_clnt *clnt,
802*4882a593Smuzhiyun int (*fn)(struct rpc_clnt *, struct rpc_xprt *, void *),
803*4882a593Smuzhiyun void *data)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun struct rpc_xprt_iter xpi;
806*4882a593Smuzhiyun int ret;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun ret = rpc_clnt_xprt_iter_init(clnt, &xpi);
809*4882a593Smuzhiyun if (ret)
810*4882a593Smuzhiyun return ret;
811*4882a593Smuzhiyun for (;;) {
812*4882a593Smuzhiyun struct rpc_xprt *xprt = xprt_iter_get_next(&xpi);
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun if (!xprt)
815*4882a593Smuzhiyun break;
816*4882a593Smuzhiyun ret = fn(clnt, xprt, data);
817*4882a593Smuzhiyun xprt_put(xprt);
818*4882a593Smuzhiyun if (ret < 0)
819*4882a593Smuzhiyun break;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun xprt_iter_destroy(&xpi);
822*4882a593Smuzhiyun return ret;
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_iterate_for_each_xprt);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun /*
827*4882a593Smuzhiyun * Kill all tasks for the given client.
828*4882a593Smuzhiyun * XXX: kill their descendants as well?
829*4882a593Smuzhiyun */
rpc_killall_tasks(struct rpc_clnt * clnt)830*4882a593Smuzhiyun void rpc_killall_tasks(struct rpc_clnt *clnt)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun struct rpc_task *rovr;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun if (list_empty(&clnt->cl_tasks))
836*4882a593Smuzhiyun return;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun /*
839*4882a593Smuzhiyun * Spin lock all_tasks to prevent changes...
840*4882a593Smuzhiyun */
841*4882a593Smuzhiyun trace_rpc_clnt_killall(clnt);
842*4882a593Smuzhiyun spin_lock(&clnt->cl_lock);
843*4882a593Smuzhiyun list_for_each_entry(rovr, &clnt->cl_tasks, tk_task)
844*4882a593Smuzhiyun rpc_signal_task(rovr);
845*4882a593Smuzhiyun spin_unlock(&clnt->cl_lock);
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_killall_tasks);
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /*
850*4882a593Smuzhiyun * Properly shut down an RPC client, terminating all outstanding
851*4882a593Smuzhiyun * requests.
852*4882a593Smuzhiyun */
rpc_shutdown_client(struct rpc_clnt * clnt)853*4882a593Smuzhiyun void rpc_shutdown_client(struct rpc_clnt *clnt)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun might_sleep();
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun trace_rpc_clnt_shutdown(clnt);
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun while (!list_empty(&clnt->cl_tasks)) {
860*4882a593Smuzhiyun rpc_killall_tasks(clnt);
861*4882a593Smuzhiyun wait_event_timeout(destroy_wait,
862*4882a593Smuzhiyun list_empty(&clnt->cl_tasks), 1*HZ);
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun rpc_release_client(clnt);
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_shutdown_client);
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun /*
870*4882a593Smuzhiyun * Free an RPC client
871*4882a593Smuzhiyun */
rpc_free_client_work(struct work_struct * work)872*4882a593Smuzhiyun static void rpc_free_client_work(struct work_struct *work)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun struct rpc_clnt *clnt = container_of(work, struct rpc_clnt, cl_work);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun trace_rpc_clnt_free(clnt);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun /* These might block on processes that might allocate memory,
879*4882a593Smuzhiyun * so they cannot be called in rpciod, so they are handled separately
880*4882a593Smuzhiyun * here.
881*4882a593Smuzhiyun */
882*4882a593Smuzhiyun rpc_clnt_debugfs_unregister(clnt);
883*4882a593Smuzhiyun rpc_free_clid(clnt);
884*4882a593Smuzhiyun rpc_clnt_remove_pipedir(clnt);
885*4882a593Smuzhiyun xprt_put(rcu_dereference_raw(clnt->cl_xprt));
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun kfree(clnt);
888*4882a593Smuzhiyun rpciod_down();
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun static struct rpc_clnt *
rpc_free_client(struct rpc_clnt * clnt)891*4882a593Smuzhiyun rpc_free_client(struct rpc_clnt *clnt)
892*4882a593Smuzhiyun {
893*4882a593Smuzhiyun struct rpc_clnt *parent = NULL;
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun trace_rpc_clnt_release(clnt);
896*4882a593Smuzhiyun if (clnt->cl_parent != clnt)
897*4882a593Smuzhiyun parent = clnt->cl_parent;
898*4882a593Smuzhiyun rpc_unregister_client(clnt);
899*4882a593Smuzhiyun rpc_free_iostats(clnt->cl_metrics);
900*4882a593Smuzhiyun clnt->cl_metrics = NULL;
901*4882a593Smuzhiyun xprt_iter_destroy(&clnt->cl_xpi);
902*4882a593Smuzhiyun put_cred(clnt->cl_cred);
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun INIT_WORK(&clnt->cl_work, rpc_free_client_work);
905*4882a593Smuzhiyun schedule_work(&clnt->cl_work);
906*4882a593Smuzhiyun return parent;
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun /*
910*4882a593Smuzhiyun * Free an RPC client
911*4882a593Smuzhiyun */
912*4882a593Smuzhiyun static struct rpc_clnt *
rpc_free_auth(struct rpc_clnt * clnt)913*4882a593Smuzhiyun rpc_free_auth(struct rpc_clnt *clnt)
914*4882a593Smuzhiyun {
915*4882a593Smuzhiyun if (clnt->cl_auth == NULL)
916*4882a593Smuzhiyun return rpc_free_client(clnt);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun /*
919*4882a593Smuzhiyun * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
920*4882a593Smuzhiyun * release remaining GSS contexts. This mechanism ensures
921*4882a593Smuzhiyun * that it can do so safely.
922*4882a593Smuzhiyun */
923*4882a593Smuzhiyun atomic_inc(&clnt->cl_count);
924*4882a593Smuzhiyun rpcauth_release(clnt->cl_auth);
925*4882a593Smuzhiyun clnt->cl_auth = NULL;
926*4882a593Smuzhiyun if (atomic_dec_and_test(&clnt->cl_count))
927*4882a593Smuzhiyun return rpc_free_client(clnt);
928*4882a593Smuzhiyun return NULL;
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /*
932*4882a593Smuzhiyun * Release reference to the RPC client
933*4882a593Smuzhiyun */
934*4882a593Smuzhiyun void
rpc_release_client(struct rpc_clnt * clnt)935*4882a593Smuzhiyun rpc_release_client(struct rpc_clnt *clnt)
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun do {
938*4882a593Smuzhiyun if (list_empty(&clnt->cl_tasks))
939*4882a593Smuzhiyun wake_up(&destroy_wait);
940*4882a593Smuzhiyun if (!atomic_dec_and_test(&clnt->cl_count))
941*4882a593Smuzhiyun break;
942*4882a593Smuzhiyun clnt = rpc_free_auth(clnt);
943*4882a593Smuzhiyun } while (clnt != NULL);
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_release_client);
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun /**
948*4882a593Smuzhiyun * rpc_bind_new_program - bind a new RPC program to an existing client
949*4882a593Smuzhiyun * @old: old rpc_client
950*4882a593Smuzhiyun * @program: rpc program to set
951*4882a593Smuzhiyun * @vers: rpc program version
952*4882a593Smuzhiyun *
953*4882a593Smuzhiyun * Clones the rpc client and sets up a new RPC program. This is mainly
954*4882a593Smuzhiyun * of use for enabling different RPC programs to share the same transport.
955*4882a593Smuzhiyun * The Sun NFSv2/v3 ACL protocol can do this.
956*4882a593Smuzhiyun */
rpc_bind_new_program(struct rpc_clnt * old,const struct rpc_program * program,u32 vers)957*4882a593Smuzhiyun struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
958*4882a593Smuzhiyun const struct rpc_program *program,
959*4882a593Smuzhiyun u32 vers)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun struct rpc_create_args args = {
962*4882a593Smuzhiyun .program = program,
963*4882a593Smuzhiyun .prognumber = program->number,
964*4882a593Smuzhiyun .version = vers,
965*4882a593Smuzhiyun .authflavor = old->cl_auth->au_flavor,
966*4882a593Smuzhiyun .cred = old->cl_cred,
967*4882a593Smuzhiyun };
968*4882a593Smuzhiyun struct rpc_clnt *clnt;
969*4882a593Smuzhiyun int err;
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun clnt = __rpc_clone_client(&args, old);
972*4882a593Smuzhiyun if (IS_ERR(clnt))
973*4882a593Smuzhiyun goto out;
974*4882a593Smuzhiyun err = rpc_ping(clnt);
975*4882a593Smuzhiyun if (err != 0) {
976*4882a593Smuzhiyun rpc_shutdown_client(clnt);
977*4882a593Smuzhiyun clnt = ERR_PTR(err);
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun out:
980*4882a593Smuzhiyun return clnt;
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_bind_new_program);
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun struct rpc_xprt *
rpc_task_get_xprt(struct rpc_clnt * clnt,struct rpc_xprt * xprt)985*4882a593Smuzhiyun rpc_task_get_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
986*4882a593Smuzhiyun {
987*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun if (!xprt)
990*4882a593Smuzhiyun return NULL;
991*4882a593Smuzhiyun rcu_read_lock();
992*4882a593Smuzhiyun xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
993*4882a593Smuzhiyun atomic_long_inc(&xps->xps_queuelen);
994*4882a593Smuzhiyun rcu_read_unlock();
995*4882a593Smuzhiyun atomic_long_inc(&xprt->queuelen);
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun return xprt;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun static void
rpc_task_release_xprt(struct rpc_clnt * clnt,struct rpc_xprt * xprt)1001*4882a593Smuzhiyun rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun atomic_long_dec(&xprt->queuelen);
1006*4882a593Smuzhiyun rcu_read_lock();
1007*4882a593Smuzhiyun xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
1008*4882a593Smuzhiyun atomic_long_dec(&xps->xps_queuelen);
1009*4882a593Smuzhiyun rcu_read_unlock();
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun xprt_put(xprt);
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun
rpc_task_release_transport(struct rpc_task * task)1014*4882a593Smuzhiyun void rpc_task_release_transport(struct rpc_task *task)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun struct rpc_xprt *xprt = task->tk_xprt;
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun if (xprt) {
1019*4882a593Smuzhiyun task->tk_xprt = NULL;
1020*4882a593Smuzhiyun if (task->tk_client)
1021*4882a593Smuzhiyun rpc_task_release_xprt(task->tk_client, xprt);
1022*4882a593Smuzhiyun else
1023*4882a593Smuzhiyun xprt_put(xprt);
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_task_release_transport);
1027*4882a593Smuzhiyun
rpc_task_release_client(struct rpc_task * task)1028*4882a593Smuzhiyun void rpc_task_release_client(struct rpc_task *task)
1029*4882a593Smuzhiyun {
1030*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun rpc_task_release_transport(task);
1033*4882a593Smuzhiyun if (clnt != NULL) {
1034*4882a593Smuzhiyun /* Remove from client task list */
1035*4882a593Smuzhiyun spin_lock(&clnt->cl_lock);
1036*4882a593Smuzhiyun list_del(&task->tk_task);
1037*4882a593Smuzhiyun spin_unlock(&clnt->cl_lock);
1038*4882a593Smuzhiyun task->tk_client = NULL;
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun rpc_release_client(clnt);
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun static struct rpc_xprt *
rpc_task_get_first_xprt(struct rpc_clnt * clnt)1045*4882a593Smuzhiyun rpc_task_get_first_xprt(struct rpc_clnt *clnt)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun struct rpc_xprt *xprt;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun rcu_read_lock();
1050*4882a593Smuzhiyun xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
1051*4882a593Smuzhiyun rcu_read_unlock();
1052*4882a593Smuzhiyun return rpc_task_get_xprt(clnt, xprt);
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun static struct rpc_xprt *
rpc_task_get_next_xprt(struct rpc_clnt * clnt)1056*4882a593Smuzhiyun rpc_task_get_next_xprt(struct rpc_clnt *clnt)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun return rpc_task_get_xprt(clnt, xprt_iter_get_next(&clnt->cl_xpi));
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun static
rpc_task_set_transport(struct rpc_task * task,struct rpc_clnt * clnt)1062*4882a593Smuzhiyun void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
1063*4882a593Smuzhiyun {
1064*4882a593Smuzhiyun if (task->tk_xprt)
1065*4882a593Smuzhiyun return;
1066*4882a593Smuzhiyun if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
1067*4882a593Smuzhiyun task->tk_xprt = rpc_task_get_first_xprt(clnt);
1068*4882a593Smuzhiyun else
1069*4882a593Smuzhiyun task->tk_xprt = rpc_task_get_next_xprt(clnt);
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun static
rpc_task_set_client(struct rpc_task * task,struct rpc_clnt * clnt)1073*4882a593Smuzhiyun void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun if (clnt != NULL) {
1077*4882a593Smuzhiyun rpc_task_set_transport(task, clnt);
1078*4882a593Smuzhiyun task->tk_client = clnt;
1079*4882a593Smuzhiyun atomic_inc(&clnt->cl_count);
1080*4882a593Smuzhiyun if (clnt->cl_softrtry)
1081*4882a593Smuzhiyun task->tk_flags |= RPC_TASK_SOFT;
1082*4882a593Smuzhiyun if (clnt->cl_softerr)
1083*4882a593Smuzhiyun task->tk_flags |= RPC_TASK_TIMEOUT;
1084*4882a593Smuzhiyun if (clnt->cl_noretranstimeo)
1085*4882a593Smuzhiyun task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT;
1086*4882a593Smuzhiyun if (atomic_read(&clnt->cl_swapper))
1087*4882a593Smuzhiyun task->tk_flags |= RPC_TASK_SWAPPER;
1088*4882a593Smuzhiyun /* Add to the client's list of all tasks */
1089*4882a593Smuzhiyun spin_lock(&clnt->cl_lock);
1090*4882a593Smuzhiyun list_add_tail(&task->tk_task, &clnt->cl_tasks);
1091*4882a593Smuzhiyun spin_unlock(&clnt->cl_lock);
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun static void
rpc_task_set_rpc_message(struct rpc_task * task,const struct rpc_message * msg)1096*4882a593Smuzhiyun rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun if (msg != NULL) {
1099*4882a593Smuzhiyun task->tk_msg.rpc_proc = msg->rpc_proc;
1100*4882a593Smuzhiyun task->tk_msg.rpc_argp = msg->rpc_argp;
1101*4882a593Smuzhiyun task->tk_msg.rpc_resp = msg->rpc_resp;
1102*4882a593Smuzhiyun task->tk_msg.rpc_cred = msg->rpc_cred;
1103*4882a593Smuzhiyun if (!(task->tk_flags & RPC_TASK_CRED_NOREF))
1104*4882a593Smuzhiyun get_cred(task->tk_msg.rpc_cred);
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun /*
1109*4882a593Smuzhiyun * Default callback for async RPC calls
1110*4882a593Smuzhiyun */
1111*4882a593Smuzhiyun static void
rpc_default_callback(struct rpc_task * task,void * data)1112*4882a593Smuzhiyun rpc_default_callback(struct rpc_task *task, void *data)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun static const struct rpc_call_ops rpc_default_ops = {
1117*4882a593Smuzhiyun .rpc_call_done = rpc_default_callback,
1118*4882a593Smuzhiyun };
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun /**
1121*4882a593Smuzhiyun * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
1122*4882a593Smuzhiyun * @task_setup_data: pointer to task initialisation data
1123*4882a593Smuzhiyun */
rpc_run_task(const struct rpc_task_setup * task_setup_data)1124*4882a593Smuzhiyun struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
1125*4882a593Smuzhiyun {
1126*4882a593Smuzhiyun struct rpc_task *task;
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun task = rpc_new_task(task_setup_data);
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun if (!RPC_IS_ASYNC(task))
1131*4882a593Smuzhiyun task->tk_flags |= RPC_TASK_CRED_NOREF;
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun rpc_task_set_client(task, task_setup_data->rpc_client);
1134*4882a593Smuzhiyun rpc_task_set_rpc_message(task, task_setup_data->rpc_message);
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun if (task->tk_action == NULL)
1137*4882a593Smuzhiyun rpc_call_start(task);
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun atomic_inc(&task->tk_count);
1140*4882a593Smuzhiyun rpc_execute(task);
1141*4882a593Smuzhiyun return task;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_run_task);
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun /**
1146*4882a593Smuzhiyun * rpc_call_sync - Perform a synchronous RPC call
1147*4882a593Smuzhiyun * @clnt: pointer to RPC client
1148*4882a593Smuzhiyun * @msg: RPC call parameters
1149*4882a593Smuzhiyun * @flags: RPC call flags
1150*4882a593Smuzhiyun */
rpc_call_sync(struct rpc_clnt * clnt,const struct rpc_message * msg,int flags)1151*4882a593Smuzhiyun int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun struct rpc_task *task;
1154*4882a593Smuzhiyun struct rpc_task_setup task_setup_data = {
1155*4882a593Smuzhiyun .rpc_client = clnt,
1156*4882a593Smuzhiyun .rpc_message = msg,
1157*4882a593Smuzhiyun .callback_ops = &rpc_default_ops,
1158*4882a593Smuzhiyun .flags = flags,
1159*4882a593Smuzhiyun };
1160*4882a593Smuzhiyun int status;
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun WARN_ON_ONCE(flags & RPC_TASK_ASYNC);
1163*4882a593Smuzhiyun if (flags & RPC_TASK_ASYNC) {
1164*4882a593Smuzhiyun rpc_release_calldata(task_setup_data.callback_ops,
1165*4882a593Smuzhiyun task_setup_data.callback_data);
1166*4882a593Smuzhiyun return -EINVAL;
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun task = rpc_run_task(&task_setup_data);
1170*4882a593Smuzhiyun if (IS_ERR(task))
1171*4882a593Smuzhiyun return PTR_ERR(task);
1172*4882a593Smuzhiyun status = task->tk_status;
1173*4882a593Smuzhiyun rpc_put_task(task);
1174*4882a593Smuzhiyun return status;
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_call_sync);
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun /**
1179*4882a593Smuzhiyun * rpc_call_async - Perform an asynchronous RPC call
1180*4882a593Smuzhiyun * @clnt: pointer to RPC client
1181*4882a593Smuzhiyun * @msg: RPC call parameters
1182*4882a593Smuzhiyun * @flags: RPC call flags
1183*4882a593Smuzhiyun * @tk_ops: RPC call ops
1184*4882a593Smuzhiyun * @data: user call data
1185*4882a593Smuzhiyun */
1186*4882a593Smuzhiyun int
rpc_call_async(struct rpc_clnt * clnt,const struct rpc_message * msg,int flags,const struct rpc_call_ops * tk_ops,void * data)1187*4882a593Smuzhiyun rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
1188*4882a593Smuzhiyun const struct rpc_call_ops *tk_ops, void *data)
1189*4882a593Smuzhiyun {
1190*4882a593Smuzhiyun struct rpc_task *task;
1191*4882a593Smuzhiyun struct rpc_task_setup task_setup_data = {
1192*4882a593Smuzhiyun .rpc_client = clnt,
1193*4882a593Smuzhiyun .rpc_message = msg,
1194*4882a593Smuzhiyun .callback_ops = tk_ops,
1195*4882a593Smuzhiyun .callback_data = data,
1196*4882a593Smuzhiyun .flags = flags|RPC_TASK_ASYNC,
1197*4882a593Smuzhiyun };
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun task = rpc_run_task(&task_setup_data);
1200*4882a593Smuzhiyun if (IS_ERR(task))
1201*4882a593Smuzhiyun return PTR_ERR(task);
1202*4882a593Smuzhiyun rpc_put_task(task);
1203*4882a593Smuzhiyun return 0;
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_call_async);
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun #if defined(CONFIG_SUNRPC_BACKCHANNEL)
1208*4882a593Smuzhiyun static void call_bc_encode(struct rpc_task *task);
1209*4882a593Smuzhiyun
1210*4882a593Smuzhiyun /**
1211*4882a593Smuzhiyun * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
1212*4882a593Smuzhiyun * rpc_execute against it
1213*4882a593Smuzhiyun * @req: RPC request
1214*4882a593Smuzhiyun */
rpc_run_bc_task(struct rpc_rqst * req)1215*4882a593Smuzhiyun struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)
1216*4882a593Smuzhiyun {
1217*4882a593Smuzhiyun struct rpc_task *task;
1218*4882a593Smuzhiyun struct rpc_task_setup task_setup_data = {
1219*4882a593Smuzhiyun .callback_ops = &rpc_default_ops,
1220*4882a593Smuzhiyun .flags = RPC_TASK_SOFTCONN |
1221*4882a593Smuzhiyun RPC_TASK_NO_RETRANS_TIMEOUT,
1222*4882a593Smuzhiyun };
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun dprintk("RPC: rpc_run_bc_task req= %p\n", req);
1225*4882a593Smuzhiyun /*
1226*4882a593Smuzhiyun * Create an rpc_task to send the data
1227*4882a593Smuzhiyun */
1228*4882a593Smuzhiyun task = rpc_new_task(&task_setup_data);
1229*4882a593Smuzhiyun xprt_init_bc_request(req, task);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun task->tk_action = call_bc_encode;
1232*4882a593Smuzhiyun atomic_inc(&task->tk_count);
1233*4882a593Smuzhiyun WARN_ON_ONCE(atomic_read(&task->tk_count) != 2);
1234*4882a593Smuzhiyun rpc_execute(task);
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
1237*4882a593Smuzhiyun return task;
1238*4882a593Smuzhiyun }
1239*4882a593Smuzhiyun #endif /* CONFIG_SUNRPC_BACKCHANNEL */
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun /**
1242*4882a593Smuzhiyun * rpc_prepare_reply_pages - Prepare to receive a reply data payload into pages
1243*4882a593Smuzhiyun * @req: RPC request to prepare
1244*4882a593Smuzhiyun * @pages: vector of struct page pointers
1245*4882a593Smuzhiyun * @base: offset in first page where receive should start, in bytes
1246*4882a593Smuzhiyun * @len: expected size of the upper layer data payload, in bytes
1247*4882a593Smuzhiyun * @hdrsize: expected size of upper layer reply header, in XDR words
1248*4882a593Smuzhiyun *
1249*4882a593Smuzhiyun */
rpc_prepare_reply_pages(struct rpc_rqst * req,struct page ** pages,unsigned int base,unsigned int len,unsigned int hdrsize)1250*4882a593Smuzhiyun void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
1251*4882a593Smuzhiyun unsigned int base, unsigned int len,
1252*4882a593Smuzhiyun unsigned int hdrsize)
1253*4882a593Smuzhiyun {
1254*4882a593Smuzhiyun /* Subtract one to force an extra word of buffer space for the
1255*4882a593Smuzhiyun * payload's XDR pad to fall into the rcv_buf's tail iovec.
1256*4882a593Smuzhiyun */
1257*4882a593Smuzhiyun hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_ralign - 1;
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun xdr_inline_pages(&req->rq_rcv_buf, hdrsize << 2, pages, base, len);
1260*4882a593Smuzhiyun trace_rpc_xdr_reply_pages(req->rq_task, &req->rq_rcv_buf);
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_prepare_reply_pages);
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun void
rpc_call_start(struct rpc_task * task)1265*4882a593Smuzhiyun rpc_call_start(struct rpc_task *task)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun task->tk_action = call_start;
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_call_start);
1270*4882a593Smuzhiyun
1271*4882a593Smuzhiyun /**
1272*4882a593Smuzhiyun * rpc_peeraddr - extract remote peer address from clnt's xprt
1273*4882a593Smuzhiyun * @clnt: RPC client structure
1274*4882a593Smuzhiyun * @buf: target buffer
1275*4882a593Smuzhiyun * @bufsize: length of target buffer
1276*4882a593Smuzhiyun *
1277*4882a593Smuzhiyun * Returns the number of bytes that are actually in the stored address.
1278*4882a593Smuzhiyun */
rpc_peeraddr(struct rpc_clnt * clnt,struct sockaddr * buf,size_t bufsize)1279*4882a593Smuzhiyun size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize)
1280*4882a593Smuzhiyun {
1281*4882a593Smuzhiyun size_t bytes;
1282*4882a593Smuzhiyun struct rpc_xprt *xprt;
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun rcu_read_lock();
1285*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun bytes = xprt->addrlen;
1288*4882a593Smuzhiyun if (bytes > bufsize)
1289*4882a593Smuzhiyun bytes = bufsize;
1290*4882a593Smuzhiyun memcpy(buf, &xprt->addr, bytes);
1291*4882a593Smuzhiyun rcu_read_unlock();
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun return bytes;
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_peeraddr);
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun /**
1298*4882a593Smuzhiyun * rpc_peeraddr2str - return remote peer address in printable format
1299*4882a593Smuzhiyun * @clnt: RPC client structure
1300*4882a593Smuzhiyun * @format: address format
1301*4882a593Smuzhiyun *
1302*4882a593Smuzhiyun * NB: the lifetime of the memory referenced by the returned pointer is
1303*4882a593Smuzhiyun * the same as the rpc_xprt itself. As long as the caller uses this
1304*4882a593Smuzhiyun * pointer, it must hold the RCU read lock.
1305*4882a593Smuzhiyun */
rpc_peeraddr2str(struct rpc_clnt * clnt,enum rpc_display_format_t format)1306*4882a593Smuzhiyun const char *rpc_peeraddr2str(struct rpc_clnt *clnt,
1307*4882a593Smuzhiyun enum rpc_display_format_t format)
1308*4882a593Smuzhiyun {
1309*4882a593Smuzhiyun struct rpc_xprt *xprt;
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun if (xprt->address_strings[format] != NULL)
1314*4882a593Smuzhiyun return xprt->address_strings[format];
1315*4882a593Smuzhiyun else
1316*4882a593Smuzhiyun return "unprintable";
1317*4882a593Smuzhiyun }
1318*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_peeraddr2str);
1319*4882a593Smuzhiyun
1320*4882a593Smuzhiyun static const struct sockaddr_in rpc_inaddr_loopback = {
1321*4882a593Smuzhiyun .sin_family = AF_INET,
1322*4882a593Smuzhiyun .sin_addr.s_addr = htonl(INADDR_ANY),
1323*4882a593Smuzhiyun };
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun static const struct sockaddr_in6 rpc_in6addr_loopback = {
1326*4882a593Smuzhiyun .sin6_family = AF_INET6,
1327*4882a593Smuzhiyun .sin6_addr = IN6ADDR_ANY_INIT,
1328*4882a593Smuzhiyun };
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun /*
1331*4882a593Smuzhiyun * Try a getsockname() on a connected datagram socket. Using a
1332*4882a593Smuzhiyun * connected datagram socket prevents leaving a socket in TIME_WAIT.
1333*4882a593Smuzhiyun * This conserves the ephemeral port number space.
1334*4882a593Smuzhiyun *
1335*4882a593Smuzhiyun * Returns zero and fills in "buf" if successful; otherwise, a
1336*4882a593Smuzhiyun * negative errno is returned.
1337*4882a593Smuzhiyun */
rpc_sockname(struct net * net,struct sockaddr * sap,size_t salen,struct sockaddr * buf)1338*4882a593Smuzhiyun static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen,
1339*4882a593Smuzhiyun struct sockaddr *buf)
1340*4882a593Smuzhiyun {
1341*4882a593Smuzhiyun struct socket *sock;
1342*4882a593Smuzhiyun int err;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun err = __sock_create(net, sap->sa_family,
1345*4882a593Smuzhiyun SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
1346*4882a593Smuzhiyun if (err < 0) {
1347*4882a593Smuzhiyun dprintk("RPC: can't create UDP socket (%d)\n", err);
1348*4882a593Smuzhiyun goto out;
1349*4882a593Smuzhiyun }
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun switch (sap->sa_family) {
1352*4882a593Smuzhiyun case AF_INET:
1353*4882a593Smuzhiyun err = kernel_bind(sock,
1354*4882a593Smuzhiyun (struct sockaddr *)&rpc_inaddr_loopback,
1355*4882a593Smuzhiyun sizeof(rpc_inaddr_loopback));
1356*4882a593Smuzhiyun break;
1357*4882a593Smuzhiyun case AF_INET6:
1358*4882a593Smuzhiyun err = kernel_bind(sock,
1359*4882a593Smuzhiyun (struct sockaddr *)&rpc_in6addr_loopback,
1360*4882a593Smuzhiyun sizeof(rpc_in6addr_loopback));
1361*4882a593Smuzhiyun break;
1362*4882a593Smuzhiyun default:
1363*4882a593Smuzhiyun err = -EAFNOSUPPORT;
1364*4882a593Smuzhiyun goto out;
1365*4882a593Smuzhiyun }
1366*4882a593Smuzhiyun if (err < 0) {
1367*4882a593Smuzhiyun dprintk("RPC: can't bind UDP socket (%d)\n", err);
1368*4882a593Smuzhiyun goto out_release;
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun err = kernel_connect(sock, sap, salen, 0);
1372*4882a593Smuzhiyun if (err < 0) {
1373*4882a593Smuzhiyun dprintk("RPC: can't connect UDP socket (%d)\n", err);
1374*4882a593Smuzhiyun goto out_release;
1375*4882a593Smuzhiyun }
1376*4882a593Smuzhiyun
1377*4882a593Smuzhiyun err = kernel_getsockname(sock, buf);
1378*4882a593Smuzhiyun if (err < 0) {
1379*4882a593Smuzhiyun dprintk("RPC: getsockname failed (%d)\n", err);
1380*4882a593Smuzhiyun goto out_release;
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun err = 0;
1384*4882a593Smuzhiyun if (buf->sa_family == AF_INET6) {
1385*4882a593Smuzhiyun struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
1386*4882a593Smuzhiyun sin6->sin6_scope_id = 0;
1387*4882a593Smuzhiyun }
1388*4882a593Smuzhiyun dprintk("RPC: %s succeeded\n", __func__);
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun out_release:
1391*4882a593Smuzhiyun sock_release(sock);
1392*4882a593Smuzhiyun out:
1393*4882a593Smuzhiyun return err;
1394*4882a593Smuzhiyun }
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun /*
1397*4882a593Smuzhiyun * Scraping a connected socket failed, so we don't have a useable
1398*4882a593Smuzhiyun * local address. Fallback: generate an address that will prevent
1399*4882a593Smuzhiyun * the server from calling us back.
1400*4882a593Smuzhiyun *
1401*4882a593Smuzhiyun * Returns zero and fills in "buf" if successful; otherwise, a
1402*4882a593Smuzhiyun * negative errno is returned.
1403*4882a593Smuzhiyun */
rpc_anyaddr(int family,struct sockaddr * buf,size_t buflen)1404*4882a593Smuzhiyun static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen)
1405*4882a593Smuzhiyun {
1406*4882a593Smuzhiyun switch (family) {
1407*4882a593Smuzhiyun case AF_INET:
1408*4882a593Smuzhiyun if (buflen < sizeof(rpc_inaddr_loopback))
1409*4882a593Smuzhiyun return -EINVAL;
1410*4882a593Smuzhiyun memcpy(buf, &rpc_inaddr_loopback,
1411*4882a593Smuzhiyun sizeof(rpc_inaddr_loopback));
1412*4882a593Smuzhiyun break;
1413*4882a593Smuzhiyun case AF_INET6:
1414*4882a593Smuzhiyun if (buflen < sizeof(rpc_in6addr_loopback))
1415*4882a593Smuzhiyun return -EINVAL;
1416*4882a593Smuzhiyun memcpy(buf, &rpc_in6addr_loopback,
1417*4882a593Smuzhiyun sizeof(rpc_in6addr_loopback));
1418*4882a593Smuzhiyun break;
1419*4882a593Smuzhiyun default:
1420*4882a593Smuzhiyun dprintk("RPC: %s: address family not supported\n",
1421*4882a593Smuzhiyun __func__);
1422*4882a593Smuzhiyun return -EAFNOSUPPORT;
1423*4882a593Smuzhiyun }
1424*4882a593Smuzhiyun dprintk("RPC: %s: succeeded\n", __func__);
1425*4882a593Smuzhiyun return 0;
1426*4882a593Smuzhiyun }
1427*4882a593Smuzhiyun
1428*4882a593Smuzhiyun /**
1429*4882a593Smuzhiyun * rpc_localaddr - discover local endpoint address for an RPC client
1430*4882a593Smuzhiyun * @clnt: RPC client structure
1431*4882a593Smuzhiyun * @buf: target buffer
1432*4882a593Smuzhiyun * @buflen: size of target buffer, in bytes
1433*4882a593Smuzhiyun *
1434*4882a593Smuzhiyun * Returns zero and fills in "buf" and "buflen" if successful;
1435*4882a593Smuzhiyun * otherwise, a negative errno is returned.
1436*4882a593Smuzhiyun *
1437*4882a593Smuzhiyun * This works even if the underlying transport is not currently connected,
1438*4882a593Smuzhiyun * or if the upper layer never previously provided a source address.
1439*4882a593Smuzhiyun *
1440*4882a593Smuzhiyun * The result of this function call is transient: multiple calls in
1441*4882a593Smuzhiyun * succession may give different results, depending on how local
1442*4882a593Smuzhiyun * networking configuration changes over time.
1443*4882a593Smuzhiyun */
rpc_localaddr(struct rpc_clnt * clnt,struct sockaddr * buf,size_t buflen)1444*4882a593Smuzhiyun int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen)
1445*4882a593Smuzhiyun {
1446*4882a593Smuzhiyun struct sockaddr_storage address;
1447*4882a593Smuzhiyun struct sockaddr *sap = (struct sockaddr *)&address;
1448*4882a593Smuzhiyun struct rpc_xprt *xprt;
1449*4882a593Smuzhiyun struct net *net;
1450*4882a593Smuzhiyun size_t salen;
1451*4882a593Smuzhiyun int err;
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun rcu_read_lock();
1454*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1455*4882a593Smuzhiyun salen = xprt->addrlen;
1456*4882a593Smuzhiyun memcpy(sap, &xprt->addr, salen);
1457*4882a593Smuzhiyun net = get_net(xprt->xprt_net);
1458*4882a593Smuzhiyun rcu_read_unlock();
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun rpc_set_port(sap, 0);
1461*4882a593Smuzhiyun err = rpc_sockname(net, sap, salen, buf);
1462*4882a593Smuzhiyun put_net(net);
1463*4882a593Smuzhiyun if (err != 0)
1464*4882a593Smuzhiyun /* Couldn't discover local address, return ANYADDR */
1465*4882a593Smuzhiyun return rpc_anyaddr(sap->sa_family, buf, buflen);
1466*4882a593Smuzhiyun return 0;
1467*4882a593Smuzhiyun }
1468*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_localaddr);
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun void
rpc_setbufsize(struct rpc_clnt * clnt,unsigned int sndsize,unsigned int rcvsize)1471*4882a593Smuzhiyun rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
1472*4882a593Smuzhiyun {
1473*4882a593Smuzhiyun struct rpc_xprt *xprt;
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun rcu_read_lock();
1476*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1477*4882a593Smuzhiyun if (xprt->ops->set_buffer_size)
1478*4882a593Smuzhiyun xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
1479*4882a593Smuzhiyun rcu_read_unlock();
1480*4882a593Smuzhiyun }
1481*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_setbufsize);
1482*4882a593Smuzhiyun
1483*4882a593Smuzhiyun /**
1484*4882a593Smuzhiyun * rpc_net_ns - Get the network namespace for this RPC client
1485*4882a593Smuzhiyun * @clnt: RPC client to query
1486*4882a593Smuzhiyun *
1487*4882a593Smuzhiyun */
rpc_net_ns(struct rpc_clnt * clnt)1488*4882a593Smuzhiyun struct net *rpc_net_ns(struct rpc_clnt *clnt)
1489*4882a593Smuzhiyun {
1490*4882a593Smuzhiyun struct net *ret;
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun rcu_read_lock();
1493*4882a593Smuzhiyun ret = rcu_dereference(clnt->cl_xprt)->xprt_net;
1494*4882a593Smuzhiyun rcu_read_unlock();
1495*4882a593Smuzhiyun return ret;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_net_ns);
1498*4882a593Smuzhiyun
1499*4882a593Smuzhiyun /**
1500*4882a593Smuzhiyun * rpc_max_payload - Get maximum payload size for a transport, in bytes
1501*4882a593Smuzhiyun * @clnt: RPC client to query
1502*4882a593Smuzhiyun *
1503*4882a593Smuzhiyun * For stream transports, this is one RPC record fragment (see RFC
1504*4882a593Smuzhiyun * 1831), as we don't support multi-record requests yet. For datagram
1505*4882a593Smuzhiyun * transports, this is the size of an IP packet minus the IP, UDP, and
1506*4882a593Smuzhiyun * RPC header sizes.
1507*4882a593Smuzhiyun */
rpc_max_payload(struct rpc_clnt * clnt)1508*4882a593Smuzhiyun size_t rpc_max_payload(struct rpc_clnt *clnt)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun size_t ret;
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun rcu_read_lock();
1513*4882a593Smuzhiyun ret = rcu_dereference(clnt->cl_xprt)->max_payload;
1514*4882a593Smuzhiyun rcu_read_unlock();
1515*4882a593Smuzhiyun return ret;
1516*4882a593Smuzhiyun }
1517*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_max_payload);
1518*4882a593Smuzhiyun
1519*4882a593Smuzhiyun /**
1520*4882a593Smuzhiyun * rpc_max_bc_payload - Get maximum backchannel payload size, in bytes
1521*4882a593Smuzhiyun * @clnt: RPC client to query
1522*4882a593Smuzhiyun */
rpc_max_bc_payload(struct rpc_clnt * clnt)1523*4882a593Smuzhiyun size_t rpc_max_bc_payload(struct rpc_clnt *clnt)
1524*4882a593Smuzhiyun {
1525*4882a593Smuzhiyun struct rpc_xprt *xprt;
1526*4882a593Smuzhiyun size_t ret;
1527*4882a593Smuzhiyun
1528*4882a593Smuzhiyun rcu_read_lock();
1529*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1530*4882a593Smuzhiyun ret = xprt->ops->bc_maxpayload(xprt);
1531*4882a593Smuzhiyun rcu_read_unlock();
1532*4882a593Smuzhiyun return ret;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_max_bc_payload);
1535*4882a593Smuzhiyun
rpc_num_bc_slots(struct rpc_clnt * clnt)1536*4882a593Smuzhiyun unsigned int rpc_num_bc_slots(struct rpc_clnt *clnt)
1537*4882a593Smuzhiyun {
1538*4882a593Smuzhiyun struct rpc_xprt *xprt;
1539*4882a593Smuzhiyun unsigned int ret;
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun rcu_read_lock();
1542*4882a593Smuzhiyun xprt = rcu_dereference(clnt->cl_xprt);
1543*4882a593Smuzhiyun ret = xprt->ops->bc_num_slots(xprt);
1544*4882a593Smuzhiyun rcu_read_unlock();
1545*4882a593Smuzhiyun return ret;
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_num_bc_slots);
1548*4882a593Smuzhiyun
1549*4882a593Smuzhiyun /**
1550*4882a593Smuzhiyun * rpc_force_rebind - force transport to check that remote port is unchanged
1551*4882a593Smuzhiyun * @clnt: client to rebind
1552*4882a593Smuzhiyun *
1553*4882a593Smuzhiyun */
rpc_force_rebind(struct rpc_clnt * clnt)1554*4882a593Smuzhiyun void rpc_force_rebind(struct rpc_clnt *clnt)
1555*4882a593Smuzhiyun {
1556*4882a593Smuzhiyun if (clnt->cl_autobind) {
1557*4882a593Smuzhiyun rcu_read_lock();
1558*4882a593Smuzhiyun xprt_clear_bound(rcu_dereference(clnt->cl_xprt));
1559*4882a593Smuzhiyun rcu_read_unlock();
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_force_rebind);
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun static int
__rpc_restart_call(struct rpc_task * task,void (* action)(struct rpc_task *))1565*4882a593Smuzhiyun __rpc_restart_call(struct rpc_task *task, void (*action)(struct rpc_task *))
1566*4882a593Smuzhiyun {
1567*4882a593Smuzhiyun task->tk_status = 0;
1568*4882a593Smuzhiyun task->tk_rpc_status = 0;
1569*4882a593Smuzhiyun task->tk_action = action;
1570*4882a593Smuzhiyun return 1;
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun /*
1574*4882a593Smuzhiyun * Restart an (async) RPC call. Usually called from within the
1575*4882a593Smuzhiyun * exit handler.
1576*4882a593Smuzhiyun */
1577*4882a593Smuzhiyun int
rpc_restart_call(struct rpc_task * task)1578*4882a593Smuzhiyun rpc_restart_call(struct rpc_task *task)
1579*4882a593Smuzhiyun {
1580*4882a593Smuzhiyun return __rpc_restart_call(task, call_start);
1581*4882a593Smuzhiyun }
1582*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_restart_call);
1583*4882a593Smuzhiyun
1584*4882a593Smuzhiyun /*
1585*4882a593Smuzhiyun * Restart an (async) RPC call from the call_prepare state.
1586*4882a593Smuzhiyun * Usually called from within the exit handler.
1587*4882a593Smuzhiyun */
1588*4882a593Smuzhiyun int
rpc_restart_call_prepare(struct rpc_task * task)1589*4882a593Smuzhiyun rpc_restart_call_prepare(struct rpc_task *task)
1590*4882a593Smuzhiyun {
1591*4882a593Smuzhiyun if (task->tk_ops->rpc_call_prepare != NULL)
1592*4882a593Smuzhiyun return __rpc_restart_call(task, rpc_prepare_task);
1593*4882a593Smuzhiyun return rpc_restart_call(task);
1594*4882a593Smuzhiyun }
1595*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
1596*4882a593Smuzhiyun
1597*4882a593Smuzhiyun const char
rpc_proc_name(const struct rpc_task * task)1598*4882a593Smuzhiyun *rpc_proc_name(const struct rpc_task *task)
1599*4882a593Smuzhiyun {
1600*4882a593Smuzhiyun const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyun if (proc) {
1603*4882a593Smuzhiyun if (proc->p_name)
1604*4882a593Smuzhiyun return proc->p_name;
1605*4882a593Smuzhiyun else
1606*4882a593Smuzhiyun return "NULL";
1607*4882a593Smuzhiyun } else
1608*4882a593Smuzhiyun return "no proc";
1609*4882a593Smuzhiyun }
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun static void
__rpc_call_rpcerror(struct rpc_task * task,int tk_status,int rpc_status)1612*4882a593Smuzhiyun __rpc_call_rpcerror(struct rpc_task *task, int tk_status, int rpc_status)
1613*4882a593Smuzhiyun {
1614*4882a593Smuzhiyun trace_rpc_call_rpcerror(task, tk_status, rpc_status);
1615*4882a593Smuzhiyun task->tk_rpc_status = rpc_status;
1616*4882a593Smuzhiyun rpc_exit(task, tk_status);
1617*4882a593Smuzhiyun }
1618*4882a593Smuzhiyun
1619*4882a593Smuzhiyun static void
rpc_call_rpcerror(struct rpc_task * task,int status)1620*4882a593Smuzhiyun rpc_call_rpcerror(struct rpc_task *task, int status)
1621*4882a593Smuzhiyun {
1622*4882a593Smuzhiyun __rpc_call_rpcerror(task, status, status);
1623*4882a593Smuzhiyun }
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun /*
1626*4882a593Smuzhiyun * 0. Initial state
1627*4882a593Smuzhiyun *
1628*4882a593Smuzhiyun * Other FSM states can be visited zero or more times, but
1629*4882a593Smuzhiyun * this state is visited exactly once for each RPC.
1630*4882a593Smuzhiyun */
1631*4882a593Smuzhiyun static void
call_start(struct rpc_task * task)1632*4882a593Smuzhiyun call_start(struct rpc_task *task)
1633*4882a593Smuzhiyun {
1634*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
1635*4882a593Smuzhiyun int idx = task->tk_msg.rpc_proc->p_statidx;
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun trace_rpc_request(task);
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun /* Increment call count (version might not be valid for ping) */
1640*4882a593Smuzhiyun if (clnt->cl_program->version[clnt->cl_vers])
1641*4882a593Smuzhiyun clnt->cl_program->version[clnt->cl_vers]->counts[idx]++;
1642*4882a593Smuzhiyun clnt->cl_stats->rpccnt++;
1643*4882a593Smuzhiyun task->tk_action = call_reserve;
1644*4882a593Smuzhiyun rpc_task_set_transport(task, clnt);
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun /*
1648*4882a593Smuzhiyun * 1. Reserve an RPC call slot
1649*4882a593Smuzhiyun */
1650*4882a593Smuzhiyun static void
call_reserve(struct rpc_task * task)1651*4882a593Smuzhiyun call_reserve(struct rpc_task *task)
1652*4882a593Smuzhiyun {
1653*4882a593Smuzhiyun task->tk_status = 0;
1654*4882a593Smuzhiyun task->tk_action = call_reserveresult;
1655*4882a593Smuzhiyun xprt_reserve(task);
1656*4882a593Smuzhiyun }
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun static void call_retry_reserve(struct rpc_task *task);
1659*4882a593Smuzhiyun
1660*4882a593Smuzhiyun /*
1661*4882a593Smuzhiyun * 1b. Grok the result of xprt_reserve()
1662*4882a593Smuzhiyun */
1663*4882a593Smuzhiyun static void
call_reserveresult(struct rpc_task * task)1664*4882a593Smuzhiyun call_reserveresult(struct rpc_task *task)
1665*4882a593Smuzhiyun {
1666*4882a593Smuzhiyun int status = task->tk_status;
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun /*
1669*4882a593Smuzhiyun * After a call to xprt_reserve(), we must have either
1670*4882a593Smuzhiyun * a request slot or else an error status.
1671*4882a593Smuzhiyun */
1672*4882a593Smuzhiyun task->tk_status = 0;
1673*4882a593Smuzhiyun if (status >= 0) {
1674*4882a593Smuzhiyun if (task->tk_rqstp) {
1675*4882a593Smuzhiyun task->tk_action = call_refresh;
1676*4882a593Smuzhiyun return;
1677*4882a593Smuzhiyun }
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun rpc_call_rpcerror(task, -EIO);
1680*4882a593Smuzhiyun return;
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun switch (status) {
1684*4882a593Smuzhiyun case -ENOMEM:
1685*4882a593Smuzhiyun rpc_delay(task, HZ >> 2);
1686*4882a593Smuzhiyun fallthrough;
1687*4882a593Smuzhiyun case -EAGAIN: /* woken up; retry */
1688*4882a593Smuzhiyun task->tk_action = call_retry_reserve;
1689*4882a593Smuzhiyun return;
1690*4882a593Smuzhiyun default:
1691*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
1692*4882a593Smuzhiyun }
1693*4882a593Smuzhiyun }
1694*4882a593Smuzhiyun
1695*4882a593Smuzhiyun /*
1696*4882a593Smuzhiyun * 1c. Retry reserving an RPC call slot
1697*4882a593Smuzhiyun */
1698*4882a593Smuzhiyun static void
call_retry_reserve(struct rpc_task * task)1699*4882a593Smuzhiyun call_retry_reserve(struct rpc_task *task)
1700*4882a593Smuzhiyun {
1701*4882a593Smuzhiyun task->tk_status = 0;
1702*4882a593Smuzhiyun task->tk_action = call_reserveresult;
1703*4882a593Smuzhiyun xprt_retry_reserve(task);
1704*4882a593Smuzhiyun }
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun /*
1707*4882a593Smuzhiyun * 2. Bind and/or refresh the credentials
1708*4882a593Smuzhiyun */
1709*4882a593Smuzhiyun static void
call_refresh(struct rpc_task * task)1710*4882a593Smuzhiyun call_refresh(struct rpc_task *task)
1711*4882a593Smuzhiyun {
1712*4882a593Smuzhiyun task->tk_action = call_refreshresult;
1713*4882a593Smuzhiyun task->tk_status = 0;
1714*4882a593Smuzhiyun task->tk_client->cl_stats->rpcauthrefresh++;
1715*4882a593Smuzhiyun rpcauth_refreshcred(task);
1716*4882a593Smuzhiyun }
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun /*
1719*4882a593Smuzhiyun * 2a. Process the results of a credential refresh
1720*4882a593Smuzhiyun */
1721*4882a593Smuzhiyun static void
call_refreshresult(struct rpc_task * task)1722*4882a593Smuzhiyun call_refreshresult(struct rpc_task *task)
1723*4882a593Smuzhiyun {
1724*4882a593Smuzhiyun int status = task->tk_status;
1725*4882a593Smuzhiyun
1726*4882a593Smuzhiyun task->tk_status = 0;
1727*4882a593Smuzhiyun task->tk_action = call_refresh;
1728*4882a593Smuzhiyun switch (status) {
1729*4882a593Smuzhiyun case 0:
1730*4882a593Smuzhiyun if (rpcauth_uptodatecred(task)) {
1731*4882a593Smuzhiyun task->tk_action = call_allocate;
1732*4882a593Smuzhiyun return;
1733*4882a593Smuzhiyun }
1734*4882a593Smuzhiyun /* Use rate-limiting and a max number of retries if refresh
1735*4882a593Smuzhiyun * had status 0 but failed to update the cred.
1736*4882a593Smuzhiyun */
1737*4882a593Smuzhiyun fallthrough;
1738*4882a593Smuzhiyun case -ETIMEDOUT:
1739*4882a593Smuzhiyun rpc_delay(task, 3*HZ);
1740*4882a593Smuzhiyun fallthrough;
1741*4882a593Smuzhiyun case -EAGAIN:
1742*4882a593Smuzhiyun status = -EACCES;
1743*4882a593Smuzhiyun fallthrough;
1744*4882a593Smuzhiyun case -EKEYEXPIRED:
1745*4882a593Smuzhiyun if (!task->tk_cred_retry)
1746*4882a593Smuzhiyun break;
1747*4882a593Smuzhiyun task->tk_cred_retry--;
1748*4882a593Smuzhiyun trace_rpc_retry_refresh_status(task);
1749*4882a593Smuzhiyun return;
1750*4882a593Smuzhiyun }
1751*4882a593Smuzhiyun trace_rpc_refresh_status(task);
1752*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
1753*4882a593Smuzhiyun }
1754*4882a593Smuzhiyun
1755*4882a593Smuzhiyun /*
1756*4882a593Smuzhiyun * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc.
1757*4882a593Smuzhiyun * (Note: buffer memory is freed in xprt_release).
1758*4882a593Smuzhiyun */
1759*4882a593Smuzhiyun static void
call_allocate(struct rpc_task * task)1760*4882a593Smuzhiyun call_allocate(struct rpc_task *task)
1761*4882a593Smuzhiyun {
1762*4882a593Smuzhiyun const struct rpc_auth *auth = task->tk_rqstp->rq_cred->cr_auth;
1763*4882a593Smuzhiyun struct rpc_rqst *req = task->tk_rqstp;
1764*4882a593Smuzhiyun struct rpc_xprt *xprt = req->rq_xprt;
1765*4882a593Smuzhiyun const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
1766*4882a593Smuzhiyun int status;
1767*4882a593Smuzhiyun
1768*4882a593Smuzhiyun task->tk_status = 0;
1769*4882a593Smuzhiyun task->tk_action = call_encode;
1770*4882a593Smuzhiyun
1771*4882a593Smuzhiyun if (req->rq_buffer)
1772*4882a593Smuzhiyun return;
1773*4882a593Smuzhiyun
1774*4882a593Smuzhiyun if (proc->p_proc != 0) {
1775*4882a593Smuzhiyun BUG_ON(proc->p_arglen == 0);
1776*4882a593Smuzhiyun if (proc->p_decode != NULL)
1777*4882a593Smuzhiyun BUG_ON(proc->p_replen == 0);
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun
1780*4882a593Smuzhiyun /*
1781*4882a593Smuzhiyun * Calculate the size (in quads) of the RPC call
1782*4882a593Smuzhiyun * and reply headers, and convert both values
1783*4882a593Smuzhiyun * to byte sizes.
1784*4882a593Smuzhiyun */
1785*4882a593Smuzhiyun req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) +
1786*4882a593Smuzhiyun proc->p_arglen;
1787*4882a593Smuzhiyun req->rq_callsize <<= 2;
1788*4882a593Smuzhiyun /*
1789*4882a593Smuzhiyun * Note: the reply buffer must at minimum allocate enough space
1790*4882a593Smuzhiyun * for the 'struct accepted_reply' from RFC5531.
1791*4882a593Smuzhiyun */
1792*4882a593Smuzhiyun req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + \
1793*4882a593Smuzhiyun max_t(size_t, proc->p_replen, 2);
1794*4882a593Smuzhiyun req->rq_rcvsize <<= 2;
1795*4882a593Smuzhiyun
1796*4882a593Smuzhiyun status = xprt->ops->buf_alloc(task);
1797*4882a593Smuzhiyun trace_rpc_buf_alloc(task, status);
1798*4882a593Smuzhiyun if (status == 0)
1799*4882a593Smuzhiyun return;
1800*4882a593Smuzhiyun if (status != -ENOMEM) {
1801*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
1802*4882a593Smuzhiyun return;
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
1806*4882a593Smuzhiyun task->tk_action = call_allocate;
1807*4882a593Smuzhiyun rpc_delay(task, HZ>>4);
1808*4882a593Smuzhiyun return;
1809*4882a593Smuzhiyun }
1810*4882a593Smuzhiyun
1811*4882a593Smuzhiyun rpc_call_rpcerror(task, -ERESTARTSYS);
1812*4882a593Smuzhiyun }
1813*4882a593Smuzhiyun
1814*4882a593Smuzhiyun static int
rpc_task_need_encode(struct rpc_task * task)1815*4882a593Smuzhiyun rpc_task_need_encode(struct rpc_task *task)
1816*4882a593Smuzhiyun {
1817*4882a593Smuzhiyun return test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate) == 0 &&
1818*4882a593Smuzhiyun (!(task->tk_flags & RPC_TASK_SENT) ||
1819*4882a593Smuzhiyun !(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) ||
1820*4882a593Smuzhiyun xprt_request_need_retransmit(task));
1821*4882a593Smuzhiyun }
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun static void
rpc_xdr_encode(struct rpc_task * task)1824*4882a593Smuzhiyun rpc_xdr_encode(struct rpc_task *task)
1825*4882a593Smuzhiyun {
1826*4882a593Smuzhiyun struct rpc_rqst *req = task->tk_rqstp;
1827*4882a593Smuzhiyun struct xdr_stream xdr;
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun xdr_buf_init(&req->rq_snd_buf,
1830*4882a593Smuzhiyun req->rq_buffer,
1831*4882a593Smuzhiyun req->rq_callsize);
1832*4882a593Smuzhiyun xdr_buf_init(&req->rq_rcv_buf,
1833*4882a593Smuzhiyun req->rq_rbuffer,
1834*4882a593Smuzhiyun req->rq_rcvsize);
1835*4882a593Smuzhiyun
1836*4882a593Smuzhiyun req->rq_reply_bytes_recvd = 0;
1837*4882a593Smuzhiyun req->rq_snd_buf.head[0].iov_len = 0;
1838*4882a593Smuzhiyun xdr_init_encode(&xdr, &req->rq_snd_buf,
1839*4882a593Smuzhiyun req->rq_snd_buf.head[0].iov_base, req);
1840*4882a593Smuzhiyun xdr_free_bvec(&req->rq_snd_buf);
1841*4882a593Smuzhiyun if (rpc_encode_header(task, &xdr))
1842*4882a593Smuzhiyun return;
1843*4882a593Smuzhiyun
1844*4882a593Smuzhiyun task->tk_status = rpcauth_wrap_req(task, &xdr);
1845*4882a593Smuzhiyun }
1846*4882a593Smuzhiyun
1847*4882a593Smuzhiyun /*
1848*4882a593Smuzhiyun * 3. Encode arguments of an RPC call
1849*4882a593Smuzhiyun */
1850*4882a593Smuzhiyun static void
call_encode(struct rpc_task * task)1851*4882a593Smuzhiyun call_encode(struct rpc_task *task)
1852*4882a593Smuzhiyun {
1853*4882a593Smuzhiyun if (!rpc_task_need_encode(task))
1854*4882a593Smuzhiyun goto out;
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun /* Dequeue task from the receive queue while we're encoding */
1857*4882a593Smuzhiyun xprt_request_dequeue_xprt(task);
1858*4882a593Smuzhiyun /* Encode here so that rpcsec_gss can use correct sequence number. */
1859*4882a593Smuzhiyun rpc_xdr_encode(task);
1860*4882a593Smuzhiyun /* Did the encode result in an error condition? */
1861*4882a593Smuzhiyun if (task->tk_status != 0) {
1862*4882a593Smuzhiyun /* Was the error nonfatal? */
1863*4882a593Smuzhiyun switch (task->tk_status) {
1864*4882a593Smuzhiyun case -EAGAIN:
1865*4882a593Smuzhiyun case -ENOMEM:
1866*4882a593Smuzhiyun rpc_delay(task, HZ >> 4);
1867*4882a593Smuzhiyun break;
1868*4882a593Smuzhiyun case -EKEYEXPIRED:
1869*4882a593Smuzhiyun if (!task->tk_cred_retry) {
1870*4882a593Smuzhiyun rpc_call_rpcerror(task, task->tk_status);
1871*4882a593Smuzhiyun } else {
1872*4882a593Smuzhiyun task->tk_action = call_refresh;
1873*4882a593Smuzhiyun task->tk_cred_retry--;
1874*4882a593Smuzhiyun trace_rpc_retry_refresh_status(task);
1875*4882a593Smuzhiyun }
1876*4882a593Smuzhiyun break;
1877*4882a593Smuzhiyun default:
1878*4882a593Smuzhiyun rpc_call_rpcerror(task, task->tk_status);
1879*4882a593Smuzhiyun }
1880*4882a593Smuzhiyun return;
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun /* Add task to reply queue before transmission to avoid races */
1884*4882a593Smuzhiyun if (rpc_reply_expected(task))
1885*4882a593Smuzhiyun xprt_request_enqueue_receive(task);
1886*4882a593Smuzhiyun xprt_request_enqueue_transmit(task);
1887*4882a593Smuzhiyun out:
1888*4882a593Smuzhiyun task->tk_action = call_transmit;
1889*4882a593Smuzhiyun /* Check that the connection is OK */
1890*4882a593Smuzhiyun if (!xprt_bound(task->tk_xprt))
1891*4882a593Smuzhiyun task->tk_action = call_bind;
1892*4882a593Smuzhiyun else if (!xprt_connected(task->tk_xprt))
1893*4882a593Smuzhiyun task->tk_action = call_connect;
1894*4882a593Smuzhiyun }
1895*4882a593Smuzhiyun
1896*4882a593Smuzhiyun /*
1897*4882a593Smuzhiyun * Helpers to check if the task was already transmitted, and
1898*4882a593Smuzhiyun * to take action when that is the case.
1899*4882a593Smuzhiyun */
1900*4882a593Smuzhiyun static bool
rpc_task_transmitted(struct rpc_task * task)1901*4882a593Smuzhiyun rpc_task_transmitted(struct rpc_task *task)
1902*4882a593Smuzhiyun {
1903*4882a593Smuzhiyun return !test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate);
1904*4882a593Smuzhiyun }
1905*4882a593Smuzhiyun
1906*4882a593Smuzhiyun static void
rpc_task_handle_transmitted(struct rpc_task * task)1907*4882a593Smuzhiyun rpc_task_handle_transmitted(struct rpc_task *task)
1908*4882a593Smuzhiyun {
1909*4882a593Smuzhiyun xprt_end_transmit(task);
1910*4882a593Smuzhiyun task->tk_action = call_transmit_status;
1911*4882a593Smuzhiyun }
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun /*
1914*4882a593Smuzhiyun * 4. Get the server port number if not yet set
1915*4882a593Smuzhiyun */
1916*4882a593Smuzhiyun static void
call_bind(struct rpc_task * task)1917*4882a593Smuzhiyun call_bind(struct rpc_task *task)
1918*4882a593Smuzhiyun {
1919*4882a593Smuzhiyun struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
1922*4882a593Smuzhiyun rpc_task_handle_transmitted(task);
1923*4882a593Smuzhiyun return;
1924*4882a593Smuzhiyun }
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun if (xprt_bound(xprt)) {
1927*4882a593Smuzhiyun task->tk_action = call_connect;
1928*4882a593Smuzhiyun return;
1929*4882a593Smuzhiyun }
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun task->tk_action = call_bind_status;
1932*4882a593Smuzhiyun if (!xprt_prepare_transmit(task))
1933*4882a593Smuzhiyun return;
1934*4882a593Smuzhiyun
1935*4882a593Smuzhiyun xprt->ops->rpcbind(task);
1936*4882a593Smuzhiyun }
1937*4882a593Smuzhiyun
1938*4882a593Smuzhiyun /*
1939*4882a593Smuzhiyun * 4a. Sort out bind result
1940*4882a593Smuzhiyun */
1941*4882a593Smuzhiyun static void
call_bind_status(struct rpc_task * task)1942*4882a593Smuzhiyun call_bind_status(struct rpc_task *task)
1943*4882a593Smuzhiyun {
1944*4882a593Smuzhiyun struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
1945*4882a593Smuzhiyun int status = -EIO;
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
1948*4882a593Smuzhiyun rpc_task_handle_transmitted(task);
1949*4882a593Smuzhiyun return;
1950*4882a593Smuzhiyun }
1951*4882a593Smuzhiyun
1952*4882a593Smuzhiyun if (task->tk_status >= 0)
1953*4882a593Smuzhiyun goto out_next;
1954*4882a593Smuzhiyun if (xprt_bound(xprt)) {
1955*4882a593Smuzhiyun task->tk_status = 0;
1956*4882a593Smuzhiyun goto out_next;
1957*4882a593Smuzhiyun }
1958*4882a593Smuzhiyun
1959*4882a593Smuzhiyun switch (task->tk_status) {
1960*4882a593Smuzhiyun case -ENOMEM:
1961*4882a593Smuzhiyun rpc_delay(task, HZ >> 2);
1962*4882a593Smuzhiyun goto retry_timeout;
1963*4882a593Smuzhiyun case -EACCES:
1964*4882a593Smuzhiyun trace_rpcb_prog_unavail_err(task);
1965*4882a593Smuzhiyun /* fail immediately if this is an RPC ping */
1966*4882a593Smuzhiyun if (task->tk_msg.rpc_proc->p_proc == 0) {
1967*4882a593Smuzhiyun status = -EOPNOTSUPP;
1968*4882a593Smuzhiyun break;
1969*4882a593Smuzhiyun }
1970*4882a593Smuzhiyun if (task->tk_rebind_retry == 0)
1971*4882a593Smuzhiyun break;
1972*4882a593Smuzhiyun task->tk_rebind_retry--;
1973*4882a593Smuzhiyun rpc_delay(task, 3*HZ);
1974*4882a593Smuzhiyun goto retry_timeout;
1975*4882a593Smuzhiyun case -ENOBUFS:
1976*4882a593Smuzhiyun rpc_delay(task, HZ >> 2);
1977*4882a593Smuzhiyun goto retry_timeout;
1978*4882a593Smuzhiyun case -EAGAIN:
1979*4882a593Smuzhiyun goto retry_timeout;
1980*4882a593Smuzhiyun case -ETIMEDOUT:
1981*4882a593Smuzhiyun trace_rpcb_timeout_err(task);
1982*4882a593Smuzhiyun goto retry_timeout;
1983*4882a593Smuzhiyun case -EPFNOSUPPORT:
1984*4882a593Smuzhiyun /* server doesn't support any rpcbind version we know of */
1985*4882a593Smuzhiyun trace_rpcb_bind_version_err(task);
1986*4882a593Smuzhiyun break;
1987*4882a593Smuzhiyun case -EPROTONOSUPPORT:
1988*4882a593Smuzhiyun trace_rpcb_bind_version_err(task);
1989*4882a593Smuzhiyun goto retry_timeout;
1990*4882a593Smuzhiyun case -ECONNREFUSED: /* connection problems */
1991*4882a593Smuzhiyun case -ECONNRESET:
1992*4882a593Smuzhiyun case -ECONNABORTED:
1993*4882a593Smuzhiyun case -ENOTCONN:
1994*4882a593Smuzhiyun case -EHOSTDOWN:
1995*4882a593Smuzhiyun case -ENETDOWN:
1996*4882a593Smuzhiyun case -EHOSTUNREACH:
1997*4882a593Smuzhiyun case -ENETUNREACH:
1998*4882a593Smuzhiyun case -EPIPE:
1999*4882a593Smuzhiyun trace_rpcb_unreachable_err(task);
2000*4882a593Smuzhiyun if (!RPC_IS_SOFTCONN(task)) {
2001*4882a593Smuzhiyun rpc_delay(task, 5*HZ);
2002*4882a593Smuzhiyun goto retry_timeout;
2003*4882a593Smuzhiyun }
2004*4882a593Smuzhiyun status = task->tk_status;
2005*4882a593Smuzhiyun break;
2006*4882a593Smuzhiyun default:
2007*4882a593Smuzhiyun trace_rpcb_unrecognized_err(task);
2008*4882a593Smuzhiyun }
2009*4882a593Smuzhiyun
2010*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
2011*4882a593Smuzhiyun return;
2012*4882a593Smuzhiyun out_next:
2013*4882a593Smuzhiyun task->tk_action = call_connect;
2014*4882a593Smuzhiyun return;
2015*4882a593Smuzhiyun retry_timeout:
2016*4882a593Smuzhiyun task->tk_status = 0;
2017*4882a593Smuzhiyun task->tk_action = call_bind;
2018*4882a593Smuzhiyun rpc_check_timeout(task);
2019*4882a593Smuzhiyun }
2020*4882a593Smuzhiyun
2021*4882a593Smuzhiyun /*
2022*4882a593Smuzhiyun * 4b. Connect to the RPC server
2023*4882a593Smuzhiyun */
2024*4882a593Smuzhiyun static void
call_connect(struct rpc_task * task)2025*4882a593Smuzhiyun call_connect(struct rpc_task *task)
2026*4882a593Smuzhiyun {
2027*4882a593Smuzhiyun struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
2028*4882a593Smuzhiyun
2029*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
2030*4882a593Smuzhiyun rpc_task_handle_transmitted(task);
2031*4882a593Smuzhiyun return;
2032*4882a593Smuzhiyun }
2033*4882a593Smuzhiyun
2034*4882a593Smuzhiyun if (xprt_connected(xprt)) {
2035*4882a593Smuzhiyun task->tk_action = call_transmit;
2036*4882a593Smuzhiyun return;
2037*4882a593Smuzhiyun }
2038*4882a593Smuzhiyun
2039*4882a593Smuzhiyun task->tk_action = call_connect_status;
2040*4882a593Smuzhiyun if (task->tk_status < 0)
2041*4882a593Smuzhiyun return;
2042*4882a593Smuzhiyun if (task->tk_flags & RPC_TASK_NOCONNECT) {
2043*4882a593Smuzhiyun rpc_call_rpcerror(task, -ENOTCONN);
2044*4882a593Smuzhiyun return;
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun if (!xprt_prepare_transmit(task))
2047*4882a593Smuzhiyun return;
2048*4882a593Smuzhiyun xprt_connect(task);
2049*4882a593Smuzhiyun }
2050*4882a593Smuzhiyun
2051*4882a593Smuzhiyun /*
2052*4882a593Smuzhiyun * 4c. Sort out connect result
2053*4882a593Smuzhiyun */
2054*4882a593Smuzhiyun static void
call_connect_status(struct rpc_task * task)2055*4882a593Smuzhiyun call_connect_status(struct rpc_task *task)
2056*4882a593Smuzhiyun {
2057*4882a593Smuzhiyun struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
2058*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2059*4882a593Smuzhiyun int status = task->tk_status;
2060*4882a593Smuzhiyun
2061*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
2062*4882a593Smuzhiyun rpc_task_handle_transmitted(task);
2063*4882a593Smuzhiyun return;
2064*4882a593Smuzhiyun }
2065*4882a593Smuzhiyun
2066*4882a593Smuzhiyun trace_rpc_connect_status(task);
2067*4882a593Smuzhiyun
2068*4882a593Smuzhiyun if (task->tk_status == 0) {
2069*4882a593Smuzhiyun clnt->cl_stats->netreconn++;
2070*4882a593Smuzhiyun goto out_next;
2071*4882a593Smuzhiyun }
2072*4882a593Smuzhiyun if (xprt_connected(xprt)) {
2073*4882a593Smuzhiyun task->tk_status = 0;
2074*4882a593Smuzhiyun goto out_next;
2075*4882a593Smuzhiyun }
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun task->tk_status = 0;
2078*4882a593Smuzhiyun switch (status) {
2079*4882a593Smuzhiyun case -ECONNREFUSED:
2080*4882a593Smuzhiyun /* A positive refusal suggests a rebind is needed. */
2081*4882a593Smuzhiyun if (RPC_IS_SOFTCONN(task))
2082*4882a593Smuzhiyun break;
2083*4882a593Smuzhiyun if (clnt->cl_autobind) {
2084*4882a593Smuzhiyun rpc_force_rebind(clnt);
2085*4882a593Smuzhiyun goto out_retry;
2086*4882a593Smuzhiyun }
2087*4882a593Smuzhiyun fallthrough;
2088*4882a593Smuzhiyun case -ECONNRESET:
2089*4882a593Smuzhiyun case -ECONNABORTED:
2090*4882a593Smuzhiyun case -ENETDOWN:
2091*4882a593Smuzhiyun case -ENETUNREACH:
2092*4882a593Smuzhiyun case -EHOSTUNREACH:
2093*4882a593Smuzhiyun case -EPIPE:
2094*4882a593Smuzhiyun case -EPROTO:
2095*4882a593Smuzhiyun xprt_conditional_disconnect(task->tk_rqstp->rq_xprt,
2096*4882a593Smuzhiyun task->tk_rqstp->rq_connect_cookie);
2097*4882a593Smuzhiyun if (RPC_IS_SOFTCONN(task))
2098*4882a593Smuzhiyun break;
2099*4882a593Smuzhiyun /* retry with existing socket, after a delay */
2100*4882a593Smuzhiyun rpc_delay(task, 3*HZ);
2101*4882a593Smuzhiyun fallthrough;
2102*4882a593Smuzhiyun case -EADDRINUSE:
2103*4882a593Smuzhiyun case -ENOTCONN:
2104*4882a593Smuzhiyun case -EAGAIN:
2105*4882a593Smuzhiyun case -ETIMEDOUT:
2106*4882a593Smuzhiyun goto out_retry;
2107*4882a593Smuzhiyun case -ENOBUFS:
2108*4882a593Smuzhiyun rpc_delay(task, HZ >> 2);
2109*4882a593Smuzhiyun goto out_retry;
2110*4882a593Smuzhiyun }
2111*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
2112*4882a593Smuzhiyun return;
2113*4882a593Smuzhiyun out_next:
2114*4882a593Smuzhiyun task->tk_action = call_transmit;
2115*4882a593Smuzhiyun return;
2116*4882a593Smuzhiyun out_retry:
2117*4882a593Smuzhiyun /* Check for timeouts before looping back to call_bind */
2118*4882a593Smuzhiyun task->tk_action = call_bind;
2119*4882a593Smuzhiyun rpc_check_timeout(task);
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun
2122*4882a593Smuzhiyun /*
2123*4882a593Smuzhiyun * 5. Transmit the RPC request, and wait for reply
2124*4882a593Smuzhiyun */
2125*4882a593Smuzhiyun static void
call_transmit(struct rpc_task * task)2126*4882a593Smuzhiyun call_transmit(struct rpc_task *task)
2127*4882a593Smuzhiyun {
2128*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
2129*4882a593Smuzhiyun rpc_task_handle_transmitted(task);
2130*4882a593Smuzhiyun return;
2131*4882a593Smuzhiyun }
2132*4882a593Smuzhiyun
2133*4882a593Smuzhiyun task->tk_action = call_transmit_status;
2134*4882a593Smuzhiyun if (!xprt_prepare_transmit(task))
2135*4882a593Smuzhiyun return;
2136*4882a593Smuzhiyun task->tk_status = 0;
2137*4882a593Smuzhiyun if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
2138*4882a593Smuzhiyun if (!xprt_connected(task->tk_xprt)) {
2139*4882a593Smuzhiyun task->tk_status = -ENOTCONN;
2140*4882a593Smuzhiyun return;
2141*4882a593Smuzhiyun }
2142*4882a593Smuzhiyun xprt_transmit(task);
2143*4882a593Smuzhiyun }
2144*4882a593Smuzhiyun xprt_end_transmit(task);
2145*4882a593Smuzhiyun }
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun /*
2148*4882a593Smuzhiyun * 5a. Handle cleanup after a transmission
2149*4882a593Smuzhiyun */
2150*4882a593Smuzhiyun static void
call_transmit_status(struct rpc_task * task)2151*4882a593Smuzhiyun call_transmit_status(struct rpc_task *task)
2152*4882a593Smuzhiyun {
2153*4882a593Smuzhiyun task->tk_action = call_status;
2154*4882a593Smuzhiyun
2155*4882a593Smuzhiyun /*
2156*4882a593Smuzhiyun * Common case: success. Force the compiler to put this
2157*4882a593Smuzhiyun * test first.
2158*4882a593Smuzhiyun */
2159*4882a593Smuzhiyun if (rpc_task_transmitted(task)) {
2160*4882a593Smuzhiyun task->tk_status = 0;
2161*4882a593Smuzhiyun xprt_request_wait_receive(task);
2162*4882a593Smuzhiyun return;
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun switch (task->tk_status) {
2166*4882a593Smuzhiyun default:
2167*4882a593Smuzhiyun break;
2168*4882a593Smuzhiyun case -EBADMSG:
2169*4882a593Smuzhiyun task->tk_status = 0;
2170*4882a593Smuzhiyun task->tk_action = call_encode;
2171*4882a593Smuzhiyun break;
2172*4882a593Smuzhiyun /*
2173*4882a593Smuzhiyun * Special cases: if we've been waiting on the
2174*4882a593Smuzhiyun * socket's write_space() callback, or if the
2175*4882a593Smuzhiyun * socket just returned a connection error,
2176*4882a593Smuzhiyun * then hold onto the transport lock.
2177*4882a593Smuzhiyun */
2178*4882a593Smuzhiyun case -ENOMEM:
2179*4882a593Smuzhiyun case -ENOBUFS:
2180*4882a593Smuzhiyun rpc_delay(task, HZ>>2);
2181*4882a593Smuzhiyun fallthrough;
2182*4882a593Smuzhiyun case -EBADSLT:
2183*4882a593Smuzhiyun case -EAGAIN:
2184*4882a593Smuzhiyun task->tk_action = call_transmit;
2185*4882a593Smuzhiyun task->tk_status = 0;
2186*4882a593Smuzhiyun break;
2187*4882a593Smuzhiyun case -ECONNREFUSED:
2188*4882a593Smuzhiyun case -EHOSTDOWN:
2189*4882a593Smuzhiyun case -ENETDOWN:
2190*4882a593Smuzhiyun case -EHOSTUNREACH:
2191*4882a593Smuzhiyun case -ENETUNREACH:
2192*4882a593Smuzhiyun case -EPERM:
2193*4882a593Smuzhiyun if (RPC_IS_SOFTCONN(task)) {
2194*4882a593Smuzhiyun if (!task->tk_msg.rpc_proc->p_proc)
2195*4882a593Smuzhiyun trace_xprt_ping(task->tk_xprt,
2196*4882a593Smuzhiyun task->tk_status);
2197*4882a593Smuzhiyun rpc_call_rpcerror(task, task->tk_status);
2198*4882a593Smuzhiyun return;
2199*4882a593Smuzhiyun }
2200*4882a593Smuzhiyun fallthrough;
2201*4882a593Smuzhiyun case -ECONNRESET:
2202*4882a593Smuzhiyun case -ECONNABORTED:
2203*4882a593Smuzhiyun case -EADDRINUSE:
2204*4882a593Smuzhiyun case -ENOTCONN:
2205*4882a593Smuzhiyun case -EPIPE:
2206*4882a593Smuzhiyun task->tk_action = call_bind;
2207*4882a593Smuzhiyun task->tk_status = 0;
2208*4882a593Smuzhiyun break;
2209*4882a593Smuzhiyun }
2210*4882a593Smuzhiyun rpc_check_timeout(task);
2211*4882a593Smuzhiyun }
2212*4882a593Smuzhiyun
2213*4882a593Smuzhiyun #if defined(CONFIG_SUNRPC_BACKCHANNEL)
2214*4882a593Smuzhiyun static void call_bc_transmit(struct rpc_task *task);
2215*4882a593Smuzhiyun static void call_bc_transmit_status(struct rpc_task *task);
2216*4882a593Smuzhiyun
2217*4882a593Smuzhiyun static void
call_bc_encode(struct rpc_task * task)2218*4882a593Smuzhiyun call_bc_encode(struct rpc_task *task)
2219*4882a593Smuzhiyun {
2220*4882a593Smuzhiyun xprt_request_enqueue_transmit(task);
2221*4882a593Smuzhiyun task->tk_action = call_bc_transmit;
2222*4882a593Smuzhiyun }
2223*4882a593Smuzhiyun
2224*4882a593Smuzhiyun /*
2225*4882a593Smuzhiyun * 5b. Send the backchannel RPC reply. On error, drop the reply. In
2226*4882a593Smuzhiyun * addition, disconnect on connectivity errors.
2227*4882a593Smuzhiyun */
2228*4882a593Smuzhiyun static void
call_bc_transmit(struct rpc_task * task)2229*4882a593Smuzhiyun call_bc_transmit(struct rpc_task *task)
2230*4882a593Smuzhiyun {
2231*4882a593Smuzhiyun task->tk_action = call_bc_transmit_status;
2232*4882a593Smuzhiyun if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
2233*4882a593Smuzhiyun if (!xprt_prepare_transmit(task))
2234*4882a593Smuzhiyun return;
2235*4882a593Smuzhiyun task->tk_status = 0;
2236*4882a593Smuzhiyun xprt_transmit(task);
2237*4882a593Smuzhiyun }
2238*4882a593Smuzhiyun xprt_end_transmit(task);
2239*4882a593Smuzhiyun }
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun static void
call_bc_transmit_status(struct rpc_task * task)2242*4882a593Smuzhiyun call_bc_transmit_status(struct rpc_task *task)
2243*4882a593Smuzhiyun {
2244*4882a593Smuzhiyun struct rpc_rqst *req = task->tk_rqstp;
2245*4882a593Smuzhiyun
2246*4882a593Smuzhiyun if (rpc_task_transmitted(task))
2247*4882a593Smuzhiyun task->tk_status = 0;
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun switch (task->tk_status) {
2250*4882a593Smuzhiyun case 0:
2251*4882a593Smuzhiyun /* Success */
2252*4882a593Smuzhiyun case -ENETDOWN:
2253*4882a593Smuzhiyun case -EHOSTDOWN:
2254*4882a593Smuzhiyun case -EHOSTUNREACH:
2255*4882a593Smuzhiyun case -ENETUNREACH:
2256*4882a593Smuzhiyun case -ECONNRESET:
2257*4882a593Smuzhiyun case -ECONNREFUSED:
2258*4882a593Smuzhiyun case -EADDRINUSE:
2259*4882a593Smuzhiyun case -ENOTCONN:
2260*4882a593Smuzhiyun case -EPIPE:
2261*4882a593Smuzhiyun break;
2262*4882a593Smuzhiyun case -ENOMEM:
2263*4882a593Smuzhiyun case -ENOBUFS:
2264*4882a593Smuzhiyun rpc_delay(task, HZ>>2);
2265*4882a593Smuzhiyun fallthrough;
2266*4882a593Smuzhiyun case -EBADSLT:
2267*4882a593Smuzhiyun case -EAGAIN:
2268*4882a593Smuzhiyun task->tk_status = 0;
2269*4882a593Smuzhiyun task->tk_action = call_bc_transmit;
2270*4882a593Smuzhiyun return;
2271*4882a593Smuzhiyun case -ETIMEDOUT:
2272*4882a593Smuzhiyun /*
2273*4882a593Smuzhiyun * Problem reaching the server. Disconnect and let the
2274*4882a593Smuzhiyun * forechannel reestablish the connection. The server will
2275*4882a593Smuzhiyun * have to retransmit the backchannel request and we'll
2276*4882a593Smuzhiyun * reprocess it. Since these ops are idempotent, there's no
2277*4882a593Smuzhiyun * need to cache our reply at this time.
2278*4882a593Smuzhiyun */
2279*4882a593Smuzhiyun printk(KERN_NOTICE "RPC: Could not send backchannel reply "
2280*4882a593Smuzhiyun "error: %d\n", task->tk_status);
2281*4882a593Smuzhiyun xprt_conditional_disconnect(req->rq_xprt,
2282*4882a593Smuzhiyun req->rq_connect_cookie);
2283*4882a593Smuzhiyun break;
2284*4882a593Smuzhiyun default:
2285*4882a593Smuzhiyun /*
2286*4882a593Smuzhiyun * We were unable to reply and will have to drop the
2287*4882a593Smuzhiyun * request. The server should reconnect and retransmit.
2288*4882a593Smuzhiyun */
2289*4882a593Smuzhiyun printk(KERN_NOTICE "RPC: Could not send backchannel reply "
2290*4882a593Smuzhiyun "error: %d\n", task->tk_status);
2291*4882a593Smuzhiyun break;
2292*4882a593Smuzhiyun }
2293*4882a593Smuzhiyun task->tk_action = rpc_exit_task;
2294*4882a593Smuzhiyun }
2295*4882a593Smuzhiyun #endif /* CONFIG_SUNRPC_BACKCHANNEL */
2296*4882a593Smuzhiyun
2297*4882a593Smuzhiyun /*
2298*4882a593Smuzhiyun * 6. Sort out the RPC call status
2299*4882a593Smuzhiyun */
2300*4882a593Smuzhiyun static void
call_status(struct rpc_task * task)2301*4882a593Smuzhiyun call_status(struct rpc_task *task)
2302*4882a593Smuzhiyun {
2303*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2304*4882a593Smuzhiyun int status;
2305*4882a593Smuzhiyun
2306*4882a593Smuzhiyun if (!task->tk_msg.rpc_proc->p_proc)
2307*4882a593Smuzhiyun trace_xprt_ping(task->tk_xprt, task->tk_status);
2308*4882a593Smuzhiyun
2309*4882a593Smuzhiyun status = task->tk_status;
2310*4882a593Smuzhiyun if (status >= 0) {
2311*4882a593Smuzhiyun task->tk_action = call_decode;
2312*4882a593Smuzhiyun return;
2313*4882a593Smuzhiyun }
2314*4882a593Smuzhiyun
2315*4882a593Smuzhiyun trace_rpc_call_status(task);
2316*4882a593Smuzhiyun task->tk_status = 0;
2317*4882a593Smuzhiyun switch(status) {
2318*4882a593Smuzhiyun case -EHOSTDOWN:
2319*4882a593Smuzhiyun case -ENETDOWN:
2320*4882a593Smuzhiyun case -EHOSTUNREACH:
2321*4882a593Smuzhiyun case -ENETUNREACH:
2322*4882a593Smuzhiyun case -EPERM:
2323*4882a593Smuzhiyun if (RPC_IS_SOFTCONN(task))
2324*4882a593Smuzhiyun goto out_exit;
2325*4882a593Smuzhiyun /*
2326*4882a593Smuzhiyun * Delay any retries for 3 seconds, then handle as if it
2327*4882a593Smuzhiyun * were a timeout.
2328*4882a593Smuzhiyun */
2329*4882a593Smuzhiyun rpc_delay(task, 3*HZ);
2330*4882a593Smuzhiyun fallthrough;
2331*4882a593Smuzhiyun case -ETIMEDOUT:
2332*4882a593Smuzhiyun break;
2333*4882a593Smuzhiyun case -ECONNREFUSED:
2334*4882a593Smuzhiyun case -ECONNRESET:
2335*4882a593Smuzhiyun case -ECONNABORTED:
2336*4882a593Smuzhiyun case -ENOTCONN:
2337*4882a593Smuzhiyun rpc_force_rebind(clnt);
2338*4882a593Smuzhiyun break;
2339*4882a593Smuzhiyun case -EADDRINUSE:
2340*4882a593Smuzhiyun rpc_delay(task, 3*HZ);
2341*4882a593Smuzhiyun fallthrough;
2342*4882a593Smuzhiyun case -EPIPE:
2343*4882a593Smuzhiyun case -EAGAIN:
2344*4882a593Smuzhiyun break;
2345*4882a593Smuzhiyun case -ENFILE:
2346*4882a593Smuzhiyun case -ENOBUFS:
2347*4882a593Smuzhiyun case -ENOMEM:
2348*4882a593Smuzhiyun rpc_delay(task, HZ>>2);
2349*4882a593Smuzhiyun break;
2350*4882a593Smuzhiyun case -EIO:
2351*4882a593Smuzhiyun /* shutdown or soft timeout */
2352*4882a593Smuzhiyun goto out_exit;
2353*4882a593Smuzhiyun default:
2354*4882a593Smuzhiyun if (clnt->cl_chatty)
2355*4882a593Smuzhiyun printk("%s: RPC call returned error %d\n",
2356*4882a593Smuzhiyun clnt->cl_program->name, -status);
2357*4882a593Smuzhiyun goto out_exit;
2358*4882a593Smuzhiyun }
2359*4882a593Smuzhiyun task->tk_action = call_encode;
2360*4882a593Smuzhiyun if (status != -ECONNRESET && status != -ECONNABORTED)
2361*4882a593Smuzhiyun rpc_check_timeout(task);
2362*4882a593Smuzhiyun return;
2363*4882a593Smuzhiyun out_exit:
2364*4882a593Smuzhiyun rpc_call_rpcerror(task, status);
2365*4882a593Smuzhiyun }
2366*4882a593Smuzhiyun
2367*4882a593Smuzhiyun static bool
rpc_check_connected(const struct rpc_rqst * req)2368*4882a593Smuzhiyun rpc_check_connected(const struct rpc_rqst *req)
2369*4882a593Smuzhiyun {
2370*4882a593Smuzhiyun /* No allocated request or transport? return true */
2371*4882a593Smuzhiyun if (!req || !req->rq_xprt)
2372*4882a593Smuzhiyun return true;
2373*4882a593Smuzhiyun return xprt_connected(req->rq_xprt);
2374*4882a593Smuzhiyun }
2375*4882a593Smuzhiyun
2376*4882a593Smuzhiyun static void
rpc_check_timeout(struct rpc_task * task)2377*4882a593Smuzhiyun rpc_check_timeout(struct rpc_task *task)
2378*4882a593Smuzhiyun {
2379*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2380*4882a593Smuzhiyun
2381*4882a593Smuzhiyun if (RPC_SIGNALLED(task)) {
2382*4882a593Smuzhiyun rpc_call_rpcerror(task, -ERESTARTSYS);
2383*4882a593Smuzhiyun return;
2384*4882a593Smuzhiyun }
2385*4882a593Smuzhiyun
2386*4882a593Smuzhiyun if (xprt_adjust_timeout(task->tk_rqstp) == 0)
2387*4882a593Smuzhiyun return;
2388*4882a593Smuzhiyun
2389*4882a593Smuzhiyun trace_rpc_timeout_status(task);
2390*4882a593Smuzhiyun task->tk_timeouts++;
2391*4882a593Smuzhiyun
2392*4882a593Smuzhiyun if (RPC_IS_SOFTCONN(task) && !rpc_check_connected(task->tk_rqstp)) {
2393*4882a593Smuzhiyun rpc_call_rpcerror(task, -ETIMEDOUT);
2394*4882a593Smuzhiyun return;
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun if (RPC_IS_SOFT(task)) {
2398*4882a593Smuzhiyun /*
2399*4882a593Smuzhiyun * Once a "no retrans timeout" soft tasks (a.k.a NFSv4) has
2400*4882a593Smuzhiyun * been sent, it should time out only if the transport
2401*4882a593Smuzhiyun * connection gets terminally broken.
2402*4882a593Smuzhiyun */
2403*4882a593Smuzhiyun if ((task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) &&
2404*4882a593Smuzhiyun rpc_check_connected(task->tk_rqstp))
2405*4882a593Smuzhiyun return;
2406*4882a593Smuzhiyun
2407*4882a593Smuzhiyun if (clnt->cl_chatty) {
2408*4882a593Smuzhiyun pr_notice_ratelimited(
2409*4882a593Smuzhiyun "%s: server %s not responding, timed out\n",
2410*4882a593Smuzhiyun clnt->cl_program->name,
2411*4882a593Smuzhiyun task->tk_xprt->servername);
2412*4882a593Smuzhiyun }
2413*4882a593Smuzhiyun if (task->tk_flags & RPC_TASK_TIMEOUT)
2414*4882a593Smuzhiyun rpc_call_rpcerror(task, -ETIMEDOUT);
2415*4882a593Smuzhiyun else
2416*4882a593Smuzhiyun __rpc_call_rpcerror(task, -EIO, -ETIMEDOUT);
2417*4882a593Smuzhiyun return;
2418*4882a593Smuzhiyun }
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
2421*4882a593Smuzhiyun task->tk_flags |= RPC_CALL_MAJORSEEN;
2422*4882a593Smuzhiyun if (clnt->cl_chatty) {
2423*4882a593Smuzhiyun pr_notice_ratelimited(
2424*4882a593Smuzhiyun "%s: server %s not responding, still trying\n",
2425*4882a593Smuzhiyun clnt->cl_program->name,
2426*4882a593Smuzhiyun task->tk_xprt->servername);
2427*4882a593Smuzhiyun }
2428*4882a593Smuzhiyun }
2429*4882a593Smuzhiyun rpc_force_rebind(clnt);
2430*4882a593Smuzhiyun /*
2431*4882a593Smuzhiyun * Did our request time out due to an RPCSEC_GSS out-of-sequence
2432*4882a593Smuzhiyun * event? RFC2203 requires the server to drop all such requests.
2433*4882a593Smuzhiyun */
2434*4882a593Smuzhiyun rpcauth_invalcred(task);
2435*4882a593Smuzhiyun }
2436*4882a593Smuzhiyun
2437*4882a593Smuzhiyun /*
2438*4882a593Smuzhiyun * 7. Decode the RPC reply
2439*4882a593Smuzhiyun */
2440*4882a593Smuzhiyun static void
call_decode(struct rpc_task * task)2441*4882a593Smuzhiyun call_decode(struct rpc_task *task)
2442*4882a593Smuzhiyun {
2443*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2444*4882a593Smuzhiyun struct rpc_rqst *req = task->tk_rqstp;
2445*4882a593Smuzhiyun struct xdr_stream xdr;
2446*4882a593Smuzhiyun int err;
2447*4882a593Smuzhiyun
2448*4882a593Smuzhiyun if (!task->tk_msg.rpc_proc->p_decode) {
2449*4882a593Smuzhiyun task->tk_action = rpc_exit_task;
2450*4882a593Smuzhiyun return;
2451*4882a593Smuzhiyun }
2452*4882a593Smuzhiyun
2453*4882a593Smuzhiyun if (task->tk_flags & RPC_CALL_MAJORSEEN) {
2454*4882a593Smuzhiyun if (clnt->cl_chatty) {
2455*4882a593Smuzhiyun pr_notice_ratelimited("%s: server %s OK\n",
2456*4882a593Smuzhiyun clnt->cl_program->name,
2457*4882a593Smuzhiyun task->tk_xprt->servername);
2458*4882a593Smuzhiyun }
2459*4882a593Smuzhiyun task->tk_flags &= ~RPC_CALL_MAJORSEEN;
2460*4882a593Smuzhiyun }
2461*4882a593Smuzhiyun
2462*4882a593Smuzhiyun /*
2463*4882a593Smuzhiyun * Did we ever call xprt_complete_rqst()? If not, we should assume
2464*4882a593Smuzhiyun * the message is incomplete.
2465*4882a593Smuzhiyun */
2466*4882a593Smuzhiyun err = -EAGAIN;
2467*4882a593Smuzhiyun if (!req->rq_reply_bytes_recvd)
2468*4882a593Smuzhiyun goto out;
2469*4882a593Smuzhiyun
2470*4882a593Smuzhiyun /* Ensure that we see all writes made by xprt_complete_rqst()
2471*4882a593Smuzhiyun * before it changed req->rq_reply_bytes_recvd.
2472*4882a593Smuzhiyun */
2473*4882a593Smuzhiyun smp_rmb();
2474*4882a593Smuzhiyun
2475*4882a593Smuzhiyun req->rq_rcv_buf.len = req->rq_private_buf.len;
2476*4882a593Smuzhiyun trace_rpc_xdr_recvfrom(task, &req->rq_rcv_buf);
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun /* Check that the softirq receive buffer is valid */
2479*4882a593Smuzhiyun WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
2480*4882a593Smuzhiyun sizeof(req->rq_rcv_buf)) != 0);
2481*4882a593Smuzhiyun
2482*4882a593Smuzhiyun xdr_init_decode(&xdr, &req->rq_rcv_buf,
2483*4882a593Smuzhiyun req->rq_rcv_buf.head[0].iov_base, req);
2484*4882a593Smuzhiyun err = rpc_decode_header(task, &xdr);
2485*4882a593Smuzhiyun out:
2486*4882a593Smuzhiyun switch (err) {
2487*4882a593Smuzhiyun case 0:
2488*4882a593Smuzhiyun task->tk_action = rpc_exit_task;
2489*4882a593Smuzhiyun task->tk_status = rpcauth_unwrap_resp(task, &xdr);
2490*4882a593Smuzhiyun return;
2491*4882a593Smuzhiyun case -EAGAIN:
2492*4882a593Smuzhiyun task->tk_status = 0;
2493*4882a593Smuzhiyun if (task->tk_client->cl_discrtry)
2494*4882a593Smuzhiyun xprt_conditional_disconnect(req->rq_xprt,
2495*4882a593Smuzhiyun req->rq_connect_cookie);
2496*4882a593Smuzhiyun task->tk_action = call_encode;
2497*4882a593Smuzhiyun rpc_check_timeout(task);
2498*4882a593Smuzhiyun break;
2499*4882a593Smuzhiyun case -EKEYREJECTED:
2500*4882a593Smuzhiyun task->tk_action = call_reserve;
2501*4882a593Smuzhiyun rpc_check_timeout(task);
2502*4882a593Smuzhiyun rpcauth_invalcred(task);
2503*4882a593Smuzhiyun /* Ensure we obtain a new XID if we retry! */
2504*4882a593Smuzhiyun xprt_release(task);
2505*4882a593Smuzhiyun }
2506*4882a593Smuzhiyun }
2507*4882a593Smuzhiyun
2508*4882a593Smuzhiyun static int
rpc_encode_header(struct rpc_task * task,struct xdr_stream * xdr)2509*4882a593Smuzhiyun rpc_encode_header(struct rpc_task *task, struct xdr_stream *xdr)
2510*4882a593Smuzhiyun {
2511*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2512*4882a593Smuzhiyun struct rpc_rqst *req = task->tk_rqstp;
2513*4882a593Smuzhiyun __be32 *p;
2514*4882a593Smuzhiyun int error;
2515*4882a593Smuzhiyun
2516*4882a593Smuzhiyun error = -EMSGSIZE;
2517*4882a593Smuzhiyun p = xdr_reserve_space(xdr, RPC_CALLHDRSIZE << 2);
2518*4882a593Smuzhiyun if (!p)
2519*4882a593Smuzhiyun goto out_fail;
2520*4882a593Smuzhiyun *p++ = req->rq_xid;
2521*4882a593Smuzhiyun *p++ = rpc_call;
2522*4882a593Smuzhiyun *p++ = cpu_to_be32(RPC_VERSION);
2523*4882a593Smuzhiyun *p++ = cpu_to_be32(clnt->cl_prog);
2524*4882a593Smuzhiyun *p++ = cpu_to_be32(clnt->cl_vers);
2525*4882a593Smuzhiyun *p = cpu_to_be32(task->tk_msg.rpc_proc->p_proc);
2526*4882a593Smuzhiyun
2527*4882a593Smuzhiyun error = rpcauth_marshcred(task, xdr);
2528*4882a593Smuzhiyun if (error < 0)
2529*4882a593Smuzhiyun goto out_fail;
2530*4882a593Smuzhiyun return 0;
2531*4882a593Smuzhiyun out_fail:
2532*4882a593Smuzhiyun trace_rpc_bad_callhdr(task);
2533*4882a593Smuzhiyun rpc_call_rpcerror(task, error);
2534*4882a593Smuzhiyun return error;
2535*4882a593Smuzhiyun }
2536*4882a593Smuzhiyun
2537*4882a593Smuzhiyun static noinline int
rpc_decode_header(struct rpc_task * task,struct xdr_stream * xdr)2538*4882a593Smuzhiyun rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2539*4882a593Smuzhiyun {
2540*4882a593Smuzhiyun struct rpc_clnt *clnt = task->tk_client;
2541*4882a593Smuzhiyun int error;
2542*4882a593Smuzhiyun __be32 *p;
2543*4882a593Smuzhiyun
2544*4882a593Smuzhiyun /* RFC-1014 says that the representation of XDR data must be a
2545*4882a593Smuzhiyun * multiple of four bytes
2546*4882a593Smuzhiyun * - if it isn't pointer subtraction in the NFS client may give
2547*4882a593Smuzhiyun * undefined results
2548*4882a593Smuzhiyun */
2549*4882a593Smuzhiyun if (task->tk_rqstp->rq_rcv_buf.len & 3)
2550*4882a593Smuzhiyun goto out_unparsable;
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun p = xdr_inline_decode(xdr, 3 * sizeof(*p));
2553*4882a593Smuzhiyun if (!p)
2554*4882a593Smuzhiyun goto out_unparsable;
2555*4882a593Smuzhiyun p++; /* skip XID */
2556*4882a593Smuzhiyun if (*p++ != rpc_reply)
2557*4882a593Smuzhiyun goto out_unparsable;
2558*4882a593Smuzhiyun if (*p++ != rpc_msg_accepted)
2559*4882a593Smuzhiyun goto out_msg_denied;
2560*4882a593Smuzhiyun
2561*4882a593Smuzhiyun error = rpcauth_checkverf(task, xdr);
2562*4882a593Smuzhiyun if (error)
2563*4882a593Smuzhiyun goto out_verifier;
2564*4882a593Smuzhiyun
2565*4882a593Smuzhiyun p = xdr_inline_decode(xdr, sizeof(*p));
2566*4882a593Smuzhiyun if (!p)
2567*4882a593Smuzhiyun goto out_unparsable;
2568*4882a593Smuzhiyun switch (*p) {
2569*4882a593Smuzhiyun case rpc_success:
2570*4882a593Smuzhiyun return 0;
2571*4882a593Smuzhiyun case rpc_prog_unavail:
2572*4882a593Smuzhiyun trace_rpc__prog_unavail(task);
2573*4882a593Smuzhiyun error = -EPFNOSUPPORT;
2574*4882a593Smuzhiyun goto out_err;
2575*4882a593Smuzhiyun case rpc_prog_mismatch:
2576*4882a593Smuzhiyun trace_rpc__prog_mismatch(task);
2577*4882a593Smuzhiyun error = -EPROTONOSUPPORT;
2578*4882a593Smuzhiyun goto out_err;
2579*4882a593Smuzhiyun case rpc_proc_unavail:
2580*4882a593Smuzhiyun trace_rpc__proc_unavail(task);
2581*4882a593Smuzhiyun error = -EOPNOTSUPP;
2582*4882a593Smuzhiyun goto out_err;
2583*4882a593Smuzhiyun case rpc_garbage_args:
2584*4882a593Smuzhiyun case rpc_system_err:
2585*4882a593Smuzhiyun trace_rpc__garbage_args(task);
2586*4882a593Smuzhiyun error = -EIO;
2587*4882a593Smuzhiyun break;
2588*4882a593Smuzhiyun default:
2589*4882a593Smuzhiyun goto out_unparsable;
2590*4882a593Smuzhiyun }
2591*4882a593Smuzhiyun
2592*4882a593Smuzhiyun out_garbage:
2593*4882a593Smuzhiyun clnt->cl_stats->rpcgarbage++;
2594*4882a593Smuzhiyun if (task->tk_garb_retry) {
2595*4882a593Smuzhiyun task->tk_garb_retry--;
2596*4882a593Smuzhiyun task->tk_action = call_encode;
2597*4882a593Smuzhiyun return -EAGAIN;
2598*4882a593Smuzhiyun }
2599*4882a593Smuzhiyun out_err:
2600*4882a593Smuzhiyun rpc_call_rpcerror(task, error);
2601*4882a593Smuzhiyun return error;
2602*4882a593Smuzhiyun
2603*4882a593Smuzhiyun out_unparsable:
2604*4882a593Smuzhiyun trace_rpc__unparsable(task);
2605*4882a593Smuzhiyun error = -EIO;
2606*4882a593Smuzhiyun goto out_garbage;
2607*4882a593Smuzhiyun
2608*4882a593Smuzhiyun out_verifier:
2609*4882a593Smuzhiyun trace_rpc_bad_verifier(task);
2610*4882a593Smuzhiyun goto out_garbage;
2611*4882a593Smuzhiyun
2612*4882a593Smuzhiyun out_msg_denied:
2613*4882a593Smuzhiyun error = -EACCES;
2614*4882a593Smuzhiyun p = xdr_inline_decode(xdr, sizeof(*p));
2615*4882a593Smuzhiyun if (!p)
2616*4882a593Smuzhiyun goto out_unparsable;
2617*4882a593Smuzhiyun switch (*p++) {
2618*4882a593Smuzhiyun case rpc_auth_error:
2619*4882a593Smuzhiyun break;
2620*4882a593Smuzhiyun case rpc_mismatch:
2621*4882a593Smuzhiyun trace_rpc__mismatch(task);
2622*4882a593Smuzhiyun error = -EPROTONOSUPPORT;
2623*4882a593Smuzhiyun goto out_err;
2624*4882a593Smuzhiyun default:
2625*4882a593Smuzhiyun goto out_unparsable;
2626*4882a593Smuzhiyun }
2627*4882a593Smuzhiyun
2628*4882a593Smuzhiyun p = xdr_inline_decode(xdr, sizeof(*p));
2629*4882a593Smuzhiyun if (!p)
2630*4882a593Smuzhiyun goto out_unparsable;
2631*4882a593Smuzhiyun switch (*p++) {
2632*4882a593Smuzhiyun case rpc_autherr_rejectedcred:
2633*4882a593Smuzhiyun case rpc_autherr_rejectedverf:
2634*4882a593Smuzhiyun case rpcsec_gsserr_credproblem:
2635*4882a593Smuzhiyun case rpcsec_gsserr_ctxproblem:
2636*4882a593Smuzhiyun if (!task->tk_cred_retry)
2637*4882a593Smuzhiyun break;
2638*4882a593Smuzhiyun task->tk_cred_retry--;
2639*4882a593Smuzhiyun trace_rpc__stale_creds(task);
2640*4882a593Smuzhiyun return -EKEYREJECTED;
2641*4882a593Smuzhiyun case rpc_autherr_badcred:
2642*4882a593Smuzhiyun case rpc_autherr_badverf:
2643*4882a593Smuzhiyun /* possibly garbled cred/verf? */
2644*4882a593Smuzhiyun if (!task->tk_garb_retry)
2645*4882a593Smuzhiyun break;
2646*4882a593Smuzhiyun task->tk_garb_retry--;
2647*4882a593Smuzhiyun trace_rpc__bad_creds(task);
2648*4882a593Smuzhiyun task->tk_action = call_encode;
2649*4882a593Smuzhiyun return -EAGAIN;
2650*4882a593Smuzhiyun case rpc_autherr_tooweak:
2651*4882a593Smuzhiyun trace_rpc__auth_tooweak(task);
2652*4882a593Smuzhiyun pr_warn("RPC: server %s requires stronger authentication.\n",
2653*4882a593Smuzhiyun task->tk_xprt->servername);
2654*4882a593Smuzhiyun break;
2655*4882a593Smuzhiyun default:
2656*4882a593Smuzhiyun goto out_unparsable;
2657*4882a593Smuzhiyun }
2658*4882a593Smuzhiyun goto out_err;
2659*4882a593Smuzhiyun }
2660*4882a593Smuzhiyun
rpcproc_encode_null(struct rpc_rqst * rqstp,struct xdr_stream * xdr,const void * obj)2661*4882a593Smuzhiyun static void rpcproc_encode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
2662*4882a593Smuzhiyun const void *obj)
2663*4882a593Smuzhiyun {
2664*4882a593Smuzhiyun }
2665*4882a593Smuzhiyun
rpcproc_decode_null(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * obj)2666*4882a593Smuzhiyun static int rpcproc_decode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
2667*4882a593Smuzhiyun void *obj)
2668*4882a593Smuzhiyun {
2669*4882a593Smuzhiyun return 0;
2670*4882a593Smuzhiyun }
2671*4882a593Smuzhiyun
2672*4882a593Smuzhiyun static const struct rpc_procinfo rpcproc_null = {
2673*4882a593Smuzhiyun .p_encode = rpcproc_encode_null,
2674*4882a593Smuzhiyun .p_decode = rpcproc_decode_null,
2675*4882a593Smuzhiyun };
2676*4882a593Smuzhiyun
rpc_ping(struct rpc_clnt * clnt)2677*4882a593Smuzhiyun static int rpc_ping(struct rpc_clnt *clnt)
2678*4882a593Smuzhiyun {
2679*4882a593Smuzhiyun struct rpc_message msg = {
2680*4882a593Smuzhiyun .rpc_proc = &rpcproc_null,
2681*4882a593Smuzhiyun };
2682*4882a593Smuzhiyun int err;
2683*4882a593Smuzhiyun err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN |
2684*4882a593Smuzhiyun RPC_TASK_NULLCREDS);
2685*4882a593Smuzhiyun return err;
2686*4882a593Smuzhiyun }
2687*4882a593Smuzhiyun
2688*4882a593Smuzhiyun static
rpc_call_null_helper(struct rpc_clnt * clnt,struct rpc_xprt * xprt,struct rpc_cred * cred,int flags,const struct rpc_call_ops * ops,void * data)2689*4882a593Smuzhiyun struct rpc_task *rpc_call_null_helper(struct rpc_clnt *clnt,
2690*4882a593Smuzhiyun struct rpc_xprt *xprt, struct rpc_cred *cred, int flags,
2691*4882a593Smuzhiyun const struct rpc_call_ops *ops, void *data)
2692*4882a593Smuzhiyun {
2693*4882a593Smuzhiyun struct rpc_message msg = {
2694*4882a593Smuzhiyun .rpc_proc = &rpcproc_null,
2695*4882a593Smuzhiyun };
2696*4882a593Smuzhiyun struct rpc_task_setup task_setup_data = {
2697*4882a593Smuzhiyun .rpc_client = clnt,
2698*4882a593Smuzhiyun .rpc_xprt = xprt,
2699*4882a593Smuzhiyun .rpc_message = &msg,
2700*4882a593Smuzhiyun .rpc_op_cred = cred,
2701*4882a593Smuzhiyun .callback_ops = (ops != NULL) ? ops : &rpc_default_ops,
2702*4882a593Smuzhiyun .callback_data = data,
2703*4882a593Smuzhiyun .flags = flags | RPC_TASK_SOFT | RPC_TASK_SOFTCONN |
2704*4882a593Smuzhiyun RPC_TASK_NULLCREDS,
2705*4882a593Smuzhiyun };
2706*4882a593Smuzhiyun
2707*4882a593Smuzhiyun return rpc_run_task(&task_setup_data);
2708*4882a593Smuzhiyun }
2709*4882a593Smuzhiyun
rpc_call_null(struct rpc_clnt * clnt,struct rpc_cred * cred,int flags)2710*4882a593Smuzhiyun struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
2711*4882a593Smuzhiyun {
2712*4882a593Smuzhiyun return rpc_call_null_helper(clnt, NULL, cred, flags, NULL, NULL);
2713*4882a593Smuzhiyun }
2714*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_call_null);
2715*4882a593Smuzhiyun
2716*4882a593Smuzhiyun struct rpc_cb_add_xprt_calldata {
2717*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
2718*4882a593Smuzhiyun struct rpc_xprt *xprt;
2719*4882a593Smuzhiyun };
2720*4882a593Smuzhiyun
rpc_cb_add_xprt_done(struct rpc_task * task,void * calldata)2721*4882a593Smuzhiyun static void rpc_cb_add_xprt_done(struct rpc_task *task, void *calldata)
2722*4882a593Smuzhiyun {
2723*4882a593Smuzhiyun struct rpc_cb_add_xprt_calldata *data = calldata;
2724*4882a593Smuzhiyun
2725*4882a593Smuzhiyun if (task->tk_status == 0)
2726*4882a593Smuzhiyun rpc_xprt_switch_add_xprt(data->xps, data->xprt);
2727*4882a593Smuzhiyun }
2728*4882a593Smuzhiyun
rpc_cb_add_xprt_release(void * calldata)2729*4882a593Smuzhiyun static void rpc_cb_add_xprt_release(void *calldata)
2730*4882a593Smuzhiyun {
2731*4882a593Smuzhiyun struct rpc_cb_add_xprt_calldata *data = calldata;
2732*4882a593Smuzhiyun
2733*4882a593Smuzhiyun xprt_put(data->xprt);
2734*4882a593Smuzhiyun xprt_switch_put(data->xps);
2735*4882a593Smuzhiyun kfree(data);
2736*4882a593Smuzhiyun }
2737*4882a593Smuzhiyun
2738*4882a593Smuzhiyun static const struct rpc_call_ops rpc_cb_add_xprt_call_ops = {
2739*4882a593Smuzhiyun .rpc_call_done = rpc_cb_add_xprt_done,
2740*4882a593Smuzhiyun .rpc_release = rpc_cb_add_xprt_release,
2741*4882a593Smuzhiyun };
2742*4882a593Smuzhiyun
2743*4882a593Smuzhiyun /**
2744*4882a593Smuzhiyun * rpc_clnt_test_and_add_xprt - Test and add a new transport to a rpc_clnt
2745*4882a593Smuzhiyun * @clnt: pointer to struct rpc_clnt
2746*4882a593Smuzhiyun * @xps: pointer to struct rpc_xprt_switch,
2747*4882a593Smuzhiyun * @xprt: pointer struct rpc_xprt
2748*4882a593Smuzhiyun * @dummy: unused
2749*4882a593Smuzhiyun */
rpc_clnt_test_and_add_xprt(struct rpc_clnt * clnt,struct rpc_xprt_switch * xps,struct rpc_xprt * xprt,void * dummy)2750*4882a593Smuzhiyun int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
2751*4882a593Smuzhiyun struct rpc_xprt_switch *xps, struct rpc_xprt *xprt,
2752*4882a593Smuzhiyun void *dummy)
2753*4882a593Smuzhiyun {
2754*4882a593Smuzhiyun struct rpc_cb_add_xprt_calldata *data;
2755*4882a593Smuzhiyun struct rpc_task *task;
2756*4882a593Smuzhiyun
2757*4882a593Smuzhiyun data = kmalloc(sizeof(*data), GFP_NOFS);
2758*4882a593Smuzhiyun if (!data)
2759*4882a593Smuzhiyun return -ENOMEM;
2760*4882a593Smuzhiyun data->xps = xprt_switch_get(xps);
2761*4882a593Smuzhiyun data->xprt = xprt_get(xprt);
2762*4882a593Smuzhiyun if (rpc_xprt_switch_has_addr(data->xps, (struct sockaddr *)&xprt->addr)) {
2763*4882a593Smuzhiyun rpc_cb_add_xprt_release(data);
2764*4882a593Smuzhiyun goto success;
2765*4882a593Smuzhiyun }
2766*4882a593Smuzhiyun
2767*4882a593Smuzhiyun task = rpc_call_null_helper(clnt, xprt, NULL, RPC_TASK_ASYNC,
2768*4882a593Smuzhiyun &rpc_cb_add_xprt_call_ops, data);
2769*4882a593Smuzhiyun
2770*4882a593Smuzhiyun rpc_put_task(task);
2771*4882a593Smuzhiyun success:
2772*4882a593Smuzhiyun return 1;
2773*4882a593Smuzhiyun }
2774*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);
2775*4882a593Smuzhiyun
2776*4882a593Smuzhiyun /**
2777*4882a593Smuzhiyun * rpc_clnt_setup_test_and_add_xprt()
2778*4882a593Smuzhiyun *
2779*4882a593Smuzhiyun * This is an rpc_clnt_add_xprt setup() function which returns 1 so:
2780*4882a593Smuzhiyun * 1) caller of the test function must dereference the rpc_xprt_switch
2781*4882a593Smuzhiyun * and the rpc_xprt.
2782*4882a593Smuzhiyun * 2) test function must call rpc_xprt_switch_add_xprt, usually in
2783*4882a593Smuzhiyun * the rpc_call_done routine.
2784*4882a593Smuzhiyun *
2785*4882a593Smuzhiyun * Upon success (return of 1), the test function adds the new
2786*4882a593Smuzhiyun * transport to the rpc_clnt xprt switch
2787*4882a593Smuzhiyun *
2788*4882a593Smuzhiyun * @clnt: struct rpc_clnt to get the new transport
2789*4882a593Smuzhiyun * @xps: the rpc_xprt_switch to hold the new transport
2790*4882a593Smuzhiyun * @xprt: the rpc_xprt to test
2791*4882a593Smuzhiyun * @data: a struct rpc_add_xprt_test pointer that holds the test function
2792*4882a593Smuzhiyun * and test function call data
2793*4882a593Smuzhiyun */
rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt * clnt,struct rpc_xprt_switch * xps,struct rpc_xprt * xprt,void * data)2794*4882a593Smuzhiyun int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *clnt,
2795*4882a593Smuzhiyun struct rpc_xprt_switch *xps,
2796*4882a593Smuzhiyun struct rpc_xprt *xprt,
2797*4882a593Smuzhiyun void *data)
2798*4882a593Smuzhiyun {
2799*4882a593Smuzhiyun struct rpc_task *task;
2800*4882a593Smuzhiyun struct rpc_add_xprt_test *xtest = (struct rpc_add_xprt_test *)data;
2801*4882a593Smuzhiyun int status = -EADDRINUSE;
2802*4882a593Smuzhiyun
2803*4882a593Smuzhiyun xprt = xprt_get(xprt);
2804*4882a593Smuzhiyun xprt_switch_get(xps);
2805*4882a593Smuzhiyun
2806*4882a593Smuzhiyun if (rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr))
2807*4882a593Smuzhiyun goto out_err;
2808*4882a593Smuzhiyun
2809*4882a593Smuzhiyun /* Test the connection */
2810*4882a593Smuzhiyun task = rpc_call_null_helper(clnt, xprt, NULL, 0, NULL, NULL);
2811*4882a593Smuzhiyun if (IS_ERR(task)) {
2812*4882a593Smuzhiyun status = PTR_ERR(task);
2813*4882a593Smuzhiyun goto out_err;
2814*4882a593Smuzhiyun }
2815*4882a593Smuzhiyun status = task->tk_status;
2816*4882a593Smuzhiyun rpc_put_task(task);
2817*4882a593Smuzhiyun
2818*4882a593Smuzhiyun if (status < 0)
2819*4882a593Smuzhiyun goto out_err;
2820*4882a593Smuzhiyun
2821*4882a593Smuzhiyun /* rpc_xprt_switch and rpc_xprt are deferrenced by add_xprt_test() */
2822*4882a593Smuzhiyun xtest->add_xprt_test(clnt, xprt, xtest->data);
2823*4882a593Smuzhiyun
2824*4882a593Smuzhiyun xprt_put(xprt);
2825*4882a593Smuzhiyun xprt_switch_put(xps);
2826*4882a593Smuzhiyun
2827*4882a593Smuzhiyun /* so that rpc_clnt_add_xprt does not call rpc_xprt_switch_add_xprt */
2828*4882a593Smuzhiyun return 1;
2829*4882a593Smuzhiyun out_err:
2830*4882a593Smuzhiyun xprt_put(xprt);
2831*4882a593Smuzhiyun xprt_switch_put(xps);
2832*4882a593Smuzhiyun pr_info("RPC: rpc_clnt_test_xprt failed: %d addr %s not added\n",
2833*4882a593Smuzhiyun status, xprt->address_strings[RPC_DISPLAY_ADDR]);
2834*4882a593Smuzhiyun return status;
2835*4882a593Smuzhiyun }
2836*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_setup_test_and_add_xprt);
2837*4882a593Smuzhiyun
2838*4882a593Smuzhiyun /**
2839*4882a593Smuzhiyun * rpc_clnt_add_xprt - Add a new transport to a rpc_clnt
2840*4882a593Smuzhiyun * @clnt: pointer to struct rpc_clnt
2841*4882a593Smuzhiyun * @xprtargs: pointer to struct xprt_create
2842*4882a593Smuzhiyun * @setup: callback to test and/or set up the connection
2843*4882a593Smuzhiyun * @data: pointer to setup function data
2844*4882a593Smuzhiyun *
2845*4882a593Smuzhiyun * Creates a new transport using the parameters set in args and
2846*4882a593Smuzhiyun * adds it to clnt.
2847*4882a593Smuzhiyun * If ping is set, then test that connectivity succeeds before
2848*4882a593Smuzhiyun * adding the new transport.
2849*4882a593Smuzhiyun *
2850*4882a593Smuzhiyun */
rpc_clnt_add_xprt(struct rpc_clnt * clnt,struct xprt_create * xprtargs,int (* setup)(struct rpc_clnt *,struct rpc_xprt_switch *,struct rpc_xprt *,void *),void * data)2851*4882a593Smuzhiyun int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
2852*4882a593Smuzhiyun struct xprt_create *xprtargs,
2853*4882a593Smuzhiyun int (*setup)(struct rpc_clnt *,
2854*4882a593Smuzhiyun struct rpc_xprt_switch *,
2855*4882a593Smuzhiyun struct rpc_xprt *,
2856*4882a593Smuzhiyun void *),
2857*4882a593Smuzhiyun void *data)
2858*4882a593Smuzhiyun {
2859*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
2860*4882a593Smuzhiyun struct rpc_xprt *xprt;
2861*4882a593Smuzhiyun unsigned long connect_timeout;
2862*4882a593Smuzhiyun unsigned long reconnect_timeout;
2863*4882a593Smuzhiyun unsigned char resvport, reuseport;
2864*4882a593Smuzhiyun int ret = 0;
2865*4882a593Smuzhiyun
2866*4882a593Smuzhiyun rcu_read_lock();
2867*4882a593Smuzhiyun xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
2868*4882a593Smuzhiyun xprt = xprt_iter_xprt(&clnt->cl_xpi);
2869*4882a593Smuzhiyun if (xps == NULL || xprt == NULL) {
2870*4882a593Smuzhiyun rcu_read_unlock();
2871*4882a593Smuzhiyun xprt_switch_put(xps);
2872*4882a593Smuzhiyun return -EAGAIN;
2873*4882a593Smuzhiyun }
2874*4882a593Smuzhiyun resvport = xprt->resvport;
2875*4882a593Smuzhiyun reuseport = xprt->reuseport;
2876*4882a593Smuzhiyun connect_timeout = xprt->connect_timeout;
2877*4882a593Smuzhiyun reconnect_timeout = xprt->max_reconnect_timeout;
2878*4882a593Smuzhiyun rcu_read_unlock();
2879*4882a593Smuzhiyun
2880*4882a593Smuzhiyun xprt = xprt_create_transport(xprtargs);
2881*4882a593Smuzhiyun if (IS_ERR(xprt)) {
2882*4882a593Smuzhiyun ret = PTR_ERR(xprt);
2883*4882a593Smuzhiyun goto out_put_switch;
2884*4882a593Smuzhiyun }
2885*4882a593Smuzhiyun xprt->resvport = resvport;
2886*4882a593Smuzhiyun xprt->reuseport = reuseport;
2887*4882a593Smuzhiyun if (xprt->ops->set_connect_timeout != NULL)
2888*4882a593Smuzhiyun xprt->ops->set_connect_timeout(xprt,
2889*4882a593Smuzhiyun connect_timeout,
2890*4882a593Smuzhiyun reconnect_timeout);
2891*4882a593Smuzhiyun
2892*4882a593Smuzhiyun rpc_xprt_switch_set_roundrobin(xps);
2893*4882a593Smuzhiyun if (setup) {
2894*4882a593Smuzhiyun ret = setup(clnt, xps, xprt, data);
2895*4882a593Smuzhiyun if (ret != 0)
2896*4882a593Smuzhiyun goto out_put_xprt;
2897*4882a593Smuzhiyun }
2898*4882a593Smuzhiyun rpc_xprt_switch_add_xprt(xps, xprt);
2899*4882a593Smuzhiyun out_put_xprt:
2900*4882a593Smuzhiyun xprt_put(xprt);
2901*4882a593Smuzhiyun out_put_switch:
2902*4882a593Smuzhiyun xprt_switch_put(xps);
2903*4882a593Smuzhiyun return ret;
2904*4882a593Smuzhiyun }
2905*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt);
2906*4882a593Smuzhiyun
2907*4882a593Smuzhiyun struct connect_timeout_data {
2908*4882a593Smuzhiyun unsigned long connect_timeout;
2909*4882a593Smuzhiyun unsigned long reconnect_timeout;
2910*4882a593Smuzhiyun };
2911*4882a593Smuzhiyun
2912*4882a593Smuzhiyun static int
rpc_xprt_set_connect_timeout(struct rpc_clnt * clnt,struct rpc_xprt * xprt,void * data)2913*4882a593Smuzhiyun rpc_xprt_set_connect_timeout(struct rpc_clnt *clnt,
2914*4882a593Smuzhiyun struct rpc_xprt *xprt,
2915*4882a593Smuzhiyun void *data)
2916*4882a593Smuzhiyun {
2917*4882a593Smuzhiyun struct connect_timeout_data *timeo = data;
2918*4882a593Smuzhiyun
2919*4882a593Smuzhiyun if (xprt->ops->set_connect_timeout)
2920*4882a593Smuzhiyun xprt->ops->set_connect_timeout(xprt,
2921*4882a593Smuzhiyun timeo->connect_timeout,
2922*4882a593Smuzhiyun timeo->reconnect_timeout);
2923*4882a593Smuzhiyun return 0;
2924*4882a593Smuzhiyun }
2925*4882a593Smuzhiyun
2926*4882a593Smuzhiyun void
rpc_set_connect_timeout(struct rpc_clnt * clnt,unsigned long connect_timeout,unsigned long reconnect_timeout)2927*4882a593Smuzhiyun rpc_set_connect_timeout(struct rpc_clnt *clnt,
2928*4882a593Smuzhiyun unsigned long connect_timeout,
2929*4882a593Smuzhiyun unsigned long reconnect_timeout)
2930*4882a593Smuzhiyun {
2931*4882a593Smuzhiyun struct connect_timeout_data timeout = {
2932*4882a593Smuzhiyun .connect_timeout = connect_timeout,
2933*4882a593Smuzhiyun .reconnect_timeout = reconnect_timeout,
2934*4882a593Smuzhiyun };
2935*4882a593Smuzhiyun rpc_clnt_iterate_for_each_xprt(clnt,
2936*4882a593Smuzhiyun rpc_xprt_set_connect_timeout,
2937*4882a593Smuzhiyun &timeout);
2938*4882a593Smuzhiyun }
2939*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_set_connect_timeout);
2940*4882a593Smuzhiyun
rpc_clnt_xprt_switch_put(struct rpc_clnt * clnt)2941*4882a593Smuzhiyun void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt)
2942*4882a593Smuzhiyun {
2943*4882a593Smuzhiyun rcu_read_lock();
2944*4882a593Smuzhiyun xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
2945*4882a593Smuzhiyun rcu_read_unlock();
2946*4882a593Smuzhiyun }
2947*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put);
2948*4882a593Smuzhiyun
rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt * clnt,struct rpc_xprt * xprt)2949*4882a593Smuzhiyun void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
2950*4882a593Smuzhiyun {
2951*4882a593Smuzhiyun rcu_read_lock();
2952*4882a593Smuzhiyun rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch),
2953*4882a593Smuzhiyun xprt);
2954*4882a593Smuzhiyun rcu_read_unlock();
2955*4882a593Smuzhiyun }
2956*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt);
2957*4882a593Smuzhiyun
rpc_clnt_xprt_switch_has_addr(struct rpc_clnt * clnt,const struct sockaddr * sap)2958*4882a593Smuzhiyun bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
2959*4882a593Smuzhiyun const struct sockaddr *sap)
2960*4882a593Smuzhiyun {
2961*4882a593Smuzhiyun struct rpc_xprt_switch *xps;
2962*4882a593Smuzhiyun bool ret;
2963*4882a593Smuzhiyun
2964*4882a593Smuzhiyun rcu_read_lock();
2965*4882a593Smuzhiyun xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
2966*4882a593Smuzhiyun ret = rpc_xprt_switch_has_addr(xps, sap);
2967*4882a593Smuzhiyun rcu_read_unlock();
2968*4882a593Smuzhiyun return ret;
2969*4882a593Smuzhiyun }
2970*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_has_addr);
2971*4882a593Smuzhiyun
2972*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
rpc_show_header(void)2973*4882a593Smuzhiyun static void rpc_show_header(void)
2974*4882a593Smuzhiyun {
2975*4882a593Smuzhiyun printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
2976*4882a593Smuzhiyun "-timeout ---ops--\n");
2977*4882a593Smuzhiyun }
2978*4882a593Smuzhiyun
rpc_show_task(const struct rpc_clnt * clnt,const struct rpc_task * task)2979*4882a593Smuzhiyun static void rpc_show_task(const struct rpc_clnt *clnt,
2980*4882a593Smuzhiyun const struct rpc_task *task)
2981*4882a593Smuzhiyun {
2982*4882a593Smuzhiyun const char *rpc_waitq = "none";
2983*4882a593Smuzhiyun
2984*4882a593Smuzhiyun if (RPC_IS_QUEUED(task))
2985*4882a593Smuzhiyun rpc_waitq = rpc_qname(task->tk_waitqueue);
2986*4882a593Smuzhiyun
2987*4882a593Smuzhiyun printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n",
2988*4882a593Smuzhiyun task->tk_pid, task->tk_flags, task->tk_status,
2989*4882a593Smuzhiyun clnt, task->tk_rqstp, rpc_task_timeout(task), task->tk_ops,
2990*4882a593Smuzhiyun clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task),
2991*4882a593Smuzhiyun task->tk_action, rpc_waitq);
2992*4882a593Smuzhiyun }
2993*4882a593Smuzhiyun
rpc_show_tasks(struct net * net)2994*4882a593Smuzhiyun void rpc_show_tasks(struct net *net)
2995*4882a593Smuzhiyun {
2996*4882a593Smuzhiyun struct rpc_clnt *clnt;
2997*4882a593Smuzhiyun struct rpc_task *task;
2998*4882a593Smuzhiyun int header = 0;
2999*4882a593Smuzhiyun struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
3000*4882a593Smuzhiyun
3001*4882a593Smuzhiyun spin_lock(&sn->rpc_client_lock);
3002*4882a593Smuzhiyun list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
3003*4882a593Smuzhiyun spin_lock(&clnt->cl_lock);
3004*4882a593Smuzhiyun list_for_each_entry(task, &clnt->cl_tasks, tk_task) {
3005*4882a593Smuzhiyun if (!header) {
3006*4882a593Smuzhiyun rpc_show_header();
3007*4882a593Smuzhiyun header++;
3008*4882a593Smuzhiyun }
3009*4882a593Smuzhiyun rpc_show_task(clnt, task);
3010*4882a593Smuzhiyun }
3011*4882a593Smuzhiyun spin_unlock(&clnt->cl_lock);
3012*4882a593Smuzhiyun }
3013*4882a593Smuzhiyun spin_unlock(&sn->rpc_client_lock);
3014*4882a593Smuzhiyun }
3015*4882a593Smuzhiyun #endif
3016*4882a593Smuzhiyun
3017*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SUNRPC_SWAP)
3018*4882a593Smuzhiyun static int
rpc_clnt_swap_activate_callback(struct rpc_clnt * clnt,struct rpc_xprt * xprt,void * dummy)3019*4882a593Smuzhiyun rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt,
3020*4882a593Smuzhiyun struct rpc_xprt *xprt,
3021*4882a593Smuzhiyun void *dummy)
3022*4882a593Smuzhiyun {
3023*4882a593Smuzhiyun return xprt_enable_swap(xprt);
3024*4882a593Smuzhiyun }
3025*4882a593Smuzhiyun
3026*4882a593Smuzhiyun int
rpc_clnt_swap_activate(struct rpc_clnt * clnt)3027*4882a593Smuzhiyun rpc_clnt_swap_activate(struct rpc_clnt *clnt)
3028*4882a593Smuzhiyun {
3029*4882a593Smuzhiyun if (atomic_inc_return(&clnt->cl_swapper) == 1)
3030*4882a593Smuzhiyun return rpc_clnt_iterate_for_each_xprt(clnt,
3031*4882a593Smuzhiyun rpc_clnt_swap_activate_callback, NULL);
3032*4882a593Smuzhiyun return 0;
3033*4882a593Smuzhiyun }
3034*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate);
3035*4882a593Smuzhiyun
3036*4882a593Smuzhiyun static int
rpc_clnt_swap_deactivate_callback(struct rpc_clnt * clnt,struct rpc_xprt * xprt,void * dummy)3037*4882a593Smuzhiyun rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt,
3038*4882a593Smuzhiyun struct rpc_xprt *xprt,
3039*4882a593Smuzhiyun void *dummy)
3040*4882a593Smuzhiyun {
3041*4882a593Smuzhiyun xprt_disable_swap(xprt);
3042*4882a593Smuzhiyun return 0;
3043*4882a593Smuzhiyun }
3044*4882a593Smuzhiyun
3045*4882a593Smuzhiyun void
rpc_clnt_swap_deactivate(struct rpc_clnt * clnt)3046*4882a593Smuzhiyun rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
3047*4882a593Smuzhiyun {
3048*4882a593Smuzhiyun if (atomic_dec_if_positive(&clnt->cl_swapper) == 0)
3049*4882a593Smuzhiyun rpc_clnt_iterate_for_each_xprt(clnt,
3050*4882a593Smuzhiyun rpc_clnt_swap_deactivate_callback, NULL);
3051*4882a593Smuzhiyun }
3052*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate);
3053*4882a593Smuzhiyun #endif /* CONFIG_SUNRPC_SWAP */
3054