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

Archive Download this file



interactive