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