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