Blame view

fs/nfsd/nfsproc.c 22.2 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
   * Process version 2 NFS requests.
   *
   * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8

9a74af213   Boaz Harrosh   nfsd: Move privat...
9
10
  #include "cache.h"
  #include "xdr.h"
0a3adadee   J. Bruce Fields   nfsd: make fs/nfs...
11
  #include "vfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #define NFSDDBG_FACILITY		NFSDDBG_PROC
7111c66e4   Al Viro   [PATCH] fix svc_p...
14
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
15
  nfsd_proc_null(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
17
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
  }
  
  /*
   * Get a file's attributes
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
24
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
25
  nfsd_proc_getattr(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
27
28
  	struct nfsd_fhandle *argp = rqstp->rq_argp;
  	struct nfsd_attrstat *resp = rqstp->rq_resp;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
29

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
  	dprintk("nfsd: GETATTR  %s
  ", SVCFH_fmt(&argp->fh));
  
  	fh_copy(&resp->fh, &argp->fh);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
34
35
36
37
38
39
  	resp->status = fh_verify(rqstp, &resp->fh, 0,
  				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  	if (resp->status != nfs_ok)
  		goto out;
  	resp->status = fh_getattr(&resp->fh, &resp->stat);
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
40
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
  }
  
  /*
   * Set a file's attributes
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
47
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
48
  nfsd_proc_setattr(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
50
51
  	struct nfsd_sattrargs *argp = rqstp->rq_argp;
  	struct nfsd_attrstat *resp = rqstp->rq_resp;
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
52
53
  	struct iattr *iap = &argp->attrs;
  	struct svc_fh *fhp;
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
54

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
  	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld
  ",
  		SVCFH_fmt(&argp->fh),
  		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
59
60
61
62
63
64
65
  	fhp = fh_copy(&resp->fh, &argp->fh);
  
  	/*
  	 * NFSv2 does not differentiate between "set-[ac]time-to-now"
  	 * which only requires access, and "set-[ac]time-to-X" which
  	 * requires ownership.
  	 * So if it looks like it might be "set both to the same time which
31051c85b   Jan Kara   fs: Give dentry t...
66
  	 * is close to now", and if setattr_prepare fails, then we
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
67
68
  	 * convert to "set to now" instead of "set to explicit time"
  	 *
31051c85b   Jan Kara   fs: Give dentry t...
69
  	 * We only call setattr_prepare as the last test as technically
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
70
71
72
73
74
75
76
77
78
79
80
81
82
  	 * it is not an interface that we should be using.
  	 */
  #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
  #define	MAX_TOUCH_TIME_ERROR (30*60)
  	if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
  	    iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) {
  		/*
  		 * Looks probable.
  		 *
  		 * Now just make sure time is in the right ballpark.
  		 * Solaris, at least, doesn't seem to care what the time
  		 * request is.  We require it be within 30 minutes of now.
  		 */
b6356d420   Arnd Bergmann   nfsd: use time64_...
83
  		time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
84

f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
85
86
  		resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
  		if (resp->status != nfs_ok)
cc028a10a   Chuck Lever   NFSD: Hoist statu...
87
  			goto out;
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
88
89
90
91
  
  		if (delta < 0)
  			delta = -delta;
  		if (delta < MAX_TOUCH_TIME_ERROR &&
31051c85b   Jan Kara   fs: Give dentry t...
92
  		    setattr_prepare(fhp->fh_dentry, iap) != 0) {
cc265089c   Andreas Gruenbacher   nfsd: Disable NFS...
93
94
95
96
97
98
99
100
  			/*
  			 * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
  			 * This will cause notify_change to set these times
  			 * to "now"
  			 */
  			iap->ia_valid &= ~BOTH_TIME_SET;
  		}
  	}
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
101
102
103
104
105
106
  	resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
  	if (resp->status != nfs_ok)
  		goto out;
  
  	resp->status = fh_getattr(&resp->fh, &resp->stat);
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
107
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  }
6b3dccd48   Chuck Lever   NFSD: Add missing...
109
110
111
112
  /* Obsolete, replaced by MNTPROC_MNT. */
  static __be32
  nfsd_proc_root(struct svc_rqst *rqstp)
  {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
113
  	return rpc_success;
6b3dccd48   Chuck Lever   NFSD: Add missing...
114
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
  /*
   * Look up a path name component
   * Note: the dentry in the resp->fh may be negative if the file
   * doesn't exist yet.
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
121
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
122
  nfsd_proc_lookup(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
124
125
  	struct nfsd_diropargs *argp = rqstp->rq_argp;
  	struct nfsd_diropres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
  
  	dprintk("nfsd: LOOKUP   %s %.*s
  ",
  		SVCFH_fmt(&argp->fh), argp->len, argp->name);
  
  	fh_init(&resp->fh, NFS_FHSIZE);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
132
133
  	resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
  				   &resp->fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  	fh_put(&argp->fh);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
135
136
137
138
139
  	if (resp->status != nfs_ok)
  		goto out;
  
  	resp->status = fh_getattr(&resp->fh, &resp->stat);
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
140
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
  }
  
  /*
   * Read a symlink.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
146
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
147
  nfsd_proc_readlink(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
149
150
  	struct nfsd_readlinkargs *argp = rqstp->rq_argp;
  	struct nfsd_readlinkres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
  
  	dprintk("nfsd: READLINK %s
  ", SVCFH_fmt(&argp->fh));
  
  	/* Read the symlink. */
  	resp->len = NFS_MAXPATHLEN;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
157
  	resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  
  	fh_put(&argp->fh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
160
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
  }
  
  /*
   * Read a portion of a file.
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
167
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
168
  nfsd_proc_read(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
170
171
  	struct nfsd_readargs *argp = rqstp->rq_argp;
  	struct nfsd_readres *resp = rqstp->rq_resp;
83a63072c   Trond Myklebust   nfsd: fix nfs rea...
172
  	u32 eof;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
178
179
180
181
  
  	dprintk("nfsd: READ    %s %d bytes at %d
  ",
  		SVCFH_fmt(&argp->fh),
  		argp->count, argp->offset);
  
  	/* Obtain buffer pointer for payload. 19 is 1 word for
  	 * status, 17 words for fattr, and 1 word for the byte count.
  	 */
7adae489f   Greg Banks   [PATCH] knfsd: Pr...
182
  	if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
ad06e4bd6   Chuck Lever   [PATCH] knfsd: SU...
183
  		char buf[RPC_MAX_ADDRBUFLEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  		printk(KERN_NOTICE
ad06e4bd6   Chuck Lever   [PATCH] knfsd: SU...
185
186
187
  			"oversized read request from %s (%d bytes)
  ",
  				svc_print_addr(rqstp, buf, sizeof(buf)),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  				argp->count);
7adae489f   Greg Banks   [PATCH] knfsd: Pr...
189
  		argp->count = NFSSVC_MAXBLKSIZE_V2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  	}
cd123012d   Jeff Layton   RPC: add wrapper ...
191
  	svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
  
  	resp->count = argp->count;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
194
195
196
197
198
  	resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
  				 argp->offset,
  				 rqstp->rq_vec, argp->vlen,
  				 &resp->count,
  				 &eof);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
199
200
201
202
203
  	if (resp->status == nfs_ok)
  		resp->status = fh_getattr(&resp->fh, &resp->stat);
  	else if (resp->status == nfserr_jukebox)
  		return rpc_drop_reply;
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  }
6b3dccd48   Chuck Lever   NFSD: Add missing...
205
206
207
208
  /* Reserved */
  static __be32
  nfsd_proc_writecache(struct svc_rqst *rqstp)
  {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
209
  	return rpc_success;
6b3dccd48   Chuck Lever   NFSD: Add missing...
210
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
  /*
   * Write data to a file
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
215
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
216
  nfsd_proc_write(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
218
219
  	struct nfsd_writeargs *argp = rqstp->rq_argp;
  	struct nfsd_attrstat *resp = rqstp->rq_resp;
31dec2538   David Shaw   Short write in nf...
220
  	unsigned long cnt = argp->len;
8154ef277   Chuck Lever   NFSD: Clean up le...
221
  	unsigned int nvecs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
  
  	dprintk("nfsd: WRITE    %s %d bytes at %d
  ",
  		SVCFH_fmt(&argp->fh),
  		argp->len, argp->offset);
3fd9557ae   Chuck Lever   NFSD: Refactor th...
227
228
  	nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
  				      &argp->first, cnt);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
229
230
231
232
233
234
235
236
  	if (!nvecs) {
  		resp->status = nfserr_io;
  		goto out;
  	}
  
  	resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
  				  argp->offset, rqstp->rq_vec, nvecs,
  				  &cnt, NFS_DATA_SYNC, NULL);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
237
238
239
240
  	if (resp->status == nfs_ok)
  		resp->status = fh_getattr(&resp->fh, &resp->stat);
  	else if (resp->status == nfserr_jukebox)
  		return rpc_drop_reply;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
241
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
242
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
249
250
  }
  
  /*
   * CREATE processing is complicated. The keyword here is `overloaded.'
   * The parent directory is kept locked between the check for existence
   * and the actual create() call in compliance with VFS protocols.
   * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
251
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
252
  nfsd_proc_create(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
254
255
  	struct nfsd_createargs *argp = rqstp->rq_argp;
  	struct nfsd_diropres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
260
  	svc_fh		*dirfhp = &argp->fh;
  	svc_fh		*newfhp = &resp->fh;
  	struct iattr	*attr = &argp->attrs;
  	struct inode	*inode;
  	struct dentry	*dchild;
c4d987ba8   Al Viro   [PATCH] nfsd: NFS...
261
  	int		type, mode;
4a55c1017   Jan Kara   nfsd: Push mnt_wa...
262
  	int		hosterr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
266
267
268
269
  	dev_t		rdev = 0, wanted = new_decode_dev(attr->ia_size);
  
  	dprintk("nfsd: CREATE   %s %.*s
  ",
  		SVCFH_fmt(dirfhp), argp->len, argp->name);
  
  	/* First verify the parent file handle */
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
270
271
  	resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
  	if (resp->status != nfs_ok)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  		goto done; /* must fh_put dirfhp even on error */
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
273
  	/* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274

f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
275
  	resp->status = nfserr_exist;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
  	if (isdotent(argp->name, argp->len))
  		goto done;
4a55c1017   Jan Kara   nfsd: Push mnt_wa...
278
279
  	hosterr = fh_want_write(dirfhp);
  	if (hosterr) {
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
280
  		resp->status = nfserrno(hosterr);
4a55c1017   Jan Kara   nfsd: Push mnt_wa...
281
282
  		goto done;
  	}
7ed94296a   NeilBrown   [PATCH] knfsd: nf...
283
  	fh_lock_nested(dirfhp, I_MUTEX_PARENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
  	dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
  	if (IS_ERR(dchild)) {
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
286
  		resp->status = nfserrno(PTR_ERR(dchild));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
  		goto out_unlock;
  	}
  	fh_init(newfhp, NFS_FHSIZE);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
290
291
292
  	resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
  	if (!resp->status && d_really_is_negative(dchild))
  		resp->status = nfserr_noent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  	dput(dchild);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
294
295
  	if (resp->status) {
  		if (resp->status != nfserr_noent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  			goto out_unlock;
  		/*
  		 * If the new file handle wasn't verified, we can't tell
  		 * whether the file exists or not. Time to bail ...
  		 */
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
301
  		resp->status = nfserr_acces;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
307
308
  		if (!newfhp->fh_dentry) {
  			printk(KERN_WARNING 
  				"nfsd_proc_create: file handle not verified
  ");
  			goto out_unlock;
  		}
  	}
2b0143b5c   David Howells   VFS: normal files...
309
  	inode = d_inode(newfhp->fh_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  
  	/* Unfudge the mode bits */
  	if (attr->ia_valid & ATTR_MODE) {
  		type = attr->ia_mode & S_IFMT;
  		mode = attr->ia_mode & ~S_IFMT;
  		if (!type) {
  			/* no type, so if target exists, assume same as that,
  			 * else assume a file */
  			if (inode) {
  				type = inode->i_mode & S_IFMT;
  				switch(type) {
  				case S_IFCHR:
  				case S_IFBLK:
  					/* reserve rdev for later checking */
  					rdev = inode->i_rdev;
  					attr->ia_valid |= ATTR_SIZE;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
326
  					fallthrough;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
  				case S_IFIFO:
  					/* this is probably a permission check..
  					 * at least IRIX implements perm checking on
  					 *   echo thing > device-special-file-or-pipe
  					 * by doing a CREATE with type==0
  					 */
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
333
  					resp->status = nfsd_permission(rqstp,
0ec757df9   J. Bruce Fields   knfsd: nfsd4: mak...
334
  								 newfhp->fh_export,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  								 newfhp->fh_dentry,
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
336
  								 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
337
  					if (resp->status && resp->status != nfserr_rofs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  						goto out_unlock;
  				}
  			} else
  				type = S_IFREG;
  		}
  	} else if (inode) {
  		type = inode->i_mode & S_IFMT;
  		mode = inode->i_mode & ~S_IFMT;
  	} else {
  		type = S_IFREG;
  		mode = 0;	/* ??? */
  	}
  
  	attr->ia_valid |= ATTR_MODE;
  	attr->ia_mode = mode;
  
  	/* Special treatment for non-regular files according to the
  	 * gospel of sun micro
  	 */
  	if (type != S_IFREG) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
360
361
362
363
364
  		if (type != S_IFBLK && type != S_IFCHR) {
  			rdev = 0;
  		} else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
  			/* If you think you've seen the worst, grok this. */
  			type = S_IFIFO;
  		} else {
  			/* Okay, char or block special */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
369
370
371
372
  			if (!rdev)
  				rdev = wanted;
  		}
  
  		/* we've used the SIZE information, so discard it */
  		attr->ia_valid &= ~ATTR_SIZE;
  
  		/* Make sure the type and device matches */
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
373
  		resp->status = nfserr_exist;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
  		if (inode && type != (inode->i_mode & S_IFMT))
  			goto out_unlock;
  	}
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
377
  	resp->status = nfs_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
  	if (!inode) {
  		/* File doesn't exist. Create it and set attrs */
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
380
381
382
  		resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
  						  argp->len, attr, type, rdev,
  						  newfhp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
389
390
391
392
  	} else if (type == S_IFREG) {
  		dprintk("nfsd:   existing %s, valid=%x, size=%ld
  ",
  			argp->name, attr->ia_valid, (long) attr->ia_size);
  		/* File already exists. We ignore all attributes except
  		 * size, so that creat() behaves exactly like
  		 * open(..., O_CREAT|O_TRUNC|O_WRONLY).
  		 */
  		attr->ia_valid &= ATTR_SIZE;
  		if (attr->ia_valid)
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
393
394
  			resp->status = nfsd_setattr(rqstp, newfhp, attr, 0,
  						    (time64_t)0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
398
399
  	}
  
  out_unlock:
  	/* We don't really need to unlock, as fh_put does it. */
  	fh_unlock(dirfhp);
4a55c1017   Jan Kara   nfsd: Push mnt_wa...
400
  	fh_drop_write(dirfhp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
  done:
  	fh_put(dirfhp);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
403
404
405
406
  	if (resp->status != nfs_ok)
  		goto out;
  	resp->status = fh_getattr(&resp->fh, &resp->stat);
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
407
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  }
7111c66e4   Al Viro   [PATCH] fix svc_p...
409
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
410
  nfsd_proc_remove(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
412
  	struct nfsd_diropargs *argp = rqstp->rq_argp;
cc028a10a   Chuck Lever   NFSD: Hoist statu...
413
  	struct nfsd_stat *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
418
419
  
  	dprintk("nfsd: REMOVE   %s %.*s
  ", SVCFH_fmt(&argp->fh),
  		argp->len, argp->name);
  
  	/* Unlink. -SIFDIR means file must not be a directory */
cc028a10a   Chuck Lever   NFSD: Hoist statu...
420
421
  	resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR,
  				   argp->name, argp->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  	fh_put(&argp->fh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
423
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  }
7111c66e4   Al Viro   [PATCH] fix svc_p...
425
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
426
  nfsd_proc_rename(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
428
  	struct nfsd_renameargs *argp = rqstp->rq_argp;
cc028a10a   Chuck Lever   NFSD: Hoist statu...
429
  	struct nfsd_stat *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
435
436
  
  	dprintk("nfsd: RENAME   %s %.*s -> 
  ",
  		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
  	dprintk("nfsd:        ->  %s %.*s
  ",
  		SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
437
438
  	resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
  				   &argp->tfh, argp->tname, argp->tlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  	fh_put(&argp->ffh);
  	fh_put(&argp->tfh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
441
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  }
7111c66e4   Al Viro   [PATCH] fix svc_p...
443
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
444
  nfsd_proc_link(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
446
  	struct nfsd_linkargs *argp = rqstp->rq_argp;
cc028a10a   Chuck Lever   NFSD: Hoist statu...
447
  	struct nfsd_stat *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
455
456
  
  	dprintk("nfsd: LINK     %s ->
  ",
  		SVCFH_fmt(&argp->ffh));
  	dprintk("nfsd:    %s %.*s
  ",
  		SVCFH_fmt(&argp->tfh),
  		argp->tlen,
  		argp->tname);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
457
458
  	resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
  				 &argp->ffh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
  	fh_put(&argp->ffh);
  	fh_put(&argp->tfh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
461
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  }
7111c66e4   Al Viro   [PATCH] fix svc_p...
463
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
464
  nfsd_proc_symlink(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
466
  	struct nfsd_symlinkargs *argp = rqstp->rq_argp;
cc028a10a   Chuck Lever   NFSD: Hoist statu...
467
  	struct nfsd_stat *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  	struct svc_fh	newfh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469

f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
470
  	if (argp->tlen > NFS_MAXPATHLEN) {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
471
  		resp->status = nfserr_nametoolong;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
472
473
  		goto out;
  	}
38a703155   Chuck Lever   NFSD: Clean up le...
474
475
  
  	argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
11b4d66ea   Chuck Lever   NFSD: Handle full...
476
  						page_address(rqstp->rq_arg.pages[0]),
38a703155   Chuck Lever   NFSD: Clean up le...
477
  						argp->tlen);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
478
  	if (IS_ERR(argp->tname)) {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
479
  		resp->status = nfserrno(PTR_ERR(argp->tname));
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
480
481
  		goto out;
  	}
38a703155   Chuck Lever   NFSD: Clean up le...
482

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
487
488
  	dprintk("nfsd: SYMLINK  %s %.*s -> %.*s
  ",
  		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
  		argp->tlen, argp->tname);
  
  	fh_init(&newfh, NFS_FHSIZE);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
489
490
  	resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
  				    argp->tname, &newfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491

11b4d66ea   Chuck Lever   NFSD: Handle full...
492
  	kfree(argp->tname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
  	fh_put(&argp->ffh);
  	fh_put(&newfh);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
495
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
496
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
500
501
502
  }
  
  /*
   * Make directory. This operation is not idempotent.
   * N.B. After this call resp->fh needs an fh_put
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
503
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
504
  nfsd_proc_mkdir(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
506
507
  	struct nfsd_createargs *argp = rqstp->rq_argp;
  	struct nfsd_diropres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
512
513
514
515
516
517
518
519
  
  	dprintk("nfsd: MKDIR    %s %.*s
  ", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  
  	if (resp->fh.fh_dentry) {
  		printk(KERN_WARNING
  			"nfsd_proc_mkdir: response already verified??
  ");
  	}
  
  	argp->attrs.ia_valid &= ~ATTR_SIZE;
  	fh_init(&resp->fh, NFS_FHSIZE);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
520
521
  	resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
  				   &argp->attrs, S_IFDIR, 0, &resp->fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  	fh_put(&argp->fh);
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
523
524
525
526
527
  	if (resp->status != nfs_ok)
  		goto out;
  
  	resp->status = fh_getattr(&resp->fh, &resp->stat);
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
528
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
  }
  
  /*
   * Remove a directory
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
534
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
535
  nfsd_proc_rmdir(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
537
  	struct nfsd_diropargs *argp = rqstp->rq_argp;
cc028a10a   Chuck Lever   NFSD: Hoist statu...
538
  	struct nfsd_stat *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
  
  	dprintk("nfsd: RMDIR    %s %.*s
  ", SVCFH_fmt(&argp->fh), argp->len, argp->name);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
542
543
  	resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR,
  				   argp->name, argp->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  	fh_put(&argp->fh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
545
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
550
  }
  
  /*
   * Read a portion of a directory.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
551
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
552
  nfsd_proc_readdir(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
554
555
  	struct nfsd_readdirargs *argp = rqstp->rq_argp;
  	struct nfsd_readdirres *resp = rqstp->rq_resp;
c4d987ba8   Al Viro   [PATCH] nfsd: NFS...
556
  	int		count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  	loff_t		offset;
  
  	dprintk("nfsd: READDIR  %s %d bytes at %d
  ",
  		SVCFH_fmt(&argp->fh),		
  		argp->count, argp->cookie);
  
  	/* Shrink to the client read size */
  	count = (argp->count >> 2) - 2;
  
  	/* Make sure we've room for the NULL ptr & eof flag */
  	count -= 2;
  	if (count < 0)
  		count = 0;
  
  	resp->buffer = argp->buffer;
  	resp->offset = NULL;
  	resp->buflen = count;
  	resp->common.err = nfs_ok;
  	/* Read directory and encode entries on the fly */
  	offset = argp->cookie;
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
578
579
  	resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
  				    &resp->common, nfssvc_encode_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
  
  	resp->count = resp->buffer - argp->buffer;
  	if (resp->offset)
  		*resp->offset = htonl(offset);
  
  	fh_put(&argp->fh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
586
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
590
591
  }
  
  /*
   * Get file system info
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
592
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
593
  nfsd_proc_statfs(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
595
596
  	struct nfsd_fhandle *argp = rqstp->rq_argp;
  	struct nfsd_statfsres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
  
  	dprintk("nfsd: STATFS   %s
  ", SVCFH_fmt(&argp->fh));
f0af22101   Chuck Lever   NFSD: Call NFSv2 ...
600
601
  	resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
  				   NFSD_MAY_BYPASS_GSS_ON_ROOT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  	fh_put(&argp->fh);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
603
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
607
608
609
  }
  
  /*
   * NFSv2 Server procedures.
   * Only the results of non-idempotent operations are cached.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
  struct nfsd_void { int dummy; };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
613
  #define ST 1		/* status */
  #define FH 8		/* filehandle */
  #define	AT 18		/* attributes */
860bda29b   Christoph Hellwig   sunrpc: mark all ...
614
  static const struct svc_procedure nfsd_procedures2[18] = {
b9081d90f   Yu Zhiguo   NFS: kill off com...
615
  	[NFSPROC_NULL] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
616
  		.pc_func = nfsd_proc_null,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
617
  		.pc_decode = nfssvc_decode_void,
63f8de379   Christoph Hellwig   sunrpc: properly ...
618
  		.pc_encode = nfssvc_encode_void,
b9081d90f   Yu Zhiguo   NFS: kill off com...
619
620
621
  		.pc_argsize = sizeof(struct nfsd_void),
  		.pc_ressize = sizeof(struct nfsd_void),
  		.pc_cachetype = RC_NOCACHE,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
622
  		.pc_xdrressize = 0,
b9081d90f   Yu Zhiguo   NFS: kill off com...
623
624
  	},
  	[NFSPROC_GETATTR] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
625
  		.pc_func = nfsd_proc_getattr,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
626
  		.pc_decode = nfssvc_decode_fhandle,
63f8de379   Christoph Hellwig   sunrpc: properly ...
627
  		.pc_encode = nfssvc_encode_attrstat,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
628
  		.pc_release = nfssvc_release_attrstat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
629
630
631
632
633
634
  		.pc_argsize = sizeof(struct nfsd_fhandle),
  		.pc_ressize = sizeof(struct nfsd_attrstat),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = ST+AT,
  	},
  	[NFSPROC_SETATTR] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
635
  		.pc_func = nfsd_proc_setattr,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
636
  		.pc_decode = nfssvc_decode_sattrargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
637
  		.pc_encode = nfssvc_encode_attrstat,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
638
  		.pc_release = nfssvc_release_attrstat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
639
640
641
642
643
644
  		.pc_argsize = sizeof(struct nfsd_sattrargs),
  		.pc_ressize = sizeof(struct nfsd_attrstat),
  		.pc_cachetype = RC_REPLBUFF,
  		.pc_xdrressize = ST+AT,
  	},
  	[NFSPROC_ROOT] = {
6b3dccd48   Chuck Lever   NFSD: Add missing...
645
  		.pc_func = nfsd_proc_root,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
646
  		.pc_decode = nfssvc_decode_void,
63f8de379   Christoph Hellwig   sunrpc: properly ...
647
  		.pc_encode = nfssvc_encode_void,
b9081d90f   Yu Zhiguo   NFS: kill off com...
648
649
650
  		.pc_argsize = sizeof(struct nfsd_void),
  		.pc_ressize = sizeof(struct nfsd_void),
  		.pc_cachetype = RC_NOCACHE,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
651
  		.pc_xdrressize = 0,
b9081d90f   Yu Zhiguo   NFS: kill off com...
652
653
  	},
  	[NFSPROC_LOOKUP] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
654
  		.pc_func = nfsd_proc_lookup,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
655
  		.pc_decode = nfssvc_decode_diropargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
656
  		.pc_encode = nfssvc_encode_diropres,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
657
  		.pc_release = nfssvc_release_diropres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
658
659
660
661
662
663
  		.pc_argsize = sizeof(struct nfsd_diropargs),
  		.pc_ressize = sizeof(struct nfsd_diropres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = ST+FH+AT,
  	},
  	[NFSPROC_READLINK] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
664
  		.pc_func = nfsd_proc_readlink,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
665
  		.pc_decode = nfssvc_decode_readlinkargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
666
  		.pc_encode = nfssvc_encode_readlinkres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
667
668
669
670
671
672
  		.pc_argsize = sizeof(struct nfsd_readlinkargs),
  		.pc_ressize = sizeof(struct nfsd_readlinkres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = ST+1+NFS_MAXPATHLEN/4,
  	},
  	[NFSPROC_READ] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
673
  		.pc_func = nfsd_proc_read,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
674
  		.pc_decode = nfssvc_decode_readargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
675
  		.pc_encode = nfssvc_encode_readres,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
676
  		.pc_release = nfssvc_release_readres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
677
678
679
680
681
682
  		.pc_argsize = sizeof(struct nfsd_readargs),
  		.pc_ressize = sizeof(struct nfsd_readres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
  	},
  	[NFSPROC_WRITECACHE] = {
6b3dccd48   Chuck Lever   NFSD: Add missing...
683
  		.pc_func = nfsd_proc_writecache,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
684
  		.pc_decode = nfssvc_decode_void,
63f8de379   Christoph Hellwig   sunrpc: properly ...
685
  		.pc_encode = nfssvc_encode_void,
b9081d90f   Yu Zhiguo   NFS: kill off com...
686
687
688
  		.pc_argsize = sizeof(struct nfsd_void),
  		.pc_ressize = sizeof(struct nfsd_void),
  		.pc_cachetype = RC_NOCACHE,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
689
  		.pc_xdrressize = 0,
b9081d90f   Yu Zhiguo   NFS: kill off com...
690
691
  	},
  	[NFSPROC_WRITE] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
692
  		.pc_func = nfsd_proc_write,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
693
  		.pc_decode = nfssvc_decode_writeargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
694
  		.pc_encode = nfssvc_encode_attrstat,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
695
  		.pc_release = nfssvc_release_attrstat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
696
697
698
699
700
701
  		.pc_argsize = sizeof(struct nfsd_writeargs),
  		.pc_ressize = sizeof(struct nfsd_attrstat),
  		.pc_cachetype = RC_REPLBUFF,
  		.pc_xdrressize = ST+AT,
  	},
  	[NFSPROC_CREATE] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
702
  		.pc_func = nfsd_proc_create,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
703
  		.pc_decode = nfssvc_decode_createargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
704
  		.pc_encode = nfssvc_encode_diropres,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
705
  		.pc_release = nfssvc_release_diropres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
706
707
708
709
710
711
  		.pc_argsize = sizeof(struct nfsd_createargs),
  		.pc_ressize = sizeof(struct nfsd_diropres),
  		.pc_cachetype = RC_REPLBUFF,
  		.pc_xdrressize = ST+FH+AT,
  	},
  	[NFSPROC_REMOVE] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
712
  		.pc_func = nfsd_proc_remove,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
713
  		.pc_decode = nfssvc_decode_diropargs,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
714
  		.pc_encode = nfssvc_encode_stat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
715
  		.pc_argsize = sizeof(struct nfsd_diropargs),
cc028a10a   Chuck Lever   NFSD: Hoist statu...
716
  		.pc_ressize = sizeof(struct nfsd_stat),
b9081d90f   Yu Zhiguo   NFS: kill off com...
717
718
719
720
  		.pc_cachetype = RC_REPLSTAT,
  		.pc_xdrressize = ST,
  	},
  	[NFSPROC_RENAME] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
721
  		.pc_func = nfsd_proc_rename,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
722
  		.pc_decode = nfssvc_decode_renameargs,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
723
  		.pc_encode = nfssvc_encode_stat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
724
  		.pc_argsize = sizeof(struct nfsd_renameargs),
cc028a10a   Chuck Lever   NFSD: Hoist statu...
725
  		.pc_ressize = sizeof(struct nfsd_stat),
b9081d90f   Yu Zhiguo   NFS: kill off com...
726
727
728
729
  		.pc_cachetype = RC_REPLSTAT,
  		.pc_xdrressize = ST,
  	},
  	[NFSPROC_LINK] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
730
  		.pc_func = nfsd_proc_link,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
731
  		.pc_decode = nfssvc_decode_linkargs,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
732
  		.pc_encode = nfssvc_encode_stat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
733
  		.pc_argsize = sizeof(struct nfsd_linkargs),
cc028a10a   Chuck Lever   NFSD: Hoist statu...
734
  		.pc_ressize = sizeof(struct nfsd_stat),
b9081d90f   Yu Zhiguo   NFS: kill off com...
735
736
737
738
  		.pc_cachetype = RC_REPLSTAT,
  		.pc_xdrressize = ST,
  	},
  	[NFSPROC_SYMLINK] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
739
  		.pc_func = nfsd_proc_symlink,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
740
  		.pc_decode = nfssvc_decode_symlinkargs,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
741
  		.pc_encode = nfssvc_encode_stat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
742
  		.pc_argsize = sizeof(struct nfsd_symlinkargs),
cc028a10a   Chuck Lever   NFSD: Hoist statu...
743
  		.pc_ressize = sizeof(struct nfsd_stat),
b9081d90f   Yu Zhiguo   NFS: kill off com...
744
745
746
747
  		.pc_cachetype = RC_REPLSTAT,
  		.pc_xdrressize = ST,
  	},
  	[NFSPROC_MKDIR] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
748
  		.pc_func = nfsd_proc_mkdir,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
749
  		.pc_decode = nfssvc_decode_createargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
750
  		.pc_encode = nfssvc_encode_diropres,
1841b9b61   Chuck Lever   NFSD: Fix .pc_rel...
751
  		.pc_release = nfssvc_release_diropres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
752
753
754
755
756
757
  		.pc_argsize = sizeof(struct nfsd_createargs),
  		.pc_ressize = sizeof(struct nfsd_diropres),
  		.pc_cachetype = RC_REPLBUFF,
  		.pc_xdrressize = ST+FH+AT,
  	},
  	[NFSPROC_RMDIR] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
758
  		.pc_func = nfsd_proc_rmdir,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
759
  		.pc_decode = nfssvc_decode_diropargs,
cc028a10a   Chuck Lever   NFSD: Hoist statu...
760
  		.pc_encode = nfssvc_encode_stat,
b9081d90f   Yu Zhiguo   NFS: kill off com...
761
  		.pc_argsize = sizeof(struct nfsd_diropargs),
cc028a10a   Chuck Lever   NFSD: Hoist statu...
762
  		.pc_ressize = sizeof(struct nfsd_stat),
b9081d90f   Yu Zhiguo   NFS: kill off com...
763
764
765
766
  		.pc_cachetype = RC_REPLSTAT,
  		.pc_xdrressize = ST,
  	},
  	[NFSPROC_READDIR] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
767
  		.pc_func = nfsd_proc_readdir,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
768
  		.pc_decode = nfssvc_decode_readdirargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
769
  		.pc_encode = nfssvc_encode_readdirres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
770
771
772
773
774
  		.pc_argsize = sizeof(struct nfsd_readdirargs),
  		.pc_ressize = sizeof(struct nfsd_readdirres),
  		.pc_cachetype = RC_NOCACHE,
  	},
  	[NFSPROC_STATFS] = {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
775
  		.pc_func = nfsd_proc_statfs,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
776
  		.pc_decode = nfssvc_decode_fhandle,
63f8de379   Christoph Hellwig   sunrpc: properly ...
777
  		.pc_encode = nfssvc_encode_statfsres,
b9081d90f   Yu Zhiguo   NFS: kill off com...
778
779
780
781
782
  		.pc_argsize = sizeof(struct nfsd_fhandle),
  		.pc_ressize = sizeof(struct nfsd_statfsres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = ST+5,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
  };
7fd38af9c   Christoph Hellwig   sunrpc: move pc_c...
784
  static unsigned int nfsd_count2[ARRAY_SIZE(nfsd_procedures2)];
e9679189e   Christoph Hellwig   sunrpc: mark all ...
785
786
787
788
789
790
791
  const struct svc_version nfsd_version2 = {
  	.vs_vers	= 2,
  	.vs_nproc	= 18,
  	.vs_proc	= nfsd_procedures2,
  	.vs_count	= nfsd_count2,
  	.vs_dispatch	= nfsd_dispatch,
  	.vs_xdrsize	= NFS2_SVC_XDRSIZE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
795
796
  };
  
  /*
   * Map errnos to NFS errnos.
   */
63f103111   Al Viro   [PATCH] nfsd: nfs...
797
  __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
799
800
  nfserrno (int errno)
  {
  	static struct {
63f103111   Al Viro   [PATCH] nfsd: nfs...
801
  		__be32	nfserr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
806
807
808
  		int	syserr;
  	} nfs_errtbl[] = {
  		{ nfs_ok, 0 },
  		{ nfserr_perm, -EPERM },
  		{ nfserr_noent, -ENOENT },
  		{ nfserr_io, -EIO },
  		{ nfserr_nxio, -ENXIO },
62814d6a9   Jeff Layton   nfsd: add a nfser...
809
  		{ nfserr_fbig, -E2BIG },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  		{ nfserr_acces, -EACCES },
  		{ nfserr_exist, -EEXIST },
  		{ nfserr_xdev, -EXDEV },
  		{ nfserr_mlink, -EMLINK },
  		{ nfserr_nodev, -ENODEV },
  		{ nfserr_notdir, -ENOTDIR },
  		{ nfserr_isdir, -EISDIR },
  		{ nfserr_inval, -EINVAL },
  		{ nfserr_fbig, -EFBIG },
  		{ nfserr_nospc, -ENOSPC },
  		{ nfserr_rofs, -EROFS },
  		{ nfserr_mlink, -EMLINK },
  		{ nfserr_nametoolong, -ENAMETOOLONG },
  		{ nfserr_notempty, -ENOTEMPTY },
  #ifdef EDQUOT
  		{ nfserr_dquot, -EDQUOT },
  #endif
  		{ nfserr_stale, -ESTALE },
  		{ nfserr_jukebox, -ETIMEDOUT },
599eb3046   NeilBrown   knfsd: nfsd: Hand...
829
  		{ nfserr_jukebox, -ERESTARTSYS },
062304a81   J. Bruce Fields   nfsd: stop transl...
830
831
  		{ nfserr_jukebox, -EAGAIN },
  		{ nfserr_jukebox, -EWOULDBLOCK },
3beb6cd1d   J. Bruce Fields   nfsd: don't drop ...
832
  		{ nfserr_jukebox, -ENOMEM },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  		{ nfserr_io, -ETXTBSY },
a838cc49d   Andreas Gruenbacher   [PATCH] NFSD: Add...
834
  		{ nfserr_notsupp, -EOPNOTSUPP },
b7aeda40d   Dean Hildebrand   nfsd: add etoosma...
835
  		{ nfserr_toosmall, -ETOOSMALL },
f39bde24b   J. Bruce Fields   nfsd4: fix error ...
836
  		{ nfserr_serverfault, -ESERVERFAULT },
b3fbfe0e7   Jeff Layton   nfsd: print statu...
837
  		{ nfserr_serverfault, -ENFILE },
42e616167   J. Bruce Fields   nfsd: handle EUCLEAN
838
  		{ nfserr_io, -EUCLEAN },
c952cd4e9   Kinglong Mee   nfsd: map the ENO...
839
  		{ nfserr_perm, -ENOKEY },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
  	};
  	int	i;
63f103111   Al Viro   [PATCH] nfsd: nfs...
842
  	for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
  		if (nfs_errtbl[i].syserr == errno)
  			return nfs_errtbl[i].nfserr;
  	}
ff30f08c3   J. Bruce Fields   nfsd: only WARN o...
846
847
  	WARN_ONCE(1, "nfsd: non-standard errno: %d
  ", errno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
849
  	return nfserr_io;
  }