Blame view

fs/nfs/mount_clnt.c 12.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
19207231c   Chuck Lever   NFS: Clean up in-...
2
   * In-kernel MOUNT protocol client
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
10
11
12
13
14
   *
   * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
   */
  
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/uio.h>
  #include <linux/net.h>
  #include <linux/in.h>
  #include <linux/sunrpc/clnt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include <linux/sunrpc/sched.h>
  #include <linux/nfs_fs.h>
8491945f1   Steve Dickson   NFS: Client mount...
17
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

39de493e8   Kinglong Mee   NFS: Remove unnee...
19
  #define NFSDBG_FACILITY	NFSDBG_MOUNT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20

2ad780978   Chuck Lever   NFS: Clean up MNT...
21
  /*
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
22
23
24
25
26
27
28
29
   * Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4
   */
  #define MNTPATHLEN		(1024)
  
  /*
   * XDR data type sizes
   */
  #define encode_dirpath_sz	(1 + XDR_QUADLEN(MNTPATHLEN))
fb1252957   Chuck Lever   NFS: Add separate...
30
31
  #define MNT_status_sz		(1)
  #define MNT_fhs_status_sz	(1)
4fdcd9966   Chuck Lever   NFS: add new file...
32
33
  #define MNT_fhandle_sz		XDR_QUADLEN(NFS2_FHSIZE)
  #define MNT_fhandle3_sz		(1 + XDR_QUADLEN(NFS3_FHSIZE))
a14017db2   Chuck Lever   NFS: add XDR deco...
34
  #define MNT_authflav3_sz	(1 + NFS_MAX_SECFLAVORS)
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
35
36
37
38
39
  
  /*
   * XDR argument and result sizes
   */
  #define MNT_enc_dirpath_sz	encode_dirpath_sz
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
40
41
42
  #define MNT_dec_mountres_sz	(MNT_status_sz + MNT_fhandle_sz)
  #define MNT_dec_mountres3_sz	(MNT_status_sz + MNT_fhandle_sz + \
  				 MNT_authflav3_sz)
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
43
44
  
  /*
2ad780978   Chuck Lever   NFS: Clean up MNT...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
   * Defined by RFC 1094, section A.5
   */
  enum {
  	MOUNTPROC_NULL		= 0,
  	MOUNTPROC_MNT		= 1,
  	MOUNTPROC_DUMP		= 2,
  	MOUNTPROC_UMNT		= 3,
  	MOUNTPROC_UMNTALL	= 4,
  	MOUNTPROC_EXPORT	= 5,
  };
  
  /*
   * Defined by RFC 1813, section 5.2
   */
  enum {
  	MOUNTPROC3_NULL		= 0,
  	MOUNTPROC3_MNT		= 1,
  	MOUNTPROC3_DUMP		= 2,
  	MOUNTPROC3_UMNT		= 3,
  	MOUNTPROC3_UMNTALL	= 4,
  	MOUNTPROC3_EXPORT	= 5,
  };
a613fa168   Trond Myklebust   SUNRPC: constify ...
67
  static const struct rpc_program mnt_program;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68

fb1252957   Chuck Lever   NFS: Add separate...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  /*
   * Defined by OpenGroup XNFS Version 3W, chapter 8
   */
  enum mountstat {
  	MNT_OK			= 0,
  	MNT_EPERM		= 1,
  	MNT_ENOENT		= 2,
  	MNT_EACCES		= 13,
  	MNT_EINVAL		= 22,
  };
  
  static struct {
  	u32 status;
  	int errno;
  } mnt_errtbl[] = {
  	{ .status = MNT_OK,			.errno = 0,		},
  	{ .status = MNT_EPERM,			.errno = -EPERM,	},
  	{ .status = MNT_ENOENT,			.errno = -ENOENT,	},
  	{ .status = MNT_EACCES,			.errno = -EACCES,	},
  	{ .status = MNT_EINVAL,			.errno = -EINVAL,	},
  };
  
  /*
   * Defined by RFC 1813, section 5.1.5
   */
  enum mountstat3 {
  	MNT3_OK			= 0,		/* no error */
  	MNT3ERR_PERM		= 1,		/* Not owner */
  	MNT3ERR_NOENT		= 2,		/* No such file or directory */
  	MNT3ERR_IO		= 5,		/* I/O error */
  	MNT3ERR_ACCES		= 13,		/* Permission denied */
  	MNT3ERR_NOTDIR		= 20,		/* Not a directory */
  	MNT3ERR_INVAL		= 22,		/* Invalid argument */
  	MNT3ERR_NAMETOOLONG	= 63,		/* Filename too long */
  	MNT3ERR_NOTSUPP		= 10004,	/* Operation not supported */
  	MNT3ERR_SERVERFAULT	= 10006,	/* A failure on the server */
  };
  
  static struct {
  	u32 status;
  	int errno;
  } mnt3_errtbl[] = {
  	{ .status = MNT3_OK,			.errno = 0,		},
  	{ .status = MNT3ERR_PERM,		.errno = -EPERM,	},
  	{ .status = MNT3ERR_NOENT,		.errno = -ENOENT,	},
  	{ .status = MNT3ERR_IO,			.errno = -EIO,		},
  	{ .status = MNT3ERR_ACCES,		.errno = -EACCES,	},
  	{ .status = MNT3ERR_NOTDIR,		.errno = -ENOTDIR,	},
  	{ .status = MNT3ERR_INVAL,		.errno = -EINVAL,	},
  	{ .status = MNT3ERR_NAMETOOLONG,	.errno = -ENAMETOOLONG,	},
  	{ .status = MNT3ERR_NOTSUPP,		.errno = -ENOTSUPP,	},
fdcb45777   Trond Myklebust   NFS: Fix the mapp...
120
  	{ .status = MNT3ERR_SERVERFAULT,	.errno = -EREMOTEIO,	},
fb1252957   Chuck Lever   NFS: Add separate...
121
122
123
124
125
  };
  
  struct mountres {
  	int errno;
  	struct nfs_fh *fh;
a14017db2   Chuck Lever   NFS: add XDR deco...
126
127
  	unsigned int *auth_count;
  	rpc_authflavor_t *auth_flavors;
fb1252957   Chuck Lever   NFS: Add separate...
128
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  struct mnt_fhstatus {
19207231c   Chuck Lever   NFS: Clean up in-...
130
131
  	u32 status;
  	struct nfs_fh *fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  };
3ea97309e   Chuck Lever   NFS: Remake nfsro...
133
134
  /**
   * nfs_mount - Obtain an NFS file handle for the given host and path
c5d120f8e   Chuck Lever   NFS: introduce nf...
135
   * @info: pointer to mount request arguments
3ea97309e   Chuck Lever   NFS: Remake nfsro...
136
   *
fb9b02fda   Jeff Layton   nfs: have nfs_mou...
137
138
139
140
   * Uses default timeout parameters specified by underlying transport. On
   * successful return, the auth_flavs list and auth_flav_len will be populated
   * with the list from the server or a faked-up list if the server didn't
   * provide one.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
   */
c5d120f8e   Chuck Lever   NFS: introduce nf...
142
  int nfs_mount(struct nfs_mount_request *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  {
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
144
145
146
147
  	struct mountres	result = {
  		.fh		= info->fh,
  		.auth_count	= info->auth_flav_len,
  		.auth_flavors	= info->auth_flavs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
149
  	struct rpc_message msg	= {
c5d120f8e   Chuck Lever   NFS: introduce nf...
150
  		.rpc_argp	= info->dirpath,
dead28da8   Chuck Lever   SUNRPC: eliminate...
151
152
  		.rpc_resp	= &result,
  	};
3ea97309e   Chuck Lever   NFS: Remake nfsro...
153
  	struct rpc_create_args args = {
6d59b8d59   Stanislav Kinsbursky   NFS: pass NFS cli...
154
  		.net		= info->net,
c5d120f8e   Chuck Lever   NFS: introduce nf...
155
156
157
158
  		.protocol	= info->protocol,
  		.address	= info->sap,
  		.addrsize	= info->salen,
  		.servername	= info->hostname,
3ea97309e   Chuck Lever   NFS: Remake nfsro...
159
  		.program	= &mnt_program,
c5d120f8e   Chuck Lever   NFS: introduce nf...
160
  		.version	= info->version,
3ea97309e   Chuck Lever   NFS: Remake nfsro...
161
  		.authflavor	= RPC_AUTH_UNIX,
3ea97309e   Chuck Lever   NFS: Remake nfsro...
162
163
  	};
  	struct rpc_clnt		*mnt_clnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  	int			status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

3ea97309e   Chuck Lever   NFS: Remake nfsro...
166
167
  	dprintk("NFS: sending MNT request for %s:%s
  ",
c5d120f8e   Chuck Lever   NFS: introduce nf...
168
169
  		(info->hostname ? info->hostname : "server"),
  			info->dirpath);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

28d79ea33   Trond Myklebust   NFS: Remove the B...
171
172
  	if (strlen(info->dirpath) > MNTPATHLEN)
  		return -ENAMETOOLONG;
50a737f86   Chuck Lever   NFS: "[no]resvpor...
173
174
  	if (info->noresvport)
  		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
3ea97309e   Chuck Lever   NFS: Remake nfsro...
175
  	mnt_clnt = rpc_create(&args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	if (IS_ERR(mnt_clnt))
013a8c1ab   Chuck Lever   NFS: Improve debu...
177
  		goto out_clnt_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178

c5d120f8e   Chuck Lever   NFS: introduce nf...
179
  	if (info->version == NFS_MNT3_VERSION)
dead28da8   Chuck Lever   SUNRPC: eliminate...
180
181
  		msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
  	else
2ad780978   Chuck Lever   NFS: Clean up MNT...
182
  		msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
dead28da8   Chuck Lever   SUNRPC: eliminate...
183

acce94e68   Scott Mayhew   nfsv3: Make v3 mo...
184
  	status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
90c5755ff   Trond Myklebust   SUNRPC: Kill rpc_...
185
  	rpc_shutdown_client(mnt_clnt);
013a8c1ab   Chuck Lever   NFS: Improve debu...
186
187
188
  
  	if (status < 0)
  		goto out_call_err;
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
189
  	if (result.errno != 0)
013a8c1ab   Chuck Lever   NFS: Improve debu...
190
191
192
193
194
  		goto out_mnt_err;
  
  	dprintk("NFS: MNT request succeeded
  ");
  	status = 0;
fb9b02fda   Jeff Layton   nfs: have nfs_mou...
195
196
197
198
199
200
201
202
203
204
  	/*
  	 * If the server didn't provide a flavor list, allow the
  	 * client to try any flavor.
  	 */
  	if (info->version != NFS_MNT3_VERSION || *info->auth_flav_len == 0) {
  		dprintk("NFS: Faking up auth_flavs list
  ");
  		info->auth_flavs[0] = RPC_AUTH_NULL;
  		*info->auth_flav_len = 1;
  	}
013a8c1ab   Chuck Lever   NFS: Improve debu...
205
206
207
208
209
  out:
  	return status;
  
  out_clnt_err:
  	status = PTR_ERR(mnt_clnt);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
210
211
  	dprintk("NFS: failed to create MNT RPC client, status=%d
  ", status);
013a8c1ab   Chuck Lever   NFS: Improve debu...
212
213
214
  	goto out;
  
  out_call_err:
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
215
216
  	dprintk("NFS: MNT request failed, status=%d
  ", status);
013a8c1ab   Chuck Lever   NFS: Improve debu...
217
218
219
  	goto out;
  
  out_mnt_err:
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
220
221
222
  	dprintk("NFS: MNT server returned result %d
  ", result.errno);
  	status = result.errno;
013a8c1ab   Chuck Lever   NFS: Improve debu...
223
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  }
0b524123c   Chuck Lever   NFS: Add ability ...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  /**
   * nfs_umount - Notify a server that we have unmounted this export
   * @info: pointer to umount request arguments
   *
   * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always
   * use UDP.
   */
  void nfs_umount(const struct nfs_mount_request *info)
  {
  	static const struct rpc_timeout nfs_umnt_timeout = {
  		.to_initval = 1 * HZ,
  		.to_maxval = 3 * HZ,
  		.to_retries = 2,
  	};
  	struct rpc_create_args args = {
6d59b8d59   Stanislav Kinsbursky   NFS: pass NFS cli...
240
  		.net		= info->net,
0b524123c   Chuck Lever   NFS: Add ability ...
241
242
243
244
245
246
247
248
249
250
  		.protocol	= IPPROTO_UDP,
  		.address	= info->sap,
  		.addrsize	= info->salen,
  		.timeout	= &nfs_umnt_timeout,
  		.servername	= info->hostname,
  		.program	= &mnt_program,
  		.version	= info->version,
  		.authflavor	= RPC_AUTH_UNIX,
  		.flags		= RPC_CLNT_CREATE_NOPING,
  	};
0b524123c   Chuck Lever   NFS: Add ability ...
251
252
  	struct rpc_message msg	= {
  		.rpc_argp	= info->dirpath,
0b524123c   Chuck Lever   NFS: Add ability ...
253
254
255
  	};
  	struct rpc_clnt *clnt;
  	int status;
28d79ea33   Trond Myklebust   NFS: Remove the B...
256
257
  	if (strlen(info->dirpath) > MNTPATHLEN)
  		return;
0b524123c   Chuck Lever   NFS: Add ability ...
258
259
260
261
  	if (info->noresvport)
  		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
  
  	clnt = rpc_create(&args);
c8b031ebc   Tobias Klauser   NFS: Remove redun...
262
  	if (IS_ERR(clnt))
0b524123c   Chuck Lever   NFS: Add ability ...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  		goto out_clnt_err;
  
  	dprintk("NFS: sending UMNT request for %s:%s
  ",
  		(info->hostname ? info->hostname : "server"), info->dirpath);
  
  	if (info->version == NFS_MNT3_VERSION)
  		msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT];
  	else
  		msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT];
  
  	status = rpc_call_sync(clnt, &msg, 0);
  	rpc_shutdown_client(clnt);
  
  	if (unlikely(status < 0))
  		goto out_call_err;
  
  	return;
  
  out_clnt_err:
  	dprintk("NFS: failed to create UMNT RPC client, status=%ld
  ",
  			PTR_ERR(clnt));
  	return;
  
  out_call_err:
  	dprintk("NFS: UMNT request failed, status=%d
  ", status);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
  /*
   * XDR encode/decode functions for MOUNT
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

98eb2b4f9   Chuck Lever   NFS: Avoid return...
296
  static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname)
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
297
298
299
  {
  	const u32 pathname_len = strlen(pathname);
  	__be32 *p;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
300
  	p = xdr_reserve_space(xdr, 4 + pathname_len);
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
301
  	xdr_encode_opaque(p, pathname, pathname_len);
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
302
  }
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
303
304
  static void mnt_xdr_enc_dirpath(struct rpc_rqst *req, struct xdr_stream *xdr,
  				const char *dirpath)
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
305
  {
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
306
  	encode_mntdirpath(xdr, dirpath);
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
307
  }
fb1252957   Chuck Lever   NFS: Add separate...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  /*
   * RFC 1094: "A non-zero status indicates some sort of error.  In this
   * case, the status is a UNIX error number."  This can be problematic
   * if the server and client use different errno values for the same
   * error.
   *
   * However, the OpenGroup XNFS spec provides a simple mapping that is
   * independent of local errno values on the server and the client.
   */
  static int decode_status(struct xdr_stream *xdr, struct mountres *res)
  {
  	unsigned int i;
  	u32 status;
  	__be32 *p;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
322
  	p = xdr_inline_decode(xdr, 4);
fb1252957   Chuck Lever   NFS: Add separate...
323
324
  	if (unlikely(p == NULL))
  		return -EIO;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
325
  	status = be32_to_cpup(p);
fb1252957   Chuck Lever   NFS: Add separate...
326

dd8ac1da4   Roel Kluin   nfs: Keep index w...
327
  	for (i = 0; i < ARRAY_SIZE(mnt_errtbl); i++) {
fb1252957   Chuck Lever   NFS: Add separate...
328
329
330
331
332
333
334
335
336
337
338
  		if (mnt_errtbl[i].status == status) {
  			res->errno = mnt_errtbl[i].errno;
  			return 0;
  		}
  	}
  
  	dprintk("NFS: unrecognized MNT status code: %u
  ", status);
  	res->errno = -EACCES;
  	return 0;
  }
4fdcd9966   Chuck Lever   NFS: add new file...
339
340
341
342
343
344
345
346
347
348
349
350
351
  static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res)
  {
  	struct nfs_fh *fh = res->fh;
  	__be32 *p;
  
  	p = xdr_inline_decode(xdr, NFS2_FHSIZE);
  	if (unlikely(p == NULL))
  		return -EIO;
  
  	fh->size = NFS2_FHSIZE;
  	memcpy(fh->data, p, NFS2_FHSIZE);
  	return 0;
  }
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
352
353
354
  static int mnt_xdr_dec_mountres(struct rpc_rqst *req,
  				struct xdr_stream *xdr,
  				struct mountres *res)
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
355
  {
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
356
  	int status;
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
357
  	status = decode_status(xdr, res);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
358
359
  	if (unlikely(status != 0 || res->errno != 0))
  		return status;
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
360
  	return decode_fhandle(xdr, res);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
361
  }
fb1252957   Chuck Lever   NFS: Add separate...
362
363
364
365
366
  static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
  {
  	unsigned int i;
  	u32 status;
  	__be32 *p;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
367
  	p = xdr_inline_decode(xdr, 4);
fb1252957   Chuck Lever   NFS: Add separate...
368
369
  	if (unlikely(p == NULL))
  		return -EIO;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
370
  	status = be32_to_cpup(p);
fb1252957   Chuck Lever   NFS: Add separate...
371

dd8ac1da4   Roel Kluin   nfs: Keep index w...
372
  	for (i = 0; i < ARRAY_SIZE(mnt3_errtbl); i++) {
fb1252957   Chuck Lever   NFS: Add separate...
373
374
375
376
377
378
379
380
381
382
383
  		if (mnt3_errtbl[i].status == status) {
  			res->errno = mnt3_errtbl[i].errno;
  			return 0;
  		}
  	}
  
  	dprintk("NFS: unrecognized MNT3 status code: %u
  ", status);
  	res->errno = -EACCES;
  	return 0;
  }
4fdcd9966   Chuck Lever   NFS: add new file...
384
385
386
387
388
  static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res)
  {
  	struct nfs_fh *fh = res->fh;
  	u32 size;
  	__be32 *p;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
389
  	p = xdr_inline_decode(xdr, 4);
4fdcd9966   Chuck Lever   NFS: add new file...
390
391
  	if (unlikely(p == NULL))
  		return -EIO;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
392
  	size = be32_to_cpup(p);
4fdcd9966   Chuck Lever   NFS: add new file...
393
394
395
396
397
398
399
400
401
402
403
  	if (size > NFS3_FHSIZE || size == 0)
  		return -EIO;
  
  	p = xdr_inline_decode(xdr, size);
  	if (unlikely(p == NULL))
  		return -EIO;
  
  	fh->size = size;
  	memcpy(fh->data, p, size);
  	return 0;
  }
a14017db2   Chuck Lever   NFS: add XDR deco...
404
405
406
407
408
409
410
411
412
  static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
  {
  	rpc_authflavor_t *flavors = res->auth_flavors;
  	unsigned int *count = res->auth_count;
  	u32 entries, i;
  	__be32 *p;
  
  	if (*count == 0)
  		return 0;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
413
  	p = xdr_inline_decode(xdr, 4);
a14017db2   Chuck Lever   NFS: add XDR deco...
414
415
  	if (unlikely(p == NULL))
  		return -EIO;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
416
  	entries = be32_to_cpup(p);
a14017db2   Chuck Lever   NFS: add XDR deco...
417
418
419
420
  	dprintk("NFS: received %u auth flavors
  ", entries);
  	if (entries > NFS_MAX_SECFLAVORS)
  		entries = NFS_MAX_SECFLAVORS;
98eb2b4f9   Chuck Lever   NFS: Avoid return...
421
  	p = xdr_inline_decode(xdr, 4 * entries);
a14017db2   Chuck Lever   NFS: add XDR deco...
422
423
424
425
426
427
428
  	if (unlikely(p == NULL))
  		return -EIO;
  
  	if (entries > *count)
  		entries = *count;
  
  	for (i = 0; i < entries; i++) {
98eb2b4f9   Chuck Lever   NFS: Avoid return...
429
  		flavors[i] = be32_to_cpup(p++);
ed58b2917   Chuck Lever   NFS: Remove \t fr...
430
431
  		dprintk("NFS:   auth flavor[%u]: %d
  ", i, flavors[i]);
a14017db2   Chuck Lever   NFS: add XDR deco...
432
433
434
435
436
  	}
  	*count = i;
  
  	return 0;
  }
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
437
438
439
  static int mnt_xdr_dec_mountres3(struct rpc_rqst *req,
  				 struct xdr_stream *xdr,
  				 struct mountres *res)
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
440
  {
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
441
  	int status;
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
442
  	status = decode_fhs_status(xdr, res);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
443
444
  	if (unlikely(status != 0 || res->errno != 0))
  		return status;
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
445
  	status = decode_fhandle3(xdr, res);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
446
447
448
449
  	if (unlikely(status != 0)) {
  		res->errno = -EBADHANDLE;
  		return 0;
  	}
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
450
  	return decode_auth_flavors(xdr, res);
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
451
  }
19207231c   Chuck Lever   NFS: Clean up in-...
452
  static struct rpc_procinfo mnt_procedures[] = {
2ad780978   Chuck Lever   NFS: Clean up MNT...
453
454
  	[MOUNTPROC_MNT] = {
  		.p_proc		= MOUNTPROC_MNT,
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
455
  		.p_encode	= (kxdreproc_t)mnt_xdr_enc_dirpath,
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
456
  		.p_decode	= (kxdrdproc_t)mnt_xdr_dec_mountres,
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
457
  		.p_arglen	= MNT_enc_dirpath_sz,
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
458
  		.p_replen	= MNT_dec_mountres_sz,
2ad780978   Chuck Lever   NFS: Clean up MNT...
459
  		.p_statidx	= MOUNTPROC_MNT,
19207231c   Chuck Lever   NFS: Clean up in-...
460
  		.p_name		= "MOUNT",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  	},
0b524123c   Chuck Lever   NFS: Add ability ...
462
463
  	[MOUNTPROC_UMNT] = {
  		.p_proc		= MOUNTPROC_UMNT,
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
464
  		.p_encode	= (kxdreproc_t)mnt_xdr_enc_dirpath,
0b524123c   Chuck Lever   NFS: Add ability ...
465
466
467
468
  		.p_arglen	= MNT_enc_dirpath_sz,
  		.p_statidx	= MOUNTPROC_UMNT,
  		.p_name		= "UMOUNT",
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
  };
  
  static struct rpc_procinfo mnt3_procedures[] = {
19207231c   Chuck Lever   NFS: Clean up in-...
472
473
  	[MOUNTPROC3_MNT] = {
  		.p_proc		= MOUNTPROC3_MNT,
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
474
  		.p_encode	= (kxdreproc_t)mnt_xdr_enc_dirpath,
bf2695516   Chuck Lever   SUNRPC: New xdr_s...
475
  		.p_decode	= (kxdrdproc_t)mnt_xdr_dec_mountres3,
29a1bd6bf   Chuck Lever   NFS: Use xdr_stre...
476
  		.p_arglen	= MNT_enc_dirpath_sz,
8e02f6b9a   Chuck Lever   NFS: Update MNT a...
477
  		.p_replen	= MNT_dec_mountres3_sz,
19207231c   Chuck Lever   NFS: Clean up in-...
478
479
  		.p_statidx	= MOUNTPROC3_MNT,
  		.p_name		= "MOUNT",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  	},
0b524123c   Chuck Lever   NFS: Add ability ...
481
482
  	[MOUNTPROC3_UMNT] = {
  		.p_proc		= MOUNTPROC3_UMNT,
9f06c719f   Chuck Lever   SUNRPC: New xdr_s...
483
  		.p_encode	= (kxdreproc_t)mnt_xdr_enc_dirpath,
0b524123c   Chuck Lever   NFS: Add ability ...
484
485
486
487
  		.p_arglen	= MNT_enc_dirpath_sz,
  		.p_statidx	= MOUNTPROC3_UMNT,
  		.p_name		= "UMOUNT",
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  };
a613fa168   Trond Myklebust   SUNRPC: constify ...
489
  static const struct rpc_version mnt_version1 = {
19207231c   Chuck Lever   NFS: Clean up in-...
490
  	.number		= 1,
5b362ac37   Chuck Lever   NFS: Fix panic af...
491
  	.nrprocs	= ARRAY_SIZE(mnt_procedures),
19207231c   Chuck Lever   NFS: Clean up in-...
492
  	.procs		= mnt_procedures,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  };
a613fa168   Trond Myklebust   SUNRPC: constify ...
494
  static const struct rpc_version mnt_version3 = {
19207231c   Chuck Lever   NFS: Clean up in-...
495
  	.number		= 3,
5b362ac37   Chuck Lever   NFS: Fix panic af...
496
  	.nrprocs	= ARRAY_SIZE(mnt3_procedures),
19207231c   Chuck Lever   NFS: Clean up in-...
497
  	.procs		= mnt3_procedures,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  };
a613fa168   Trond Myklebust   SUNRPC: constify ...
499
  static const struct rpc_version *mnt_version[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
504
  	NULL,
  	&mnt_version1,
  	NULL,
  	&mnt_version3,
  };
19207231c   Chuck Lever   NFS: Clean up in-...
505
  static struct rpc_stat mnt_stats;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506

a613fa168   Trond Myklebust   SUNRPC: constify ...
507
  static const struct rpc_program mnt_program = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
  	.name		= "mount",
  	.number		= NFS_MNT_PROGRAM,
e8c96f8c2   Tobias Klauser   [PATCH] fs: Use A...
510
  	.nrvers		= ARRAY_SIZE(mnt_version),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
  	.version	= mnt_version,
  	.stats		= &mnt_stats,
  };