GNU Linux-libre 5.19-gnu
[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 #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 };