xref: /linux/fs/nfsd/nfs3proc.c (revision 24bce201d79807b668bf9d9e0aca801c5c0d5f78)
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 
17 #define NFSDDBG_FACILITY		NFSDDBG_PROC
18 
19 static int	nfs3_ftypes[] = {
20 	0,			/* NF3NON */
21 	S_IFREG,		/* NF3REG */
22 	S_IFDIR,		/* NF3DIR */
23 	S_IFBLK,		/* NF3BLK */
24 	S_IFCHR,		/* NF3CHR */
25 	S_IFLNK,		/* NF3LNK */
26 	S_IFSOCK,		/* NF3SOCK */
27 	S_IFIFO,		/* NF3FIFO */
28 };
29 
30 /*
31  * NULL call.
32  */
33 static __be32
34 nfsd3_proc_null(struct svc_rqst *rqstp)
35 {
36 	return rpc_success;
37 }
38 
39 /*
40  * Get a file's attributes
41  */
42 static __be32
43 nfsd3_proc_getattr(struct svc_rqst *rqstp)
44 {
45 	struct nfsd_fhandle *argp = rqstp->rq_argp;
46 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
47 
48 	dprintk("nfsd: GETATTR(3)  %s\n",
49 		SVCFH_fmt(&argp->fh));
50 
51 	fh_copy(&resp->fh, &argp->fh);
52 	resp->status = fh_verify(rqstp, &resp->fh, 0,
53 				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
54 	if (resp->status != nfs_ok)
55 		goto out;
56 
57 	resp->status = fh_getattr(&resp->fh, &resp->stat);
58 out:
59 	return rpc_success;
60 }
61 
62 /*
63  * Set a file's attributes
64  */
65 static __be32
66 nfsd3_proc_setattr(struct svc_rqst *rqstp)
67 {
68 	struct nfsd3_sattrargs *argp = rqstp->rq_argp;
69 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
70 
71 	dprintk("nfsd: SETATTR(3)  %s\n",
72 				SVCFH_fmt(&argp->fh));
73 
74 	fh_copy(&resp->fh, &argp->fh);
75 	resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
76 				    argp->check_guard, argp->guardtime);
77 	return rpc_success;
78 }
79 
80 /*
81  * Look up a path name component
82  */
83 static __be32
84 nfsd3_proc_lookup(struct svc_rqst *rqstp)
85 {
86 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
87 	struct nfsd3_diropres  *resp = rqstp->rq_resp;
88 
89 	dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
90 				SVCFH_fmt(&argp->fh),
91 				argp->len,
92 				argp->name);
93 
94 	fh_copy(&resp->dirfh, &argp->fh);
95 	fh_init(&resp->fh, NFS3_FHSIZE);
96 
97 	resp->status = nfsd_lookup(rqstp, &resp->dirfh,
98 				   argp->name, argp->len,
99 				   &resp->fh);
100 	return rpc_success;
101 }
102 
103 /*
104  * Check file access
105  */
106 static __be32
107 nfsd3_proc_access(struct svc_rqst *rqstp)
108 {
109 	struct nfsd3_accessargs *argp = rqstp->rq_argp;
110 	struct nfsd3_accessres *resp = rqstp->rq_resp;
111 
112 	dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
113 				SVCFH_fmt(&argp->fh),
114 				argp->access);
115 
116 	fh_copy(&resp->fh, &argp->fh);
117 	resp->access = argp->access;
118 	resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
119 	return rpc_success;
120 }
121 
122 /*
123  * Read a symlink.
124  */
125 static __be32
126 nfsd3_proc_readlink(struct svc_rqst *rqstp)
127 {
128 	struct nfsd_fhandle *argp = rqstp->rq_argp;
129 	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
130 
131 	dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
132 
133 	/* Read the symlink. */
134 	fh_copy(&resp->fh, &argp->fh);
135 	resp->len = NFS3_MAXPATHLEN;
136 	resp->pages = rqstp->rq_next_page++;
137 	resp->status = nfsd_readlink(rqstp, &resp->fh,
138 				     page_address(*resp->pages), &resp->len);
139 	return rpc_success;
140 }
141 
142 /*
143  * Read a portion of a file.
144  */
145 static __be32
146 nfsd3_proc_read(struct svc_rqst *rqstp)
147 {
148 	struct nfsd3_readargs *argp = rqstp->rq_argp;
149 	struct nfsd3_readres *resp = rqstp->rq_resp;
150 	u32 max_blocksize = svc_max_payload(rqstp);
151 	unsigned int len;
152 	int v;
153 
154 	dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
155 				SVCFH_fmt(&argp->fh),
156 				(unsigned long) argp->count,
157 				(unsigned long long) argp->offset);
158 
159 	argp->count = min_t(u32, argp->count, max_blocksize);
160 	if (argp->offset > (u64)OFFSET_MAX)
161 		argp->offset = (u64)OFFSET_MAX;
162 	if (argp->offset + argp->count > (u64)OFFSET_MAX)
163 		argp->count = (u64)OFFSET_MAX - argp->offset;
164 
165 	v = 0;
166 	len = argp->count;
167 	resp->pages = rqstp->rq_next_page;
168 	while (len > 0) {
169 		struct page *page = *(rqstp->rq_next_page++);
170 
171 		rqstp->rq_vec[v].iov_base = page_address(page);
172 		rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
173 		len -= rqstp->rq_vec[v].iov_len;
174 		v++;
175 	}
176 
177 	/* Obtain buffer pointer for payload.
178 	 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
179 	 * + 1 (xdr opaque byte count) = 26
180 	 */
181 	resp->count = argp->count;
182 	svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
183 
184 	fh_copy(&resp->fh, &argp->fh);
185 	resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
186 				 rqstp->rq_vec, v, &resp->count, &resp->eof);
187 	return rpc_success;
188 }
189 
190 /*
191  * Write data to a file
192  */
193 static __be32
194 nfsd3_proc_write(struct svc_rqst *rqstp)
195 {
196 	struct nfsd3_writeargs *argp = rqstp->rq_argp;
197 	struct nfsd3_writeres *resp = rqstp->rq_resp;
198 	unsigned long cnt = argp->len;
199 	unsigned int nvecs;
200 
201 	dprintk("nfsd: WRITE(3)    %s %d bytes at %Lu%s\n",
202 				SVCFH_fmt(&argp->fh),
203 				argp->len,
204 				(unsigned long long) argp->offset,
205 				argp->stable? " stable" : "");
206 
207 	resp->status = nfserr_fbig;
208 	if (argp->offset > (u64)OFFSET_MAX ||
209 	    argp->offset + argp->len > (u64)OFFSET_MAX)
210 		return rpc_success;
211 
212 	fh_copy(&resp->fh, &argp->fh);
213 	resp->committed = argp->stable;
214 	nvecs = svc_fill_write_vector(rqstp, &argp->payload);
215 
216 	resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
217 				  rqstp->rq_vec, nvecs, &cnt,
218 				  resp->committed, resp->verf);
219 	resp->count = cnt;
220 	return rpc_success;
221 }
222 
223 /*
224  * Implement NFSv3's unchecked, guarded, and exclusive CREATE
225  * semantics for regular files. Except for the created file,
226  * this operation is stateless on the server.
227  *
228  * Upon return, caller must release @fhp and @resfhp.
229  */
230 static __be32
231 nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
232 		  struct svc_fh *resfhp, struct nfsd3_createargs *argp)
233 {
234 	struct iattr *iap = &argp->attrs;
235 	struct dentry *parent, *child;
236 	__u32 v_mtime, v_atime;
237 	struct inode *inode;
238 	__be32 status;
239 	int host_err;
240 
241 	if (isdotent(argp->name, argp->len))
242 		return nfserr_exist;
243 	if (!(iap->ia_valid & ATTR_MODE))
244 		iap->ia_mode = 0;
245 
246 	status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
247 	if (status != nfs_ok)
248 		return status;
249 
250 	parent = fhp->fh_dentry;
251 	inode = d_inode(parent);
252 
253 	host_err = fh_want_write(fhp);
254 	if (host_err)
255 		return nfserrno(host_err);
256 
257 	fh_lock_nested(fhp, I_MUTEX_PARENT);
258 
259 	child = lookup_one_len(argp->name, parent, argp->len);
260 	if (IS_ERR(child)) {
261 		status = nfserrno(PTR_ERR(child));
262 		goto out;
263 	}
264 
265 	if (d_really_is_negative(child)) {
266 		status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
267 		if (status != nfs_ok)
268 			goto out;
269 	}
270 
271 	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
272 	if (status != nfs_ok)
273 		goto out;
274 
275 	v_mtime = 0;
276 	v_atime = 0;
277 	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
278 		u32 *verifier = (u32 *)argp->verf;
279 
280 		/*
281 		 * Solaris 7 gets confused (bugid 4218508) if these have
282 		 * the high bit set, as do xfs filesystems without the
283 		 * "bigtime" feature. So just clear the high bits.
284 		 */
285 		v_mtime = verifier[0] & 0x7fffffff;
286 		v_atime = verifier[1] & 0x7fffffff;
287 	}
288 
289 	if (d_really_is_positive(child)) {
290 		status = nfs_ok;
291 
292 		switch (argp->createmode) {
293 		case NFS3_CREATE_UNCHECKED:
294 			if (!d_is_reg(child))
295 				break;
296 			iap->ia_valid &= ATTR_SIZE;
297 			goto set_attr;
298 		case NFS3_CREATE_GUARDED:
299 			status = nfserr_exist;
300 			break;
301 		case NFS3_CREATE_EXCLUSIVE:
302 			if (d_inode(child)->i_mtime.tv_sec == v_mtime &&
303 			    d_inode(child)->i_atime.tv_sec == v_atime &&
304 			    d_inode(child)->i_size == 0) {
305 				break;
306 			}
307 			status = nfserr_exist;
308 		}
309 		goto out;
310 	}
311 
312 	if (!IS_POSIXACL(inode))
313 		iap->ia_mode &= ~current_umask();
314 
315 	host_err = vfs_create(&init_user_ns, inode, child, iap->ia_mode, true);
316 	if (host_err < 0) {
317 		status = nfserrno(host_err);
318 		goto out;
319 	}
320 
321 	/* A newly created file already has a file size of zero. */
322 	if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
323 		iap->ia_valid &= ~ATTR_SIZE;
324 	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
325 		iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
326 				ATTR_MTIME_SET | ATTR_ATIME_SET;
327 		iap->ia_mtime.tv_sec = v_mtime;
328 		iap->ia_atime.tv_sec = v_atime;
329 		iap->ia_mtime.tv_nsec = 0;
330 		iap->ia_atime.tv_nsec = 0;
331 	}
332 
333 set_attr:
334 	status = nfsd_create_setattr(rqstp, fhp, resfhp, iap);
335 
336 out:
337 	fh_unlock(fhp);
338 	if (child && !IS_ERR(child))
339 		dput(child);
340 	fh_drop_write(fhp);
341 	return status;
342 }
343 
344 static __be32
345 nfsd3_proc_create(struct svc_rqst *rqstp)
346 {
347 	struct nfsd3_createargs *argp = rqstp->rq_argp;
348 	struct nfsd3_diropres *resp = rqstp->rq_resp;
349 	svc_fh *dirfhp, *newfhp;
350 
351 	dprintk("nfsd: CREATE(3)   %s %.*s\n",
352 				SVCFH_fmt(&argp->fh),
353 				argp->len,
354 				argp->name);
355 
356 	dirfhp = fh_copy(&resp->dirfh, &argp->fh);
357 	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
358 
359 	resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
360 	return rpc_success;
361 }
362 
363 /*
364  * Make directory. This operation is not idempotent.
365  */
366 static __be32
367 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
368 {
369 	struct nfsd3_createargs *argp = rqstp->rq_argp;
370 	struct nfsd3_diropres *resp = rqstp->rq_resp;
371 
372 	dprintk("nfsd: MKDIR(3)    %s %.*s\n",
373 				SVCFH_fmt(&argp->fh),
374 				argp->len,
375 				argp->name);
376 
377 	argp->attrs.ia_valid &= ~ATTR_SIZE;
378 	fh_copy(&resp->dirfh, &argp->fh);
379 	fh_init(&resp->fh, NFS3_FHSIZE);
380 	resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
381 				   &argp->attrs, S_IFDIR, 0, &resp->fh);
382 	fh_unlock(&resp->dirfh);
383 	return rpc_success;
384 }
385 
386 static __be32
387 nfsd3_proc_symlink(struct svc_rqst *rqstp)
388 {
389 	struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
390 	struct nfsd3_diropres *resp = rqstp->rq_resp;
391 
392 	if (argp->tlen == 0) {
393 		resp->status = nfserr_inval;
394 		goto out;
395 	}
396 	if (argp->tlen > NFS3_MAXPATHLEN) {
397 		resp->status = nfserr_nametoolong;
398 		goto out;
399 	}
400 
401 	argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
402 						page_address(rqstp->rq_arg.pages[0]),
403 						argp->tlen);
404 	if (IS_ERR(argp->tname)) {
405 		resp->status = nfserrno(PTR_ERR(argp->tname));
406 		goto out;
407 	}
408 
409 	dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
410 				SVCFH_fmt(&argp->ffh),
411 				argp->flen, argp->fname,
412 				argp->tlen, argp->tname);
413 
414 	fh_copy(&resp->dirfh, &argp->ffh);
415 	fh_init(&resp->fh, NFS3_FHSIZE);
416 	resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
417 				    argp->flen, argp->tname, &resp->fh);
418 	kfree(argp->tname);
419 out:
420 	return rpc_success;
421 }
422 
423 /*
424  * Make socket/fifo/device.
425  */
426 static __be32
427 nfsd3_proc_mknod(struct svc_rqst *rqstp)
428 {
429 	struct nfsd3_mknodargs *argp = rqstp->rq_argp;
430 	struct nfsd3_diropres  *resp = rqstp->rq_resp;
431 	int type;
432 	dev_t	rdev = 0;
433 
434 	dprintk("nfsd: MKNOD(3)    %s %.*s\n",
435 				SVCFH_fmt(&argp->fh),
436 				argp->len,
437 				argp->name);
438 
439 	fh_copy(&resp->dirfh, &argp->fh);
440 	fh_init(&resp->fh, NFS3_FHSIZE);
441 
442 	if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
443 		rdev = MKDEV(argp->major, argp->minor);
444 		if (MAJOR(rdev) != argp->major ||
445 		    MINOR(rdev) != argp->minor) {
446 			resp->status = nfserr_inval;
447 			goto out;
448 		}
449 	} else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
450 		resp->status = nfserr_badtype;
451 		goto out;
452 	}
453 
454 	type = nfs3_ftypes[argp->ftype];
455 	resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
456 				   &argp->attrs, type, rdev, &resp->fh);
457 	fh_unlock(&resp->dirfh);
458 out:
459 	return rpc_success;
460 }
461 
462 /*
463  * Remove file/fifo/socket etc.
464  */
465 static __be32
466 nfsd3_proc_remove(struct svc_rqst *rqstp)
467 {
468 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
469 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
470 
471 	dprintk("nfsd: REMOVE(3)   %s %.*s\n",
472 				SVCFH_fmt(&argp->fh),
473 				argp->len,
474 				argp->name);
475 
476 	/* Unlink. -S_IFDIR means file must not be a directory */
477 	fh_copy(&resp->fh, &argp->fh);
478 	resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
479 				   argp->name, argp->len);
480 	fh_unlock(&resp->fh);
481 	return rpc_success;
482 }
483 
484 /*
485  * Remove a directory
486  */
487 static __be32
488 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
489 {
490 	struct nfsd3_diropargs *argp = rqstp->rq_argp;
491 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
492 
493 	dprintk("nfsd: RMDIR(3)    %s %.*s\n",
494 				SVCFH_fmt(&argp->fh),
495 				argp->len,
496 				argp->name);
497 
498 	fh_copy(&resp->fh, &argp->fh);
499 	resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
500 				   argp->name, argp->len);
501 	fh_unlock(&resp->fh);
502 	return rpc_success;
503 }
504 
505 static __be32
506 nfsd3_proc_rename(struct svc_rqst *rqstp)
507 {
508 	struct nfsd3_renameargs *argp = rqstp->rq_argp;
509 	struct nfsd3_renameres *resp = rqstp->rq_resp;
510 
511 	dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
512 				SVCFH_fmt(&argp->ffh),
513 				argp->flen,
514 				argp->fname);
515 	dprintk("nfsd: -> %s %.*s\n",
516 				SVCFH_fmt(&argp->tfh),
517 				argp->tlen,
518 				argp->tname);
519 
520 	fh_copy(&resp->ffh, &argp->ffh);
521 	fh_copy(&resp->tfh, &argp->tfh);
522 	resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
523 				   &resp->tfh, argp->tname, argp->tlen);
524 	return rpc_success;
525 }
526 
527 static __be32
528 nfsd3_proc_link(struct svc_rqst *rqstp)
529 {
530 	struct nfsd3_linkargs *argp = rqstp->rq_argp;
531 	struct nfsd3_linkres  *resp = rqstp->rq_resp;
532 
533 	dprintk("nfsd: LINK(3)     %s ->\n",
534 				SVCFH_fmt(&argp->ffh));
535 	dprintk("nfsd:   -> %s %.*s\n",
536 				SVCFH_fmt(&argp->tfh),
537 				argp->tlen,
538 				argp->tname);
539 
540 	fh_copy(&resp->fh,  &argp->ffh);
541 	fh_copy(&resp->tfh, &argp->tfh);
542 	resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
543 				 &resp->fh);
544 	return rpc_success;
545 }
546 
547 static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
548 				     struct nfsd3_readdirres *resp,
549 				     u32 count)
550 {
551 	struct xdr_buf *buf = &resp->dirlist;
552 	struct xdr_stream *xdr = &resp->xdr;
553 
554 	count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
555 
556 	memset(buf, 0, sizeof(*buf));
557 
558 	/* Reserve room for the NULL ptr & eof flag (-2 words) */
559 	buf->buflen = count - XDR_UNIT * 2;
560 	buf->pages = rqstp->rq_next_page;
561 	rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
562 
563 	/* This is xdr_init_encode(), but it assumes that
564 	 * the head kvec has already been consumed. */
565 	xdr_set_scratch_buffer(xdr, NULL, 0);
566 	xdr->buf = buf;
567 	xdr->page_ptr = buf->pages;
568 	xdr->iov = NULL;
569 	xdr->p = page_address(*buf->pages);
570 	xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE);
571 	xdr->rqst = 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 
761 	dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
762 				SVCFH_fmt(&argp->fh),
763 				argp->count,
764 				(unsigned long long) argp->offset);
765 
766 	fh_copy(&resp->fh, &argp->fh);
767 	resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
768 				   argp->count, resp->verf);
769 	return rpc_success;
770 }
771 
772 
773 /*
774  * NFSv3 Server procedures.
775  * Only the results of non-idempotent operations are cached.
776  */
777 #define nfs3svc_encode_attrstatres	nfs3svc_encode_attrstat
778 #define nfs3svc_encode_wccstatres	nfs3svc_encode_wccstat
779 #define nfsd3_mkdirargs			nfsd3_createargs
780 #define nfsd3_readdirplusargs		nfsd3_readdirargs
781 #define nfsd3_fhandleargs		nfsd_fhandle
782 #define nfsd3_attrstatres		nfsd3_attrstat
783 #define nfsd3_wccstatres		nfsd3_attrstat
784 #define nfsd3_createres			nfsd3_diropres
785 
786 #define ST 1		/* status*/
787 #define FH 17		/* filehandle with length */
788 #define AT 21		/* attributes */
789 #define pAT (1+AT)	/* post attributes - conditional */
790 #define WC (7+pAT)	/* WCC attributes */
791 
792 static const struct svc_procedure nfsd_procedures3[22] = {
793 	[NFS3PROC_NULL] = {
794 		.pc_func = nfsd3_proc_null,
795 		.pc_decode = nfssvc_decode_voidarg,
796 		.pc_encode = nfssvc_encode_voidres,
797 		.pc_argsize = sizeof(struct nfsd_voidargs),
798 		.pc_ressize = sizeof(struct nfsd_voidres),
799 		.pc_cachetype = RC_NOCACHE,
800 		.pc_xdrressize = ST,
801 		.pc_name = "NULL",
802 	},
803 	[NFS3PROC_GETATTR] = {
804 		.pc_func = nfsd3_proc_getattr,
805 		.pc_decode = nfs3svc_decode_fhandleargs,
806 		.pc_encode = nfs3svc_encode_getattrres,
807 		.pc_release = nfs3svc_release_fhandle,
808 		.pc_argsize = sizeof(struct nfsd_fhandle),
809 		.pc_ressize = sizeof(struct nfsd3_attrstatres),
810 		.pc_cachetype = RC_NOCACHE,
811 		.pc_xdrressize = ST+AT,
812 		.pc_name = "GETATTR",
813 	},
814 	[NFS3PROC_SETATTR] = {
815 		.pc_func = nfsd3_proc_setattr,
816 		.pc_decode = nfs3svc_decode_sattrargs,
817 		.pc_encode = nfs3svc_encode_wccstatres,
818 		.pc_release = nfs3svc_release_fhandle,
819 		.pc_argsize = sizeof(struct nfsd3_sattrargs),
820 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
821 		.pc_cachetype = RC_REPLBUFF,
822 		.pc_xdrressize = ST+WC,
823 		.pc_name = "SETATTR",
824 	},
825 	[NFS3PROC_LOOKUP] = {
826 		.pc_func = nfsd3_proc_lookup,
827 		.pc_decode = nfs3svc_decode_diropargs,
828 		.pc_encode = nfs3svc_encode_lookupres,
829 		.pc_release = nfs3svc_release_fhandle2,
830 		.pc_argsize = sizeof(struct nfsd3_diropargs),
831 		.pc_ressize = sizeof(struct nfsd3_diropres),
832 		.pc_cachetype = RC_NOCACHE,
833 		.pc_xdrressize = ST+FH+pAT+pAT,
834 		.pc_name = "LOOKUP",
835 	},
836 	[NFS3PROC_ACCESS] = {
837 		.pc_func = nfsd3_proc_access,
838 		.pc_decode = nfs3svc_decode_accessargs,
839 		.pc_encode = nfs3svc_encode_accessres,
840 		.pc_release = nfs3svc_release_fhandle,
841 		.pc_argsize = sizeof(struct nfsd3_accessargs),
842 		.pc_ressize = sizeof(struct nfsd3_accessres),
843 		.pc_cachetype = RC_NOCACHE,
844 		.pc_xdrressize = ST+pAT+1,
845 		.pc_name = "ACCESS",
846 	},
847 	[NFS3PROC_READLINK] = {
848 		.pc_func = nfsd3_proc_readlink,
849 		.pc_decode = nfs3svc_decode_fhandleargs,
850 		.pc_encode = nfs3svc_encode_readlinkres,
851 		.pc_release = nfs3svc_release_fhandle,
852 		.pc_argsize = sizeof(struct nfsd_fhandle),
853 		.pc_ressize = sizeof(struct nfsd3_readlinkres),
854 		.pc_cachetype = RC_NOCACHE,
855 		.pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
856 		.pc_name = "READLINK",
857 	},
858 	[NFS3PROC_READ] = {
859 		.pc_func = nfsd3_proc_read,
860 		.pc_decode = nfs3svc_decode_readargs,
861 		.pc_encode = nfs3svc_encode_readres,
862 		.pc_release = nfs3svc_release_fhandle,
863 		.pc_argsize = sizeof(struct nfsd3_readargs),
864 		.pc_ressize = sizeof(struct nfsd3_readres),
865 		.pc_cachetype = RC_NOCACHE,
866 		.pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
867 		.pc_name = "READ",
868 	},
869 	[NFS3PROC_WRITE] = {
870 		.pc_func = nfsd3_proc_write,
871 		.pc_decode = nfs3svc_decode_writeargs,
872 		.pc_encode = nfs3svc_encode_writeres,
873 		.pc_release = nfs3svc_release_fhandle,
874 		.pc_argsize = sizeof(struct nfsd3_writeargs),
875 		.pc_ressize = sizeof(struct nfsd3_writeres),
876 		.pc_cachetype = RC_REPLBUFF,
877 		.pc_xdrressize = ST+WC+4,
878 		.pc_name = "WRITE",
879 	},
880 	[NFS3PROC_CREATE] = {
881 		.pc_func = nfsd3_proc_create,
882 		.pc_decode = nfs3svc_decode_createargs,
883 		.pc_encode = nfs3svc_encode_createres,
884 		.pc_release = nfs3svc_release_fhandle2,
885 		.pc_argsize = sizeof(struct nfsd3_createargs),
886 		.pc_ressize = sizeof(struct nfsd3_createres),
887 		.pc_cachetype = RC_REPLBUFF,
888 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
889 		.pc_name = "CREATE",
890 	},
891 	[NFS3PROC_MKDIR] = {
892 		.pc_func = nfsd3_proc_mkdir,
893 		.pc_decode = nfs3svc_decode_mkdirargs,
894 		.pc_encode = nfs3svc_encode_createres,
895 		.pc_release = nfs3svc_release_fhandle2,
896 		.pc_argsize = sizeof(struct nfsd3_mkdirargs),
897 		.pc_ressize = sizeof(struct nfsd3_createres),
898 		.pc_cachetype = RC_REPLBUFF,
899 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
900 		.pc_name = "MKDIR",
901 	},
902 	[NFS3PROC_SYMLINK] = {
903 		.pc_func = nfsd3_proc_symlink,
904 		.pc_decode = nfs3svc_decode_symlinkargs,
905 		.pc_encode = nfs3svc_encode_createres,
906 		.pc_release = nfs3svc_release_fhandle2,
907 		.pc_argsize = sizeof(struct nfsd3_symlinkargs),
908 		.pc_ressize = sizeof(struct nfsd3_createres),
909 		.pc_cachetype = RC_REPLBUFF,
910 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
911 		.pc_name = "SYMLINK",
912 	},
913 	[NFS3PROC_MKNOD] = {
914 		.pc_func = nfsd3_proc_mknod,
915 		.pc_decode = nfs3svc_decode_mknodargs,
916 		.pc_encode = nfs3svc_encode_createres,
917 		.pc_release = nfs3svc_release_fhandle2,
918 		.pc_argsize = sizeof(struct nfsd3_mknodargs),
919 		.pc_ressize = sizeof(struct nfsd3_createres),
920 		.pc_cachetype = RC_REPLBUFF,
921 		.pc_xdrressize = ST+(1+FH+pAT)+WC,
922 		.pc_name = "MKNOD",
923 	},
924 	[NFS3PROC_REMOVE] = {
925 		.pc_func = nfsd3_proc_remove,
926 		.pc_decode = nfs3svc_decode_diropargs,
927 		.pc_encode = nfs3svc_encode_wccstatres,
928 		.pc_release = nfs3svc_release_fhandle,
929 		.pc_argsize = sizeof(struct nfsd3_diropargs),
930 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
931 		.pc_cachetype = RC_REPLBUFF,
932 		.pc_xdrressize = ST+WC,
933 		.pc_name = "REMOVE",
934 	},
935 	[NFS3PROC_RMDIR] = {
936 		.pc_func = nfsd3_proc_rmdir,
937 		.pc_decode = nfs3svc_decode_diropargs,
938 		.pc_encode = nfs3svc_encode_wccstatres,
939 		.pc_release = nfs3svc_release_fhandle,
940 		.pc_argsize = sizeof(struct nfsd3_diropargs),
941 		.pc_ressize = sizeof(struct nfsd3_wccstatres),
942 		.pc_cachetype = RC_REPLBUFF,
943 		.pc_xdrressize = ST+WC,
944 		.pc_name = "RMDIR",
945 	},
946 	[NFS3PROC_RENAME] = {
947 		.pc_func = nfsd3_proc_rename,
948 		.pc_decode = nfs3svc_decode_renameargs,
949 		.pc_encode = nfs3svc_encode_renameres,
950 		.pc_release = nfs3svc_release_fhandle2,
951 		.pc_argsize = sizeof(struct nfsd3_renameargs),
952 		.pc_ressize = sizeof(struct nfsd3_renameres),
953 		.pc_cachetype = RC_REPLBUFF,
954 		.pc_xdrressize = ST+WC+WC,
955 		.pc_name = "RENAME",
956 	},
957 	[NFS3PROC_LINK] = {
958 		.pc_func = nfsd3_proc_link,
959 		.pc_decode = nfs3svc_decode_linkargs,
960 		.pc_encode = nfs3svc_encode_linkres,
961 		.pc_release = nfs3svc_release_fhandle2,
962 		.pc_argsize = sizeof(struct nfsd3_linkargs),
963 		.pc_ressize = sizeof(struct nfsd3_linkres),
964 		.pc_cachetype = RC_REPLBUFF,
965 		.pc_xdrressize = ST+pAT+WC,
966 		.pc_name = "LINK",
967 	},
968 	[NFS3PROC_READDIR] = {
969 		.pc_func = nfsd3_proc_readdir,
970 		.pc_decode = nfs3svc_decode_readdirargs,
971 		.pc_encode = nfs3svc_encode_readdirres,
972 		.pc_release = nfs3svc_release_fhandle,
973 		.pc_argsize = sizeof(struct nfsd3_readdirargs),
974 		.pc_ressize = sizeof(struct nfsd3_readdirres),
975 		.pc_cachetype = RC_NOCACHE,
976 		.pc_name = "READDIR",
977 	},
978 	[NFS3PROC_READDIRPLUS] = {
979 		.pc_func = nfsd3_proc_readdirplus,
980 		.pc_decode = nfs3svc_decode_readdirplusargs,
981 		.pc_encode = nfs3svc_encode_readdirres,
982 		.pc_release = nfs3svc_release_fhandle,
983 		.pc_argsize = sizeof(struct nfsd3_readdirplusargs),
984 		.pc_ressize = sizeof(struct nfsd3_readdirres),
985 		.pc_cachetype = RC_NOCACHE,
986 		.pc_name = "READDIRPLUS",
987 	},
988 	[NFS3PROC_FSSTAT] = {
989 		.pc_func = nfsd3_proc_fsstat,
990 		.pc_decode = nfs3svc_decode_fhandleargs,
991 		.pc_encode = nfs3svc_encode_fsstatres,
992 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
993 		.pc_ressize = sizeof(struct nfsd3_fsstatres),
994 		.pc_cachetype = RC_NOCACHE,
995 		.pc_xdrressize = ST+pAT+2*6+1,
996 		.pc_name = "FSSTAT",
997 	},
998 	[NFS3PROC_FSINFO] = {
999 		.pc_func = nfsd3_proc_fsinfo,
1000 		.pc_decode = nfs3svc_decode_fhandleargs,
1001 		.pc_encode = nfs3svc_encode_fsinfores,
1002 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
1003 		.pc_ressize = sizeof(struct nfsd3_fsinfores),
1004 		.pc_cachetype = RC_NOCACHE,
1005 		.pc_xdrressize = ST+pAT+12,
1006 		.pc_name = "FSINFO",
1007 	},
1008 	[NFS3PROC_PATHCONF] = {
1009 		.pc_func = nfsd3_proc_pathconf,
1010 		.pc_decode = nfs3svc_decode_fhandleargs,
1011 		.pc_encode = nfs3svc_encode_pathconfres,
1012 		.pc_argsize = sizeof(struct nfsd3_fhandleargs),
1013 		.pc_ressize = sizeof(struct nfsd3_pathconfres),
1014 		.pc_cachetype = RC_NOCACHE,
1015 		.pc_xdrressize = ST+pAT+6,
1016 		.pc_name = "PATHCONF",
1017 	},
1018 	[NFS3PROC_COMMIT] = {
1019 		.pc_func = nfsd3_proc_commit,
1020 		.pc_decode = nfs3svc_decode_commitargs,
1021 		.pc_encode = nfs3svc_encode_commitres,
1022 		.pc_release = nfs3svc_release_fhandle,
1023 		.pc_argsize = sizeof(struct nfsd3_commitargs),
1024 		.pc_ressize = sizeof(struct nfsd3_commitres),
1025 		.pc_cachetype = RC_NOCACHE,
1026 		.pc_xdrressize = ST+WC+2,
1027 		.pc_name = "COMMIT",
1028 	},
1029 };
1030 
1031 static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
1032 const struct svc_version nfsd_version3 = {
1033 	.vs_vers	= 3,
1034 	.vs_nproc	= 22,
1035 	.vs_proc	= nfsd_procedures3,
1036 	.vs_dispatch	= nfsd_dispatch,
1037 	.vs_count	= nfsd_count3,
1038 	.vs_xdrsize	= NFS3_SVC_XDRSIZE,
1039 };
1040