Blame view

net/sunrpc/clnt.c 54.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
55aa4f58a   Chuck Lever   [PATCH] RPC: clie...
2
   *  linux/net/sunrpc/clnt.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
10
11
12
13
14
15
   *
   *  This file contains the high-level RPC interface.
   *  It is modeled as a finite state machine to support both synchronous
   *  and asynchronous requests.
   *
   *  -	RPC header generation and argument serialization.
   *  -	Credential refresh.
   *  -	TCP connect handling.
   *  -	Retry of operation when it is suspected the operation failed because
   *	of uid squashing on the server, or when the credentials were stale
   *	and need to be refreshed, or when a packet was damaged in transit.
   *	This may be have to be moved to the VFS layer.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
   *  Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com>
   *  Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
  
  #include <linux/module.h>
  #include <linux/types.h>
cb3997b5a   Chuck Lever   SUNRPC: Display s...
22
  #include <linux/kallsyms.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include <linux/mm.h>
23ac65817   Trond Myklebust   SUNRPC: clean up ...
24
25
  #include <linux/namei.h>
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <linux/utsname.h>
11c556b3d   Chuck Lever   SUNRPC: provide a...
28
  #include <linux/workqueue.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
29
  #include <linux/in.h>
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
30
  #include <linux/in6.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
31
  #include <linux/un.h>
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
32
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  
  #include <linux/sunrpc/clnt.h>
5976687a2   Jeff Layton   sunrpc: move addr...
35
  #include <linux/sunrpc/addr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include <linux/sunrpc/rpc_pipe_fs.h>
11c556b3d   Chuck Lever   SUNRPC: provide a...
37
  #include <linux/sunrpc/metrics.h>
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
38
  #include <linux/sunrpc/bc_xprt.h>
5753cba17   Steve Dickson   SUNRPC: Adding st...
39
  #include <trace/events/sunrpc.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
41
  #include "sunrpc.h"
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
42
  #include "netns.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
  #ifdef RPC_DEBUG
  # define RPCDBG_FACILITY	RPCDBG_CALL
  #endif
46121cf7d   Chuck Lever   SUNRPC: fix print...
47
48
49
  #define dprint_status(t)					\
  	dprintk("RPC: %5u %s (status %d)
  ", t->tk_pid,		\
0dc47877a   Harvey Harrison   net: replace rema...
50
  			__func__, t->tk_status)
46121cf7d   Chuck Lever   SUNRPC: fix print...
51

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
52
53
54
  /*
   * All RPC clients are linked into this list
   */
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
55

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
62
  static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
  
  
  static void	call_start(struct rpc_task *task);
  static void	call_reserve(struct rpc_task *task);
  static void	call_reserveresult(struct rpc_task *task);
  static void	call_allocate(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
  static void	call_decode(struct rpc_task *task);
  static void	call_bind(struct rpc_task *task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
65
  static void	call_bind_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  static void	call_transmit(struct rpc_task *task);
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
67
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
68
  static void	call_bc_transmit(struct rpc_task *task);
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
69
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  static void	call_status(struct rpc_task *task);
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
71
  static void	call_transmit_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
  static void	call_refresh(struct rpc_task *task);
  static void	call_refreshresult(struct rpc_task *task);
  static void	call_timeout(struct rpc_task *task);
  static void	call_connect(struct rpc_task *task);
  static void	call_connect_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77

b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
78
79
  static __be32	*rpc_encode_header(struct rpc_task *task);
  static __be32	*rpc_verify_header(struct rpc_task *task);
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
80
  static int	rpc_ping(struct rpc_clnt *clnt);
64c91a1f1   Trond Myklebust   SUNRPC: Make rpc_...
81

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
82
83
  static void rpc_register_client(struct rpc_clnt *clnt)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
84
85
  	struct net *net = rpc_net_ns(clnt);
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
86
87
88
89
  
  	spin_lock(&sn->rpc_client_lock);
  	list_add(&clnt->cl_clients, &sn->all_clients);
  	spin_unlock(&sn->rpc_client_lock);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
90
91
92
93
  }
  
  static void rpc_unregister_client(struct rpc_clnt *clnt)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
94
95
  	struct net *net = rpc_net_ns(clnt);
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
96
97
  
  	spin_lock(&sn->rpc_client_lock);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
98
  	list_del(&clnt->cl_clients);
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
99
  	spin_unlock(&sn->rpc_client_lock);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
100
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101

0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
102
103
  static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
  {
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
104
  	if (clnt->cl_dentry) {
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
105
106
  		if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy)
  			clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth);
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
107
  		rpc_remove_client_dir(clnt->cl_dentry);
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
108
  	}
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
109
  	clnt->cl_dentry = NULL;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
110
111
112
113
  }
  
  static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
114
  	struct net *net = rpc_net_ns(clnt);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
115
  	struct super_block *pipefs_sb;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
116

2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
117
  	pipefs_sb = rpc_get_sb_net(net);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
118
  	if (pipefs_sb) {
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
119
  		__rpc_clnt_remove_pipedir(clnt);
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
120
  		rpc_put_sb_net(net);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
121
  	}
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
122
123
124
  }
  
  static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
080b794ce   Trond Myklebust   SUNRPC: constify ...
125
126
  				    struct rpc_clnt *clnt,
  				    const char *dir_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  {
f134585a7   Trond Myklebust   Revert "[PATCH] R...
128
  	static uint32_t clntid;
23ac65817   Trond Myklebust   SUNRPC: clean up ...
129
  	char name[15];
26fe57502   Linus Torvalds   vfs: make it poss...
130
  	struct qstr q = { .name = name };
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
131
  	struct dentry *dir, *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  	int error;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
133
  	dir = rpc_d_lookup_sb(sb, dir_name);
922eeac30   Weston Andros Adamson   SUNRPC: remove BU...
134
135
136
  	if (dir == NULL) {
  		pr_info("RPC: pipefs directory doesn't exist: %s
  ", dir_name);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
137
  		return dir;
922eeac30   Weston Andros Adamson   SUNRPC: remove BU...
138
  	}
f134585a7   Trond Myklebust   Revert "[PATCH] R...
139
  	for (;;) {
23ac65817   Trond Myklebust   SUNRPC: clean up ...
140
141
142
  		q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
  		name[sizeof(name) - 1] = '\0';
  		q.hash = full_name_hash(q.name, q.len);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
143
144
  		dentry = rpc_create_client_dir(dir, &q, clnt);
  		if (!IS_ERR(dentry))
23ac65817   Trond Myklebust   SUNRPC: clean up ...
145
  			break;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
146
  		error = PTR_ERR(dentry);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
147
  		if (error != -EEXIST) {
23ac65817   Trond Myklebust   SUNRPC: clean up ...
148
149
150
151
  			printk(KERN_INFO "RPC: Couldn't create pipefs entry"
  					" %s/%s, error %d
  ",
  					dir_name, name, error);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
152
  			break;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
153
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  	}
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
155
156
157
158
159
  	dput(dir);
  	return dentry;
  }
  
  static int
080b794ce   Trond Myklebust   SUNRPC: constify ...
160
  rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name)
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
161
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
162
  	struct net *net = rpc_net_ns(clnt);
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
163
  	struct super_block *pipefs_sb;
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
164
  	struct dentry *dentry;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
165

30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
166
  	clnt->cl_dentry = NULL;
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
167
168
  	if (dir_name == NULL)
  		return 0;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
169
  	pipefs_sb = rpc_get_sb_net(net);
70fe25b6e   Stanislav Kinsbursky   SUNRPC: remove RP...
170
171
  	if (!pipefs_sb)
  		return 0;
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
172
  	dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
173
  	rpc_put_sb_net(net);
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
174
175
176
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
  	clnt->cl_dentry = dentry;
23ac65817   Trond Myklebust   SUNRPC: clean up ...
177
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  }
ea8cfa067   Stanislav Kinsbursky   SUNRPC: traverse ...
179
180
181
182
183
184
185
186
187
188
  static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
  {
  	if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
  	    ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
  		return 1;
  	return 0;
  }
  
  static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
  				   struct super_block *sb)
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
189
190
191
192
193
194
  {
  	struct dentry *dentry;
  	int err = 0;
  
  	switch (event) {
  	case RPC_PIPEFS_MOUNT:
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
195
196
  		dentry = rpc_setup_pipedir_sb(sb, clnt,
  					      clnt->cl_program->pipe_dir_name);
922eeac30   Weston Andros Adamson   SUNRPC: remove BU...
197
198
  		if (!dentry)
  			return -ENOENT;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
199
200
  		if (IS_ERR(dentry))
  			return PTR_ERR(dentry);
30507f58c   Stanislav Kinsbursky   SUNRPC: remove RP...
201
  		clnt->cl_dentry = dentry;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  		if (clnt->cl_auth->au_ops->pipes_create) {
  			err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth);
  			if (err)
  				__rpc_clnt_remove_pipedir(clnt);
  		}
  		break;
  	case RPC_PIPEFS_UMOUNT:
  		__rpc_clnt_remove_pipedir(clnt);
  		break;
  	default:
  		printk(KERN_ERR "%s: unknown event: %ld
  ", __func__, event);
  		return -ENOTSUPP;
  	}
  	return err;
  }
ea8cfa067   Stanislav Kinsbursky   SUNRPC: traverse ...
218
219
220
221
222
223
224
225
226
227
228
229
230
  static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
  				struct super_block *sb)
  {
  	int error = 0;
  
  	for (;; clnt = clnt->cl_parent) {
  		if (!rpc_clnt_skip_event(clnt, event))
  			error = __rpc_clnt_handle_event(clnt, event, sb);
  		if (error || clnt == clnt->cl_parent)
  			break;
  	}
  	return error;
  }
da3b46229   Stanislav Kinsbursky   SUNRPC: release p...
231
232
233
234
235
236
237
  static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  	struct rpc_clnt *clnt;
  
  	spin_lock(&sn->rpc_client_lock);
  	list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
7aab449e5   Stanislav Kinsbursky   SUNRPC: skip clie...
238
  		if (clnt->cl_program->pipe_dir_name == NULL)
cd6c59685   Stanislav Kinsbursky   SUNRPC: continue ...
239
  			continue;
ea8cfa067   Stanislav Kinsbursky   SUNRPC: traverse ...
240
  		if (rpc_clnt_skip_event(clnt, event))
da3b46229   Stanislav Kinsbursky   SUNRPC: release p...
241
  			continue;
a4dff1bc4   Stanislav Kinsbursky   SUNRPC: skip dead...
242
243
  		if (atomic_inc_not_zero(&clnt->cl_count) == 0)
  			continue;
da3b46229   Stanislav Kinsbursky   SUNRPC: release p...
244
245
246
247
248
249
  		spin_unlock(&sn->rpc_client_lock);
  		return clnt;
  	}
  	spin_unlock(&sn->rpc_client_lock);
  	return NULL;
  }
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
250
251
252
253
254
255
  static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
  			    void *ptr)
  {
  	struct super_block *sb = ptr;
  	struct rpc_clnt *clnt;
  	int error = 0;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
256

da3b46229   Stanislav Kinsbursky   SUNRPC: release p...
257
  	while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) {
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
258
  		error = __rpc_pipefs_event(clnt, event, sb);
da3b46229   Stanislav Kinsbursky   SUNRPC: release p...
259
  		rpc_release_client(clnt);
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
260
261
262
  		if (error)
  			break;
  	}
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
263
264
265
266
267
  	return error;
  }
  
  static struct notifier_block rpc_clients_block = {
  	.notifier_call	= rpc_pipefs_event,
eee17325f   Stanislav Kinsbursky   NFS: idmap PipeFS...
268
  	.priority	= SUNRPC_PIPEFS_RPC_PRIO,
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
269
270
271
272
273
274
275
276
277
278
279
  };
  
  int rpc_clients_notifier_register(void)
  {
  	return rpc_pipefs_notifier_register(&rpc_clients_block);
  }
  
  void rpc_clients_notifier_unregister(void)
  {
  	return rpc_pipefs_notifier_unregister(&rpc_clients_block);
  }
cbbb34498   Trond Myklebust   SUNRPC: RPC clien...
280
281
282
283
284
285
286
  static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
  {
  	clnt->cl_nodelen = strlen(nodename);
  	if (clnt->cl_nodelen > UNX_MAXNODENAME)
  		clnt->cl_nodelen = UNX_MAXNODENAME;
  	memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
  }
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
287
  static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  {
a613fa168   Trond Myklebust   SUNRPC: constify ...
289
290
  	const struct rpc_program *program = args->program;
  	const struct rpc_version *version;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  	struct rpc_clnt		*clnt = NULL;
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
292
  	struct rpc_auth		*auth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  	int err;
06b8d2552   Chuck Lever   SUNRPC: Make sure...
294
295
  
  	/* sanity check the name before trying to print it */
46121cf7d   Chuck Lever   SUNRPC: fix print...
296
297
  	dprintk("RPC:       creating %s client for %s (xprt %p)
  ",
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
298
  			program->name, args->servername, xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

4ada539ed   Trond Myklebust   SUNRPC: Make crea...
300
301
302
  	err = rpciod_up();
  	if (err)
  		goto out_no_rpciod;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
303

f05c124a7   Trond Myklebust   SUNRPC: Fix a pot...
304
  	err = -EINVAL;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
305
306
307
308
  	if (args->version >= program->nrvers)
  		goto out_err;
  	version = program->version[args->version];
  	if (version == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
  		goto out_err;
  
  	err = -ENOMEM;
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
312
  	clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  	if (!clnt)
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	clnt->cl_parent = clnt;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
316
  	rcu_assign_pointer(clnt->cl_xprt, xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
  	clnt->cl_procinfo = version->procs;
  	clnt->cl_maxproc  = version->nrprocs;
  	clnt->cl_protname = program->name;
d5b337b48   Benny Halevy   nfsd: use nfs cli...
320
  	clnt->cl_prog     = args->prognumber ? : program->number;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	clnt->cl_vers     = version->number;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	clnt->cl_stats    = program->stats;
11c556b3d   Chuck Lever   SUNRPC: provide a...
323
  	clnt->cl_metrics  = rpc_alloc_iostats(clnt);
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
324
325
326
  	err = -ENOMEM;
  	if (clnt->cl_metrics == NULL)
  		goto out_no_stats;
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
327
  	clnt->cl_program  = program;
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
328
  	INIT_LIST_HEAD(&clnt->cl_tasks);
4bef61ff7   Trond Myklebust   SUNRPC: Add a per...
329
  	spin_lock_init(&clnt->cl_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330

2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
331
  	if (!xprt_bound(xprt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  		clnt->cl_autobind = 1;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
333
334
335
336
337
338
  	clnt->cl_timeout = xprt->timeout;
  	if (args->timeout != NULL) {
  		memcpy(&clnt->cl_timeout_default, args->timeout,
  				sizeof(clnt->cl_timeout_default));
  		clnt->cl_timeout = &clnt->cl_timeout_default;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  	clnt->cl_rtt = &clnt->cl_rtt_default;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
340
  	rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
608207e88   Olga Kornievskaia   rpc: pass target ...
341
342
343
344
345
346
  	clnt->cl_principal = NULL;
  	if (args->client_name) {
  		clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL);
  		if (!clnt->cl_principal)
  			goto out_no_principal;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347

006abe887   Trond Myklebust   SUNRPC: Fix a rac...
348
  	atomic_set(&clnt->cl_count, 1);
34f52e359   Trond Myklebust   SUNRPC: Convert r...
349

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
  	err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
  	if (err < 0)
  		goto out_no_path;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
353
  	auth = rpcauth_create(args->authflavor, clnt);
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
354
  	if (IS_ERR(auth)) {
9b1d75b75   Trond Myklebust   SUNRPC: Don't spa...
355
356
  		dprintk("RPC:       Couldn't create auth handle (flavor %u)
  ",
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
357
  				args->authflavor);
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
358
  		err = PTR_ERR(auth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
  		goto out_no_auth;
  	}
  
  	/* save the nodename */
cbbb34498   Trond Myklebust   SUNRPC: RPC clien...
363
  	rpc_clnt_set_nodename(clnt, utsname()->nodename);
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
364
  	rpc_register_client(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
  	return clnt;
  
  out_no_auth:
0157d021d   Stanislav Kinsbursky   SUNRPC: handle RP...
368
  	rpc_clnt_remove_pipedir(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  out_no_path:
608207e88   Olga Kornievskaia   rpc: pass target ...
370
371
  	kfree(clnt->cl_principal);
  out_no_principal:
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
372
373
  	rpc_free_iostats(clnt->cl_metrics);
  out_no_stats:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
  	kfree(clnt);
  out_err:
4ada539ed   Trond Myklebust   SUNRPC: Make crea...
376
377
  	rpciod_down();
  out_no_rpciod:
f05c124a7   Trond Myklebust   SUNRPC: Fix a pot...
378
  	xprt_put(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
  	return ERR_PTR(err);
  }
2c53040f0   Ben Hutchings   net: Fix (nearly-...
381
  /**
c2866763b   Chuck Lever   SUNRPC: use socka...
382
383
384
385
386
387
388
389
390
391
392
393
394
   * rpc_create - create an RPC client and transport with one call
   * @args: rpc_clnt create argument structure
   *
   * Creates and initializes an RPC transport and an RPC client.
   *
   * It can ping the server in order to determine if it is up, and to see if
   * it supports this program and version.  RPC_CLNT_CREATE_NOPING disables
   * this behavior so asynchronous tasks can also use rpc_create.
   */
  struct rpc_clnt *rpc_create(struct rpc_create_args *args)
  {
  	struct rpc_xprt *xprt;
  	struct rpc_clnt *clnt;
3c341b0b9   \"Talpey, Thomas\   SUNRPC: rename th...
395
  	struct xprt_create xprtargs = {
9a23e332e   Pavel Emelyanov   sunrpc: Add net t...
396
  		.net = args->net,
4fa016eb2   \"Talpey, Thomas\   NFS/SUNRPC: suppo...
397
  		.ident = args->protocol,
d3bc9a1de   Frank van Maarseveen   SUNRPC client: ad...
398
  		.srcaddr = args->saddress,
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
399
400
  		.dstaddr = args->address,
  		.addrlen = args->addrsize,
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
401
  		.servername = args->servername,
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
402
  		.bc_xprt = args->bc_xprt,
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
403
  	};
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
404
  	char servername[48];
c2866763b   Chuck Lever   SUNRPC: use socka...
405

b7993cebb   Trond Myklebust   SUNRPC: Allow rpc...
406
407
  	if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
  		xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
33d90ac05   J. Bruce Fields   SUNRPC: allow dis...
408
409
  	if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
  		xprtargs.flags |= XPRT_CREATE_NO_IDLE_TIMEOUT;
c2866763b   Chuck Lever   SUNRPC: use socka...
410
  	/*
43780b87f   Chuck Lever   SUNRPC: Add a con...
411
412
413
  	 * If the caller chooses not to specify a hostname, whip
  	 * up a string representation of the passed-in address.
  	 */
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
414
  	if (xprtargs.servername == NULL) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
415
416
  		struct sockaddr_un *sun =
  				(struct sockaddr_un *)args->address;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
417
418
419
420
  		struct sockaddr_in *sin =
  				(struct sockaddr_in *)args->address;
  		struct sockaddr_in6 *sin6 =
  				(struct sockaddr_in6 *)args->address;
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
421
422
  		servername[0] = '\0';
  		switch (args->address->sa_family) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
423
424
425
426
  		case AF_LOCAL:
  			snprintf(servername, sizeof(servername), "%s",
  				 sun->sun_path);
  			break;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
427
  		case AF_INET:
21454aaad   Harvey Harrison   net: replace NIPQ...
428
429
  			snprintf(servername, sizeof(servername), "%pI4",
  				 &sin->sin_addr.s_addr);
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
430
  			break;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
431
  		case AF_INET6:
5b095d989   Harvey Harrison   net: replace %p6 ...
432
  			snprintf(servername, sizeof(servername), "%pI6",
da09eb930   Chuck Lever   SUNRPC: Clean up ...
433
  				 &sin6->sin6_addr);
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
434
  			break;
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
435
436
437
438
439
  		default:
  			/* caller wants default server name, but
  			 * address family isn't recognized. */
  			return ERR_PTR(-EINVAL);
  		}
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
440
  		xprtargs.servername = servername;
43780b87f   Chuck Lever   SUNRPC: Add a con...
441
  	}
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
442
443
444
  	xprt = xprt_create_transport(&xprtargs);
  	if (IS_ERR(xprt))
  		return (struct rpc_clnt *)xprt;
43780b87f   Chuck Lever   SUNRPC: Add a con...
445
  	/*
c2866763b   Chuck Lever   SUNRPC: use socka...
446
447
448
449
450
451
452
453
  	 * By default, kernel RPC client connects from a reserved port.
  	 * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
  	 * but it is always enabled for rpciod, which handles the connect
  	 * operation.
  	 */
  	xprt->resvport = 1;
  	if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
  		xprt->resvport = 0;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
454
  	clnt = rpc_new_client(args, xprt);
c2866763b   Chuck Lever   SUNRPC: use socka...
455
456
457
458
  	if (IS_ERR(clnt))
  		return clnt;
  
  	if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
459
  		int err = rpc_ping(clnt);
c2866763b   Chuck Lever   SUNRPC: use socka...
460
461
462
463
464
465
466
467
468
  		if (err != 0) {
  			rpc_shutdown_client(clnt);
  			return ERR_PTR(err);
  		}
  	}
  
  	clnt->cl_softrtry = 1;
  	if (args->flags & RPC_CLNT_CREATE_HARDRTRY)
  		clnt->cl_softrtry = 0;
c2866763b   Chuck Lever   SUNRPC: use socka...
469
470
  	if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
  		clnt->cl_autobind = 1;
43d78ef2b   Chuck Lever   NFS: disconnect b...
471
472
  	if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
  		clnt->cl_discrtry = 1;
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
473
474
  	if (!(args->flags & RPC_CLNT_CREATE_QUIET))
  		clnt->cl_chatty = 1;
c2866763b   Chuck Lever   SUNRPC: use socka...
475
476
477
  
  	return clnt;
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
478
  EXPORT_SYMBOL_GPL(rpc_create);
c2866763b   Chuck Lever   SUNRPC: use socka...
479

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
  /*
   * This function clones the RPC client structure. It allows us to share the
   * same transport while varying parameters such as the authentication
   * flavour.
   */
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
485
486
  static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
  					   struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
488
  	struct rpc_xprt *xprt;
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
489
490
  	struct rpc_clnt *new;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491

1b63a7518   Chuck Lever   SUNRPC: Refactor ...
492
  	err = -ENOMEM;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
493
494
495
496
  	rcu_read_lock();
  	xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
  	rcu_read_unlock();
  	if (xprt == NULL)
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
497
498
499
500
501
502
  		goto out_err;
  	args->servername = xprt->servername;
  
  	new = rpc_new_client(args, xprt);
  	if (IS_ERR(new)) {
  		err = PTR_ERR(new);
a58e0be6f   Chuck Lever   SUNRPC: Remove ex...
503
  		goto out_err;
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
504
  	}
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
505
  	atomic_inc(&clnt->cl_count);
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
506
507
508
509
510
511
512
  	new->cl_parent = clnt;
  
  	/* Turn off autobind on clones */
  	new->cl_autobind = 0;
  	new->cl_softrtry = clnt->cl_softrtry;
  	new->cl_discrtry = clnt->cl_discrtry;
  	new->cl_chatty = clnt->cl_chatty;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  	return new;
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
514

1b63a7518   Chuck Lever   SUNRPC: Refactor ...
515
  out_err:
0dc47877a   Harvey Harrison   net: replace rema...
516
517
  	dprintk("RPC:       %s: returned error %d
  ", __func__, err);
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
518
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  }
1b63a7518   Chuck Lever   SUNRPC: Refactor ...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  
  /**
   * rpc_clone_client - Clone an RPC client structure
   *
   * @clnt: RPC client whose parameters are copied
   *
   * Returns a fresh RPC client or an ERR_PTR.
   */
  struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
  {
  	struct rpc_create_args args = {
  		.program	= clnt->cl_program,
  		.prognumber	= clnt->cl_prog,
  		.version	= clnt->cl_vers,
  		.authflavor	= clnt->cl_auth->au_flavor,
  		.client_name	= clnt->cl_principal,
  	};
  	return __rpc_clone_client(&args, clnt);
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
539
  EXPORT_SYMBOL_GPL(rpc_clone_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540

ba9b584c1   Chuck Lever   SUNRPC: Introduce...
541
542
543
544
  /**
   * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
   *
   * @clnt: RPC client whose parameters are copied
7144bca68   Randy Dunlap   nfs: fix sunrpc/c...
545
   * @flavor: security flavor for new client
ba9b584c1   Chuck Lever   SUNRPC: Introduce...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
   *
   * Returns a fresh RPC client or an ERR_PTR.
   */
  struct rpc_clnt *
  rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
  {
  	struct rpc_create_args args = {
  		.program	= clnt->cl_program,
  		.prognumber	= clnt->cl_prog,
  		.version	= clnt->cl_vers,
  		.authflavor	= flavor,
  		.client_name	= clnt->cl_principal,
  	};
  	return __rpc_clone_client(&args, clnt);
  }
  EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  /*
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
   * Kill all tasks for the given client.
   * XXX: kill their descendants as well?
   */
  void rpc_killall_tasks(struct rpc_clnt *clnt)
  {
  	struct rpc_task	*rovr;
  
  
  	if (list_empty(&clnt->cl_tasks))
  		return;
  	dprintk("RPC:       killing all tasks for client %p
  ", clnt);
  	/*
  	 * Spin lock all_tasks to prevent changes...
  	 */
  	spin_lock(&clnt->cl_lock);
  	list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
  		if (!RPC_IS_ACTIVATED(rovr))
  			continue;
  		if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
  			rovr->tk_flags |= RPC_TASK_KILLED;
  			rpc_exit(rovr, -EIO);
8e26de238   Stanislav Kinsbursky   RPC: killing RPC ...
585
586
587
  			if (RPC_IS_QUEUED(rovr))
  				rpc_wake_up_queued_task(rovr->tk_waitqueue,
  							rovr);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
588
589
590
591
592
593
594
  		}
  	}
  	spin_unlock(&clnt->cl_lock);
  }
  EXPORT_SYMBOL_GPL(rpc_killall_tasks);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
   * Properly shut down an RPC client, terminating all outstanding
90c5755ff   Trond Myklebust   SUNRPC: Kill rpc_...
596
   * requests.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
   */
4c402b409   Trond Myklebust   SUNRPC: Remove rp...
598
  void rpc_shutdown_client(struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
  {
168e4b39d   Weston Andros Adamson   SUNRPC: add WARN_...
600
  	might_sleep();
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
601
602
603
604
  	dprintk_rcu("RPC:       shutting down %s client for %s
  ",
  			clnt->cl_protname,
  			rcu_dereference(clnt->cl_xprt)->servername);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

34f52e359   Trond Myklebust   SUNRPC: Convert r...
606
  	while (!list_empty(&clnt->cl_tasks)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  		rpc_killall_tasks(clnt);
532347e2b   Ingo Molnar   [PATCH] nfs: slee...
608
  		wait_event_timeout(destroy_wait,
34f52e359   Trond Myklebust   SUNRPC: Convert r...
609
  			list_empty(&clnt->cl_tasks), 1*HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
  	}
4c402b409   Trond Myklebust   SUNRPC: Remove rp...
611
  	rpc_release_client(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
613
  EXPORT_SYMBOL_GPL(rpc_shutdown_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
  
  /*
34f52e359   Trond Myklebust   SUNRPC: Convert r...
616
   * Free an RPC client
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
   */
34f52e359   Trond Myklebust   SUNRPC: Convert r...
618
  static void
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
619
  rpc_free_client(struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  {
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
621
622
623
624
  	dprintk_rcu("RPC:       destroying %s client for %s
  ",
  			clnt->cl_protname,
  			rcu_dereference(clnt->cl_xprt)->servername);
6eac7d3f4   Trond Myklebust   SUNRPC: constify ...
625
  	if (clnt->cl_parent != clnt)
8ad7c892e   Trond Myklebust   SUNRPC: Make rpc_...
626
  		rpc_release_client(clnt->cl_parent);
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
627
  	rpc_unregister_client(clnt);
f5131257f   Stanislav Kinsbursky   SUNRPC: remove RP...
628
  	rpc_clnt_remove_pipedir(clnt);
11c556b3d   Chuck Lever   SUNRPC: provide a...
629
  	rpc_free_iostats(clnt->cl_metrics);
608207e88   Olga Kornievskaia   rpc: pass target ...
630
  	kfree(clnt->cl_principal);
11c556b3d   Chuck Lever   SUNRPC: provide a...
631
  	clnt->cl_metrics = NULL;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
632
  	xprt_put(rcu_dereference_raw(clnt->cl_xprt));
4ada539ed   Trond Myklebust   SUNRPC: Make crea...
633
  	rpciod_down();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  	kfree(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
  }
  
  /*
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
638
639
640
   * Free an RPC client
   */
  static void
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
641
  rpc_free_auth(struct rpc_clnt *clnt)
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
642
  {
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
643
  	if (clnt->cl_auth == NULL) {
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
644
  		rpc_free_client(clnt);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
645
646
647
648
649
650
651
652
  		return;
  	}
  
  	/*
  	 * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
  	 *       release remaining GSS contexts. This mechanism ensures
  	 *       that it can do so safely.
  	 */
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
653
  	atomic_inc(&clnt->cl_count);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
654
655
  	rpcauth_release(clnt->cl_auth);
  	clnt->cl_auth = NULL;
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
656
657
  	if (atomic_dec_and_test(&clnt->cl_count))
  		rpc_free_client(clnt);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
658
659
660
  }
  
  /*
34f52e359   Trond Myklebust   SUNRPC: Convert r...
661
   * Release reference to the RPC client
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
   */
  void
  rpc_release_client(struct rpc_clnt *clnt)
  {
34f52e359   Trond Myklebust   SUNRPC: Convert r...
666
667
  	dprintk("RPC:       rpc_release_client(%p)
  ", clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668

34f52e359   Trond Myklebust   SUNRPC: Convert r...
669
670
  	if (list_empty(&clnt->cl_tasks))
  		wake_up(&destroy_wait);
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
671
672
  	if (atomic_dec_and_test(&clnt->cl_count))
  		rpc_free_auth(clnt);
34f52e359   Trond Myklebust   SUNRPC: Convert r...
673
  }
1d658336b   Simo Sorce   SUNRPC: Add RPC b...
674
  EXPORT_SYMBOL_GPL(rpc_release_client);
34f52e359   Trond Myklebust   SUNRPC: Convert r...
675

007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
676
677
  /**
   * rpc_bind_new_program - bind a new RPC program to an existing client
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
678
679
680
   * @old: old rpc_client
   * @program: rpc program to set
   * @vers: rpc program version
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
681
682
683
684
685
686
   *
   * Clones the rpc client and sets up a new RPC program. This is mainly
   * of use for enabling different RPC programs to share the same transport.
   * The Sun NFSv2/v3 ACL protocol can do this.
   */
  struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
a613fa168   Trond Myklebust   SUNRPC: constify ...
687
  				      const struct rpc_program *program,
89eb21c35   Chuck Lever   SUNRPC: fix a sig...
688
  				      u32 vers)
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
689
  {
f994c43d1   Trond Myklebust   SUNRPC: Clean up ...
690
691
692
693
694
695
696
  	struct rpc_create_args args = {
  		.program	= program,
  		.prognumber	= program->number,
  		.version	= vers,
  		.authflavor	= old->cl_auth->au_flavor,
  		.client_name	= old->cl_principal,
  	};
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
697
  	struct rpc_clnt *clnt;
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
698
  	int err;
f994c43d1   Trond Myklebust   SUNRPC: Clean up ...
699
  	clnt = __rpc_clone_client(&args, old);
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
700
701
  	if (IS_ERR(clnt))
  		goto out;
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
702
  	err = rpc_ping(clnt);
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
703
704
705
706
  	if (err != 0) {
  		rpc_shutdown_client(clnt);
  		clnt = ERR_PTR(err);
  	}
cca5172a7   YOSHIFUJI Hideaki   [NET] SUNRPC: Fix...
707
  out:
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
708
709
  	return clnt;
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
710
  EXPORT_SYMBOL_GPL(rpc_bind_new_program);
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
711

58f9612c6   Trond Myklebust   SUNRPC: Move rema...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
  void rpc_task_release_client(struct rpc_task *task)
  {
  	struct rpc_clnt *clnt = task->tk_client;
  
  	if (clnt != NULL) {
  		/* Remove from client task list */
  		spin_lock(&clnt->cl_lock);
  		list_del(&task->tk_task);
  		spin_unlock(&clnt->cl_lock);
  		task->tk_client = NULL;
  
  		rpc_release_client(clnt);
  	}
  }
  
  static
  void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
  {
  	if (clnt != NULL) {
  		rpc_task_release_client(task);
  		task->tk_client = clnt;
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
733
  		atomic_inc(&clnt->cl_count);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
734
735
  		if (clnt->cl_softrtry)
  			task->tk_flags |= RPC_TASK_SOFT;
a564b8f03   Mel Gorman   nfs: enable swap ...
736
737
738
739
740
741
742
743
744
  		if (sk_memalloc_socks()) {
  			struct rpc_xprt *xprt;
  
  			rcu_read_lock();
  			xprt = rcu_dereference(clnt->cl_xprt);
  			if (xprt->swapper)
  				task->tk_flags |= RPC_TASK_SWAPPER;
  			rcu_read_unlock();
  		}
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
745
746
747
748
749
750
  		/* Add to the client's list of all tasks */
  		spin_lock(&clnt->cl_lock);
  		list_add_tail(&task->tk_task, &clnt->cl_tasks);
  		spin_unlock(&clnt->cl_lock);
  	}
  }
cbdabc7f8   Andy Adamson   NFSv4.1: filelayo...
751
752
753
754
755
756
  void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt)
  {
  	rpc_task_release_client(task);
  	rpc_task_set_client(task, clnt);
  }
  EXPORT_SYMBOL_GPL(rpc_task_reset_client);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
757
758
759
760
761
762
763
  static void
  rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg)
  {
  	if (msg != NULL) {
  		task->tk_msg.rpc_proc = msg->rpc_proc;
  		task->tk_msg.rpc_argp = msg->rpc_argp;
  		task->tk_msg.rpc_resp = msg->rpc_resp;
a17c2153d   Trond Myklebust   SUNRPC: Move the ...
764
765
  		if (msg->rpc_cred != NULL)
  			task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
766
767
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
770
771
  /*
   * Default callback for async RPC calls
   */
  static void
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
772
  rpc_default_callback(struct rpc_task *task, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
774
  {
  }
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
775
776
777
  static const struct rpc_call_ops rpc_default_ops = {
  	.rpc_call_done = rpc_default_callback,
  };
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
778
779
780
781
782
  /**
   * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
   * @task_setup_data: pointer to task initialisation data
   */
  struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
783
  {
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
784
  	struct rpc_task *task;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
785

84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
786
  	task = rpc_new_task(task_setup_data);
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
787
  	if (IS_ERR(task))
508592590   Trond Myklebust   SUNRPC: Mask sign...
788
  		goto out;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
789

58f9612c6   Trond Myklebust   SUNRPC: Move rema...
790
791
  	rpc_task_set_client(task, task_setup_data->rpc_client);
  	rpc_task_set_rpc_message(task, task_setup_data->rpc_message);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
792
793
  	if (task->tk_action == NULL)
  		rpc_call_start(task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
794
795
  	atomic_inc(&task->tk_count);
  	rpc_execute(task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
796
  out:
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
797
  	return task;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
798
  }
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
799
  EXPORT_SYMBOL_GPL(rpc_run_task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
800
801
802
803
804
805
  
  /**
   * rpc_call_sync - Perform a synchronous RPC call
   * @clnt: pointer to RPC client
   * @msg: RPC call parameters
   * @flags: RPC call flags
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
   */
cbc200592   Trond Myklebust   SUNRPC: Declare a...
807
  int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
809
  {
  	struct rpc_task	*task;
84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
810
811
812
813
814
815
  	struct rpc_task_setup task_setup_data = {
  		.rpc_client = clnt,
  		.rpc_message = msg,
  		.callback_ops = &rpc_default_ops,
  		.flags = flags,
  	};
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
816
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817

50d2bdb19   Weston Andros Adamson   SUNRPC: remove BU...
818
819
820
821
822
823
  	WARN_ON_ONCE(flags & RPC_TASK_ASYNC);
  	if (flags & RPC_TASK_ASYNC) {
  		rpc_release_calldata(task_setup_data.callback_ops,
  			task_setup_data.callback_data);
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
825
  	task = rpc_run_task(&task_setup_data);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
826
827
  	if (IS_ERR(task))
  		return PTR_ERR(task);
e60859ac0   Trond Myklebust   SUNRPC: rpc_execu...
828
  	status = task->tk_status;
bde8f00ce   Trond Myklebust   [PATCH] NFS: Fix ...
829
  	rpc_put_task(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
  	return status;
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
832
  EXPORT_SYMBOL_GPL(rpc_call_sync);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833

6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
834
835
836
837
838
  /**
   * rpc_call_async - Perform an asynchronous RPC call
   * @clnt: pointer to RPC client
   * @msg: RPC call parameters
   * @flags: RPC call flags
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
839
   * @tk_ops: RPC call ops
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
840
   * @data: user call data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
842
   */
  int
cbc200592   Trond Myklebust   SUNRPC: Declare a...
843
  rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
844
  	       const struct rpc_call_ops *tk_ops, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
  {
  	struct rpc_task	*task;
84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
847
848
849
850
851
852
853
  	struct rpc_task_setup task_setup_data = {
  		.rpc_client = clnt,
  		.rpc_message = msg,
  		.callback_ops = tk_ops,
  		.callback_data = data,
  		.flags = flags|RPC_TASK_ASYNC,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
855
  	task = rpc_run_task(&task_setup_data);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
856
857
858
859
  	if (IS_ERR(task))
  		return PTR_ERR(task);
  	rpc_put_task(task);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
861
  EXPORT_SYMBOL_GPL(rpc_call_async);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862

9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
863
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
864
865
866
  /**
   * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
   * rpc_execute against it
7a73fdde3   Jaswinder Singh Rajput   net: fix htmldocs...
867
868
   * @req: RPC request
   * @tk_ops: RPC call ops
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
869
870
   */
  struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
7a73fdde3   Jaswinder Singh Rajput   net: fix htmldocs...
871
  				const struct rpc_call_ops *tk_ops)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
872
873
874
875
876
877
878
879
880
881
882
883
884
  {
  	struct rpc_task *task;
  	struct xdr_buf *xbufp = &req->rq_snd_buf;
  	struct rpc_task_setup task_setup_data = {
  		.callback_ops = tk_ops,
  	};
  
  	dprintk("RPC: rpc_run_bc_task req= %p
  ", req);
  	/*
  	 * Create an rpc_task to send the data
  	 */
  	task = rpc_new_task(&task_setup_data);
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
885
  	if (IS_ERR(task)) {
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
  		xprt_free_bc_request(req);
  		goto out;
  	}
  	task->tk_rqstp = req;
  
  	/*
  	 * Set up the xdr_buf length.
  	 * This also indicates that the buffer is XDR encoded already.
  	 */
  	xbufp->len = xbufp->head[0].iov_len + xbufp->page_len +
  			xbufp->tail[0].iov_len;
  
  	task->tk_action = call_bc_transmit;
  	atomic_inc(&task->tk_count);
9a6478f6c   Weston Andros Adamson   SUNRPC: remove BU...
900
  	WARN_ON_ONCE(atomic_read(&task->tk_count) != 2);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
901
902
903
904
905
906
907
  	rpc_execute(task);
  
  out:
  	dprintk("RPC: rpc_run_bc_task: task= %p
  ", task);
  	return task;
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
908
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
909

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
  void
77de2c590   Trond Myklebust   SUNRPC: Add a hel...
911
912
913
914
915
  rpc_call_start(struct rpc_task *task)
  {
  	task->tk_action = call_start;
  }
  EXPORT_SYMBOL_GPL(rpc_call_start);
ed39440a2   Chuck Lever   SUNRPC: create AP...
916
917
918
919
  /**
   * rpc_peeraddr - extract remote peer address from clnt's xprt
   * @clnt: RPC client structure
   * @buf: target buffer
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
920
   * @bufsize: length of target buffer
ed39440a2   Chuck Lever   SUNRPC: create AP...
921
922
923
924
925
926
   *
   * Returns the number of bytes that are actually in the stored address.
   */
  size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize)
  {
  	size_t bytes;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
927
928
929
930
  	struct rpc_xprt *xprt;
  
  	rcu_read_lock();
  	xprt = rcu_dereference(clnt->cl_xprt);
ed39440a2   Chuck Lever   SUNRPC: create AP...
931

2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
932
  	bytes = xprt->addrlen;
ed39440a2   Chuck Lever   SUNRPC: create AP...
933
934
  	if (bytes > bufsize)
  		bytes = bufsize;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
935
936
937
938
  	memcpy(buf, &xprt->addr, bytes);
  	rcu_read_unlock();
  
  	return bytes;
ed39440a2   Chuck Lever   SUNRPC: create AP...
939
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
940
  EXPORT_SYMBOL_GPL(rpc_peeraddr);
ed39440a2   Chuck Lever   SUNRPC: create AP...
941

f425eba43   Chuck Lever   SUNRPC: Create AP...
942
943
944
945
946
  /**
   * rpc_peeraddr2str - return remote peer address in printable format
   * @clnt: RPC client structure
   * @format: address format
   *
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
947
948
949
   * NB: the lifetime of the memory referenced by the returned pointer is
   * the same as the rpc_xprt itself.  As long as the caller uses this
   * pointer, it must hold the RCU read lock.
f425eba43   Chuck Lever   SUNRPC: Create AP...
950
   */
b454ae906   Chuck Lever   SUNRPC: fewer con...
951
952
  const char *rpc_peeraddr2str(struct rpc_clnt *clnt,
  			     enum rpc_display_format_t format)
f425eba43   Chuck Lever   SUNRPC: Create AP...
953
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
954
955
956
  	struct rpc_xprt *xprt;
  
  	xprt = rcu_dereference(clnt->cl_xprt);
7559c7a28   Chuck Lever   SUNRPC: Make addr...
957
958
959
960
961
  
  	if (xprt->address_strings[format] != NULL)
  		return xprt->address_strings[format];
  	else
  		return "unprintable";
f425eba43   Chuck Lever   SUNRPC: Create AP...
962
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
963
  EXPORT_SYMBOL_GPL(rpc_peeraddr2str);
f425eba43   Chuck Lever   SUNRPC: Create AP...
964

2e738fdce   Chuck Lever   SUNRPC: Add API t...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
  static const struct sockaddr_in rpc_inaddr_loopback = {
  	.sin_family		= AF_INET,
  	.sin_addr.s_addr	= htonl(INADDR_ANY),
  };
  
  static const struct sockaddr_in6 rpc_in6addr_loopback = {
  	.sin6_family		= AF_INET6,
  	.sin6_addr		= IN6ADDR_ANY_INIT,
  };
  
  /*
   * Try a getsockname() on a connected datagram socket.  Using a
   * connected datagram socket prevents leaving a socket in TIME_WAIT.
   * This conserves the ephemeral port number space.
   *
   * Returns zero and fills in "buf" if successful; otherwise, a
   * negative errno is returned.
   */
  static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen,
  			struct sockaddr *buf, int buflen)
  {
  	struct socket *sock;
  	int err;
  
  	err = __sock_create(net, sap->sa_family,
  				SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
  	if (err < 0) {
  		dprintk("RPC:       can't create UDP socket (%d)
  ", err);
  		goto out;
  	}
  
  	switch (sap->sa_family) {
  	case AF_INET:
  		err = kernel_bind(sock,
  				(struct sockaddr *)&rpc_inaddr_loopback,
  				sizeof(rpc_inaddr_loopback));
  		break;
  	case AF_INET6:
  		err = kernel_bind(sock,
  				(struct sockaddr *)&rpc_in6addr_loopback,
  				sizeof(rpc_in6addr_loopback));
  		break;
  	default:
  		err = -EAFNOSUPPORT;
  		goto out;
  	}
  	if (err < 0) {
  		dprintk("RPC:       can't bind UDP socket (%d)
  ", err);
  		goto out_release;
  	}
  
  	err = kernel_connect(sock, sap, salen, 0);
  	if (err < 0) {
  		dprintk("RPC:       can't connect UDP socket (%d)
  ", err);
  		goto out_release;
  	}
  
  	err = kernel_getsockname(sock, buf, &buflen);
  	if (err < 0) {
  		dprintk("RPC:       getsockname failed (%d)
  ", err);
  		goto out_release;
  	}
  
  	err = 0;
  	if (buf->sa_family == AF_INET6) {
  		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
  		sin6->sin6_scope_id = 0;
  	}
  	dprintk("RPC:       %s succeeded
  ", __func__);
  
  out_release:
  	sock_release(sock);
  out:
  	return err;
  }
  
  /*
   * Scraping a connected socket failed, so we don't have a useable
   * local address.  Fallback: generate an address that will prevent
   * the server from calling us back.
   *
   * Returns zero and fills in "buf" if successful; otherwise, a
   * negative errno is returned.
   */
  static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen)
  {
  	switch (family) {
  	case AF_INET:
  		if (buflen < sizeof(rpc_inaddr_loopback))
  			return -EINVAL;
  		memcpy(buf, &rpc_inaddr_loopback,
  				sizeof(rpc_inaddr_loopback));
  		break;
  	case AF_INET6:
  		if (buflen < sizeof(rpc_in6addr_loopback))
  			return -EINVAL;
  		memcpy(buf, &rpc_in6addr_loopback,
  				sizeof(rpc_in6addr_loopback));
  	default:
  		dprintk("RPC:       %s: address family not supported
  ",
  			__func__);
  		return -EAFNOSUPPORT;
  	}
  	dprintk("RPC:       %s: succeeded
  ", __func__);
  	return 0;
  }
  
  /**
   * rpc_localaddr - discover local endpoint address for an RPC client
   * @clnt: RPC client structure
   * @buf: target buffer
   * @buflen: size of target buffer, in bytes
   *
   * Returns zero and fills in "buf" and "buflen" if successful;
   * otherwise, a negative errno is returned.
   *
   * This works even if the underlying transport is not currently connected,
   * or if the upper layer never previously provided a source address.
   *
   * The result of this function call is transient: multiple calls in
   * succession may give different results, depending on how local
   * networking configuration changes over time.
   */
  int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen)
  {
  	struct sockaddr_storage address;
  	struct sockaddr *sap = (struct sockaddr *)&address;
  	struct rpc_xprt *xprt;
  	struct net *net;
  	size_t salen;
  	int err;
  
  	rcu_read_lock();
  	xprt = rcu_dereference(clnt->cl_xprt);
  	salen = xprt->addrlen;
  	memcpy(sap, &xprt->addr, salen);
  	net = get_net(xprt->xprt_net);
  	rcu_read_unlock();
  
  	rpc_set_port(sap, 0);
  	err = rpc_sockname(net, sap, salen, buf, buflen);
  	put_net(net);
  	if (err != 0)
  		/* Couldn't discover local address, return ANYADDR */
  		return rpc_anyaddr(sap->sa_family, buf, buflen);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(rpc_localaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
  void
  rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
1123
1124
1125
1126
  	struct rpc_xprt *xprt;
  
  	rcu_read_lock();
  	xprt = rcu_dereference(clnt->cl_xprt);
470056c28   Chuck Lever   [PATCH] RPC: rati...
1127
1128
  	if (xprt->ops->set_buffer_size)
  		xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
1129
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
1131
  EXPORT_SYMBOL_GPL(rpc_setbufsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132

2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
  /**
   * rpc_protocol - Get transport protocol number for an RPC client
   * @clnt: RPC client to query
   *
   */
  int rpc_protocol(struct rpc_clnt *clnt)
  {
  	int protocol;
  
  	rcu_read_lock();
  	protocol = rcu_dereference(clnt->cl_xprt)->prot;
  	rcu_read_unlock();
  	return protocol;
  }
  EXPORT_SYMBOL_GPL(rpc_protocol);
  
  /**
   * rpc_net_ns - Get the network namespace for this RPC client
   * @clnt: RPC client to query
   *
   */
  struct net *rpc_net_ns(struct rpc_clnt *clnt)
  {
  	struct net *ret;
  
  	rcu_read_lock();
  	ret = rcu_dereference(clnt->cl_xprt)->xprt_net;
  	rcu_read_unlock();
  	return ret;
  }
  EXPORT_SYMBOL_GPL(rpc_net_ns);
  
  /**
   * rpc_max_payload - Get maximum payload size for a transport, in bytes
   * @clnt: RPC client to query
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
1170
1171
1172
1173
1174
1175
   *
   * For stream transports, this is one RPC record fragment (see RFC
   * 1831), as we don't support multi-record requests yet.  For datagram
   * transports, this is the size of an IP packet minus the IP, UDP, and
   * RPC header sizes.
   */
  size_t rpc_max_payload(struct rpc_clnt *clnt)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
1176
1177
1178
1179
1180
1181
  	size_t ret;
  
  	rcu_read_lock();
  	ret = rcu_dereference(clnt->cl_xprt)->max_payload;
  	rcu_read_unlock();
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
1183
  EXPORT_SYMBOL_GPL(rpc_max_payload);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184

35f5a422c   Chuck Lever   SUNRPC: new inter...
1185
  /**
512e4b291   Trond Myklebust   SUNRPC: One line ...
1186
   * rpc_get_timeout - Get timeout for transport in units of HZ
edddbb1ed   Weston Andros Adamson   SUNRPC: add call ...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
   * @clnt: RPC client to query
   */
  unsigned long rpc_get_timeout(struct rpc_clnt *clnt)
  {
  	unsigned long ret;
  
  	rcu_read_lock();
  	ret = rcu_dereference(clnt->cl_xprt)->timeout->to_initval;
  	rcu_read_unlock();
  	return ret;
  }
  EXPORT_SYMBOL_GPL(rpc_get_timeout);
  
  /**
35f5a422c   Chuck Lever   SUNRPC: new inter...
1201
1202
1203
1204
1205
1206
   * rpc_force_rebind - force transport to check that remote port is unchanged
   * @clnt: client to rebind
   *
   */
  void rpc_force_rebind(struct rpc_clnt *clnt)
  {
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
1207
1208
1209
1210
1211
  	if (clnt->cl_autobind) {
  		rcu_read_lock();
  		xprt_clear_bound(rcu_dereference(clnt->cl_xprt));
  		rcu_read_unlock();
  	}
35f5a422c   Chuck Lever   SUNRPC: new inter...
1212
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
1213
  EXPORT_SYMBOL_GPL(rpc_force_rebind);
35f5a422c   Chuck Lever   SUNRPC: new inter...
1214

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1215
  /*
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
1216
1217
1218
   * Restart an (async) RPC call from the call_prepare state.
   * Usually called from within the exit handler.
   */
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1219
  int
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
1220
1221
1222
  rpc_restart_call_prepare(struct rpc_task *task)
  {
  	if (RPC_ASSASSINATED(task))
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1223
  		return 0;
d00c5d438   Trond Myklebust   NFS: Get rid of n...
1224
1225
1226
  	task->tk_action = call_start;
  	if (task->tk_ops->rpc_call_prepare != NULL)
  		task->tk_action = rpc_prepare_task;
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1227
  	return 1;
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
1228
1229
1230
1231
  }
  EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
1234
   * Restart an (async) RPC call. Usually called from within the
   * exit handler.
   */
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1235
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
1237
1238
  rpc_restart_call(struct rpc_task *task)
  {
  	if (RPC_ASSASSINATED(task))
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1239
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
  	task->tk_action = call_start;
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
1241
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
1243
  EXPORT_SYMBOL_GPL(rpc_restart_call);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244

3748f1e44   Chuck Lever   SUNRPC: Add a fun...
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  #ifdef RPC_DEBUG
  static const char *rpc_proc_name(const struct rpc_task *task)
  {
  	const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
  
  	if (proc) {
  		if (proc->p_name)
  			return proc->p_name;
  		else
  			return "NULL";
  	} else
  		return "no proc";
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  /*
   * 0.  Initial state
   *
   *     Other FSM states can be visited zero or more times, but
   *     this state is visited exactly once for each RPC.
   */
  static void
  call_start(struct rpc_task *task)
  {
  	struct rpc_clnt	*clnt = task->tk_client;
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
1269
1270
  	dprintk("RPC: %5u call_start %s%d proc %s (%s)
  ", task->tk_pid,
46121cf7d   Chuck Lever   SUNRPC: fix print...
1271
  			clnt->cl_protname, clnt->cl_vers,
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
1272
  			rpc_proc_name(task),
46121cf7d   Chuck Lever   SUNRPC: fix print...
1273
  			(RPC_IS_ASYNC(task) ? "async" : "sync"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  
  	/* Increment call count */
  	task->tk_msg.rpc_proc->p_count++;
  	clnt->cl_stats->rpccnt++;
  	task->tk_action = call_reserve;
  }
  
  /*
   * 1.	Reserve an RPC call slot
   */
  static void
  call_reserve(struct rpc_task *task)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1287
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
1291
1292
  	task->tk_status  = 0;
  	task->tk_action  = call_reserveresult;
  	xprt_reserve(task);
  }
ba60eb25f   Trond Myklebust   SUNRPC: Fix a liv...
1293
  static void call_retry_reserve(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
1295
1296
1297
1298
1299
1300
  /*
   * 1b.	Grok the result of xprt_reserve()
   */
  static void
  call_reserveresult(struct rpc_task *task)
  {
  	int status = task->tk_status;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1301
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
1305
1306
1307
1308
1309
  
  	/*
  	 * After a call to xprt_reserve(), we must have either
  	 * a request slot or else an error status.
  	 */
  	task->tk_status = 0;
  	if (status >= 0) {
  		if (task->tk_rqstp) {
f2d47d02f   J. Bruce Fields   Fix null derefere...
1310
  			task->tk_action = call_refresh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
1312
1313
1314
1315
  			return;
  		}
  
  		printk(KERN_ERR "%s: status=%d, but no request slot, exiting
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1316
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
  		rpc_exit(task, -EIO);
  		return;
  	}
  
  	/*
  	 * Even though there was an error, we may have acquired
  	 * a request slot somehow.  Make sure not to leak it.
  	 */
  	if (task->tk_rqstp) {
  		printk(KERN_ERR "%s: status=%d, request allocated anyway
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1328
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
1332
  		xprt_release(task);
  	}
  
  	switch (status) {
1afeaf5c2   Trond Myklebust   sunrpc: fix loss ...
1333
1334
  	case -ENOMEM:
  		rpc_delay(task, HZ >> 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  	case -EAGAIN:	/* woken up; retry */
ba60eb25f   Trond Myklebust   SUNRPC: Fix a liv...
1336
  		task->tk_action = call_retry_reserve;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
1340
1341
1342
  		return;
  	case -EIO:	/* probably a shutdown */
  		break;
  	default:
  		printk(KERN_ERR "%s: unrecognized error %d, exiting
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1343
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
1346
1347
1348
1349
  		break;
  	}
  	rpc_exit(task, status);
  }
  
  /*
ba60eb25f   Trond Myklebust   SUNRPC: Fix a liv...
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
   * 1c.	Retry reserving an RPC call slot
   */
  static void
  call_retry_reserve(struct rpc_task *task)
  {
  	dprint_status(task);
  
  	task->tk_status  = 0;
  	task->tk_action  = call_reserveresult;
  	xprt_retry_reserve(task);
  }
  
  /*
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
   * 2.	Bind and/or refresh the credentials
   */
  static void
  call_refresh(struct rpc_task *task)
  {
  	dprint_status(task);
  
  	task->tk_action = call_refreshresult;
  	task->tk_status = 0;
  	task->tk_client->cl_stats->rpcauthrefresh++;
  	rpcauth_refreshcred(task);
  }
  
  /*
   * 2a.	Process the results of a credential refresh
   */
  static void
  call_refreshresult(struct rpc_task *task)
  {
  	int status = task->tk_status;
  
  	dprint_status(task);
  
  	task->tk_status = 0;
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
1387
  	task->tk_action = call_refresh;
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
1388
  	switch (status) {
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
1389
1390
1391
  	case 0:
  		if (rpcauth_uptodatecred(task))
  			task->tk_action = call_allocate;
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
1392
1393
1394
  		return;
  	case -ETIMEDOUT:
  		rpc_delay(task, 3*HZ);
eb96d5c97   Andy Adamson   SUNRPC handle EKE...
1395
  	case -EKEYEXPIRED:
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
1396
1397
1398
1399
1400
1401
1402
1403
1404
  	case -EAGAIN:
  		status = -EACCES;
  		if (!task->tk_cred_retry)
  			break;
  		task->tk_cred_retry--;
  		dprintk("RPC: %5u %s: retry refresh creds
  ",
  				task->tk_pid, __func__);
  		return;
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
1405
  	}
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
1406
1407
1408
1409
  	dprintk("RPC: %5u %s: refresh creds failed with error %d
  ",
  				task->tk_pid, __func__, status);
  	rpc_exit(task, status);
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
1410
1411
1412
1413
  }
  
  /*
   * 2b.	Allocate the buffer. For details, see sched.c:rpc_malloc.
021071483   Chuck Lever   SUNRPC: switchabl...
1414
   *	(Note: buffer memory is freed in xprt_release).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
1416
1417
1418
   */
  static void
  call_allocate(struct rpc_task *task)
  {
f2d47d02f   J. Bruce Fields   Fix null derefere...
1419
  	unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack;
021071483   Chuck Lever   SUNRPC: switchabl...
1420
  	struct rpc_rqst *req = task->tk_rqstp;
a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
1421
  	struct rpc_xprt *xprt = req->rq_xprt;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1422
  	struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423

46121cf7d   Chuck Lever   SUNRPC: fix print...
1424
  	dprint_status(task);
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1425
  	task->tk_status = 0;
f2d47d02f   J. Bruce Fields   Fix null derefere...
1426
  	task->tk_action = call_bind;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1427

021071483   Chuck Lever   SUNRPC: switchabl...
1428
  	if (req->rq_buffer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
  		return;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1430
1431
1432
1433
1434
  	if (proc->p_proc != 0) {
  		BUG_ON(proc->p_arglen == 0);
  		if (proc->p_decode != NULL)
  			BUG_ON(proc->p_replen == 0);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435

2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1436
1437
1438
1439
1440
1441
1442
1443
1444
  	/*
  	 * Calculate the size (in quads) of the RPC call
  	 * and reply headers, and convert both values
  	 * to byte sizes.
  	 */
  	req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen;
  	req->rq_callsize <<= 2;
  	req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen;
  	req->rq_rcvsize <<= 2;
c5a4dd8b7   Chuck Lever   SUNRPC: Eliminate...
1445
1446
  	req->rq_buffer = xprt->ops->buf_alloc(task,
  					req->rq_callsize + req->rq_rcvsize);
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1447
  	if (req->rq_buffer != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  		return;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1449
1450
1451
  
  	dprintk("RPC: %5u rpc_buffer allocation failed
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452

5afa9133c   Trond Myklebust   SUNRPC: Ensure th...
1453
  	if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
b6e9c713f   Trond Myklebust   SUNRPC: Don't cal...
1454
  		task->tk_action = call_allocate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
1456
1457
1458
1459
1460
  		rpc_delay(task, HZ>>4);
  		return;
  	}
  
  	rpc_exit(task, -ERESTARTSYS);
  }
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  static inline int
  rpc_task_need_encode(struct rpc_task *task)
  {
  	return task->tk_rqstp->rq_snd_buf.len == 0;
  }
  
  static inline void
  rpc_task_force_reencode(struct rpc_task *task)
  {
  	task->tk_rqstp->rq_snd_buf.len = 0;
2574cc9f4   Trond Myklebust   SUNRPC: Fix rpc_t...
1471
  	task->tk_rqstp->rq_bytes_sent = 0;
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1472
  }
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1473
1474
1475
1476
1477
1478
1479
  static inline void
  rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
  {
  	buf->head[0].iov_base = start;
  	buf->head[0].iov_len = len;
  	buf->tail[0].iov_len = 0;
  	buf->page_len = 0;
4f22ccc34   \"Talpey, Thomas\   SUNRPC: mark bulk...
1480
  	buf->flags = 0;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1481
1482
1483
  	buf->len = 0;
  	buf->buflen = len;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
1485
1486
1487
  /*
   * 3.	Encode arguments of an RPC call
   */
  static void
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1488
  rpc_xdr_encode(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
  	struct rpc_rqst	*req = task->tk_rqstp;
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
1491
  	kxdreproc_t	encode;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1492
  	__be32		*p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493

46121cf7d   Chuck Lever   SUNRPC: fix print...
1494
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495

2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1496
1497
1498
1499
1500
1501
  	rpc_xdr_buf_init(&req->rq_snd_buf,
  			 req->rq_buffer,
  			 req->rq_callsize);
  	rpc_xdr_buf_init(&req->rq_rcv_buf,
  			 (char *)req->rq_buffer + req->rq_callsize,
  			 req->rq_rcvsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502

b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1503
1504
1505
1506
  	p = rpc_encode_header(task);
  	if (p == NULL) {
  		printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507
1508
1509
  		rpc_exit(task, -EIO);
  		return;
  	}
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1510
1511
  
  	encode = task->tk_msg.rpc_proc->p_encode;
f3680312a   J. Bruce Fields   SUNRPC: Retry wra...
1512
1513
1514
1515
1516
  	if (encode == NULL)
  		return;
  
  	task->tk_status = rpcauth_wrap_req(task, encode, req, p,
  			task->tk_msg.rpc_argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
1519
1520
1521
1522
1523
1524
  }
  
  /*
   * 4.	Get the server port number if not yet set
   */
  static void
  call_bind(struct rpc_task *task)
  {
ad2368d6f   Trond Myklebust   SUNRPC: Avoid RCU...
1525
  	struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526

46121cf7d   Chuck Lever   SUNRPC: fix print...
1527
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1528

da3518780   Chuck Lever   [PATCH] RPC: prop...
1529
  	task->tk_action = call_connect;
ec739ef03   Chuck Lever   SUNRPC: Create a ...
1530
  	if (!xprt_bound(xprt)) {
da3518780   Chuck Lever   [PATCH] RPC: prop...
1531
  		task->tk_action = call_bind_status;
ec739ef03   Chuck Lever   SUNRPC: Create a ...
1532
  		task->tk_timeout = xprt->bind_timeout;
bbf7c1dd2   Chuck Lever   SUNRPC: Introduce...
1533
  		xprt->ops->rpcbind(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
1535
1536
1537
  	}
  }
  
  /*
da3518780   Chuck Lever   [PATCH] RPC: prop...
1538
1539
1540
1541
1542
   * 4a.	Sort out bind result
   */
  static void
  call_bind_status(struct rpc_task *task)
  {
906462af4   Chuck Lever   SUNRPC: Split ano...
1543
  	int status = -EIO;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1544
1545
  
  	if (task->tk_status >= 0) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1546
  		dprint_status(task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1547
1548
1549
1550
  		task->tk_status = 0;
  		task->tk_action = call_connect;
  		return;
  	}
5753cba17   Steve Dickson   SUNRPC: Adding st...
1551
  	trace_rpc_bind_status(task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1552
  	switch (task->tk_status) {
381ba74af   Trond Myklebust   SUNRPC: Ensure ou...
1553
1554
1555
1556
  	case -ENOMEM:
  		dprintk("RPC: %5u rpcbind out of memory
  ", task->tk_pid);
  		rpc_delay(task, HZ >> 2);
2429cbf6a   Chuck Lever   SUNRPC: Add a new...
1557
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1558
  	case -EACCES:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1559
1560
1561
  		dprintk("RPC: %5u remote rpcbind: RPC program/version "
  				"unavailable
  ", task->tk_pid);
b79dc8ced   Chuck Lever   SUNRPC: RPC bind ...
1562
1563
1564
1565
1566
  		/* fail immediately if this is an RPC ping */
  		if (task->tk_msg.rpc_proc->p_proc == 0) {
  			status = -EOPNOTSUPP;
  			break;
  		}
0b760113a   Trond Myklebust   NLM: Don't hang f...
1567
1568
1569
  		if (task->tk_rebind_retry == 0)
  			break;
  		task->tk_rebind_retry--;
ea635a517   Chuck Lever   SUNRPC: Retry rpc...
1570
  		rpc_delay(task, 3*HZ);
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1571
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1572
  	case -ETIMEDOUT:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1573
1574
  		dprintk("RPC: %5u rpcbind request timed out
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1575
  				task->tk_pid);
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1576
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1577
  	case -EPFNOSUPPORT:
906462af4   Chuck Lever   SUNRPC: Split ano...
1578
  		/* server doesn't support any rpcbind version we know of */
012da158f   Chuck Lever   SUNRPC: Use soft ...
1579
1580
  		dprintk("RPC: %5u unrecognized remote rpcbind service
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1581
1582
1583
  				task->tk_pid);
  		break;
  	case -EPROTONOSUPPORT:
00a6e7bbf   Chuck Lever   SUNRPC: RPC clien...
1584
1585
  		dprintk("RPC: %5u remote rpcbind version unavailable, retrying
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1586
  				task->tk_pid);
00a6e7bbf   Chuck Lever   SUNRPC: RPC clien...
1587
1588
1589
  		task->tk_status = 0;
  		task->tk_action = call_bind;
  		return;
012da158f   Chuck Lever   SUNRPC: Use soft ...
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
  	case -ECONNREFUSED:		/* connection problems */
  	case -ECONNRESET:
  	case -ENOTCONN:
  	case -EHOSTDOWN:
  	case -EHOSTUNREACH:
  	case -ENETUNREACH:
  	case -EPIPE:
  		dprintk("RPC: %5u remote rpcbind unreachable: %d
  ",
  				task->tk_pid, task->tk_status);
  		if (!RPC_IS_SOFTCONN(task)) {
  			rpc_delay(task, 5*HZ);
  			goto retry_timeout;
  		}
  		status = task->tk_status;
  		break;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1606
  	default:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1607
1608
  		dprintk("RPC: %5u unrecognized rpcbind error (%d)
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1609
  				task->tk_pid, -task->tk_status);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1610
1611
1612
1613
  	}
  
  	rpc_exit(task, status);
  	return;
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1614
1615
  retry_timeout:
  	task->tk_action = call_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1616
1617
1618
1619
  }
  
  /*
   * 4b.	Connect to the RPC server
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1620
1621
1622
1623
   */
  static void
  call_connect(struct rpc_task *task)
  {
ad2368d6f   Trond Myklebust   SUNRPC: Avoid RCU...
1624
  	struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1625

46121cf7d   Chuck Lever   SUNRPC: fix print...
1626
1627
  	dprintk("RPC: %5u call_connect xprt %p %s connected
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1628
1629
  			task->tk_pid, xprt,
  			(xprt_connected(xprt) ? "is" : "is not"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1630

da3518780   Chuck Lever   [PATCH] RPC: prop...
1631
1632
1633
1634
1635
  	task->tk_action = call_transmit;
  	if (!xprt_connected(xprt)) {
  		task->tk_action = call_connect_status;
  		if (task->tk_status < 0)
  			return;
4662ffcbe   Trond Myklebust   SUNRPC: If the rp...
1636
1637
1638
1639
  		if (task->tk_flags & RPC_TASK_NOCONNECT) {
  			rpc_exit(task, -ENOTCONN);
  			return;
  		}
da3518780   Chuck Lever   [PATCH] RPC: prop...
1640
  		xprt_connect(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1642
1643
1644
  }
  
  /*
da3518780   Chuck Lever   [PATCH] RPC: prop...
1645
   * 4c.	Sort out connect result
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
1647
1648
1649
1650
1651
   */
  static void
  call_connect_status(struct rpc_task *task)
  {
  	struct rpc_clnt *clnt = task->tk_client;
  	int status = task->tk_status;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1652
  	dprint_status(task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1653

5753cba17   Steve Dickson   SUNRPC: Adding st...
1654
  	trace_rpc_connect_status(task, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655
  	switch (status) {
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1656
1657
1658
  		/* if soft mounted, test if we've timed out */
  	case -ETIMEDOUT:
  		task->tk_action = call_timeout;
3ed5e2a2c   Trond Myklebust   SUNRPC: Report ne...
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
  		return;
  	case -ECONNREFUSED:
  	case -ECONNRESET:
  	case -ENETUNREACH:
  		if (RPC_IS_SOFTCONN(task))
  			break;
  		/* retry with existing socket, after a delay */
  	case 0:
  	case -EAGAIN:
  		task->tk_status = 0;
  		clnt->cl_stats->netreconn++;
  		task->tk_action = call_transmit;
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
  	}
3ed5e2a2c   Trond Myklebust   SUNRPC: Report ne...
1673
  	rpc_exit(task, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
1675
1676
1677
1678
1679
1680
1681
  }
  
  /*
   * 5.	Transmit the RPC request, and wait for reply
   */
  static void
  call_transmit(struct rpc_task *task)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1682
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
1684
1685
1686
1687
1688
1689
  
  	task->tk_action = call_status;
  	if (task->tk_status < 0)
  		return;
  	task->tk_status = xprt_prepare_transmit(task);
  	if (task->tk_status != 0)
  		return;
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1690
  	task->tk_action = call_transmit_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
  	/* Encode here so that rpcsec_gss can use correct sequence number. */
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1692
  	if (rpc_task_need_encode(task)) {
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1693
  		rpc_xdr_encode(task);
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
1694
  		/* Did the encode result in an error condition? */
8b39f2b41   Trond Myklebust   SUNRPC: Ensure we...
1695
1696
1697
1698
1699
1700
  		if (task->tk_status != 0) {
  			/* Was the error nonfatal? */
  			if (task->tk_status == -EAGAIN)
  				rpc_delay(task, HZ >> 4);
  			else
  				rpc_exit(task, task->tk_status);
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1701
  			return;
8b39f2b41   Trond Myklebust   SUNRPC: Ensure we...
1702
  		}
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
1703
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1704
1705
1706
  	xprt_transmit(task);
  	if (task->tk_status < 0)
  		return;
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1707
1708
1709
1710
1711
  	/*
  	 * On success, ensure that we call xprt_end_transmit() before sleeping
  	 * in order to allow access to the socket to other RPC requests.
  	 */
  	call_transmit_status(task);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1712
  	if (rpc_reply_expected(task))
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1713
1714
  		return;
  	task->tk_action = rpc_exit_task;
a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
1715
  	rpc_wake_up_queued_task(&task->tk_rqstp->rq_xprt->pending, task);
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1716
1717
1718
1719
1720
1721
1722
1723
1724
  }
  
  /*
   * 5a.	Handle cleanup after a transmission
   */
  static void
  call_transmit_status(struct rpc_task *task)
  {
  	task->tk_action = call_status;
206a134b4   Chuck Lever   SUNRPC: Check exp...
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
  
  	/*
  	 * Common case: success.  Force the compiler to put this
  	 * test first.
  	 */
  	if (task->tk_status == 0) {
  		xprt_end_transmit(task);
  		rpc_task_force_reencode(task);
  		return;
  	}
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1735
1736
1737
1738
  	switch (task->tk_status) {
  	case -EAGAIN:
  		break;
  	default:
206a134b4   Chuck Lever   SUNRPC: Check exp...
1739
  		dprint_status(task);
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1740
  		xprt_end_transmit(task);
09a21c410   Chuck Lever   SUNRPC: Allow RPC...
1741
1742
  		rpc_task_force_reencode(task);
  		break;
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1743
1744
1745
1746
1747
1748
1749
  		/*
  		 * Special cases: if we've been waiting on the
  		 * socket's write_space() callback, or if the
  		 * socket just returned a connection error,
  		 * then hold onto the transport lock.
  		 */
  	case -ECONNREFUSED:
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1750
1751
1752
  	case -EHOSTDOWN:
  	case -EHOSTUNREACH:
  	case -ENETUNREACH:
09a21c410   Chuck Lever   SUNRPC: Allow RPC...
1753
1754
1755
1756
1757
1758
1759
  		if (RPC_IS_SOFTCONN(task)) {
  			xprt_end_transmit(task);
  			rpc_exit(task, task->tk_status);
  			break;
  		}
  	case -ECONNRESET:
  	case -ENOTCONN:
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
1760
  	case -EPIPE:
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1761
1762
  		rpc_task_force_reencode(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
1764
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1765
1766
1767
1768
1769
1770
1771
1772
  /*
   * 5b.	Send the backchannel RPC reply.  On error, drop the reply.  In
   * addition, disconnect on connectivity errors.
   */
  static void
  call_bc_transmit(struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
  	task->tk_status = xprt_prepare_transmit(task);
  	if (task->tk_status == -EAGAIN) {
  		/*
  		 * Could not reserve the transport. Try again after the
  		 * transport is released.
  		 */
  		task->tk_status = 0;
  		task->tk_action = call_bc_transmit;
  		return;
  	}
  
  	task->tk_action = rpc_exit_task;
  	if (task->tk_status < 0) {
  		printk(KERN_NOTICE "RPC: Could not send backchannel reply "
  			"error: %d
  ", task->tk_status);
  		return;
  	}
  
  	xprt_transmit(task);
  	xprt_end_transmit(task);
  	dprint_status(task);
  	switch (task->tk_status) {
  	case 0:
  		/* Success */
  		break;
  	case -EHOSTDOWN:
  	case -EHOSTUNREACH:
  	case -ENETUNREACH:
  	case -ETIMEDOUT:
  		/*
  		 * Problem reaching the server.  Disconnect and let the
  		 * forechannel reestablish the connection.  The server will
  		 * have to retransmit the backchannel request and we'll
  		 * reprocess it.  Since these ops are idempotent, there's no
  		 * need to cache our reply at this time.
  		 */
  		printk(KERN_NOTICE "RPC: Could not send backchannel reply "
  			"error: %d
  ", task->tk_status);
a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
1813
  		xprt_conditional_disconnect(req->rq_xprt,
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1814
1815
1816
1817
1818
1819
1820
  			req->rq_connect_cookie);
  		break;
  	default:
  		/*
  		 * We were unable to reply and will have to drop the
  		 * request.  The server should reconnect and retransmit.
  		 */
1facf4c4a   Weston Andros Adamson   SUNRPC: remove BU...
1821
  		WARN_ON_ONCE(task->tk_status == -EAGAIN);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1822
1823
1824
1825
1826
1827
1828
  		printk(KERN_NOTICE "RPC: Could not send backchannel reply "
  			"error: %d
  ", task->tk_status);
  		break;
  	}
  	rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
1829
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1830

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
1832
1833
1834
1835
1836
1837
1838
1839
  /*
   * 6.	Sort out the RPC call status
   */
  static void
  call_status(struct rpc_task *task)
  {
  	struct rpc_clnt	*clnt = task->tk_client;
  	struct rpc_rqst	*req = task->tk_rqstp;
  	int		status;
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
1840
1841
  	if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent)
  		task->tk_status = req->rq_reply_bytes_recvd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1842

46121cf7d   Chuck Lever   SUNRPC: fix print...
1843
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
1845
1846
1847
1848
1849
  
  	status = task->tk_status;
  	if (status >= 0) {
  		task->tk_action = call_decode;
  		return;
  	}
5753cba17   Steve Dickson   SUNRPC: Adding st...
1850
  	trace_rpc_call_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
  	task->tk_status = 0;
  	switch(status) {
76303992b   Trond Myklebust   SUNRPC: Handle EN...
1853
1854
1855
1856
1857
1858
1859
1860
  	case -EHOSTDOWN:
  	case -EHOSTUNREACH:
  	case -ENETUNREACH:
  		/*
  		 * Delay any retries for 3 seconds, then handle as if it
  		 * were a timeout.
  		 */
  		rpc_delay(task, 3*HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
1862
  	case -ETIMEDOUT:
  		task->tk_action = call_timeout;
241c39b9a   Trond Myklebust   RPC: Fix the TCP ...
1863
  		if (task->tk_client->cl_discrtry)
a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
1864
  			xprt_conditional_disconnect(req->rq_xprt,
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
1865
  					req->rq_connect_cookie);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
  		break;
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
1867
  	case -ECONNRESET:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
  	case -ECONNREFUSED:
35f5a422c   Chuck Lever   SUNRPC: new inter...
1869
  		rpc_force_rebind(clnt);
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
1870
1871
1872
  		rpc_delay(task, 3*HZ);
  	case -EPIPE:
  	case -ENOTCONN:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
  		task->tk_action = call_bind;
  		break;
  	case -EAGAIN:
  		task->tk_action = call_transmit;
  		break;
  	case -EIO:
  		/* shutdown or soft timeout */
  		rpc_exit(task, status);
  		break;
  	default:
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1883
1884
1885
  		if (clnt->cl_chatty)
  			printk("%s: RPC call returned error %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
1887
  			       clnt->cl_protname, -status);
  		rpc_exit(task, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
1890
1891
  	}
  }
  
  /*
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1892
   * 6a.	Handle RPC timeout
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
1894
1895
1896
1897
1898
1899
1900
1901
   * 	We do not release the request slot, so we keep using the
   *	same XID for all retransmits.
   */
  static void
  call_timeout(struct rpc_task *task)
  {
  	struct rpc_clnt	*clnt = task->tk_client;
  
  	if (xprt_adjust_timeout(task->tk_rqstp) == 0) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1902
1903
  		dprintk("RPC: %5u call_timeout (minor)
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
1905
  		goto retry;
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1906
1907
  	dprintk("RPC: %5u call_timeout (major)
  ", task->tk_pid);
ef759a2e5   Chuck Lever   SUNRPC: introduce...
1908
  	task->tk_timeouts++;
3a28becc3   Chuck Lever   SUNRPC: soft conn...
1909
1910
1911
1912
  	if (RPC_IS_SOFTCONN(task)) {
  		rpc_exit(task, -ETIMEDOUT);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
  	if (RPC_IS_SOFT(task)) {
cac5d07e3   Joe Perches   sunrpc: clnt: Add...
1914
  		if (clnt->cl_chatty) {
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1915
  			rcu_read_lock();
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1916
1917
  			printk(KERN_NOTICE "%s: server %s not responding, timed out
  ",
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1918
1919
1920
  				clnt->cl_protname,
  				rcu_dereference(clnt->cl_xprt)->servername);
  			rcu_read_unlock();
cac5d07e3   Joe Perches   sunrpc: clnt: Add...
1921
  		}
7494d00c7   Trond Myklebust   SUNRPC: Allow RPC...
1922
1923
1924
1925
  		if (task->tk_flags & RPC_TASK_TIMEOUT)
  			rpc_exit(task, -ETIMEDOUT);
  		else
  			rpc_exit(task, -EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
1927
  		return;
  	}
f518e35ae   Chuck Lever   SUNRPC: get rid o...
1928
  	if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1929
  		task->tk_flags |= RPC_CALL_MAJORSEEN;
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1930
1931
  		if (clnt->cl_chatty) {
  			rcu_read_lock();
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1932
1933
  			printk(KERN_NOTICE "%s: server %s not responding, still trying
  ",
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1934
1935
1936
1937
  			clnt->cl_protname,
  			rcu_dereference(clnt->cl_xprt)->servername);
  			rcu_read_unlock();
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
  	}
35f5a422c   Chuck Lever   SUNRPC: new inter...
1939
  	rpc_force_rebind(clnt);
b48633bd0   Trond Myklebust   SUNRPC: Invalidat...
1940
1941
1942
1943
1944
  	/*
  	 * Did our request time out due to an RPCSEC_GSS out-of-sequence
  	 * event? RFC2203 requires the server to drop all such requests.
  	 */
  	rpcauth_invalcred(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
  
  retry:
  	clnt->cl_stats->rpcretrans++;
  	task->tk_action = call_bind;
  	task->tk_status = 0;
  }
  
  /*
   * 7.	Decode the RPC reply
   */
  static void
  call_decode(struct rpc_task *task)
  {
  	struct rpc_clnt	*clnt = task->tk_client;
  	struct rpc_rqst	*req = task->tk_rqstp;
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
1960
  	kxdrdproc_t	decode = task->tk_msg.rpc_proc->p_decode;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1961
  	__be32		*p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1962

726fd6ad5   Vasily Averin   sunrpc: use dprin...
1963
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964

f518e35ae   Chuck Lever   SUNRPC: get rid o...
1965
  	if (task->tk_flags & RPC_CALL_MAJORSEEN) {
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1966
1967
  		if (clnt->cl_chatty) {
  			rcu_read_lock();
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1968
1969
  			printk(KERN_NOTICE "%s: server %s OK
  ",
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
1970
1971
1972
1973
  				clnt->cl_protname,
  				rcu_dereference(clnt->cl_xprt)->servername);
  			rcu_read_unlock();
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1974
1975
  		task->tk_flags &= ~RPC_CALL_MAJORSEEN;
  	}
43ac3f296   Trond Myklebust   SUNRPC: Fix memor...
1976
1977
  	/*
  	 * Ensure that we see all writes made by xprt_complete_rqst()
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
1978
  	 * before it changed req->rq_reply_bytes_recvd.
43ac3f296   Trond Myklebust   SUNRPC: Fix memor...
1979
1980
  	 */
  	smp_rmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1981
1982
1983
1984
1985
  	req->rq_rcv_buf.len = req->rq_private_buf.len;
  
  	/* Check that the softirq receive buffer is valid */
  	WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
  				sizeof(req->rq_rcv_buf)) != 0);
1e799b673   Trond Myklebust   SUNRPC: Fix read ...
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  	if (req->rq_rcv_buf.len < 12) {
  		if (!RPC_IS_SOFT(task)) {
  			task->tk_action = call_bind;
  			clnt->cl_stats->rpcretrans++;
  			goto out_retry;
  		}
  		dprintk("RPC:       %s: too small RPC reply size (%d bytes)
  ",
  				clnt->cl_protname, task->tk_status);
  		task->tk_action = call_timeout;
  		goto out_retry;
  	}
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1998
  	p = rpc_verify_header(task);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1999
2000
2001
2002
  	if (IS_ERR(p)) {
  		if (p == ERR_PTR(-EAGAIN))
  			goto out_retry;
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003
  	}
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2004
  	task->tk_action = rpc_exit_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005

6d5fcb5a5   Trond Myklebust   SUNRPC: Remove BK...
2006
  	if (decode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
  		task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
  						      task->tk_msg.rpc_resp);
6d5fcb5a5   Trond Myklebust   SUNRPC: Remove BK...
2009
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
2010
2011
2012
  	dprintk("RPC: %5u call_decode result %d
  ", task->tk_pid,
  			task->tk_status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2013
2014
  	return;
  out_retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
  	task->tk_status = 0;
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
2016
  	/* Note: rpc_verify_header() may have freed the RPC slot */
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
2017
  	if (task->tk_rqstp == req) {
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
2018
  		req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
2019
  		if (task->tk_client->cl_discrtry)
a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
2020
  			xprt_conditional_disconnect(req->rq_xprt,
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
2021
  					req->rq_connect_cookie);
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
2022
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2023
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
2024
  static __be32 *
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
2025
  rpc_encode_header(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026
2027
  {
  	struct rpc_clnt *clnt = task->tk_client;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2028
  	struct rpc_rqst	*req = task->tk_rqstp;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
2029
  	__be32		*p = req->rq_svec[0].iov_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2030
2031
  
  	/* FIXME: check buffer size? */
808012fbb   Chuck Lever   [PATCH] RPC: skip...
2032

a4f0835c6   Trond Myklebust   SUNRPC: Eliminate...
2033
  	p = xprt_skip_transport_header(req->rq_xprt, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2034
2035
2036
2037
2038
2039
  	*p++ = req->rq_xid;		/* XID */
  	*p++ = htonl(RPC_CALL);		/* CALL */
  	*p++ = htonl(RPC_VERSION);	/* RPC version */
  	*p++ = htonl(clnt->cl_prog);	/* program number */
  	*p++ = htonl(clnt->cl_vers);	/* program version */
  	*p++ = htonl(task->tk_msg.rpc_proc->p_proc);	/* procedure */
334ccfd54   Trond Myklebust   [PATCH] RPC: Ensu...
2040
2041
2042
  	p = rpcauth_marshcred(task, p);
  	req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
  	return p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2043
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
2044
  static __be32 *
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
2045
  rpc_verify_header(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2046
  {
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2047
  	struct rpc_clnt *clnt = task->tk_client;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
2049
  	struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
  	int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
2050
2051
  	__be32	*p = iov->iov_base;
  	u32 n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
  	int error = -EACCES;
e8896495b   David Howells   NFS: Check length...
2053
2054
2055
2056
2057
2058
  	if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
  		/* RFC-1014 says that the representation of XDR data must be a
  		 * multiple of four bytes
  		 * - if it isn't pointer subtraction in the NFS client may give
  		 *   undefined results
  		 */
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2059
  		dprintk("RPC: %5u %s: XDR representation not a multiple of"
0dc47877a   Harvey Harrison   net: replace rema...
2060
2061
  		       " 4 bytes: 0x%x
  ", task->tk_pid, __func__,
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2062
  		       task->tk_rqstp->rq_rcv_buf.len);
e8896495b   David Howells   NFS: Check length...
2063
2064
  		goto out_eio;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
2066
  	if ((len -= 3) < 0)
  		goto out_overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067

f4a2e418b   Ricardo Labiaga   nfs41: Process th...
2068
  	p += 1; /* skip XID */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2069
  	if ((n = ntohl(*p++)) != RPC_REPLY) {
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2070
2071
  		dprintk("RPC: %5u %s: not an RPC reply: %x
  ",
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
2072
  			task->tk_pid, __func__, n);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2073
  		goto out_garbage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2074
  	}
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
2075

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
2077
2078
2079
  	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
  		if (--len < 0)
  			goto out_overflow;
  		switch ((n = ntohl(*p++))) {
89f0e4fea   Joe Perches   sunrpc: Reduce sw...
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
  		case RPC_AUTH_ERROR:
  			break;
  		case RPC_MISMATCH:
  			dprintk("RPC: %5u %s: RPC call version mismatch!
  ",
  				task->tk_pid, __func__);
  			error = -EPROTONOSUPPORT;
  			goto out_err;
  		default:
  			dprintk("RPC: %5u %s: RPC call rejected, "
  				"unknown error: %x
  ",
  				task->tk_pid, __func__, n);
  			goto out_eio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
  		}
  		if (--len < 0)
  			goto out_overflow;
  		switch ((n = ntohl(*p++))) {
  		case RPC_AUTH_REJECTEDCRED:
  		case RPC_AUTH_REJECTEDVERF:
  		case RPCSEC_GSS_CREDPROBLEM:
  		case RPCSEC_GSS_CTXPROBLEM:
  			if (!task->tk_cred_retry)
  				break;
  			task->tk_cred_retry--;
46121cf7d   Chuck Lever   SUNRPC: fix print...
2105
2106
  			dprintk("RPC: %5u %s: retry stale creds
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2107
  					task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2108
  			rpcauth_invalcred(task);
220bcc2af   Trond Myklebust   SUNRPC: Don't cal...
2109
2110
  			/* Ensure we obtain a new XID! */
  			xprt_release(task);
118df3d17   Trond Myklebust   SUNRPC: After cal...
2111
  			task->tk_action = call_reserve;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2112
  			goto out_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2113
2114
2115
2116
2117
2118
  		case RPC_AUTH_BADCRED:
  		case RPC_AUTH_BADVERF:
  			/* possibly garbled cred/verf? */
  			if (!task->tk_garb_retry)
  				break;
  			task->tk_garb_retry--;
46121cf7d   Chuck Lever   SUNRPC: fix print...
2119
2120
  			dprintk("RPC: %5u %s: retry garbled creds
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2121
  					task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  			task->tk_action = call_bind;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2123
  			goto out_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2124
  		case RPC_AUTH_TOOWEAK:
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2125
  			rcu_read_lock();
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
2126
  			printk(KERN_NOTICE "RPC: server %s requires stronger "
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2127
2128
2129
2130
  			       "authentication.
  ",
  			       rcu_dereference(clnt->cl_xprt)->servername);
  			rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2131
2132
  			break;
  		default:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2133
2134
  			dprintk("RPC: %5u %s: unknown auth error: %x
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2135
  					task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2136
2137
  			error = -EIO;
  		}
46121cf7d   Chuck Lever   SUNRPC: fix print...
2138
2139
  		dprintk("RPC: %5u %s: call rejected %d
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2140
  				task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
2142
2143
  		goto out_err;
  	}
  	if (!(p = rpcauth_checkverf(task, p))) {
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2144
2145
  		dprintk("RPC: %5u %s: auth check failed
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2146
  				task->tk_pid, __func__);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2147
  		goto out_garbage;		/* bad verifier, retry */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2148
  	}
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
2149
  	len = p - (__be32 *)iov->iov_base - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2150
2151
2152
2153
2154
2155
  	if (len < 0)
  		goto out_overflow;
  	switch ((n = ntohl(*p++))) {
  	case RPC_SUCCESS:
  		return p;
  	case RPC_PROG_UNAVAIL:
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2156
2157
2158
2159
2160
  		dprintk_rcu("RPC: %5u %s: program %u is unsupported "
  				"by server %s
  ", task->tk_pid, __func__,
  				(unsigned int)clnt->cl_prog,
  				rcu_dereference(clnt->cl_xprt)->servername);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
2161
2162
  		error = -EPFNOSUPPORT;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2163
  	case RPC_PROG_MISMATCH:
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2164
2165
2166
2167
2168
2169
  		dprintk_rcu("RPC: %5u %s: program %u, version %u unsupported "
  				"by server %s
  ", task->tk_pid, __func__,
  				(unsigned int)clnt->cl_prog,
  				(unsigned int)clnt->cl_vers,
  				rcu_dereference(clnt->cl_xprt)->servername);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
2170
2171
  		error = -EPROTONOSUPPORT;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2172
  	case RPC_PROC_UNAVAIL:
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2173
  		dprintk_rcu("RPC: %5u %s: proc %s unsupported by program %u, "
46121cf7d   Chuck Lever   SUNRPC: fix print...
2174
2175
  				"version %u on server %s
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2176
  				task->tk_pid, __func__,
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
2177
  				rpc_proc_name(task),
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2178
2179
  				clnt->cl_prog, clnt->cl_vers,
  				rcu_dereference(clnt->cl_xprt)->servername);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
2180
2181
  		error = -EOPNOTSUPP;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2182
  	case RPC_GARBAGE_ARGS:
46121cf7d   Chuck Lever   SUNRPC: fix print...
2183
2184
  		dprintk("RPC: %5u %s: server saw garbage
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2185
  				task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2186
2187
  		break;			/* retry */
  	default:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2188
2189
  		dprintk("RPC: %5u %s: server accept status: %x
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2190
  				task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
  		/* Also retry */
  	}
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2193
  out_garbage:
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
2194
  	clnt->cl_stats->rpcgarbage++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2195
2196
  	if (task->tk_garb_retry) {
  		task->tk_garb_retry--;
46121cf7d   Chuck Lever   SUNRPC: fix print...
2197
2198
  		dprintk("RPC: %5u %s: retrying
  ",
0dc47877a   Harvey Harrison   net: replace rema...
2199
  				task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
  		task->tk_action = call_bind;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2201
2202
  out_retry:
  		return ERR_PTR(-EAGAIN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2204
2205
2206
2207
  out_eio:
  	error = -EIO;
  out_err:
  	rpc_exit(task, error);
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2208
2209
  	dprintk("RPC: %5u %s: call failed with error %d
  ", task->tk_pid,
0dc47877a   Harvey Harrison   net: replace rema...
2210
  			__func__, error);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2211
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2212
  out_overflow:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
2213
2214
  	dprintk("RPC: %5u %s: server reply was truncated.
  ", task->tk_pid,
0dc47877a   Harvey Harrison   net: replace rema...
2215
  			__func__);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
2216
  	goto out_garbage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2217
  }
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2218

9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
2219
  static void rpcproc_encode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2220
  {
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2221
  }
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
2222
  static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2223
2224
2225
2226
2227
2228
2229
2230
  {
  	return 0;
  }
  
  static struct rpc_procinfo rpcproc_null = {
  	.p_encode = rpcproc_encode_null,
  	.p_decode = rpcproc_decode_null,
  };
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
2231
  static int rpc_ping(struct rpc_clnt *clnt)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2232
2233
2234
2235
2236
2237
  {
  	struct rpc_message msg = {
  		.rpc_proc = &rpcproc_null,
  	};
  	int err;
  	msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
2238
  	err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN);
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
2239
2240
2241
  	put_rpccred(msg.rpc_cred);
  	return err;
  }
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2242

5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
2243
2244
2245
2246
2247
2248
  struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
  {
  	struct rpc_message msg = {
  		.rpc_proc = &rpcproc_null,
  		.rpc_cred = cred,
  	};
84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
2249
2250
2251
2252
2253
2254
  	struct rpc_task_setup task_setup_data = {
  		.rpc_client = clnt,
  		.rpc_message = &msg,
  		.callback_ops = &rpc_default_ops,
  		.flags = flags,
  	};
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
2255
  	return rpc_run_task(&task_setup_data);
5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
2256
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
2257
  EXPORT_SYMBOL_GPL(rpc_call_null);
5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
2258

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2259
  #ifdef RPC_DEBUG
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
2260
2261
  static void rpc_show_header(void)
  {
cb3997b5a   Chuck Lever   SUNRPC: Display s...
2262
2263
2264
  	printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
  		"-timeout ---ops--
  ");
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
2265
  }
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2266
2267
2268
2269
  static void rpc_show_task(const struct rpc_clnt *clnt,
  			  const struct rpc_task *task)
  {
  	const char *rpc_waitq = "none";
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2270
2271
2272
  
  	if (RPC_IS_QUEUED(task))
  		rpc_waitq = rpc_qname(task->tk_waitqueue);
b3bcedadf   Joe Perches   net/sunrpc/clnt.c...
2273
2274
  	printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s
  ",
cb3997b5a   Chuck Lever   SUNRPC: Display s...
2275
2276
2277
  		task->tk_pid, task->tk_flags, task->tk_status,
  		clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops,
  		clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task),
b3bcedadf   Joe Perches   net/sunrpc/clnt.c...
2278
  		task->tk_action, rpc_waitq);
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2279
  }
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
2280
  void rpc_show_tasks(struct net *net)
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2281
2282
  {
  	struct rpc_clnt *clnt;
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2283
  	struct rpc_task *task;
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
2284
  	int header = 0;
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
2285
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2286

70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
2287
2288
  	spin_lock(&sn->rpc_client_lock);
  	list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2289
  		spin_lock(&clnt->cl_lock);
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2290
  		list_for_each_entry(task, &clnt->cl_tasks, tk_task) {
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
2291
2292
2293
2294
  			if (!header) {
  				rpc_show_header();
  				header++;
  			}
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
2295
  			rpc_show_task(clnt, task);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2296
2297
2298
  		}
  		spin_unlock(&clnt->cl_lock);
  	}
70abc49b4   Stanislav Kinsbursky   SUNRPC: make SUNP...
2299
  	spin_unlock(&sn->rpc_client_lock);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
2300
2301
  }
  #endif