GNU Linux-libre 4.19.286-gnu1
[releases.git] / fs / nfsd / nfs3proc.c
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
12 #include "cache.h"
13 #include "xdr3.h"
14 #include "vfs.h"
15
16 #define NFSDDBG_FACILITY                NFSDDBG_PROC
17
18 #define RETURN_STATUS(st)       { resp->status = (st); return (st); }
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 nfs_ok;
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         __be32  nfserr;
49
50         dprintk("nfsd: GETATTR(3)  %s\n",
51                 SVCFH_fmt(&argp->fh));
52
53         fh_copy(&resp->fh, &argp->fh);
54         nfserr = fh_verify(rqstp, &resp->fh, 0,
55                         NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
56         if (nfserr)
57                 RETURN_STATUS(nfserr);
58
59         nfserr = fh_getattr(&resp->fh, &resp->stat);
60
61         RETURN_STATUS(nfserr);
62 }
63
64 /*
65  * Set a file's attributes
66  */
67 static __be32
68 nfsd3_proc_setattr(struct svc_rqst *rqstp)
69 {
70         struct nfsd3_sattrargs *argp = rqstp->rq_argp;
71         struct nfsd3_attrstat *resp = rqstp->rq_resp;
72         __be32  nfserr;
73
74         dprintk("nfsd: SETATTR(3)  %s\n",
75                                 SVCFH_fmt(&argp->fh));
76
77         fh_copy(&resp->fh, &argp->fh);
78         nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
79                               argp->check_guard, argp->guardtime);
80         RETURN_STATUS(nfserr);
81 }
82
83 /*
84  * Look up a path name component
85  */
86 static __be32
87 nfsd3_proc_lookup(struct svc_rqst *rqstp)
88 {
89         struct nfsd3_diropargs *argp = rqstp->rq_argp;
90         struct nfsd3_diropres  *resp = rqstp->rq_resp;
91         __be32  nfserr;
92
93         dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
94                                 SVCFH_fmt(&argp->fh),
95                                 argp->len,
96                                 argp->name);
97
98         fh_copy(&resp->dirfh, &argp->fh);
99         fh_init(&resp->fh, NFS3_FHSIZE);
100
101         nfserr = nfsd_lookup(rqstp, &resp->dirfh,
102                                     argp->name,
103                                     argp->len,
104                                     &resp->fh);
105         RETURN_STATUS(nfserr);
106 }
107
108 /*
109  * Check file access
110  */
111 static __be32
112 nfsd3_proc_access(struct svc_rqst *rqstp)
113 {
114         struct nfsd3_accessargs *argp = rqstp->rq_argp;
115         struct nfsd3_accessres *resp = rqstp->rq_resp;
116         __be32  nfserr;
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         nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
125         RETURN_STATUS(nfserr);
126 }
127
128 /*
129  * Read a symlink.
130  */
131 static __be32
132 nfsd3_proc_readlink(struct svc_rqst *rqstp)
133 {
134         struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
135         struct nfsd3_readlinkres *resp = rqstp->rq_resp;
136         __be32 nfserr;
137
138         dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
139
140         /* Read the symlink. */
141         fh_copy(&resp->fh, &argp->fh);
142         resp->len = NFS3_MAXPATHLEN;
143         nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
144         RETURN_STATUS(nfserr);
145 }
146
147 /*
148  * Read a portion of a file.
149  */
150 static __be32
151 nfsd3_proc_read(struct svc_rqst *rqstp)
152 {
153         struct nfsd3_readargs *argp = rqstp->rq_argp;
154         struct nfsd3_readres *resp = rqstp->rq_resp;
155         __be32  nfserr;
156         u32     max_blocksize = svc_max_payload(rqstp);
157         unsigned long cnt = min(argp->count, max_blocksize);
158
159         dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
160                                 SVCFH_fmt(&argp->fh),
161                                 (unsigned long) argp->count,
162                                 (unsigned long long) argp->offset);
163
164         /* Obtain buffer pointer for payload.
165          * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
166          * + 1 (xdr opaque byte count) = 26
167          */
168         resp->count = cnt;
169         svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
170
171         fh_copy(&resp->fh, &argp->fh);
172         nfserr = nfsd_read(rqstp, &resp->fh,
173                                   argp->offset,
174                                   rqstp->rq_vec, argp->vlen,
175                                   &resp->count);
176         if (nfserr == 0) {
177                 struct inode    *inode = d_inode(resp->fh.fh_dentry);
178                 resp->eof = nfsd_eof_on_read(cnt, resp->count, argp->offset,
179                                                         inode->i_size);
180         }
181
182         RETURN_STATUS(nfserr);
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         __be32  nfserr;
194         unsigned long cnt = argp->len;
195         unsigned int nvecs;
196
197         dprintk("nfsd: WRITE(3)    %s %d bytes at %Lu%s\n",
198                                 SVCFH_fmt(&argp->fh),
199                                 argp->len,
200                                 (unsigned long long) argp->offset,
201                                 argp->stable? " stable" : "");
202
203         resp->status = nfserr_fbig;
204         if (argp->offset > (u64)OFFSET_MAX ||
205             argp->offset + argp->len > (u64)OFFSET_MAX)
206                 return rpc_success;
207
208         fh_copy(&resp->fh, &argp->fh);
209         resp->committed = argp->stable;
210         nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
211                                       &argp->first, cnt);
212         if (!nvecs)
213                 RETURN_STATUS(nfserr_io);
214         nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
215                             rqstp->rq_vec, nvecs, &cnt,
216                             resp->committed);
217         resp->count = cnt;
218         RETURN_STATUS(nfserr);
219 }
220
221 /*
222  * With NFSv3, CREATE processing is a lot easier than with NFSv2.
223  * At least in theory; we'll see how it fares in practice when the
224  * first reports about SunOS compatibility problems start to pour in...
225  */
226 static __be32
227 nfsd3_proc_create(struct svc_rqst *rqstp)
228 {
229         struct nfsd3_createargs *argp = rqstp->rq_argp;
230         struct nfsd3_diropres *resp = rqstp->rq_resp;
231         svc_fh          *dirfhp, *newfhp = NULL;
232         struct iattr    *attr;
233         __be32          nfserr;
234
235         dprintk("nfsd: CREATE(3)   %s %.*s\n",
236                                 SVCFH_fmt(&argp->fh),
237                                 argp->len,
238                                 argp->name);
239
240         dirfhp = fh_copy(&resp->dirfh, &argp->fh);
241         newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
242         attr   = &argp->attrs;
243
244         /* Unfudge the mode bits */
245         attr->ia_mode &= ~S_IFMT;
246         if (!(attr->ia_valid & ATTR_MODE)) { 
247                 attr->ia_valid |= ATTR_MODE;
248                 attr->ia_mode = S_IFREG;
249         } else {
250                 attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
251         }
252
253         /* Now create the file and set attributes */
254         nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
255                                 attr, newfhp,
256                                 argp->createmode, (u32 *)argp->verf, NULL, NULL);
257
258         RETURN_STATUS(nfserr);
259 }
260
261 /*
262  * Make directory. This operation is not idempotent.
263  */
264 static __be32
265 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
266 {
267         struct nfsd3_createargs *argp = rqstp->rq_argp;
268         struct nfsd3_diropres *resp = rqstp->rq_resp;
269         __be32  nfserr;
270
271         dprintk("nfsd: MKDIR(3)    %s %.*s\n",
272                                 SVCFH_fmt(&argp->fh),
273                                 argp->len,
274                                 argp->name);
275
276         argp->attrs.ia_valid &= ~ATTR_SIZE;
277         fh_copy(&resp->dirfh, &argp->fh);
278         fh_init(&resp->fh, NFS3_FHSIZE);
279         nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
280                                     &argp->attrs, S_IFDIR, 0, &resp->fh);
281         fh_unlock(&resp->dirfh);
282         RETURN_STATUS(nfserr);
283 }
284
285 static __be32
286 nfsd3_proc_symlink(struct svc_rqst *rqstp)
287 {
288         struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
289         struct nfsd3_diropres *resp = rqstp->rq_resp;
290         __be32  nfserr;
291
292         if (argp->tlen == 0)
293                 RETURN_STATUS(nfserr_inval);
294         if (argp->tlen > NFS3_MAXPATHLEN)
295                 RETURN_STATUS(nfserr_nametoolong);
296
297         argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
298                                                 page_address(rqstp->rq_arg.pages[0]),
299                                                 argp->tlen);
300         if (IS_ERR(argp->tname))
301                 RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
302
303         dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
304                                 SVCFH_fmt(&argp->ffh),
305                                 argp->flen, argp->fname,
306                                 argp->tlen, argp->tname);
307
308         fh_copy(&resp->dirfh, &argp->ffh);
309         fh_init(&resp->fh, NFS3_FHSIZE);
310         nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
311                                                    argp->tname, &resp->fh);
312         kfree(argp->tname);
313         RETURN_STATUS(nfserr);
314 }
315
316 /*
317  * Make socket/fifo/device.
318  */
319 static __be32
320 nfsd3_proc_mknod(struct svc_rqst *rqstp)
321 {
322         struct nfsd3_mknodargs *argp = rqstp->rq_argp;
323         struct nfsd3_diropres  *resp = rqstp->rq_resp;
324         __be32  nfserr;
325         int type;
326         dev_t   rdev = 0;
327
328         dprintk("nfsd: MKNOD(3)    %s %.*s\n",
329                                 SVCFH_fmt(&argp->fh),
330                                 argp->len,
331                                 argp->name);
332
333         fh_copy(&resp->dirfh, &argp->fh);
334         fh_init(&resp->fh, NFS3_FHSIZE);
335
336         if (argp->ftype == 0 || argp->ftype >= NF3BAD)
337                 RETURN_STATUS(nfserr_inval);
338         if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
339                 rdev = MKDEV(argp->major, argp->minor);
340                 if (MAJOR(rdev) != argp->major ||
341                     MINOR(rdev) != argp->minor)
342                         RETURN_STATUS(nfserr_inval);
343         } else
344                 if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
345                         RETURN_STATUS(nfserr_inval);
346
347         type = nfs3_ftypes[argp->ftype];
348         nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
349                                     &argp->attrs, type, rdev, &resp->fh);
350         fh_unlock(&resp->dirfh);
351         RETURN_STATUS(nfserr);
352 }
353
354 /*
355  * Remove file/fifo/socket etc.
356  */
357 static __be32
358 nfsd3_proc_remove(struct svc_rqst *rqstp)
359 {
360         struct nfsd3_diropargs *argp = rqstp->rq_argp;
361         struct nfsd3_attrstat *resp = rqstp->rq_resp;
362         __be32  nfserr;
363
364         dprintk("nfsd: REMOVE(3)   %s %.*s\n",
365                                 SVCFH_fmt(&argp->fh),
366                                 argp->len,
367                                 argp->name);
368
369         /* Unlink. -S_IFDIR means file must not be a directory */
370         fh_copy(&resp->fh, &argp->fh);
371         nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
372         fh_unlock(&resp->fh);
373         RETURN_STATUS(nfserr);
374 }
375
376 /*
377  * Remove a directory
378  */
379 static __be32
380 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
381 {
382         struct nfsd3_diropargs *argp = rqstp->rq_argp;
383         struct nfsd3_attrstat *resp = rqstp->rq_resp;
384         __be32  nfserr;
385
386         dprintk("nfsd: RMDIR(3)    %s %.*s\n",
387                                 SVCFH_fmt(&argp->fh),
388                                 argp->len,
389                                 argp->name);
390
391         fh_copy(&resp->fh, &argp->fh);
392         nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
393         fh_unlock(&resp->fh);
394         RETURN_STATUS(nfserr);
395 }
396
397 static __be32
398 nfsd3_proc_rename(struct svc_rqst *rqstp)
399 {
400         struct nfsd3_renameargs *argp = rqstp->rq_argp;
401         struct nfsd3_renameres *resp = rqstp->rq_resp;
402         __be32  nfserr;
403
404         dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
405                                 SVCFH_fmt(&argp->ffh),
406                                 argp->flen,
407                                 argp->fname);
408         dprintk("nfsd: -> %s %.*s\n",
409                                 SVCFH_fmt(&argp->tfh),
410                                 argp->tlen,
411                                 argp->tname);
412
413         fh_copy(&resp->ffh, &argp->ffh);
414         fh_copy(&resp->tfh, &argp->tfh);
415         nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
416                                     &resp->tfh, argp->tname, argp->tlen);
417         RETURN_STATUS(nfserr);
418 }
419
420 static __be32
421 nfsd3_proc_link(struct svc_rqst *rqstp)
422 {
423         struct nfsd3_linkargs *argp = rqstp->rq_argp;
424         struct nfsd3_linkres  *resp = rqstp->rq_resp;
425         __be32  nfserr;
426
427         dprintk("nfsd: LINK(3)     %s ->\n",
428                                 SVCFH_fmt(&argp->ffh));
429         dprintk("nfsd:   -> %s %.*s\n",
430                                 SVCFH_fmt(&argp->tfh),
431                                 argp->tlen,
432                                 argp->tname);
433
434         fh_copy(&resp->fh,  &argp->ffh);
435         fh_copy(&resp->tfh, &argp->tfh);
436         nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
437                                   &resp->fh);
438         RETURN_STATUS(nfserr);
439 }
440
441 /*
442  * Read a portion of a directory.
443  */
444 static __be32
445 nfsd3_proc_readdir(struct svc_rqst *rqstp)
446 {
447         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
448         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
449         __be32          nfserr;
450         int             count;
451
452         dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
453                                 SVCFH_fmt(&argp->fh),
454                                 argp->count, (u32) argp->cookie);
455
456         /* Make sure we've room for the NULL ptr & eof flag, and shrink to
457          * client read size */
458         count = (argp->count >> 2) - 2;
459
460         /* Read directory and encode entries on the fly */
461         fh_copy(&resp->fh, &argp->fh);
462
463         resp->buflen = count;
464         resp->common.err = nfs_ok;
465         resp->buffer = argp->buffer;
466         resp->rqstp = rqstp;
467         nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 
468                                         &resp->common, nfs3svc_encode_entry);
469         memcpy(resp->verf, argp->verf, 8);
470         resp->count = resp->buffer - argp->buffer;
471         if (resp->offset) {
472                 loff_t offset = argp->cookie;
473
474                 if (unlikely(resp->offset1)) {
475                         /* we ended up with offset on a page boundary */
476                         *resp->offset = htonl(offset >> 32);
477                         *resp->offset1 = htonl(offset & 0xffffffff);
478                         resp->offset1 = NULL;
479                 } else {
480                         xdr_encode_hyper(resp->offset, offset);
481                 }
482                 resp->offset = NULL;
483         }
484
485         RETURN_STATUS(nfserr);
486 }
487
488 /*
489  * Read a portion of a directory, including file handles and attrs.
490  * For now, we choose to ignore the dircount parameter.
491  */
492 static __be32
493 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
494 {
495         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
496         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
497         __be32  nfserr;
498         int     count = 0;
499         loff_t  offset;
500         struct page **p;
501         caddr_t page_addr = NULL;
502
503         dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
504                                 SVCFH_fmt(&argp->fh),
505                                 argp->count, (u32) argp->cookie);
506
507         /* Convert byte count to number of words (i.e. >> 2),
508          * and reserve room for the NULL ptr & eof flag (-2 words) */
509         resp->count = (argp->count >> 2) - 2;
510
511         /* Read directory and encode entries on the fly */
512         fh_copy(&resp->fh, &argp->fh);
513
514         resp->common.err = nfs_ok;
515         resp->buffer = argp->buffer;
516         resp->buflen = resp->count;
517         resp->rqstp = rqstp;
518         offset = argp->cookie;
519
520         nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
521         if (nfserr)
522                 RETURN_STATUS(nfserr);
523
524         if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS)
525                 RETURN_STATUS(nfserr_notsupp);
526
527         nfserr = nfsd_readdir(rqstp, &resp->fh,
528                                      &offset,
529                                      &resp->common,
530                                      nfs3svc_encode_entry_plus);
531         memcpy(resp->verf, argp->verf, 8);
532         for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
533                 page_addr = page_address(*p);
534
535                 if (((caddr_t)resp->buffer >= page_addr) &&
536                     ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
537                         count += (caddr_t)resp->buffer - page_addr;
538                         break;
539                 }
540                 count += PAGE_SIZE;
541         }
542         resp->count = count >> 2;
543         if (resp->offset) {
544                 if (unlikely(resp->offset1)) {
545                         /* we ended up with offset on a page boundary */
546                         *resp->offset = htonl(offset >> 32);
547                         *resp->offset1 = htonl(offset & 0xffffffff);
548                         resp->offset1 = NULL;
549                 } else {
550                         xdr_encode_hyper(resp->offset, offset);
551                 }
552                 resp->offset = NULL;
553         }
554
555         RETURN_STATUS(nfserr);
556 }
557
558 /*
559  * Get file system stats
560  */
561 static __be32
562 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
563 {
564         struct nfsd_fhandle *argp = rqstp->rq_argp;
565         struct nfsd3_fsstatres *resp = rqstp->rq_resp;
566         __be32  nfserr;
567
568         dprintk("nfsd: FSSTAT(3)   %s\n",
569                                 SVCFH_fmt(&argp->fh));
570
571         nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
572         fh_put(&argp->fh);
573         RETURN_STATUS(nfserr);
574 }
575
576 /*
577  * Get file system info
578  */
579 static __be32
580 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
581 {
582         struct nfsd_fhandle *argp = rqstp->rq_argp;
583         struct nfsd3_fsinfores *resp = rqstp->rq_resp;
584         __be32  nfserr;
585         u32     max_blocksize = svc_max_payload(rqstp);
586
587         dprintk("nfsd: FSINFO(3)   %s\n",
588                                 SVCFH_fmt(&argp->fh));
589
590         resp->f_rtmax  = max_blocksize;
591         resp->f_rtpref = max_blocksize;
592         resp->f_rtmult = PAGE_SIZE;
593         resp->f_wtmax  = max_blocksize;
594         resp->f_wtpref = max_blocksize;
595         resp->f_wtmult = PAGE_SIZE;
596         resp->f_dtpref = PAGE_SIZE;
597         resp->f_maxfilesize = ~(u32) 0;
598         resp->f_properties = NFS3_FSF_DEFAULT;
599
600         nfserr = fh_verify(rqstp, &argp->fh, 0,
601                         NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
602
603         /* Check special features of the file system. May request
604          * different read/write sizes for file systems known to have
605          * problems with large blocks */
606         if (nfserr == 0) {
607                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
608
609                 /* Note that we don't care for remote fs's here */
610                 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
611                         resp->f_properties = NFS3_FSF_BILLYBOY;
612                 }
613                 resp->f_maxfilesize = sb->s_maxbytes;
614         }
615
616         fh_put(&argp->fh);
617         RETURN_STATUS(nfserr);
618 }
619
620 /*
621  * Get pathconf info for the specified file
622  */
623 static __be32
624 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
625 {
626         struct nfsd_fhandle *argp = rqstp->rq_argp;
627         struct nfsd3_pathconfres *resp = rqstp->rq_resp;
628         __be32  nfserr;
629
630         dprintk("nfsd: PATHCONF(3) %s\n",
631                                 SVCFH_fmt(&argp->fh));
632
633         /* Set default pathconf */
634         resp->p_link_max = 255;         /* at least */
635         resp->p_name_max = 255;         /* at least */
636         resp->p_no_trunc = 0;
637         resp->p_chown_restricted = 1;
638         resp->p_case_insensitive = 0;
639         resp->p_case_preserving = 1;
640
641         nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
642
643         if (nfserr == 0) {
644                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
645
646                 /* Note that we don't care for remote fs's here */
647                 switch (sb->s_magic) {
648                 case EXT2_SUPER_MAGIC:
649                         resp->p_link_max = EXT2_LINK_MAX;
650                         resp->p_name_max = EXT2_NAME_LEN;
651                         break;
652                 case MSDOS_SUPER_MAGIC:
653                         resp->p_case_insensitive = 1;
654                         resp->p_case_preserving  = 0;
655                         break;
656                 }
657         }
658
659         fh_put(&argp->fh);
660         RETURN_STATUS(nfserr);
661 }
662
663
664 /*
665  * Commit a file (range) to stable storage.
666  */
667 static __be32
668 nfsd3_proc_commit(struct svc_rqst *rqstp)
669 {
670         struct nfsd3_commitargs *argp = rqstp->rq_argp;
671         struct nfsd3_commitres *resp = rqstp->rq_resp;
672         __be32  nfserr;
673
674         dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
675                                 SVCFH_fmt(&argp->fh),
676                                 argp->count,
677                                 (unsigned long long) argp->offset);
678
679         if (argp->offset > NFS_OFFSET_MAX)
680                 RETURN_STATUS(nfserr_inval);
681
682         fh_copy(&resp->fh, &argp->fh);
683         nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
684
685         RETURN_STATUS(nfserr);
686 }
687
688
689 /*
690  * NFSv3 Server procedures.
691  * Only the results of non-idempotent operations are cached.
692  */
693 #define nfs3svc_decode_fhandleargs      nfs3svc_decode_fhandle
694 #define nfs3svc_encode_attrstatres      nfs3svc_encode_attrstat
695 #define nfs3svc_encode_wccstatres       nfs3svc_encode_wccstat
696 #define nfsd3_mkdirargs                 nfsd3_createargs
697 #define nfsd3_readdirplusargs           nfsd3_readdirargs
698 #define nfsd3_fhandleargs               nfsd_fhandle
699 #define nfsd3_fhandleres                nfsd3_attrstat
700 #define nfsd3_attrstatres               nfsd3_attrstat
701 #define nfsd3_wccstatres                nfsd3_attrstat
702 #define nfsd3_createres                 nfsd3_diropres
703 #define nfsd3_voidres                   nfsd3_voidargs
704 struct nfsd3_voidargs { int dummy; };
705
706 #define ST 1            /* status*/
707 #define FH 17           /* filehandle with length */
708 #define AT 21           /* attributes */
709 #define pAT (1+AT)      /* post attributes - conditional */
710 #define WC (7+pAT)      /* WCC attributes */
711
712 static const struct svc_procedure nfsd_procedures3[22] = {
713         [NFS3PROC_NULL] = {
714                 .pc_func = nfsd3_proc_null,
715                 .pc_encode = nfs3svc_encode_voidres,
716                 .pc_argsize = sizeof(struct nfsd3_voidargs),
717                 .pc_ressize = sizeof(struct nfsd3_voidres),
718                 .pc_cachetype = RC_NOCACHE,
719                 .pc_xdrressize = ST,
720         },
721         [NFS3PROC_GETATTR] = {
722                 .pc_func = nfsd3_proc_getattr,
723                 .pc_decode = nfs3svc_decode_fhandleargs,
724                 .pc_encode = nfs3svc_encode_attrstatres,
725                 .pc_release = nfs3svc_release_fhandle,
726                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
727                 .pc_ressize = sizeof(struct nfsd3_attrstatres),
728                 .pc_cachetype = RC_NOCACHE,
729                 .pc_xdrressize = ST+AT,
730         },
731         [NFS3PROC_SETATTR] = {
732                 .pc_func = nfsd3_proc_setattr,
733                 .pc_decode = nfs3svc_decode_sattrargs,
734                 .pc_encode = nfs3svc_encode_wccstatres,
735                 .pc_release = nfs3svc_release_fhandle,
736                 .pc_argsize = sizeof(struct nfsd3_sattrargs),
737                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
738                 .pc_cachetype = RC_REPLBUFF,
739                 .pc_xdrressize = ST+WC,
740         },
741         [NFS3PROC_LOOKUP] = {
742                 .pc_func = nfsd3_proc_lookup,
743                 .pc_decode = nfs3svc_decode_diropargs,
744                 .pc_encode = nfs3svc_encode_diropres,
745                 .pc_release = nfs3svc_release_fhandle2,
746                 .pc_argsize = sizeof(struct nfsd3_diropargs),
747                 .pc_ressize = sizeof(struct nfsd3_diropres),
748                 .pc_cachetype = RC_NOCACHE,
749                 .pc_xdrressize = ST+FH+pAT+pAT,
750         },
751         [NFS3PROC_ACCESS] = {
752                 .pc_func = nfsd3_proc_access,
753                 .pc_decode = nfs3svc_decode_accessargs,
754                 .pc_encode = nfs3svc_encode_accessres,
755                 .pc_release = nfs3svc_release_fhandle,
756                 .pc_argsize = sizeof(struct nfsd3_accessargs),
757                 .pc_ressize = sizeof(struct nfsd3_accessres),
758                 .pc_cachetype = RC_NOCACHE,
759                 .pc_xdrressize = ST+pAT+1,
760         },
761         [NFS3PROC_READLINK] = {
762                 .pc_func = nfsd3_proc_readlink,
763                 .pc_decode = nfs3svc_decode_readlinkargs,
764                 .pc_encode = nfs3svc_encode_readlinkres,
765                 .pc_release = nfs3svc_release_fhandle,
766                 .pc_argsize = sizeof(struct nfsd3_readlinkargs),
767                 .pc_ressize = sizeof(struct nfsd3_readlinkres),
768                 .pc_cachetype = RC_NOCACHE,
769                 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
770         },
771         [NFS3PROC_READ] = {
772                 .pc_func = nfsd3_proc_read,
773                 .pc_decode = nfs3svc_decode_readargs,
774                 .pc_encode = nfs3svc_encode_readres,
775                 .pc_release = nfs3svc_release_fhandle,
776                 .pc_argsize = sizeof(struct nfsd3_readargs),
777                 .pc_ressize = sizeof(struct nfsd3_readres),
778                 .pc_cachetype = RC_NOCACHE,
779                 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
780         },
781         [NFS3PROC_WRITE] = {
782                 .pc_func = nfsd3_proc_write,
783                 .pc_decode = nfs3svc_decode_writeargs,
784                 .pc_encode = nfs3svc_encode_writeres,
785                 .pc_release = nfs3svc_release_fhandle,
786                 .pc_argsize = sizeof(struct nfsd3_writeargs),
787                 .pc_ressize = sizeof(struct nfsd3_writeres),
788                 .pc_cachetype = RC_REPLBUFF,
789                 .pc_xdrressize = ST+WC+4,
790         },
791         [NFS3PROC_CREATE] = {
792                 .pc_func = nfsd3_proc_create,
793                 .pc_decode = nfs3svc_decode_createargs,
794                 .pc_encode = nfs3svc_encode_createres,
795                 .pc_release = nfs3svc_release_fhandle2,
796                 .pc_argsize = sizeof(struct nfsd3_createargs),
797                 .pc_ressize = sizeof(struct nfsd3_createres),
798                 .pc_cachetype = RC_REPLBUFF,
799                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
800         },
801         [NFS3PROC_MKDIR] = {
802                 .pc_func = nfsd3_proc_mkdir,
803                 .pc_decode = nfs3svc_decode_mkdirargs,
804                 .pc_encode = nfs3svc_encode_createres,
805                 .pc_release = nfs3svc_release_fhandle2,
806                 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
807                 .pc_ressize = sizeof(struct nfsd3_createres),
808                 .pc_cachetype = RC_REPLBUFF,
809                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
810         },
811         [NFS3PROC_SYMLINK] = {
812                 .pc_func = nfsd3_proc_symlink,
813                 .pc_decode = nfs3svc_decode_symlinkargs,
814                 .pc_encode = nfs3svc_encode_createres,
815                 .pc_release = nfs3svc_release_fhandle2,
816                 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
817                 .pc_ressize = sizeof(struct nfsd3_createres),
818                 .pc_cachetype = RC_REPLBUFF,
819                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
820         },
821         [NFS3PROC_MKNOD] = {
822                 .pc_func = nfsd3_proc_mknod,
823                 .pc_decode = nfs3svc_decode_mknodargs,
824                 .pc_encode = nfs3svc_encode_createres,
825                 .pc_release = nfs3svc_release_fhandle2,
826                 .pc_argsize = sizeof(struct nfsd3_mknodargs),
827                 .pc_ressize = sizeof(struct nfsd3_createres),
828                 .pc_cachetype = RC_REPLBUFF,
829                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
830         },
831         [NFS3PROC_REMOVE] = {
832                 .pc_func = nfsd3_proc_remove,
833                 .pc_decode = nfs3svc_decode_diropargs,
834                 .pc_encode = nfs3svc_encode_wccstatres,
835                 .pc_release = nfs3svc_release_fhandle,
836                 .pc_argsize = sizeof(struct nfsd3_diropargs),
837                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
838                 .pc_cachetype = RC_REPLBUFF,
839                 .pc_xdrressize = ST+WC,
840         },
841         [NFS3PROC_RMDIR] = {
842                 .pc_func = nfsd3_proc_rmdir,
843                 .pc_decode = nfs3svc_decode_diropargs,
844                 .pc_encode = nfs3svc_encode_wccstatres,
845                 .pc_release = nfs3svc_release_fhandle,
846                 .pc_argsize = sizeof(struct nfsd3_diropargs),
847                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
848                 .pc_cachetype = RC_REPLBUFF,
849                 .pc_xdrressize = ST+WC,
850         },
851         [NFS3PROC_RENAME] = {
852                 .pc_func = nfsd3_proc_rename,
853                 .pc_decode = nfs3svc_decode_renameargs,
854                 .pc_encode = nfs3svc_encode_renameres,
855                 .pc_release = nfs3svc_release_fhandle2,
856                 .pc_argsize = sizeof(struct nfsd3_renameargs),
857                 .pc_ressize = sizeof(struct nfsd3_renameres),
858                 .pc_cachetype = RC_REPLBUFF,
859                 .pc_xdrressize = ST+WC+WC,
860         },
861         [NFS3PROC_LINK] = {
862                 .pc_func = nfsd3_proc_link,
863                 .pc_decode = nfs3svc_decode_linkargs,
864                 .pc_encode = nfs3svc_encode_linkres,
865                 .pc_release = nfs3svc_release_fhandle2,
866                 .pc_argsize = sizeof(struct nfsd3_linkargs),
867                 .pc_ressize = sizeof(struct nfsd3_linkres),
868                 .pc_cachetype = RC_REPLBUFF,
869                 .pc_xdrressize = ST+pAT+WC,
870         },
871         [NFS3PROC_READDIR] = {
872                 .pc_func = nfsd3_proc_readdir,
873                 .pc_decode = nfs3svc_decode_readdirargs,
874                 .pc_encode = nfs3svc_encode_readdirres,
875                 .pc_release = nfs3svc_release_fhandle,
876                 .pc_argsize = sizeof(struct nfsd3_readdirargs),
877                 .pc_ressize = sizeof(struct nfsd3_readdirres),
878                 .pc_cachetype = RC_NOCACHE,
879         },
880         [NFS3PROC_READDIRPLUS] = {
881                 .pc_func = nfsd3_proc_readdirplus,
882                 .pc_decode = nfs3svc_decode_readdirplusargs,
883                 .pc_encode = nfs3svc_encode_readdirres,
884                 .pc_release = nfs3svc_release_fhandle,
885                 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
886                 .pc_ressize = sizeof(struct nfsd3_readdirres),
887                 .pc_cachetype = RC_NOCACHE,
888         },
889         [NFS3PROC_FSSTAT] = {
890                 .pc_func = nfsd3_proc_fsstat,
891                 .pc_decode = nfs3svc_decode_fhandleargs,
892                 .pc_encode = nfs3svc_encode_fsstatres,
893                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
894                 .pc_ressize = sizeof(struct nfsd3_fsstatres),
895                 .pc_cachetype = RC_NOCACHE,
896                 .pc_xdrressize = ST+pAT+2*6+1,
897         },
898         [NFS3PROC_FSINFO] = {
899                 .pc_func = nfsd3_proc_fsinfo,
900                 .pc_decode = nfs3svc_decode_fhandleargs,
901                 .pc_encode = nfs3svc_encode_fsinfores,
902                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
903                 .pc_ressize = sizeof(struct nfsd3_fsinfores),
904                 .pc_cachetype = RC_NOCACHE,
905                 .pc_xdrressize = ST+pAT+12,
906         },
907         [NFS3PROC_PATHCONF] = {
908                 .pc_func = nfsd3_proc_pathconf,
909                 .pc_decode = nfs3svc_decode_fhandleargs,
910                 .pc_encode = nfs3svc_encode_pathconfres,
911                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
912                 .pc_ressize = sizeof(struct nfsd3_pathconfres),
913                 .pc_cachetype = RC_NOCACHE,
914                 .pc_xdrressize = ST+pAT+6,
915         },
916         [NFS3PROC_COMMIT] = {
917                 .pc_func = nfsd3_proc_commit,
918                 .pc_decode = nfs3svc_decode_commitargs,
919                 .pc_encode = nfs3svc_encode_commitres,
920                 .pc_release = nfs3svc_release_fhandle,
921                 .pc_argsize = sizeof(struct nfsd3_commitargs),
922                 .pc_ressize = sizeof(struct nfsd3_commitres),
923                 .pc_cachetype = RC_NOCACHE,
924                 .pc_xdrressize = ST+WC+2,
925         },
926 };
927
928 static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
929 const struct svc_version nfsd_version3 = {
930         .vs_vers        = 3,
931         .vs_nproc       = 22,
932         .vs_proc        = nfsd_procedures3,
933         .vs_dispatch    = nfsd_dispatch,
934         .vs_count       = nfsd_count3,
935         .vs_xdrsize     = NFS3_SVC_XDRSIZE,
936 };