xref: /linux/fs/nfsd/nfs3proc.c (revision 1e525507)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Process version 3 NFS requests.
4  *
5  * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
6  */
7 
8 #include <linux/fs.h>
9 #include <linux/ext2_fs.h>
10 #include <linux/magic.h>
11 #include <linux/namei.h>
12 
13 #include "cache.h"
14 #include "xdr3.h"
15 #include "vfs.h"
16 #include "filecache.h"
17 
18 #define NFSDDBG_FACILITY		NFSDDBG_PROC
19 
20 static int	nfs3_ftypes[] = {
21 	0,			/* NF3NON */
22 	S_IFREG,		/* NF3REG */
23 	S_IFDIR,		/* NF3DIR */
24 	S_IFBLK,		/* NF3BLK */
25 	S_IFCHR,		/* NF3CHR */
26 	S_IFLNK,		/* NF3LNK */
27 	S_IFSOCK,		/* NF3SOCK */
28 	S_IFIFO,		/* NF3FIFO */
29 };
30 
31 /*
32  * NULL call.
33  */
34 static __be32
35 nfsd3_proc_null(struct svc_rqst *rqstp)
36 {
37 	return rpc_success;
38 }
39 
40 /*
41  * Get a file's attributes
42  */
43 static __be32
44 nfsd3_proc_getattr(struct svc_rqst *rqstp)
45 {
46 	struct nfsd_fhandle *argp = rqstp->rq_argp;
47 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
48 
49 	dprintk("nfsd: GETATTR(3)  %s\n",
50 		SVCFH_fmt(&argp->fh));
51 
52 	fh_copy(&resp->fh, &argp->fh);
53 	resp->status = fh_verify(rqstp, &resp->fh, 0,
54 				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
55 	if (resp->status != nfs_ok)
56 		goto out;
57 
58 	resp->status = fh_getattr(&resp->fh, &resp->stat);
59 out:
60 	return rpc_success;
61 }
62 
63 /*
64  * Set a file's attributes
65  */
66 static __be32
67 nfsd3_proc_setattr(struct svc_rqst *rqstp)
68 {
69 	struct nfsd3_sattrargs *argp = rqstp->rq_argp;
70 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
71 	struct nfsd_attrs attrs = {
72 		.na_iattr	= &argp->attrs,
73 	};
74 	const struct timespec64 *guardtime = NULL;
75 
76 	dprintk("nfsd: SETATTR(3)  %s\n",
77 				SVCFH_fmt(&argp->fh));
78 
79 	fh_copy(&resp->fh, &argp->fh);
80 	if (argp->check_guard)
81 		guardtime = &argp->guardtime;
82 	resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs, guardtime);
83 	return rpc_success;
84 }
85 
86 /*
87  * Look up a path name component
88  */
89 static __be32
90 nfsd3_proc_lookup(struct svc_rqst *rqstp)
91 {
92 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
93 	struct nfsd3_diropres  *resp = rqstp->rq_resp;
94 
95 	dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
96 				SVCFH_fmt(&argp->fh),
97 				argp->len,
98 				argp->name);
99 
100 	fh_copy(&resp->dirfh, &argp->fh);
101 	fh_init(&resp->fh, NFS3_FHSIZE);
102 
103 	resp->status = nfsd_lookup(rqstp, &resp->dirfh,
104 				   argp->name, argp->len,
105 				   &resp->fh);
106 	return rpc_success;
107 }
108 
109 /*
110  * Check file access
111  */
112 static __be32
113 nfsd3_proc_access(struct svc_rqst *rqstp)
114 {
115 	struct nfsd3_accessargs *argp = rqstp->rq_argp;
116 	struct nfsd3_accessres *resp = rqstp->rq_resp;
117 
118 	dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
119 				SVCFH_fmt(&argp->fh),
120 				argp->access);
121 
122 	fh_copy(&resp->fh, &argp->fh);
123 	resp->access = argp->access;
124 	resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
125 	return rpc_success;
126 }
127 
128 /*
129  * Read a symlink.
130  */
131 static __be32
132 nfsd3_proc_readlink(struct svc_rqst *rqstp)
133 {
134 	struct nfsd_fhandle *argp = rqstp->rq_argp;
135 	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
136 
137 	dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
138 
139 	/* Read the symlink. */
140 	fh_copy(&resp->fh, &argp->fh);
141 	resp->len = NFS3_MAXPATHLEN;
142 	resp->pages = rqstp->rq_next_page++;
143 	resp->status = nfsd_readlink(rqstp, &resp->fh,
144 				     page_address(*resp->pages), &resp->len);
145 	return rpc_success;
146 }
147 
148 /*
149  * Read a portion of a file.
150  */
151 static __be32
152 nfsd3_proc_read(struct svc_rqst *rqstp)
153 {
154 	struct nfsd3_readargs *argp = rqstp->rq_argp;
155 	struct nfsd3_readres *resp = rqstp->rq_resp;
156 
157 	dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
158 				SVCFH_fmt(&argp->fh),
159 				(unsigned long) argp->count,
160 				(unsigned long long) argp->offset);
161 
162 	argp->count = min_t(u32, argp->count, svc_max_payload(rqstp));
163 	argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
164 	if (argp->offset > (u64)OFFSET_MAX)
165 		argp->offset = (u64)OFFSET_MAX;
166 	if (argp->offset + argp->count > (u64)OFFSET_MAX)
167 		argp->count = (u64)OFFSET_MAX - argp->offset;
168 
169 	resp->pages = rqstp->rq_next_page;
170 
171 	/* Obtain buffer pointer for payload.
172 	 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
173 	 * + 1 (xdr opaque byte count) = 26
174 	 */
175 	resp->count = argp->count;
176 	svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3) << 2) +
177 			 resp->count + 4);
178 
179 	fh_copy(&resp->fh, &argp->fh);
180 	resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
181 				 &resp->count, &resp->eof);
182 	return rpc_success;
183 }
184 
185 /*
186  * Write data to a file
187  */
188 static __be32
189 nfsd3_proc_write(struct svc_rqst *rqstp)
190 {
191 	struct nfsd3_writeargs *argp = rqstp->rq_argp;
192 	struct nfsd3_writeres *resp = rqstp->rq_resp;
193 	unsigned long cnt = argp->len;
194 	unsigned int nvecs;
195 
196 	dprintk("nfsd: WRITE(3)    %s %d bytes at %Lu%s\n",
197 				SVCFH_fmt(&argp->fh),
198 				argp->len,
199 				(unsigned long long) argp->offset,
200 				argp->stable ? " stable" : "");
201 
202 	resp->status = nfserr_fbig;
203 	if (argp->offset > (u64)OFFSET_MAX ||
204 	    argp->offset + argp->len > (u64)OFFSET_MAX)
205 		return rpc_success;
206 
207 	fh_copy(&resp->fh, &argp->fh);
208 	resp->committed = argp->stable;
209 	nvecs = svc_fill_write_vector(rqstp, &argp->payload);
210 
211 	resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
212 				  rqstp->rq_vec, nvecs, &cnt,
213 				  resp->committed, resp->verf);
214 	resp->count = cnt;
215 	return rpc_success;
216 }
217 
218 /*
219  * Implement NFSv3's unchecked, guarded, and exclusive CREATE
220  * semantics for regular files. Except for the created file,
221  * this operation is stateless on the server.
222  *
223  * Upon return, caller must release @fhp and @resfhp.
224  */
225 static __be32
226 nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
227 		  struct svc_fh *resfhp, struct nfsd3_createargs *argp)
228 {
229 	struct iattr *iap = &argp->attrs;
230 	struct dentry *parent, *child;
231 	struct nfsd_attrs attrs = {
232 		.na_iattr	= iap,
233 	};
234 	__u32 v_mtime, v_atime;
235 	struct inode *inode;
236 	__be32 status;
237 	int host_err;
238 
239 	if (isdotent(argp->name, argp->len))
240 		return nfserr_exist;
241 	if (!(iap->ia_valid & ATTR_MODE))
242 		iap->ia_mode = 0;
243 
244 	status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
245 	if (status != nfs_ok)
246 		return status;
247 
248 	parent = fhp->fh_dentry;
249 	inode = d_inode(parent);
250 
251 	host_err = fh_want_write(fhp);
252 	if (host_err)
253 		return nfserrno(host_err);
254 
255 	inode_lock_nested(inode, I_MUTEX_PARENT);
256 
257 	child = lookup_one_len(argp->name, parent, argp->len);
258 	if (IS_ERR(child)) {
259 		status = nfserrno(PTR_ERR(child));
260 		goto out;
261 	}
262 
263 	if (d_really_is_negative(child)) {
264 		status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
265 		if (status != nfs_ok)
266 			goto out;
267 	}
268 
269 	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
270 	if (status != nfs_ok)
271 		goto out;
272 
273 	v_mtime = 0;
274 	v_atime = 0;
275 	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
276 		u32 *verifier = (u32 *)argp->verf;
277 
278 		/*
279 		 * Solaris 7 gets confused (bugid 4218508) if these have
280 		 * the high bit set, as do xfs filesystems without the
281 		 * "bigtime" feature. So just clear the high bits.
282 		 */
283 		v_mtime = verifier[0] & 0x7fffffff;
284 		v_atime = verifier[1] & 0x7fffffff;
285 	}
286 
287 	if (d_really_is_positive(child)) {
288 		status = nfs_ok;
289 
290 		switch (argp->createmode) {
291 		case NFS3_CREATE_UNCHECKED:
292 			if (!d_is_reg(child))
293 				break;
294 			iap->ia_valid &= ATTR_SIZE;
295 			goto set_attr;
296 		case NFS3_CREATE_GUARDED:
297 			status = nfserr_exist;
298 			break;
299 		case NFS3_CREATE_EXCLUSIVE:
300 			if (inode_get_mtime_sec(d_inode(child)) == v_mtime &&
301 			    inode_get_atime_sec(d_inode(child)) == v_atime &&
302 			    d_inode(child)->i_size == 0) {
303 				break;
304 			}
305 			status = nfserr_exist;
306 		}
307 		goto out;
308 	}
309 
310 	if (!IS_POSIXACL(inode))
311 		iap->ia_mode &= ~current_umask();
312 
313 	status = fh_fill_pre_attrs(fhp);
314 	if (status != nfs_ok)
315 		goto out;
316 	host_err = vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true);
317 	if (host_err < 0) {
318 		status = nfserrno(host_err);
319 		goto out;
320 	}
321 	fh_fill_post_attrs(fhp);
322 
323 	/* A newly created file already has a file size of zero. */
324 	if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
325 		iap->ia_valid &= ~ATTR_SIZE;
326 	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
327 		iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
328 				ATTR_MTIME_SET | ATTR_ATIME_SET;
329 		iap->ia_mtime.tv_sec = v_mtime;
330 		iap->ia_atime.tv_sec = v_atime;
331 		iap->ia_mtime.tv_nsec = 0;
332 		iap->ia_atime.tv_nsec = 0;
333 	}
334 
335 set_attr:
336 	status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
337 
338 out:
339 	inode_unlock(inode);
340 	if (child && !IS_ERR(child))
341 		dput(child);
342 	fh_drop_write(fhp);
343 	return status;
344 }
345 
346 static __be32
347 nfsd3_proc_create(struct svc_rqst *rqstp)
348 {
349 	struct nfsd3_createargs *argp = rqstp->rq_argp;
350 	struct nfsd3_diropres *resp = rqstp->rq_resp;
351 	svc_fh *dirfhp, *newfhp;
352 
353 	dprintk("nfsd: CREATE(3)   %s %.*s\n",
354 				SVCFH_fmt(&argp->fh),
355 				argp->len,
356 				argp->name);
357 
358 	dirfhp = fh_copy(&resp->dirfh, &argp->fh);
359 	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
360 
361 	resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
362 	return rpc_success;
363 }
364 
365 /*
366  * Make directory. This operation is not idempotent.
367  */
368 static __be32
369 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
370 {
371 	struct nfsd3_createargs *argp = rqstp->rq_argp;
372 	struct nfsd3_diropres *resp = rqstp->rq_resp;
373 	struct nfsd_attrs attrs = {
374 		.na_iattr	= &argp->attrs,
375 	};
376 
377 	dprintk("nfsd: MKDIR(3)    %s %.*s\n",
378 				SVCFH_fmt(&argp->fh),
379 				argp->len,
380 				argp->name);
381 
382 	argp->attrs.ia_valid &= ~ATTR_SIZE;
383 	fh_copy(&resp->dirfh, &argp->fh);
384 	fh_init(&resp->fh, NFS3_FHSIZE);
385 	resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
386 				   &attrs, S_IFDIR, 0, &resp->fh);
387 	return rpc_success;
388 }
389 
390 static __be32
391 nfsd3_proc_symlink(struct svc_rqst *rqstp)
392 {
393 	struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
394 	struct nfsd3_diropres *resp = rqstp->rq_resp;
395 	struct nfsd_attrs attrs = {
396 		.na_iattr	= &argp->attrs,
397 	};
398 
399 	if (argp->tlen == 0) {
400 		resp->status = nfserr_inval;
401 		goto out;
402 	}
403 	if (argp->tlen > NFS3_MAXPATHLEN) {
404 		resp->status = nfserr_nametoolong;
405 		goto out;
406 	}
407 
408 	argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
409 						page_address(rqstp->rq_arg.pages[0]),
410 						argp->tlen);
411 	if (IS_ERR(argp->tname)) {
412 		resp->status = nfserrno(PTR_ERR(argp->tname));
413 		goto out;
414 	}
415 
416 	dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
417 				SVCFH_fmt(&argp->ffh),
418 				argp->flen, argp->fname,
419 				argp->tlen, argp->tname);
420 
421 	fh_copy(&resp->dirfh, &argp->ffh);
422 	fh_init(&resp->fh, NFS3_FHSIZE);
423 	resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
424 				    argp->flen, argp->tname, &attrs, &resp->fh);
425 	kfree(argp->tname);
426 out:
427 	return rpc_success;
428 }
429 
430 /*
431  * Make socket/fifo/device.
432  */
433 static __be32
434 nfsd3_proc_mknod(struct svc_rqst *rqstp)
435 {
436 	struct nfsd3_mknodargs *argp = rqstp->rq_argp;
437 	struct nfsd3_diropres  *resp = rqstp->rq_resp;
438 	struct nfsd_attrs attrs = {
439 		.na_iattr	= &argp->attrs,
440 	};
441 	int type;
442 	dev_t	rdev = 0;
443 
444 	dprintk("nfsd: MKNOD(3)    %s %.*s\n",
445 				SVCFH_fmt(&argp->fh),
446 				argp->len,
447 				argp->name);
448 
449 	fh_copy(&resp->dirfh, &argp->fh);
450 	fh_init(&resp->fh, NFS3_FHSIZE);
451 
452 	if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
453 		rdev = MKDEV(argp->major, argp->minor);
454 		if (MAJOR(rdev) != argp->major ||
455 		    MINOR(rdev) != argp->minor) {
456 			resp->status = nfserr_inval;
457 			goto out;
458 		}
459 	} else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
460 		resp->status = nfserr_badtype;
461 		goto out;
462 	}
463 
464 	type = nfs3_ftypes[argp->ftype];
465 	resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
466 				   &attrs, type, rdev, &resp->fh);
467 out:
468 	return rpc_success;
469 }
470 
471 /*
472  * Remove file/fifo/socket etc.
473  */
474 static __be32
475 nfsd3_proc_remove(struct svc_rqst *rqstp)
476 {
477 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
478 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
479 
480 	dprintk("nfsd: REMOVE(3)   %s %.*s\n",
481 				SVCFH_fmt(&argp->fh),
482 				argp->len,
483 				argp->name);
484 
485 	/* Unlink. -S_IFDIR means file must not be a directory */
486 	fh_copy(&resp->fh, &argp->fh);
487 	resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
488 				   argp->name, argp->len);
489 	return rpc_success;
490 }
491 
492 /*
493  * Remove a directory
494  */
495 static __be32
496 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
497 {
498 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
499 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
500 
501 	dprintk("nfsd: RMDIR(3)    %s %.*s\n",
502 				SVCFH_fmt(&argp->fh),
503 				argp->len,
504 				argp->name);
505 
506 	fh_copy(&resp->fh, &argp->fh);
507 	resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
508 				   argp->name, argp->len);
509 	return rpc_success;
510 }
511 
512 static __be32
513 nfsd3_proc_rename(struct svc_rqst *rqstp)
514 {
515 	struct nfsd3_renameargs *argp = rqstp->rq_argp;
516 	struct nfsd3_renameres *resp = rqstp->rq_resp;
517 
518 	dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
519 				SVCFH_fmt(&argp->ffh),
520 				argp->flen,
521 				argp->fname);
522 	dprintk("nfsd: -> %s %.*s\n",
523 				SVCFH_fmt(&argp->tfh),
524 				argp->tlen,
525 				argp->tname);
526 
527 	fh_copy(&resp->ffh, &argp->ffh);
528 	fh_copy(&resp->tfh, &argp->tfh);
529 	resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
530 				   &resp->tfh, argp->tname, argp->tlen);
531 	return rpc_success;
532 }
533 
534 static __be32
535 nfsd3_proc_link(struct svc_rqst *rqstp)
536 {
537 	struct nfsd3_linkargs *argp = rqstp->rq_argp;
538 	struct nfsd3_linkres  *resp = rqstp->rq_resp;
539 
540 	dprintk("nfsd: LINK(3)     %s ->\n",
541 				SVCFH_fmt(&argp->ffh));
542 	dprintk("nfsd:   -> %s %.*s\n",
543 				SVCFH_fmt(&argp->tfh),
544 				argp->tlen,
545 				argp->tname);
546 
547 	fh_copy(&resp->fh,  &argp->ffh);
548 	fh_copy(&resp->tfh, &argp->tfh);
549 	resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
550 				 &resp->fh);
551 	return rpc_success;
552 }
553 
554 static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
555 				     struct nfsd3_readdirres *resp,
556 				     u32 count)
557 {
558 	struct xdr_buf *buf = &resp->dirlist;
559 	struct xdr_stream *xdr = &resp->xdr;
560 	unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen,
561 				     svc_max_payload(rqstp));
562 
563 	memset(buf, 0, sizeof(*buf));
564 
565 	/* Reserve room for the NULL ptr & eof flag (-2 words) */
566 	buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), sendbuf);
567 	buf->buflen -= XDR_UNIT * 2;
568 	buf->pages = rqstp->rq_next_page;
569 	rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
570 
571 	xdr_init_encode_pages(xdr, buf, buf->pages,  NULL);
572 }
573 
574 /*
575  * Read a portion of a directory.
576  */
577 static __be32
578 nfsd3_proc_readdir(struct svc_rqst *rqstp)
579 {
580 	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
581 	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
582 	loff_t		offset;
583 
584 	dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
585 				SVCFH_fmt(&argp->fh),
586 				argp->count, (u32) argp->cookie);
587 
588 	nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
589 
590 	fh_copy(&resp->fh, &argp->fh);
591 	resp->common.err = nfs_ok;
592 	resp->cookie_offset = 0;
593 	resp->rqstp = rqstp;
594 	offset = argp->cookie;
595 	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
596 				    &resp->common, nfs3svc_encode_entry3);
597 	memcpy(resp->verf, argp->verf, 8);
598 	nfs3svc_encode_cookie3(resp, offset);
599 
600 	/* Recycle only pages that were part of the reply */
601 	rqstp->rq_next_page = resp->xdr.page_ptr + 1;
602 
603 	return rpc_success;
604 }
605 
606 /*
607  * Read a portion of a directory, including file handles and attrs.
608  * For now, we choose to ignore the dircount parameter.
609  */
610 static __be32
611 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
612 {
613 	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
614 	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
615 	loff_t	offset;
616 
617 	dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
618 				SVCFH_fmt(&argp->fh),
619 				argp->count, (u32) argp->cookie);
620 
621 	nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
622 
623 	fh_copy(&resp->fh, &argp->fh);
624 	resp->common.err = nfs_ok;
625 	resp->cookie_offset = 0;
626 	resp->rqstp = rqstp;
627 	offset = argp->cookie;
628 
629 	resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
630 	if (resp->status != nfs_ok)
631 		goto out;
632 
633 	if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
634 		resp->status = nfserr_notsupp;
635 		goto out;
636 	}
637 
638 	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
639 				    &resp->common, nfs3svc_encode_entryplus3);
640 	memcpy(resp->verf, argp->verf, 8);
641 	nfs3svc_encode_cookie3(resp, offset);
642 
643 	/* Recycle only pages that were part of the reply */
644 	rqstp->rq_next_page = resp->xdr.page_ptr + 1;
645 
646 out:
647 	return rpc_success;
648 }
649 
650 /*
651  * Get file system stats
652  */
653 static __be32
654 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
655 {
656 	struct nfsd_fhandle *argp = rqstp->rq_argp;
657 	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
658 
659 	dprintk("nfsd: FSSTAT(3)   %s\n",
660 				SVCFH_fmt(&argp->fh));
661 
662 	resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
663 	fh_put(&argp->fh);
664 	return rpc_success;
665 }
666 
667 /*
668  * Get file system info
669  */
670 static __be32
671 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
672 {
673 	struct nfsd_fhandle *argp = rqstp->rq_argp;
674 	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
675 	u32	max_blocksize = svc_max_payload(rqstp);
676 
677 	dprintk("nfsd: FSINFO(3)   %s\n",
678 				SVCFH_fmt(&argp->fh));
679 
680 	resp->f_rtmax  = max_blocksize;
681 	resp->f_rtpref = max_blocksize;
682 	resp->f_rtmult = PAGE_SIZE;
683 	resp->f_wtmax  = max_blocksize;
684 	resp->f_wtpref = max_blocksize;
685 	resp->f_wtmult = PAGE_SIZE;
686 	resp->f_dtpref = max_blocksize;
687 	resp->f_maxfilesize = ~(u32) 0;
688 	resp->f_properties = NFS3_FSF_DEFAULT;
689 
690 	resp->status = fh_verify(rqstp, &argp->fh, 0,
691 				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
692 
693 	/* Check special features of the file system. May request
694 	 * different read/write sizes for file systems known to have
695 	 * problems with large blocks */
696 	if (resp->status == nfs_ok) {
697 		struct super_block *sb = argp->fh.fh_dentry->d_sb;
698 
699 		/* Note that we don't care for remote fs's here */
700 		if (sb->s_magic == MSDOS_SUPER_MAGIC) {
701 			resp->f_properties = NFS3_FSF_BILLYBOY;
702 		}
703 		resp->f_maxfilesize = sb->s_maxbytes;
704 	}
705 
706 	fh_put(&argp->fh);
707 	return rpc_success;
708 }
709 
710 /*
711  * Get pathconf info for the specified file
712  */
713 static __be32
714 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
715 {
716 	struct nfsd_fhandle *argp = rqstp->rq_argp;
717 	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
718 
719 	dprintk("nfsd: PATHCONF(3) %s\n",
720 				SVCFH_fmt(&argp->fh));
721 
722 	/* Set default pathconf */
723 	resp->p_link_max = 255;		/* at least */
724 	resp->p_name_max = 255;		/* at least */
725 	resp->p_no_trunc = 0;
726 	resp->p_chown_restricted = 1;
727 	resp->p_case_insensitive = 0;
728 	resp->p_case_preserving = 1;
729 
730 	resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
731 
732 	if (resp->status == nfs_ok) {
733 		struct super_block *sb = argp->fh.fh_dentry->d_sb;
734 
735 		/* Note that we don't care for remote fs's here */
736 		switch (sb->s_magic) {
737 		case EXT2_SUPER_MAGIC:
738 			resp->p_link_max = EXT2_LINK_MAX;
739 			resp->p_name_max = EXT2_NAME_LEN;
740 			break;
741 		case MSDOS_SUPER_MAGIC:
742 			resp->p_case_insensitive = 1;
743 			resp->p_case_preserving  = 0;
744 			break;
745 		}
746 	}
747 
748 	fh_put(&argp->fh);
749 	return rpc_success;
750 }
751 
752 /*
753  * Commit a file (range) to stable storage.
754  */
755 static __be32
756 nfsd3_proc_commit(struct svc_rqst *rqstp)
757 {
758 	struct nfsd3_commitargs *argp = rqstp->rq_argp;
759 	struct nfsd3_commitres *resp = rqstp->rq_resp;
760 	struct nfsd_file *nf;
761 
762 	dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
763 				SVCFH_fmt(&argp->fh),
764 				argp->count,
765 				(unsigned long long) argp->offset);
766 
767 	fh_copy(&resp->fh, &argp->fh);
768 	resp->status = nfsd_file_acquire_gc(rqstp, &resp->fh, NFSD_MAY_WRITE |
769 					    NFSD_MAY_NOT_BREAK_LEASE, &nf);
770 	if (resp->status)
771 		goto out;
772 	resp->status = nfsd_commit(rqstp, &resp->fh, nf, argp->offset,
773 				   argp->count, resp->verf);
774 	nfsd_file_put(nf);
775 out:
776 	return rpc_success;
777 }
778 
779 
780 /*
781  * NFSv3 Server procedures.
782  * Only the results of non-idempotent operations are cached.
783  */
784 #define nfs3svc_encode_attrstatres	nfs3svc_encode_attrstat
785 #define nfs3svc_encode_wccstatres	nfs3svc_encode_wccstat
786 #define nfsd3_mkdirargs			nfsd3_createargs
787 #define nfsd3_readdirplusargs		nfsd3_readdirargs
788 #define nfsd3_fhandleargs		nfsd_fhandle
789 #define nfsd3_attrstatres		nfsd3_attrstat
790 #define nfsd3_wccstatres		nfsd3_attrstat
791 #define nfsd3_createres			nfsd3_diropres
792 
793 #define ST 1		/* status*/
794 #define FH 17		/* filehandle with length */
795 #define AT 21		/* attributes */
796 #define pAT (1+AT)	/* post attributes - conditional */
797 #define WC (7+pAT)	/* WCC attributes */
798 
799 static const struct svc_procedure nfsd_procedures3[22] = {
800 	[NFS3PROC_NULL] = {
801 		.pc_func = nfsd3_proc_null,
802 		.pc_decode = nfssvc_decode_voidarg,
803 		.pc_encode = nfssvc_encode_voidres,
804 		.pc_argsize = sizeof(struct nfsd_voidargs),
805 		.pc_argzero = sizeof(struct nfsd_voidargs),
806 		.pc_ressize = sizeof(struct nfsd_voidres),
807 		.pc_cachetype = RC_NOCACHE,
808 		.pc_xdrressize = ST,
809 		.pc_name = "NULL",
810 	},
811 	[NFS3PROC_GETATTR] = {
812 		.pc_func = nfsd3_proc_getattr,
813 		.pc_decode = nfs3svc_decode_fhandleargs,
814 		.pc_encode = nfs3svc_encode_getattrres,
815 		.pc_release = nfs3svc_release_fhandle,
816 		.pc_argsize = sizeof(struct nfsd_fhandle),
817 		.pc_argzero = sizeof(struct nfsd_fhandle),
818 		.pc_ressize = sizeof(struct nfsd3_attrstatres),
819 		.pc_cachetype = RC_NOCACHE,
820 		.pc_xdrressize = ST+AT,
821 		.pc_name = "GETATTR",
822 	},
823 	[NFS3PROC_SETATTR] = {
824 		.pc_func = nfsd3_proc_setattr,
825 		.pc_decode = nfs3svc_decode_sattrargs,
826 		.pc_encode = nfs3svc_encode_wccstatres,
827 		.pc_release = nfs3svc_release_fhandle,
828 		.pc_argsize = sizeof(struct nfsd3_sattrargs),
829 		.pc_argzero = sizeof(struct nfsd3_sattrargs),
830 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
831 		.pc_cachetype = RC_REPLBUFF,
832 		.pc_xdrressize = ST+WC,
833 		.pc_name = "SETATTR",
834 	},
835 	[NFS3PROC_LOOKUP] = {
836 		.pc_func = nfsd3_proc_lookup,
837 		.pc_decode = nfs3svc_decode_diropargs,
838 		.pc_encode = nfs3svc_encode_lookupres,
839 		.pc_release = nfs3svc_release_fhandle2,
840 		.pc_argsize = sizeof(struct nfsd3_diropargs),
841 		.pc_argzero = sizeof(struct nfsd3_diropargs),
842 		.pc_ressize = sizeof(struct nfsd3_diropres),
843 		.pc_cachetype = RC_NOCACHE,
844 		.pc_xdrressize = ST+FH+pAT+pAT,
845 		.pc_name = "LOOKUP",
846 	},
847 	[NFS3PROC_ACCESS] = {
848 		.pc_func = nfsd3_proc_access,
849 		.pc_decode = nfs3svc_decode_accessargs,
850 		.pc_encode = nfs3svc_encode_accessres,
851 		.pc_release = nfs3svc_release_fhandle,
852 		.pc_argsize = sizeof(struct nfsd3_accessargs),
853 		.pc_argzero = sizeof(struct nfsd3_accessargs),
854 		.pc_ressize = sizeof(struct nfsd3_accessres),
855 		.pc_cachetype = RC_NOCACHE,
856 		.pc_xdrressize = ST+pAT+1,
857 		.pc_name = "ACCESS",
858 	},
859 	[NFS3PROC_READLINK] = {
860 		.pc_func = nfsd3_proc_readlink,
861 		.pc_decode = nfs3svc_decode_fhandleargs,
862 		.pc_encode = nfs3svc_encode_readlinkres,
863 		.pc_release = nfs3svc_release_fhandle,
864 		.pc_argsize = sizeof(struct nfsd_fhandle),
865 		.pc_argzero = sizeof(struct nfsd_fhandle),
866 		.pc_ressize = sizeof(struct nfsd3_readlinkres),
867 		.pc_cachetype = RC_NOCACHE,
868 		.pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
869 		.pc_name = "READLINK",
870 	},
871 	[NFS3PROC_READ] = {
872 		.pc_func = nfsd3_proc_read,
873 		.pc_decode = nfs3svc_decode_readargs,
874 		.pc_encode = nfs3svc_encode_readres,
875 		.pc_release = nfs3svc_release_fhandle,
876 		.pc_argsize = sizeof(struct nfsd3_readargs),
877 		.pc_argzero = sizeof(struct nfsd3_readargs),
878 		.pc_ressize = sizeof(struct nfsd3_readres),
879 		.pc_cachetype = RC_NOCACHE,
880 		.pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
881 		.pc_name = "READ",
882 	},
883 	[NFS3PROC_WRITE] = {
884 		.pc_func = nfsd3_proc_write,
885 		.pc_decode = nfs3svc_decode_writeargs,
886 		.pc_encode = nfs3svc_encode_writeres,
887 		.pc_release = nfs3svc_release_fhandle,
888 		.pc_argsize = sizeof(struct nfsd3_writeargs),
889 		.pc_argzero = sizeof(struct nfsd3_writeargs),
890 		.pc_ressize = sizeof(struct nfsd3_writeres),
891 		.pc_cachetype = RC_REPLBUFF,
892 		.pc_xdrressize = ST+WC+4,
893 		.pc_name = "WRITE",
894 	},
895 	[NFS3PROC_CREATE] = {
896 		.pc_func = nfsd3_proc_create,
897 		.pc_decode = nfs3svc_decode_createargs,
898 		.pc_encode = nfs3svc_encode_createres,
899 		.pc_release = nfs3svc_release_fhandle2,
900 		.pc_argsize = sizeof(struct nfsd3_createargs),
901 		.pc_argzero = sizeof(struct nfsd3_createargs),
902 		.pc_ressize = sizeof(struct nfsd3_createres),
903 		.pc_cachetype = RC_REPLBUFF,
904 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
905 		.pc_name = "CREATE",
906 	},
907 	[NFS3PROC_MKDIR] = {
908 		.pc_func = nfsd3_proc_mkdir,
909 		.pc_decode = nfs3svc_decode_mkdirargs,
910 		.pc_encode = nfs3svc_encode_createres,
911 		.pc_release = nfs3svc_release_fhandle2,
912 		.pc_argsize = sizeof(struct nfsd3_mkdirargs),
913 		.pc_argzero = sizeof(struct nfsd3_mkdirargs),
914 		.pc_ressize = sizeof(struct nfsd3_createres),
915 		.pc_cachetype = RC_REPLBUFF,
916 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
917 		.pc_name = "MKDIR",
918 	},
919 	[NFS3PROC_SYMLINK] = {
920 		.pc_func = nfsd3_proc_symlink,
921 		.pc_decode = nfs3svc_decode_symlinkargs,
922 		.pc_encode = nfs3svc_encode_createres,
923 		.pc_release = nfs3svc_release_fhandle2,
924 		.pc_argsize = sizeof(struct nfsd3_symlinkargs),
925 		.pc_argzero = sizeof(struct nfsd3_symlinkargs),
926 		.pc_ressize = sizeof(struct nfsd3_createres),
927 		.pc_cachetype = RC_REPLBUFF,
928 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
929 		.pc_name = "SYMLINK",
930 	},
931 	[NFS3PROC_MKNOD] = {
932 		.pc_func = nfsd3_proc_mknod,
933 		.pc_decode = nfs3svc_decode_mknodargs,
934 		.pc_encode = nfs3svc_encode_createres,
935 		.pc_release = nfs3svc_release_fhandle2,
936 		.pc_argsize = sizeof(struct nfsd3_mknodargs),
937 		.pc_argzero = sizeof(struct nfsd3_mknodargs),
938 		.pc_ressize = sizeof(struct nfsd3_createres),
939 		.pc_cachetype = RC_REPLBUFF,
940 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
941 		.pc_name = "MKNOD",
942 	},
943 	[NFS3PROC_REMOVE] = {
944 		.pc_func = nfsd3_proc_remove,
945 		.pc_decode = nfs3svc_decode_diropargs,
946 		.pc_encode = nfs3svc_encode_wccstatres,
947 		.pc_release = nfs3svc_release_fhandle,
948 		.pc_argsize = sizeof(struct nfsd3_diropargs),
949 		.pc_argzero = sizeof(struct nfsd3_diropargs),
950 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
951 		.pc_cachetype = RC_REPLBUFF,
952 		.pc_xdrressize = ST+WC,
953 		.pc_name = "REMOVE",
954 	},
955 	[NFS3PROC_RMDIR] = {
956 		.pc_func = nfsd3_proc_rmdir,
957 		.pc_decode = nfs3svc_decode_diropargs,
958 		.pc_encode = nfs3svc_encode_wccstatres,
959 		.pc_release = nfs3svc_release_fhandle,
960 		.pc_argsize = sizeof(struct nfsd3_diropargs),
961 		.pc_argzero = sizeof(struct nfsd3_diropargs),
962 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
963 		.pc_cachetype = RC_REPLBUFF,
964 		.pc_xdrressize = ST+WC,
965 		.pc_name = "RMDIR",
966 	},
967 	[NFS3PROC_RENAME] = {
968 		.pc_func = nfsd3_proc_rename,
969 		.pc_decode = nfs3svc_decode_renameargs,
970 		.pc_encode = nfs3svc_encode_renameres,
971 		.pc_release = nfs3svc_release_fhandle2,
972 		.pc_argsize = sizeof(struct nfsd3_renameargs),
973 		.pc_argzero = sizeof(struct nfsd3_renameargs),
974 		.pc_ressize = sizeof(struct nfsd3_renameres),
975 		.pc_cachetype = RC_REPLBUFF,
976 		.pc_xdrressize = ST+WC+WC,
977 		.pc_name = "RENAME",
978 	},
979 	[NFS3PROC_LINK] = {
980 		.pc_func = nfsd3_proc_link,
981 		.pc_decode = nfs3svc_decode_linkargs,
982 		.pc_encode = nfs3svc_encode_linkres,
983 		.pc_release = nfs3svc_release_fhandle2,
984 		.pc_argsize = sizeof(struct nfsd3_linkargs),
985 		.pc_argzero = sizeof(struct nfsd3_linkargs),
986 		.pc_ressize = sizeof(struct nfsd3_linkres),
987 		.pc_cachetype = RC_REPLBUFF,
988 		.pc_xdrressize = ST+pAT+WC,
989 		.pc_name = "LINK",
990 	},
991 	[NFS3PROC_READDIR] = {
992 		.pc_func = nfsd3_proc_readdir,
993 		.pc_decode = nfs3svc_decode_readdirargs,
994 		.pc_encode = nfs3svc_encode_readdirres,
995 		.pc_release = nfs3svc_release_fhandle,
996 		.pc_argsize = sizeof(struct nfsd3_readdirargs),
997 		.pc_argzero = sizeof(struct nfsd3_readdirargs),
998 		.pc_ressize = sizeof(struct nfsd3_readdirres),
999 		.pc_cachetype = RC_NOCACHE,
1000 		.pc_name = "READDIR",
1001 	},
1002 	[NFS3PROC_READDIRPLUS] = {
1003 		.pc_func = nfsd3_proc_readdirplus,
1004 		.pc_decode = nfs3svc_decode_readdirplusargs,
1005 		.pc_encode = nfs3svc_encode_readdirres,
1006 		.pc_release = nfs3svc_release_fhandle,
1007 		.pc_argsize = sizeof(struct nfsd3_readdirplusargs),
1008 		.pc_argzero = sizeof(struct nfsd3_readdirplusargs),
1009 		.pc_ressize = sizeof(struct nfsd3_readdirres),
1010 		.pc_cachetype = RC_NOCACHE,
1011 		.pc_name = "READDIRPLUS",
1012 	},
1013 	[NFS3PROC_FSSTAT] = {
1014 		.pc_func = nfsd3_proc_fsstat,
1015 		.pc_decode = nfs3svc_decode_fhandleargs,
1016 		.pc_encode = nfs3svc_encode_fsstatres,
1017 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
1018 		.pc_argzero = sizeof(struct nfsd3_fhandleargs),
1019 		.pc_ressize = sizeof(struct nfsd3_fsstatres),
1020 		.pc_cachetype = RC_NOCACHE,
1021 		.pc_xdrressize = ST+pAT+2*6+1,
1022 		.pc_name = "FSSTAT",
1023 	},
1024 	[NFS3PROC_FSINFO] = {
1025 		.pc_func = nfsd3_proc_fsinfo,
1026 		.pc_decode = nfs3svc_decode_fhandleargs,
1027 		.pc_encode = nfs3svc_encode_fsinfores,
1028 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
1029 		.pc_argzero = sizeof(struct nfsd3_fhandleargs),
1030 		.pc_ressize = sizeof(struct nfsd3_fsinfores),
1031 		.pc_cachetype = RC_NOCACHE,
1032 		.pc_xdrressize = ST+pAT+12,
1033 		.pc_name = "FSINFO",
1034 	},
1035 	[NFS3PROC_PATHCONF] = {
1036 		.pc_func = nfsd3_proc_pathconf,
1037 		.pc_decode = nfs3svc_decode_fhandleargs,
1038 		.pc_encode = nfs3svc_encode_pathconfres,
1039 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
1040 		.pc_argzero = sizeof(struct nfsd3_fhandleargs),
1041 		.pc_ressize = sizeof(struct nfsd3_pathconfres),
1042 		.pc_cachetype = RC_NOCACHE,
1043 		.pc_xdrressize = ST+pAT+6,
1044 		.pc_name = "PATHCONF",
1045 	},
1046 	[NFS3PROC_COMMIT] = {
1047 		.pc_func = nfsd3_proc_commit,
1048 		.pc_decode = nfs3svc_decode_commitargs,
1049 		.pc_encode = nfs3svc_encode_commitres,
1050 		.pc_release = nfs3svc_release_fhandle,
1051 		.pc_argsize = sizeof(struct nfsd3_commitargs),
1052 		.pc_argzero = sizeof(struct nfsd3_commitargs),
1053 		.pc_ressize = sizeof(struct nfsd3_commitres),
1054 		.pc_cachetype = RC_NOCACHE,
1055 		.pc_xdrressize = ST+WC+2,
1056 		.pc_name = "COMMIT",
1057 	},
1058 };
1059 
1060 static DEFINE_PER_CPU_ALIGNED(unsigned long,
1061 			      nfsd_count3[ARRAY_SIZE(nfsd_procedures3)]);
1062 const struct svc_version nfsd_version3 = {
1063 	.vs_vers	= 3,
1064 	.vs_nproc	= ARRAY_SIZE(nfsd_procedures3),
1065 	.vs_proc	= nfsd_procedures3,
1066 	.vs_dispatch	= nfsd_dispatch,
1067 	.vs_count	= nfsd_count3,
1068 	.vs_xdrsize	= NFS3_SVC_XDRSIZE,
1069 };
1070