Blame view

net/sunrpc/clnt.c 44.5 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
19
20
21
22
23
   *  Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com>
   *  Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
   */
  
  #include <asm/system.h>
  
  #include <linux/module.h>
  #include <linux/types.h>
cb3997b5a   Chuck Lever   SUNRPC: Display s...
24
  #include <linux/kallsyms.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #include <linux/mm.h>
23ac65817   Trond Myklebust   SUNRPC: clean up ...
26
27
  #include <linux/namei.h>
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/utsname.h>
11c556b3d   Chuck Lever   SUNRPC: provide a...
30
  #include <linux/workqueue.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
31
  #include <linux/in.h>
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
32
  #include <linux/in6.h>
176e21ee2   Chuck Lever   SUNRPC: Support f...
33
  #include <linux/un.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  
  #include <linux/sunrpc/clnt.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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
40
  #include "sunrpc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

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

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
50
51
52
53
54
  /*
   * All RPC clients are linked into this list
   */
  static LIST_HEAD(all_clients);
  static DEFINE_SPINLOCK(rpc_client_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
60
61
  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
62
63
  static void	call_decode(struct rpc_task *task);
  static void	call_bind(struct rpc_task *task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
64
  static void	call_bind_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  static void	call_transmit(struct rpc_task *task);
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
66
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
67
  static void	call_bc_transmit(struct rpc_task *task);
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
68
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  static void	call_status(struct rpc_task *task);
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
70
  static void	call_transmit_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
  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
76

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

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
81
82
83
84
85
86
87
88
89
90
91
92
93
  static void rpc_register_client(struct rpc_clnt *clnt)
  {
  	spin_lock(&rpc_client_lock);
  	list_add(&clnt->cl_clients, &all_clients);
  	spin_unlock(&rpc_client_lock);
  }
  
  static void rpc_unregister_client(struct rpc_clnt *clnt)
  {
  	spin_lock(&rpc_client_lock);
  	list_del(&clnt->cl_clients);
  	spin_unlock(&rpc_client_lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
  
  static int
  rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
  {
f134585a7   Trond Myklebust   Revert "[PATCH] R...
98
  	static uint32_t clntid;
e0a012493   Al Viro   switch vfs_path_l...
99
  	struct path path, dir;
23ac65817   Trond Myklebust   SUNRPC: clean up ...
100
101
102
103
  	char name[15];
  	struct qstr q = {
  		.name = name,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  	int error;
7d217caca   Trond Myklebust   SUNRPC: Replace r...
105
106
  	clnt->cl_path.mnt = ERR_PTR(-ENOENT);
  	clnt->cl_path.dentry = ERR_PTR(-ENOENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
  	if (dir_name == NULL)
  		return 0;
542815482   Trond Myklebust   SUNRPC: Fix a 'Bu...
109

23ac65817   Trond Myklebust   SUNRPC: clean up ...
110
111
112
  	path.mnt = rpc_get_mount();
  	if (IS_ERR(path.mnt))
  		return PTR_ERR(path.mnt);
e0a012493   Al Viro   switch vfs_path_l...
113
  	error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir);
23ac65817   Trond Myklebust   SUNRPC: clean up ...
114
115
  	if (error)
  		goto err;
542815482   Trond Myklebust   SUNRPC: Fix a 'Bu...
116

f134585a7   Trond Myklebust   Revert "[PATCH] R...
117
  	for (;;) {
23ac65817   Trond Myklebust   SUNRPC: clean up ...
118
119
120
  		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);
e0a012493   Al Viro   switch vfs_path_l...
121
  		path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt);
23ac65817   Trond Myklebust   SUNRPC: clean up ...
122
123
124
  		if (!IS_ERR(path.dentry))
  			break;
  		error = PTR_ERR(path.dentry);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
125
  		if (error != -EEXIST) {
23ac65817   Trond Myklebust   SUNRPC: clean up ...
126
127
128
129
130
  			printk(KERN_INFO "RPC: Couldn't create pipefs entry"
  					" %s/%s, error %d
  ",
  					dir_name, name, error);
  			goto err_path_put;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
131
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  	}
e0a012493   Al Viro   switch vfs_path_l...
133
  	path_put(&dir);
23ac65817   Trond Myklebust   SUNRPC: clean up ...
134
135
136
  	clnt->cl_path = path;
  	return 0;
  err_path_put:
e0a012493   Al Viro   switch vfs_path_l...
137
  	path_put(&dir);
23ac65817   Trond Myklebust   SUNRPC: clean up ...
138
139
140
  err:
  	rpc_put_mount();
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  }
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
142
  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
143
  {
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
144
  	struct rpc_program	*program = args->program;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  	struct rpc_version	*version;
  	struct rpc_clnt		*clnt = NULL;
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
147
  	struct rpc_auth		*auth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  	int err;
06b8d2552   Chuck Lever   SUNRPC: Make sure...
149
150
151
152
  	size_t len;
  
  	/* sanity check the name before trying to print it */
  	err = -EINVAL;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
153
  	len = strlen(args->servername);
06b8d2552   Chuck Lever   SUNRPC: Make sure...
154
155
156
  	if (len > RPC_MAXNETNAMELEN)
  		goto out_no_rpciod;
  	len++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

46121cf7d   Chuck Lever   SUNRPC: fix print...
158
159
  	dprintk("RPC:       creating %s client for %s (xprt %p)
  ",
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
160
  			program->name, args->servername, xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161

4ada539ed   Trond Myklebust   SUNRPC: Make crea...
162
163
164
  	err = rpciod_up();
  	if (err)
  		goto out_no_rpciod;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
  	err = -EINVAL;
  	if (!xprt)
712917d1c   Adrian Bunk   [PATCH] SUNRPC: f...
167
  		goto out_no_xprt;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
168
169
170
171
172
  
  	if (args->version >= program->nrvers)
  		goto out_err;
  	version = program->version[args->version];
  	if (version == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
  		goto out_err;
  
  	err = -ENOMEM;
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
176
  	clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
  	if (!clnt)
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
  	clnt->cl_parent = clnt;
  
  	clnt->cl_server = clnt->cl_inline_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	if (len > sizeof(clnt->cl_inline_name)) {
  		char *buf = kmalloc(len, GFP_KERNEL);
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
184
  		if (buf != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
  			clnt->cl_server = buf;
  		else
  			len = sizeof(clnt->cl_inline_name);
  	}
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
189
  	strlcpy(clnt->cl_server, args->servername, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
  
  	clnt->cl_xprt     = xprt;
  	clnt->cl_procinfo = version->procs;
  	clnt->cl_maxproc  = version->nrprocs;
  	clnt->cl_protname = program->name;
d5b337b48   Benny Halevy   nfsd: use nfs cli...
195
  	clnt->cl_prog     = args->prognumber ? : program->number;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  	clnt->cl_vers     = version->number;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  	clnt->cl_stats    = program->stats;
11c556b3d   Chuck Lever   SUNRPC: provide a...
198
  	clnt->cl_metrics  = rpc_alloc_iostats(clnt);
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
199
200
201
  	err = -ENOMEM;
  	if (clnt->cl_metrics == NULL)
  		goto out_no_stats;
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
202
  	clnt->cl_program  = program;
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
203
  	INIT_LIST_HEAD(&clnt->cl_tasks);
4bef61ff7   Trond Myklebust   SUNRPC: Add a per...
204
  	spin_lock_init(&clnt->cl_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205

ec739ef03   Chuck Lever   SUNRPC: Create a ...
206
  	if (!xprt_bound(clnt->cl_xprt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  		clnt->cl_autobind = 1;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
208
209
210
211
212
213
  	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
214
  	clnt->cl_rtt = &clnt->cl_rtt_default;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
215
  	rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
608207e88   Olga Kornievskaia   rpc: pass target ...
216
217
218
219
220
221
  	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
222

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
  	err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
  	if (err < 0)
  		goto out_no_path;
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
228
  	auth = rpcauth_create(args->authflavor, clnt);
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
229
  	if (IS_ERR(auth)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
  		printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)
  ",
698b6d088   Trond Myklebust   SUNRPC: cleanup f...
232
  				args->authflavor);
6a19275ad   J. Bruce Fields   [PATCH] RPC: [PAT...
233
  		err = PTR_ERR(auth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
  		goto out_no_auth;
  	}
  
  	/* save the nodename */
63ffc23d3   Cedric Le Goater   sunrpc: fix oops ...
238
  	clnt->cl_nodelen = strlen(init_utsname()->nodename);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  	if (clnt->cl_nodelen > UNX_MAXNODENAME)
  		clnt->cl_nodelen = UNX_MAXNODENAME;
63ffc23d3   Cedric Le Goater   sunrpc: fix oops ...
241
  	memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen);
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
242
  	rpc_register_client(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
  	return clnt;
  
  out_no_auth:
7d217caca   Trond Myklebust   SUNRPC: Replace r...
246
247
  	if (!IS_ERR(clnt->cl_path.dentry)) {
  		rpc_remove_client_dir(clnt->cl_path.dentry);
542815482   Trond Myklebust   SUNRPC: Fix a 'Bu...
248
249
  		rpc_put_mount();
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  out_no_path:
608207e88   Olga Kornievskaia   rpc: pass target ...
251
252
  	kfree(clnt->cl_principal);
  out_no_principal:
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
253
254
  	rpc_free_iostats(clnt->cl_metrics);
  out_no_stats:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
  	if (clnt->cl_server != clnt->cl_inline_name)
  		kfree(clnt->cl_server);
  	kfree(clnt);
  out_err:
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
259
  	xprt_put(xprt);
712917d1c   Adrian Bunk   [PATCH] SUNRPC: f...
260
  out_no_xprt:
4ada539ed   Trond Myklebust   SUNRPC: Make crea...
261
262
  	rpciod_down();
  out_no_rpciod:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
  	return ERR_PTR(err);
  }
c2866763b   Chuck Lever   SUNRPC: use socka...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  /*
   * 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...
279
  	struct xprt_create xprtargs = {
9a23e332e   Pavel Emelyanov   sunrpc: Add net t...
280
  		.net = args->net,
4fa016eb2   \"Talpey, Thomas\   NFS/SUNRPC: suppo...
281
  		.ident = args->protocol,
d3bc9a1de   Frank van Maarseveen   SUNRPC client: ad...
282
  		.srcaddr = args->saddress,
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
283
284
  		.dstaddr = args->address,
  		.addrlen = args->addrsize,
f300baba5   Alexandros Batsakis   nfsd41: sunrpc: a...
285
  		.bc_xprt = args->bc_xprt,
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
286
  	};
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
287
  	char servername[48];
c2866763b   Chuck Lever   SUNRPC: use socka...
288

c2866763b   Chuck Lever   SUNRPC: use socka...
289
  	/*
43780b87f   Chuck Lever   SUNRPC: Add a con...
290
291
292
293
  	 * If the caller chooses not to specify a hostname, whip
  	 * up a string representation of the passed-in address.
  	 */
  	if (args->servername == NULL) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
294
295
  		struct sockaddr_un *sun =
  				(struct sockaddr_un *)args->address;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
296
297
298
299
  		struct sockaddr_in *sin =
  				(struct sockaddr_in *)args->address;
  		struct sockaddr_in6 *sin6 =
  				(struct sockaddr_in6 *)args->address;
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
300
301
  		servername[0] = '\0';
  		switch (args->address->sa_family) {
176e21ee2   Chuck Lever   SUNRPC: Support f...
302
303
304
305
  		case AF_LOCAL:
  			snprintf(servername, sizeof(servername), "%s",
  				 sun->sun_path);
  			break;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
306
  		case AF_INET:
21454aaad   Harvey Harrison   net: replace NIPQ...
307
308
  			snprintf(servername, sizeof(servername), "%pI4",
  				 &sin->sin_addr.s_addr);
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
309
  			break;
da09eb930   Chuck Lever   SUNRPC: Clean up ...
310
  		case AF_INET6:
5b095d989   Harvey Harrison   net: replace %p6 ...
311
  			snprintf(servername, sizeof(servername), "%pI6",
da09eb930   Chuck Lever   SUNRPC: Clean up ...
312
  				 &sin6->sin6_addr);
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
313
  			break;
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
314
315
316
317
318
  		default:
  			/* caller wants default server name, but
  			 * address family isn't recognized. */
  			return ERR_PTR(-EINVAL);
  		}
43780b87f   Chuck Lever   SUNRPC: Add a con...
319
320
  		args->servername = servername;
  	}
510deb0d7   Chuck Lever   SUNRPC: rpc_creat...
321
322
323
  	xprt = xprt_create_transport(&xprtargs);
  	if (IS_ERR(xprt))
  		return (struct rpc_clnt *)xprt;
43780b87f   Chuck Lever   SUNRPC: Add a con...
324
  	/*
c2866763b   Chuck Lever   SUNRPC: use socka...
325
326
327
328
329
330
331
332
  	 * 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...
333
  	clnt = rpc_new_client(args, xprt);
c2866763b   Chuck Lever   SUNRPC: use socka...
334
335
336
337
  	if (IS_ERR(clnt))
  		return clnt;
  
  	if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
338
  		int err = rpc_ping(clnt);
c2866763b   Chuck Lever   SUNRPC: use socka...
339
340
341
342
343
344
345
346
347
  		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...
348
349
  	if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
  		clnt->cl_autobind = 1;
43d78ef2b   Chuck Lever   NFS: disconnect b...
350
351
  	if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
  		clnt->cl_discrtry = 1;
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
352
353
  	if (!(args->flags & RPC_CLNT_CREATE_QUIET))
  		clnt->cl_chatty = 1;
c2866763b   Chuck Lever   SUNRPC: use socka...
354
355
356
  
  	return clnt;
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
357
  EXPORT_SYMBOL_GPL(rpc_create);
c2866763b   Chuck Lever   SUNRPC: use socka...
358

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
364
365
366
367
  /*
   * This function clones the RPC client structure. It allows us to share the
   * same transport while varying parameters such as the authentication
   * flavour.
   */
  struct rpc_clnt *
  rpc_clone_client(struct rpc_clnt *clnt)
  {
  	struct rpc_clnt *new;
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
368
  	int err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369

e69062b4f   Arnaldo Carvalho de Melo   [SUNRPC]: Use k{m...
370
  	new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
  	if (!new)
  		goto out_no_clnt;
d431a555f   Trond Myklebust   SUNRPC: Don't cre...
373
374
375
376
377
  	new->cl_parent = clnt;
  	/* Turn off autobind on clones */
  	new->cl_autobind = 0;
  	INIT_LIST_HEAD(&new->cl_tasks);
  	spin_lock_init(&new->cl_lock);
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
378
  	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval);
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
379
380
381
  	new->cl_metrics = rpc_alloc_iostats(clnt);
  	if (new->cl_metrics == NULL)
  		goto out_no_stats;
608207e88   Olga Kornievskaia   rpc: pass target ...
382
383
384
385
386
  	if (clnt->cl_principal) {
  		new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL);
  		if (new->cl_principal == NULL)
  			goto out_no_principal;
  	}
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
387
  	atomic_set(&new->cl_count, 1);
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
388
389
390
  	err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
  	if (err != 0)
  		goto out_no_path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  	if (new->cl_auth)
  		atomic_inc(&new->cl_auth->au_count);
d431a555f   Trond Myklebust   SUNRPC: Don't cre...
393
  	xprt_get(clnt->cl_xprt);
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
394
  	atomic_inc(&clnt->cl_count);
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
395
  	rpc_register_client(new);
4ada539ed   Trond Myklebust   SUNRPC: Make crea...
396
  	rpciod_up();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  	return new;
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
398
  out_no_path:
608207e88   Olga Kornievskaia   rpc: pass target ...
399
400
  	kfree(new->cl_principal);
  out_no_principal:
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
401
  	rpc_free_iostats(new->cl_metrics);
23bf85ba4   Trond Myklebust   SUNRPC: Handle th...
402
403
  out_no_stats:
  	kfree(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  out_no_clnt:
0dc47877a   Harvey Harrison   net: replace rema...
405
406
  	dprintk("RPC:       %s: returned error %d
  ", __func__, err);
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
407
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
409
  EXPORT_SYMBOL_GPL(rpc_clone_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  
  /*
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
   * 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 ...
434
435
436
  			if (RPC_IS_QUEUED(rovr))
  				rpc_wake_up_queued_task(rovr->tk_waitqueue,
  							rovr);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
437
438
439
440
441
442
443
  		}
  	}
  	spin_unlock(&clnt->cl_lock);
  }
  EXPORT_SYMBOL_GPL(rpc_killall_tasks);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
   * Properly shut down an RPC client, terminating all outstanding
90c5755ff   Trond Myklebust   SUNRPC: Kill rpc_...
445
   * requests.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
   */
4c402b409   Trond Myklebust   SUNRPC: Remove rp...
447
  void rpc_shutdown_client(struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  {
34f52e359   Trond Myklebust   SUNRPC: Convert r...
449
450
451
  	dprintk("RPC:       shutting down %s client for %s
  ",
  			clnt->cl_protname, clnt->cl_server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452

34f52e359   Trond Myklebust   SUNRPC: Convert r...
453
  	while (!list_empty(&clnt->cl_tasks)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  		rpc_killall_tasks(clnt);
532347e2b   Ingo Molnar   [PATCH] nfs: slee...
455
  		wait_event_timeout(destroy_wait,
34f52e359   Trond Myklebust   SUNRPC: Convert r...
456
  			list_empty(&clnt->cl_tasks), 1*HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  	}
4c402b409   Trond Myklebust   SUNRPC: Remove rp...
458
  	rpc_release_client(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
460
  EXPORT_SYMBOL_GPL(rpc_shutdown_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
  
  /*
34f52e359   Trond Myklebust   SUNRPC: Convert r...
463
   * Free an RPC client
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
   */
34f52e359   Trond Myklebust   SUNRPC: Convert r...
465
  static void
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
466
  rpc_free_client(struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
468
469
  	dprintk("RPC:       destroying %s client for %s
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  			clnt->cl_protname, clnt->cl_server);
7d217caca   Trond Myklebust   SUNRPC: Replace r...
471
472
  	if (!IS_ERR(clnt->cl_path.dentry)) {
  		rpc_remove_client_dir(clnt->cl_path.dentry);
8f8e7a50f   Trond Myklebust   SUNRPC: Fix dentr...
473
474
  		rpc_put_mount();
  	}
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
475
  	if (clnt->cl_parent != clnt) {
8ad7c892e   Trond Myklebust   SUNRPC: Make rpc_...
476
  		rpc_release_client(clnt->cl_parent);
3e32a5d99   Trond Myklebust   SUNRPC: Give clon...
477
478
  		goto out_free;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
481
  	if (clnt->cl_server != clnt->cl_inline_name)
  		kfree(clnt->cl_server);
  out_free:
6529eba08   Trond Myklebust   SUNRPC: Move rpc_...
482
  	rpc_unregister_client(clnt);
11c556b3d   Chuck Lever   SUNRPC: provide a...
483
  	rpc_free_iostats(clnt->cl_metrics);
608207e88   Olga Kornievskaia   rpc: pass target ...
484
  	kfree(clnt->cl_principal);
11c556b3d   Chuck Lever   SUNRPC: provide a...
485
  	clnt->cl_metrics = NULL;
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
486
  	xprt_put(clnt->cl_xprt);
4ada539ed   Trond Myklebust   SUNRPC: Make crea...
487
  	rpciod_down();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  	kfree(clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
491
  }
  
  /*
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
492
493
494
   * Free an RPC client
   */
  static void
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
495
  rpc_free_auth(struct rpc_clnt *clnt)
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
496
  {
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
497
  	if (clnt->cl_auth == NULL) {
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
498
  		rpc_free_client(clnt);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
499
500
501
502
503
504
505
506
  		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...
507
  	atomic_inc(&clnt->cl_count);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
508
509
  	rpcauth_release(clnt->cl_auth);
  	clnt->cl_auth = NULL;
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
510
511
  	if (atomic_dec_and_test(&clnt->cl_count))
  		rpc_free_client(clnt);
1dd17ec69   Trond Myklebust   SUNRPC: Allow rpc...
512
513
514
  }
  
  /*
34f52e359   Trond Myklebust   SUNRPC: Convert r...
515
   * Release reference to the RPC client
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
   */
  void
  rpc_release_client(struct rpc_clnt *clnt)
  {
34f52e359   Trond Myklebust   SUNRPC: Convert r...
520
521
  	dprintk("RPC:       rpc_release_client(%p)
  ", clnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522

34f52e359   Trond Myklebust   SUNRPC: Convert r...
523
524
  	if (list_empty(&clnt->cl_tasks))
  		wake_up(&destroy_wait);
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
525
526
  	if (atomic_dec_and_test(&clnt->cl_count))
  		rpc_free_auth(clnt);
34f52e359   Trond Myklebust   SUNRPC: Convert r...
527
  }
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
528
529
  /**
   * rpc_bind_new_program - bind a new RPC program to an existing client
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
530
531
532
   * @old: old rpc_client
   * @program: rpc program to set
   * @vers: rpc program version
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
533
534
535
536
537
538
539
   *
   * 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,
  				      struct rpc_program *program,
89eb21c35   Chuck Lever   SUNRPC: fix a sig...
540
  				      u32 vers)
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  {
  	struct rpc_clnt *clnt;
  	struct rpc_version *version;
  	int err;
  
  	BUG_ON(vers >= program->nrvers || !program->version[vers]);
  	version = program->version[vers];
  	clnt = rpc_clone_client(old);
  	if (IS_ERR(clnt))
  		goto out;
  	clnt->cl_procinfo = version->procs;
  	clnt->cl_maxproc  = version->nrprocs;
  	clnt->cl_protname = program->name;
  	clnt->cl_prog     = program->number;
  	clnt->cl_vers     = version->number;
  	clnt->cl_stats    = program->stats;
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
557
  	err = rpc_ping(clnt);
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
558
559
560
561
  	if (err != 0) {
  		rpc_shutdown_client(clnt);
  		clnt = ERR_PTR(err);
  	}
cca5172a7   YOSHIFUJI Hideaki   [NET] SUNRPC: Fix...
562
  out:
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
563
564
  	return clnt;
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
565
  EXPORT_SYMBOL_GPL(rpc_bind_new_program);
007e251f2   Andreas Gruenbacher   [PATCH] RPC: Allo...
566

58f9612c6   Trond Myklebust   SUNRPC: Move rema...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  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...
588
  		atomic_inc(&clnt->cl_count);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
589
590
591
592
593
594
595
596
  		if (clnt->cl_softrtry)
  			task->tk_flags |= RPC_TASK_SOFT;
  		/* 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...
597
598
599
600
601
602
  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...
603
604
605
606
607
608
609
  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 ...
610
611
  		if (msg->rpc_cred != NULL)
  			task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred);
58f9612c6   Trond Myklebust   SUNRPC: Move rema...
612
613
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
617
  /*
   * Default callback for async RPC calls
   */
  static void
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
618
  rpc_default_callback(struct rpc_task *task, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
  {
  }
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
621
622
623
  static const struct rpc_call_ops rpc_default_ops = {
  	.rpc_call_done = rpc_default_callback,
  };
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
624
625
626
627
628
  /**
   * 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 ...
629
  {
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
630
  	struct rpc_task *task;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
631

84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
632
  	task = rpc_new_task(task_setup_data);
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
633
  	if (IS_ERR(task))
508592590   Trond Myklebust   SUNRPC: Mask sign...
634
  		goto out;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
635

58f9612c6   Trond Myklebust   SUNRPC: Move rema...
636
637
  	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...
638
639
  	if (task->tk_action == NULL)
  		rpc_call_start(task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
640
641
  	atomic_inc(&task->tk_count);
  	rpc_execute(task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
642
  out:
19445b99b   Trond Myklebust   SUNRPC: Cleanup -...
643
  	return task;
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
644
  }
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
645
  EXPORT_SYMBOL_GPL(rpc_run_task);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
646
647
648
649
650
651
  
  /**
   * 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
652
   */
cbc200592   Trond Myklebust   SUNRPC: Declare a...
653
  int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  {
  	struct rpc_task	*task;
84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
656
657
658
659
660
661
  	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 ...
662
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
  	BUG_ON(flags & RPC_TASK_ASYNC);
c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
665
  	task = rpc_run_task(&task_setup_data);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
666
667
  	if (IS_ERR(task))
  		return PTR_ERR(task);
e60859ac0   Trond Myklebust   SUNRPC: rpc_execu...
668
  	status = task->tk_status;
bde8f00ce   Trond Myklebust   [PATCH] NFS: Fix ...
669
  	rpc_put_task(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
  	return status;
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
672
  EXPORT_SYMBOL_GPL(rpc_call_sync);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673

6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
674
675
676
677
678
  /**
   * 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...
679
   * @tk_ops: RPC call ops
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
680
   * @data: user call data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
   */
  int
cbc200592   Trond Myklebust   SUNRPC: Declare a...
683
  rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
963d8fe53   Trond Myklebust   RPC: Clean up RPC...
684
  	       const struct rpc_call_ops *tk_ops, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
  {
  	struct rpc_task	*task;
84115e1cd   Trond Myklebust   SUNRPC: Cleanup o...
687
688
689
690
691
692
693
  	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
694

c970aa85e   Trond Myklebust   SUNRPC: Clean up ...
695
  	task = rpc_run_task(&task_setup_data);
6e5b70e9d   Trond Myklebust   SUNRPC: clean up ...
696
697
698
699
  	if (IS_ERR(task))
  		return PTR_ERR(task);
  	rpc_put_task(task);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
701
  EXPORT_SYMBOL_GPL(rpc_call_async);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702

9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
703
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
704
705
706
  /**
   * 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...
707
708
   * @req: RPC request
   * @tk_ops: RPC call ops
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
709
710
   */
  struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
7a73fdde3   Jaswinder Singh Rajput   net: fix htmldocs...
711
  				const struct rpc_call_ops *tk_ops)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
712
713
714
715
716
717
718
719
720
721
722
723
724
  {
  	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 -...
725
  	if (IS_ERR(task)) {
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  		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);
  	BUG_ON(atomic_read(&task->tk_count) != 2);
  	rpc_execute(task);
  
  out:
  	dprintk("RPC: rpc_run_bc_task: task= %p
  ", task);
  	return task;
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
748
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
749

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  void
77de2c590   Trond Myklebust   SUNRPC: Add a hel...
751
752
753
754
755
  rpc_call_start(struct rpc_task *task)
  {
  	task->tk_action = call_start;
  }
  EXPORT_SYMBOL_GPL(rpc_call_start);
ed39440a2   Chuck Lever   SUNRPC: create AP...
756
757
758
759
  /**
   * rpc_peeraddr - extract remote peer address from clnt's xprt
   * @clnt: RPC client structure
   * @buf: target buffer
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
760
   * @bufsize: length of target buffer
ed39440a2   Chuck Lever   SUNRPC: create AP...
761
762
763
764
765
766
767
768
769
770
771
772
   *
   * 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;
  	struct rpc_xprt *xprt = clnt->cl_xprt;
  
  	bytes = sizeof(xprt->addr);
  	if (bytes > bufsize)
  		bytes = bufsize;
  	memcpy(buf, &clnt->cl_xprt->addr, bytes);
c4efcb1d3   Chuck Lever   SUNRPC: Use "sock...
773
  	return xprt->addrlen;
ed39440a2   Chuck Lever   SUNRPC: create AP...
774
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
775
  EXPORT_SYMBOL_GPL(rpc_peeraddr);
ed39440a2   Chuck Lever   SUNRPC: create AP...
776

f425eba43   Chuck Lever   SUNRPC: Create AP...
777
778
779
780
781
782
  /**
   * rpc_peeraddr2str - return remote peer address in printable format
   * @clnt: RPC client structure
   * @format: address format
   *
   */
b454ae906   Chuck Lever   SUNRPC: fewer con...
783
784
  const char *rpc_peeraddr2str(struct rpc_clnt *clnt,
  			     enum rpc_display_format_t format)
f425eba43   Chuck Lever   SUNRPC: Create AP...
785
786
  {
  	struct rpc_xprt *xprt = clnt->cl_xprt;
7559c7a28   Chuck Lever   SUNRPC: Make addr...
787
788
789
790
791
  
  	if (xprt->address_strings[format] != NULL)
  		return xprt->address_strings[format];
  	else
  		return "unprintable";
f425eba43   Chuck Lever   SUNRPC: Create AP...
792
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
793
  EXPORT_SYMBOL_GPL(rpc_peeraddr2str);
f425eba43   Chuck Lever   SUNRPC: Create AP...
794

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
798
  void
  rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
  {
  	struct rpc_xprt *xprt = clnt->cl_xprt;
470056c28   Chuck Lever   [PATCH] RPC: rati...
799
800
  	if (xprt->ops->set_buffer_size)
  		xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
802
  EXPORT_SYMBOL_GPL(rpc_setbufsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
806
807
808
809
810
811
812
813
814
815
  
  /*
   * Return size of largest payload RPC client can support, in bytes
   *
   * 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)
  {
  	return clnt->cl_xprt->max_payload;
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
816
  EXPORT_SYMBOL_GPL(rpc_max_payload);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817

35f5a422c   Chuck Lever   SUNRPC: new inter...
818
819
820
821
822
823
824
825
  /**
   * rpc_force_rebind - force transport to check that remote port is unchanged
   * @clnt: client to rebind
   *
   */
  void rpc_force_rebind(struct rpc_clnt *clnt)
  {
  	if (clnt->cl_autobind)
ec739ef03   Chuck Lever   SUNRPC: Create a ...
826
  		xprt_clear_bound(clnt->cl_xprt);
35f5a422c   Chuck Lever   SUNRPC: new inter...
827
  }
b86acd501   Chuck Lever   SUNRPC: export ne...
828
  EXPORT_SYMBOL_GPL(rpc_force_rebind);
35f5a422c   Chuck Lever   SUNRPC: new inter...
829

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
  /*
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
831
832
833
   * Restart an (async) RPC call from the call_prepare state.
   * Usually called from within the exit handler.
   */
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
834
  int
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
835
836
837
  rpc_restart_call_prepare(struct rpc_task *task)
  {
  	if (RPC_ASSASSINATED(task))
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
838
  		return 0;
d00c5d438   Trond Myklebust   NFS: Get rid of n...
839
840
841
  	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...
842
  	return 1;
aae2006e9   Andy Adamson   nfs41: sunrpc: Ex...
843
844
845
846
  }
  EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
848
849
   * Restart an (async) RPC call. Usually called from within the
   * exit handler.
   */
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
850
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
  rpc_restart_call(struct rpc_task *task)
  {
  	if (RPC_ASSASSINATED(task))
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
854
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  	task->tk_action = call_start;
f1f88fc7e   Trond Myklebust   SUNRPC: The funct...
856
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
858
  EXPORT_SYMBOL_GPL(rpc_restart_call);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859

3748f1e44   Chuck Lever   SUNRPC: Add a fun...
860
861
862
863
864
865
866
867
868
869
870
871
872
873
  #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
874
875
876
877
878
879
880
881
882
883
  /*
   * 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...
884
885
  	dprintk("RPC: %5u call_start %s%d proc %s (%s)
  ", task->tk_pid,
46121cf7d   Chuck Lever   SUNRPC: fix print...
886
  			clnt->cl_protname, clnt->cl_vers,
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
887
  			rpc_proc_name(task),
46121cf7d   Chuck Lever   SUNRPC: fix print...
888
  			(RPC_IS_ASYNC(task) ? "async" : "sync"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
892
893
894
895
896
897
898
899
900
901
  
  	/* 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...
902
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
906
907
908
909
910
911
912
913
914
915
  	task->tk_status  = 0;
  	task->tk_action  = call_reserveresult;
  	xprt_reserve(task);
  }
  
  /*
   * 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...
916
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
923
924
  
  	/*
  	 * 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...
925
  			task->tk_action = call_refresh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
928
929
930
  			return;
  		}
  
  		printk(KERN_ERR "%s: status=%d, but no request slot, exiting
  ",
0dc47877a   Harvey Harrison   net: replace rema...
931
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
935
936
937
938
939
940
941
942
  		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...
943
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
951
952
953
954
955
  		xprt_release(task);
  	}
  
  	switch (status) {
  	case -EAGAIN:	/* woken up; retry */
  		task->tk_action = call_reserve;
  		return;
  	case -EIO:	/* probably a shutdown */
  		break;
  	default:
  		printk(KERN_ERR "%s: unrecognized error %d, exiting
  ",
0dc47877a   Harvey Harrison   net: replace rema...
956
  				__func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
959
960
961
962
  		break;
  	}
  	rpc_exit(task, status);
  }
  
  /*
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
   * 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...
987
  	task->tk_action = call_refresh;
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
988
  	switch (status) {
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
989
990
991
  	case 0:
  		if (rpcauth_uptodatecred(task))
  			task->tk_action = call_allocate;
55576244e   J. Bruce Fields   SUNRPC: cleanup s...
992
993
994
  		return;
  	case -ETIMEDOUT:
  		rpc_delay(task, 3*HZ);
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
995
996
997
998
999
1000
1001
1002
1003
  	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...
1004
  	}
5fc43978a   Trond Myklebust   SUNRPC: Fix an in...
1005
1006
1007
1008
  	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...
1009
1010
1011
1012
  }
  
  /*
   * 2b.	Allocate the buffer. For details, see sched.c:rpc_malloc.
021071483   Chuck Lever   SUNRPC: switchabl...
1013
   *	(Note: buffer memory is freed in xprt_release).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
1016
1017
   */
  static void
  call_allocate(struct rpc_task *task)
  {
f2d47d02f   J. Bruce Fields   Fix null derefere...
1018
  	unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack;
021071483   Chuck Lever   SUNRPC: switchabl...
1019
1020
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = task->tk_xprt;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1021
  	struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022

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

021071483   Chuck Lever   SUNRPC: switchabl...
1027
  	if (req->rq_buffer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  		return;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1029
1030
1031
1032
1033
  	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
1034

2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1035
1036
1037
1038
1039
1040
1041
1042
1043
  	/*
  	 * 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...
1044
1045
  	req->rq_buffer = xprt->ops->buf_alloc(task,
  					req->rq_callsize + req->rq_rcvsize);
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1046
  	if (req->rq_buffer != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
  		return;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1048
1049
1050
  
  	dprintk("RPC: %5u rpc_buffer allocation failed
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051

5afa9133c   Trond Myklebust   SUNRPC: Ensure th...
1052
  	if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
b6e9c713f   Trond Myklebust   SUNRPC: Don't cal...
1053
  		task->tk_action = call_allocate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
1055
1056
1057
1058
1059
  		rpc_delay(task, HZ>>4);
  		return;
  	}
  
  	rpc_exit(task, -ERESTARTSYS);
  }
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  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...
1070
  	task->tk_rqstp->rq_bytes_sent = 0;
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1071
  }
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1072
1073
1074
1075
1076
1077
1078
  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...
1079
  	buf->flags = 0;
2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1080
1081
1082
  	buf->len = 0;
  	buf->buflen = len;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
1086
  /*
   * 3.	Encode arguments of an RPC call
   */
  static void
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1087
  rpc_xdr_encode(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  	struct rpc_rqst	*req = task->tk_rqstp;
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
1090
  	kxdreproc_t	encode;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1091
  	__be32		*p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092

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

2bea90d43   Chuck Lever   SUNRPC: RPC buffe...
1095
1096
1097
1098
1099
1100
  	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
1101

b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1102
1103
1104
1105
  	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
1106
1107
1108
  		rpc_exit(task, -EIO);
  		return;
  	}
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1109
1110
  
  	encode = task->tk_msg.rpc_proc->p_encode;
f3680312a   J. Bruce Fields   SUNRPC: Retry wra...
1111
1112
1113
1114
1115
  	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
1116
1117
1118
1119
1120
1121
1122
1123
  }
  
  /*
   * 4.	Get the server port number if not yet set
   */
  static void
  call_bind(struct rpc_task *task)
  {
ec739ef03   Chuck Lever   SUNRPC: Create a ...
1124
  	struct rpc_xprt *xprt = task->tk_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125

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

da3518780   Chuck Lever   [PATCH] RPC: prop...
1128
  	task->tk_action = call_connect;
ec739ef03   Chuck Lever   SUNRPC: Create a ...
1129
  	if (!xprt_bound(xprt)) {
da3518780   Chuck Lever   [PATCH] RPC: prop...
1130
  		task->tk_action = call_bind_status;
ec739ef03   Chuck Lever   SUNRPC: Create a ...
1131
  		task->tk_timeout = xprt->bind_timeout;
bbf7c1dd2   Chuck Lever   SUNRPC: Introduce...
1132
  		xprt->ops->rpcbind(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
1134
1135
1136
  	}
  }
  
  /*
da3518780   Chuck Lever   [PATCH] RPC: prop...
1137
1138
1139
1140
1141
   * 4a.	Sort out bind result
   */
  static void
  call_bind_status(struct rpc_task *task)
  {
906462af4   Chuck Lever   SUNRPC: Split ano...
1142
  	int status = -EIO;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1143
1144
  
  	if (task->tk_status >= 0) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1145
  		dprint_status(task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1146
1147
1148
1149
1150
1151
  		task->tk_status = 0;
  		task->tk_action = call_connect;
  		return;
  	}
  
  	switch (task->tk_status) {
381ba74af   Trond Myklebust   SUNRPC: Ensure ou...
1152
1153
1154
1155
  	case -ENOMEM:
  		dprintk("RPC: %5u rpcbind out of memory
  ", task->tk_pid);
  		rpc_delay(task, HZ >> 2);
2429cbf6a   Chuck Lever   SUNRPC: Add a new...
1156
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1157
  	case -EACCES:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1158
1159
1160
  		dprintk("RPC: %5u remote rpcbind: RPC program/version "
  				"unavailable
  ", task->tk_pid);
b79dc8ced   Chuck Lever   SUNRPC: RPC bind ...
1161
1162
1163
1164
1165
  		/* 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...
1166
1167
1168
  		if (task->tk_rebind_retry == 0)
  			break;
  		task->tk_rebind_retry--;
ea635a517   Chuck Lever   SUNRPC: Retry rpc...
1169
  		rpc_delay(task, 3*HZ);
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1170
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1171
  	case -ETIMEDOUT:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1172
1173
  		dprintk("RPC: %5u rpcbind request timed out
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1174
  				task->tk_pid);
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1175
  		goto retry_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1176
  	case -EPFNOSUPPORT:
906462af4   Chuck Lever   SUNRPC: Split ano...
1177
  		/* server doesn't support any rpcbind version we know of */
012da158f   Chuck Lever   SUNRPC: Use soft ...
1178
1179
  		dprintk("RPC: %5u unrecognized remote rpcbind service
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1180
1181
1182
  				task->tk_pid);
  		break;
  	case -EPROTONOSUPPORT:
00a6e7bbf   Chuck Lever   SUNRPC: RPC clien...
1183
1184
  		dprintk("RPC: %5u remote rpcbind version unavailable, retrying
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1185
  				task->tk_pid);
00a6e7bbf   Chuck Lever   SUNRPC: RPC clien...
1186
1187
1188
  		task->tk_status = 0;
  		task->tk_action = call_bind;
  		return;
012da158f   Chuck Lever   SUNRPC: Use soft ...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  	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...
1205
  	default:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1206
1207
  		dprintk("RPC: %5u unrecognized rpcbind error (%d)
  ",
da3518780   Chuck Lever   [PATCH] RPC: prop...
1208
  				task->tk_pid, -task->tk_status);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1209
1210
1211
1212
  	}
  
  	rpc_exit(task, status);
  	return;
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1213
1214
  retry_timeout:
  	task->tk_action = call_timeout;
da3518780   Chuck Lever   [PATCH] RPC: prop...
1215
1216
1217
1218
  }
  
  /*
   * 4b.	Connect to the RPC server
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
1220
1221
1222
   */
  static void
  call_connect(struct rpc_task *task)
  {
da3518780   Chuck Lever   [PATCH] RPC: prop...
1223
  	struct rpc_xprt *xprt = task->tk_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224

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

da3518780   Chuck Lever   [PATCH] RPC: prop...
1230
1231
1232
1233
1234
1235
  	task->tk_action = call_transmit;
  	if (!xprt_connected(xprt)) {
  		task->tk_action = call_connect_status;
  		if (task->tk_status < 0)
  			return;
  		xprt_connect(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
  }
  
  /*
da3518780   Chuck Lever   [PATCH] RPC: prop...
1240
   * 4c.	Sort out connect result
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
1244
1245
1246
   */
  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...
1247
  	dprint_status(task);
da3518780   Chuck Lever   [PATCH] RPC: prop...
1248

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  	task->tk_status = 0;
2a4919919   Trond Myklebust   SUNRPC: Return EA...
1250
  	if (status >= 0 || status == -EAGAIN) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251
1252
1253
1254
  		clnt->cl_stats->netreconn++;
  		task->tk_action = call_transmit;
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  	switch (status) {
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
1256
1257
1258
  		/* if soft mounted, test if we've timed out */
  	case -ETIMEDOUT:
  		task->tk_action = call_timeout;
2a4919919   Trond Myklebust   SUNRPC: Return EA...
1259
1260
1261
  		break;
  	default:
  		rpc_exit(task, -EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
1263
1264
1265
1266
1267
1268
1269
1270
  	}
  }
  
  /*
   * 5.	Transmit the RPC request, and wait for reply
   */
  static void
  call_transmit(struct rpc_task *task)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1271
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
1275
1276
1277
1278
  
  	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 ...
1279
  	task->tk_action = call_transmit_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
  	/* Encode here so that rpcsec_gss can use correct sequence number. */
940e3318c   Trond Myklebust   [PATCH] SUNRPC: d...
1281
  	if (rpc_task_need_encode(task)) {
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1282
  		BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1283
  		rpc_xdr_encode(task);
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
1284
  		/* Did the encode result in an error condition? */
8b39f2b41   Trond Myklebust   SUNRPC: Ensure we...
1285
1286
1287
1288
1289
1290
  		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 ...
1291
  			return;
8b39f2b41   Trond Myklebust   SUNRPC: Ensure we...
1292
  		}
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
1293
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
1295
1296
  	xprt_transmit(task);
  	if (task->tk_status < 0)
  		return;
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1297
1298
1299
1300
1301
  	/*
  	 * 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...
1302
  	if (rpc_reply_expected(task))
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1303
1304
  		return;
  	task->tk_action = rpc_exit_task;
fda139393   Trond Myklebust   SUNRPC: Convert u...
1305
  	rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1306
1307
1308
1309
1310
1311
1312
1313
1314
  }
  
  /*
   * 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...
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
  
  	/*
  	 * 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 ...
1325
1326
1327
1328
  	switch (task->tk_status) {
  	case -EAGAIN:
  		break;
  	default:
206a134b4   Chuck Lever   SUNRPC: Check exp...
1329
  		dprint_status(task);
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1330
  		xprt_end_transmit(task);
09a21c410   Chuck Lever   SUNRPC: Allow RPC...
1331
1332
  		rpc_task_force_reencode(task);
  		break;
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1333
1334
1335
1336
1337
1338
1339
  		/*
  		 * 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 ...
1340
1341
1342
  	case -EHOSTDOWN:
  	case -EHOSTUNREACH:
  	case -ENETUNREACH:
09a21c410   Chuck Lever   SUNRPC: Allow RPC...
1343
1344
1345
1346
1347
1348
1349
  		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...
1350
  	case -EPIPE:
15f081ca8   Trond Myklebust   SUNRPC: Avoid an ...
1351
1352
  		rpc_task_force_reencode(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  }
9e00abc3c   Trond Myklebust   SUNRPC: sunrpc sh...
1354
  #if defined(CONFIG_SUNRPC_BACKCHANNEL)
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  /*
   * 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;
  
  	BUG_ON(task->tk_status != 0);
  	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);
  		xprt_conditional_disconnect(task->tk_xprt,
  			req->rq_connect_cookie);
  		break;
  	default:
  		/*
  		 * We were unable to reply and will have to drop the
  		 * request.  The server should reconnect and retransmit.
  		 */
  		BUG_ON(task->tk_status == -EAGAIN);
  		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...
1421
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1422

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
1424
1425
1426
1427
1428
1429
1430
1431
  /*
   * 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_...
1432
1433
  	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
1434

46121cf7d   Chuck Lever   SUNRPC: fix print...
1435
  	dprint_status(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1436
1437
1438
1439
1440
1441
1442
1443
1444
  
  	status = task->tk_status;
  	if (status >= 0) {
  		task->tk_action = call_decode;
  		return;
  	}
  
  	task->tk_status = 0;
  	switch(status) {
76303992b   Trond Myklebust   SUNRPC: Handle EN...
1445
1446
1447
1448
1449
1450
1451
1452
  	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
1453
1454
  	case -ETIMEDOUT:
  		task->tk_action = call_timeout;
241c39b9a   Trond Myklebust   RPC: Fix the TCP ...
1455
  		if (task->tk_client->cl_discrtry)
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
1456
1457
  			xprt_conditional_disconnect(task->tk_xprt,
  					req->rq_connect_cookie);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
  		break;
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
1459
  	case -ECONNRESET:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
  	case -ECONNREFUSED:
35f5a422c   Chuck Lever   SUNRPC: new inter...
1461
  		rpc_force_rebind(clnt);
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
1462
1463
1464
  		rpc_delay(task, 3*HZ);
  	case -EPIPE:
  	case -ENOTCONN:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
  		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...
1475
1476
1477
  		if (clnt->cl_chatty)
  			printk("%s: RPC call returned error %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
  			       clnt->cl_protname, -status);
  		rpc_exit(task, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
1482
1483
  	}
  }
  
  /*
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
1484
   * 6a.	Handle RPC timeout
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
1486
1487
1488
1489
1490
1491
1492
1493
   * 	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...
1494
1495
  		dprintk("RPC: %5u call_timeout (minor)
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
1497
  		goto retry;
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1498
1499
  	dprintk("RPC: %5u call_timeout (major)
  ", task->tk_pid);
ef759a2e5   Chuck Lever   SUNRPC: introduce...
1500
  	task->tk_timeouts++;
3a28becc3   Chuck Lever   SUNRPC: soft conn...
1501
1502
1503
1504
  	if (RPC_IS_SOFTCONN(task)) {
  		rpc_exit(task, -ETIMEDOUT);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
  	if (RPC_IS_SOFT(task)) {
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1506
1507
1508
  		if (clnt->cl_chatty)
  			printk(KERN_NOTICE "%s: server %s not responding, timed out
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
  				clnt->cl_protname, clnt->cl_server);
7494d00c7   Trond Myklebust   SUNRPC: Allow RPC...
1510
1511
1512
1513
  		if (task->tk_flags & RPC_TASK_TIMEOUT)
  			rpc_exit(task, -ETIMEDOUT);
  		else
  			rpc_exit(task, -EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514
1515
  		return;
  	}
f518e35ae   Chuck Lever   SUNRPC: get rid o...
1516
  	if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  		task->tk_flags |= RPC_CALL_MAJORSEEN;
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1518
1519
1520
  		if (clnt->cl_chatty)
  			printk(KERN_NOTICE "%s: server %s not responding, still trying
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
  			clnt->cl_protname, clnt->cl_server);
  	}
35f5a422c   Chuck Lever   SUNRPC: new inter...
1523
  	rpc_force_rebind(clnt);
b48633bd0   Trond Myklebust   SUNRPC: Invalidat...
1524
1525
1526
1527
1528
  	/*
  	 * 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
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  
  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...
1544
  	kxdrdproc_t	decode = task->tk_msg.rpc_proc->p_decode;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1545
  	__be32		*p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546

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

f518e35ae   Chuck Lever   SUNRPC: get rid o...
1549
  	if (task->tk_flags & RPC_CALL_MAJORSEEN) {
b6b6152c4   Olga Kornievskaia   rpc: bring back c...
1550
1551
1552
1553
  		if (clnt->cl_chatty)
  			printk(KERN_NOTICE "%s: server %s OK
  ",
  				clnt->cl_protname, clnt->cl_server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
1555
  		task->tk_flags &= ~RPC_CALL_MAJORSEEN;
  	}
43ac3f296   Trond Myklebust   SUNRPC: Fix memor...
1556
1557
  	/*
  	 * Ensure that we see all writes made by xprt_complete_rqst()
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
1558
  	 * before it changed req->rq_reply_bytes_recvd.
43ac3f296   Trond Myklebust   SUNRPC: Fix memor...
1559
1560
  	 */
  	smp_rmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
1562
1563
1564
1565
  	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 ...
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
  	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...
1578
  	p = rpc_verify_header(task);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1579
1580
1581
1582
  	if (IS_ERR(p)) {
  		if (p == ERR_PTR(-EAGAIN))
  			goto out_retry;
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
  	}
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1584
  	task->tk_action = rpc_exit_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585

6d5fcb5a5   Trond Myklebust   SUNRPC: Remove BK...
1586
  	if (decode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
1588
  		task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
  						      task->tk_msg.rpc_resp);
6d5fcb5a5   Trond Myklebust   SUNRPC: Remove BK...
1589
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1590
1591
1592
  	dprintk("RPC: %5u call_decode result %d
  ", task->tk_pid,
  			task->tk_status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
  	return;
  out_retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
  	task->tk_status = 0;
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1596
  	/* Note: rpc_verify_header() may have freed the RPC slot */
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
1597
  	if (task->tk_rqstp == req) {
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
1598
  		req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
1599
  		if (task->tk_client->cl_discrtry)
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
1600
1601
  			xprt_conditional_disconnect(task->tk_xprt,
  					req->rq_connect_cookie);
24b74bf0c   Trond Myklebust   SUNRPC: Fix a bug...
1602
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1604
  static __be32 *
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1605
  rpc_encode_header(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
1607
  {
  	struct rpc_clnt *clnt = task->tk_client;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  	struct rpc_rqst	*req = task->tk_rqstp;
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1609
  	__be32		*p = req->rq_svec[0].iov_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610
1611
  
  	/* FIXME: check buffer size? */
808012fbb   Chuck Lever   [PATCH] RPC: skip...
1612
1613
  
  	p = xprt_skip_transport_header(task->tk_xprt, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1614
1615
1616
1617
1618
1619
  	*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...
1620
1621
1622
  	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
1623
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1624
  static __be32 *
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1625
  rpc_verify_header(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
1627
1628
  {
  	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...
1629
1630
  	__be32	*p = iov->iov_base;
  	u32 n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
  	int error = -EACCES;
e8896495b   David Howells   NFS: Check length...
1632
1633
1634
1635
1636
1637
  	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 ...
1638
  		dprintk("RPC: %5u %s: XDR representation not a multiple of"
0dc47877a   Harvey Harrison   net: replace rema...
1639
1640
  		       " 4 bytes: 0x%x
  ", task->tk_pid, __func__,
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1641
  		       task->tk_rqstp->rq_rcv_buf.len);
e8896495b   David Howells   NFS: Check length...
1642
1643
  		goto out_eio;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
  	if ((len -= 3) < 0)
  		goto out_overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646

f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1647
  	p += 1; /* skip XID */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
  	if ((n = ntohl(*p++)) != RPC_REPLY) {
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1649
1650
  		dprintk("RPC: %5u %s: not an RPC reply: %x
  ",
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1651
  			task->tk_pid, __func__, n);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1652
  		goto out_garbage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
  	}
f4a2e418b   Ricardo Labiaga   nfs41: Process th...
1654

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655
1656
1657
1658
  	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
  		if (--len < 0)
  			goto out_overflow;
  		switch ((n = ntohl(*p++))) {
89f0e4fea   Joe Perches   sunrpc: Reduce sw...
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
  		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
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
  		}
  		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...
1684
1685
  			dprintk("RPC: %5u %s: retry stale creds
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1686
  					task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
  			rpcauth_invalcred(task);
220bcc2af   Trond Myklebust   SUNRPC: Don't cal...
1688
1689
  			/* Ensure we obtain a new XID! */
  			xprt_release(task);
118df3d17   Trond Myklebust   SUNRPC: After cal...
1690
  			task->tk_action = call_reserve;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1691
  			goto out_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
1693
1694
1695
1696
1697
  		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...
1698
1699
  			dprintk("RPC: %5u %s: retry garbled creds
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1700
  					task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
  			task->tk_action = call_bind;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1702
  			goto out_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
  		case RPC_AUTH_TOOWEAK:
b0e1c57ea   Chuck Lever   SUNRPC: Rename "c...
1704
  			printk(KERN_NOTICE "RPC: server %s requires stronger "
1356b8c28   Levent Serinol   SUNRPC: more verb...
1705
1706
  			       "authentication.
  ", task->tk_client->cl_server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1707
1708
  			break;
  		default:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1709
1710
  			dprintk("RPC: %5u %s: unknown auth error: %x
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1711
  					task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
1713
  			error = -EIO;
  		}
46121cf7d   Chuck Lever   SUNRPC: fix print...
1714
1715
  		dprintk("RPC: %5u %s: call rejected %d
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1716
  				task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1717
1718
1719
  		goto out_err;
  	}
  	if (!(p = rpcauth_checkverf(task, p))) {
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1720
1721
  		dprintk("RPC: %5u %s: auth check failed
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1722
  				task->tk_pid, __func__);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1723
  		goto out_garbage;		/* bad verifier, retry */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
  	}
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
1725
  	len = p - (__be32 *)iov->iov_base - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726
1727
1728
1729
1730
1731
  	if (len < 0)
  		goto out_overflow;
  	switch ((n = ntohl(*p++))) {
  	case RPC_SUCCESS:
  		return p;
  	case RPC_PROG_UNAVAIL:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1732
1733
  		dprintk("RPC: %5u %s: program %u is unsupported by server %s
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1734
  				task->tk_pid, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1735
1736
  				(unsigned int)task->tk_client->cl_prog,
  				task->tk_client->cl_server);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
1737
1738
  		error = -EPFNOSUPPORT;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739
  	case RPC_PROG_MISMATCH:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1740
  		dprintk("RPC: %5u %s: program %u, version %u unsupported by "
0dc47877a   Harvey Harrison   net: replace rema...
1741
1742
  				"server %s
  ", task->tk_pid, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
1744
1745
  				(unsigned int)task->tk_client->cl_prog,
  				(unsigned int)task->tk_client->cl_vers,
  				task->tk_client->cl_server);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
1746
1747
  		error = -EPROTONOSUPPORT;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
  	case RPC_PROC_UNAVAIL:
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
1749
  		dprintk("RPC: %5u %s: proc %s unsupported by program %u, "
46121cf7d   Chuck Lever   SUNRPC: fix print...
1750
1751
  				"version %u on server %s
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1752
  				task->tk_pid, __func__,
3748f1e44   Chuck Lever   SUNRPC: Add a fun...
1753
  				rpc_proc_name(task),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1754
1755
1756
  				task->tk_client->cl_prog,
  				task->tk_client->cl_vers,
  				task->tk_client->cl_server);
cdf477068   Andreas Gruenbacher   [PATCH] RPC: Retu...
1757
1758
  		error = -EOPNOTSUPP;
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
  	case RPC_GARBAGE_ARGS:
46121cf7d   Chuck Lever   SUNRPC: fix print...
1760
1761
  		dprintk("RPC: %5u %s: server saw garbage
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1762
  				task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
  		break;			/* retry */
  	default:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1765
1766
  		dprintk("RPC: %5u %s: server accept status: %x
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1767
  				task->tk_pid, __func__, n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
  		/* Also retry */
  	}
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1770
  out_garbage:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771
1772
1773
  	task->tk_client->cl_stats->rpcgarbage++;
  	if (task->tk_garb_retry) {
  		task->tk_garb_retry--;
46121cf7d   Chuck Lever   SUNRPC: fix print...
1774
1775
  		dprintk("RPC: %5u %s: retrying
  ",
0dc47877a   Harvey Harrison   net: replace rema...
1776
  				task->tk_pid, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
  		task->tk_action = call_bind;
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1778
1779
  out_retry:
  		return ERR_PTR(-EAGAIN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1781
1782
1783
1784
  out_eio:
  	error = -EIO;
  out_err:
  	rpc_exit(task, error);
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1785
1786
  	dprintk("RPC: %5u %s: call failed with error %d
  ", task->tk_pid,
0dc47877a   Harvey Harrison   net: replace rema...
1787
  			__func__, error);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1788
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789
  out_overflow:
8a702bbb7   Trond Myklebust   SUNRPC: Suppress ...
1790
1791
  	dprintk("RPC: %5u %s: server reply was truncated.
  ", task->tk_pid,
0dc47877a   Harvey Harrison   net: replace rema...
1792
  			__func__);
abbcf28f2   Trond Myklebust   SUNRPC: Yet more ...
1793
  	goto out_garbage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
  }
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1795

9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
1796
  static void rpcproc_encode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1797
  {
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1798
  }
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
1799
  static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1800
1801
1802
1803
1804
1805
1806
1807
  {
  	return 0;
  }
  
  static struct rpc_procinfo rpcproc_null = {
  	.p_encode = rpcproc_encode_null,
  	.p_decode = rpcproc_decode_null,
  };
caabea8a5   Chuck Lever   SUNRPC: Use soft ...
1808
  static int rpc_ping(struct rpc_clnt *clnt)
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1809
1810
1811
1812
1813
1814
  {
  	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 ...
1815
  	err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN);
5ee0ed7d3   Trond Myklebust   [PATCH] RPC: Make...
1816
1817
1818
  	put_rpccred(msg.rpc_cred);
  	return err;
  }
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1819

5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
1820
1821
1822
1823
1824
1825
  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...
1826
1827
1828
1829
1830
1831
  	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 ...
1832
  	return rpc_run_task(&task_setup_data);
5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
1833
  }
e8914c65f   Trond Myklebust   SUNRPC: Restrict ...
1834
  EXPORT_SYMBOL_GPL(rpc_call_null);
5e1550d6a   Trond Myklebust   SUNRPC: Add the h...
1835

188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1836
  #ifdef RPC_DEBUG
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
1837
1838
  static void rpc_show_header(void)
  {
cb3997b5a   Chuck Lever   SUNRPC: Display s...
1839
1840
1841
  	printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
  		"-timeout ---ops--
  ");
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
1842
  }
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
1843
1844
1845
1846
  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 ...
1847
1848
1849
  
  	if (RPC_IS_QUEUED(task))
  		rpc_waitq = rpc_qname(task->tk_waitqueue);
b3bcedadf   Joe Perches   net/sunrpc/clnt.c...
1850
1851
  	printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s
  ",
cb3997b5a   Chuck Lever   SUNRPC: Display s...
1852
1853
1854
  		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...
1855
  		task->tk_action, rpc_waitq);
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
1856
  }
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1857
1858
1859
  void rpc_show_tasks(void)
  {
  	struct rpc_clnt *clnt;
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
1860
  	struct rpc_task *task;
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
1861
  	int header = 0;
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1862
1863
  
  	spin_lock(&rpc_client_lock);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1864
  	list_for_each_entry(clnt, &all_clients, cl_clients) {
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1865
  		spin_lock(&clnt->cl_lock);
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
1866
  		list_for_each_entry(task, &clnt->cl_tasks, tk_task) {
68a23ee94   Chuck Lever   SUNRPC: Don't dis...
1867
1868
1869
1870
  			if (!header) {
  				rpc_show_header();
  				header++;
  			}
38e886e0c   Chuck Lever   SUNRPC: Refactor ...
1871
  			rpc_show_task(clnt, task);
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1872
1873
1874
  		}
  		spin_unlock(&clnt->cl_lock);
  	}
188fef11d   Trond Myklebust   SUNRPC: Move rpc_...
1875
1876
1877
  	spin_unlock(&rpc_client_lock);
  }
  #endif