Import 2.3.7pre9
[davej-history.git] / fs / nfsd / nfs3xdr.c
blob31a5ef88795d46021790a87bafb501fbe7724c37
1 /*
2 * linux/fs/nfsd/nfs3xdr.c
4 * XDR support for nfsd/protocol version 3.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */
9 #include <linux/types.h>
10 #include <linux/sched.h>
11 #include <linux/nfs3.h>
13 #include <linux/sunrpc/xdr.h>
14 #include <linux/sunrpc/svc.h>
15 #include <linux/nfsd/nfsd.h>
16 #include <linux/nfsd/xdr3.h>
18 #define NFSDDBG_FACILITY NFSDDBG_XDR
20 u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
21 nfserr_acces, nfserr_exist, nfserr_nodev, nfserr_notdir,
22 nfserr_isdir, nfserr_fbig, nfserr_nospc, nfserr_rofs,
23 nfserr_nametoolong, nfserr_dquot, nfserr_stale;
25 #ifdef NFSD_OPTIMIZE_SPACE
26 # define inline
27 #endif
30 * Mapping of S_IF* types to NFS file types
32 static u32 nfs3_ftypes[] = {
33 NF3NON, NF3FIFO, NF3CHR, NF3BAD,
34 NF3DIR, NF3BAD, NF3BLK, NF3BAD,
35 NF3REG, NF3BAD, NF3LNK, NF3BAD,
36 NF3SOCK, NF3BAD, NF3LNK, NF3BAD,
40 * Initialization of NFS status variables
42 void
43 nfs3xdr_init(void)
45 static int inited = 0;
47 if (inited)
48 return;
50 nfs_ok = htonl(NFS_OK);
51 nfserr_perm = htonl(NFSERR_PERM);
52 nfserr_noent = htonl(NFSERR_NOENT);
53 nfserr_io = htonl(NFSERR_IO);
54 nfserr_nxio = htonl(NFSERR_NXIO);
55 nfserr_acces = htonl(NFSERR_ACCES);
56 nfserr_exist = htonl(NFSERR_EXIST);
57 nfserr_nodev = htonl(NFSERR_NODEV);
58 nfserr_notdir = htonl(NFSERR_NOTDIR);
59 nfserr_isdir = htonl(NFSERR_ISDIR);
60 nfserr_fbig = htonl(NFSERR_FBIG);
61 nfserr_nospc = htonl(NFSERR_NOSPC);
62 nfserr_rofs = htonl(NFSERR_ROFS);
63 nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
64 nfserr_dquot = htonl(NFSERR_DQUOT);
65 nfserr_stale = htonl(NFSERR_STALE);
67 inited = 1;
71 * XDR functions for basic NFS types
73 static inline u32 *
74 enc64(u32 *p, u64 val)
76 *p++ = (val >> 32);
77 *p++ = (val & 0xffffffff);
78 return p;
81 static inline u32 *
82 dec64(u32 *p, u64 *valp)
84 *valp = ((u64) ntohl(*p++)) << 32;
85 *valp |= ntohl(*p++);
86 return p;
89 static inline u32 *
90 encode_time3(u32 *p, time_t secs)
92 *p++ = htonl((u32) secs); *p++ = 0;
93 return p;
96 static inline u32 *
97 decode_time3(u32 *p, time_t *secp)
99 *secp = ntohl(*p++);
100 return p + 1;
103 static inline u32 *
104 decode_fh(u32 *p, struct svc_fh *fhp)
106 if (*p++ != sizeof(struct knfs_fh))
107 return NULL;
109 memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
110 fhp->fh_inode = NULL;
111 fhp->fh_export = NULL;
113 return p + (sizeof(struct knfs_fh) >> 2);
116 static inline u32 *
117 encode_fh(u32 *p, struct svc_fh *fhp)
119 *p++ = htonl(sizeof(struct knfs_fh));
120 memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
121 return p + (sizeof(struct knfs_fh) >> 2);
125 * Decode a file name and make sure that the path contains
126 * no slashes or null bytes.
128 static inline u32 *
129 decode_filename(u32 *p, char **namp, int *lenp)
131 char *name;
132 int i;
134 if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
135 for (i = 0, name = *namp; i < *lenp; i++, name++) {
136 if (*name == '\0' || *name == '/')
137 return NULL;
139 *name = '\0';
142 return p;
145 static inline u32 *
146 decode_pathname(u32 *p, char **namp, int *lenp)
148 char *name;
149 int i;
151 if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
152 for (i = 0, name = *namp; i < *lenp; i++, name++) {
153 if (*name == '\0')
154 return NULL;
156 *name = '\0';
159 return p;
162 static inline u32 *
163 decode_sattr3(u32 *p, struct iattr *iap)
165 u32 tmp;
167 iap->ia_valid = 0;
169 if (*p++) {
170 iap->ia_valid |= ATTR_MODE;
171 iap->ia_mode = ntohl(*p++);
173 if (*p++) {
174 iap->ia_valid |= ATTR_UID;
175 iap->ia_uid = ntohl(*p++);
177 if (*p++) {
178 iap->ia_valid |= ATTR_GID;
179 iap->ia_gid = ntohl(*p++);
181 if (*p++) {
182 iap->ia_valid |= ATTR_SIZE;
183 iap->ia_size = ntohl(*p++);
185 if ((tmp = *p++) == 1) {
186 iap->ia_valid |= ATTR_ATIME;
187 } else if (tmp == 2) {
188 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
189 iap->ia_atime = ntohl(*p++), p++;
191 if ((tmp = *p++) != 0) {
192 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
193 } else if (tmp == 2) {
194 iap->ia_valid |= ATTR_MTIME;
195 iap->ia_mtime = ntohl(*p++), p++;
197 return p;
200 static inline u32 *
201 encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
203 if (!inode) {
204 printk("nfsd: NULL inode in %s:%d", __FILE__, __LINE__);
205 return NULL;
208 *p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
209 *p++ = htonl((u32) inode->i_mode);
210 *p++ = htonl((u32) inode->i_nlink);
211 *p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
212 *p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
213 if (S_ISLNK(inode->i_mode) && inode->i_size > NFS3_MAXPATHLEN) {
214 p = enc64(p, (u64) NFS3_MAXPATHLEN);
215 } else {
216 p = enc64(p, (u64) inode->i_size);
218 p = enc64(p, inode->i_blksize * inode->i_blocks);
219 *p++ = htonl((u32) MAJOR(inode->i_rdev));
220 *p++ = htonl((u32) MINOR(inode->i_rdev));
221 p = enc64(p, (u64) inode->i_dev);
222 p = enc64(p, (u64) inode->i_ino);
223 p = encode_time3(p, inode->i_atime);
224 p = encode_time3(p, inode->i_mtime);
225 p = encode_time3(p, inode->i_ctime);
227 return p;
231 * Encode post-operation attributes.
232 * The inode may be NULL if the call failed because of a stale file
233 * handle. In this case, no attributes are returned.
235 static u32 *
236 encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
238 if (inode == NULL) {
239 *p++ = xdr_zero;
240 return p;
242 return encode_fattr3(rqstp, p, inode);
246 * Enocde weak cache consistency data
248 static u32 *
249 encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
251 struct inode *inode = fhp->fh_inode;
253 if (fhp->fh_post_version == inode->i_version) {
254 *p++ = xdr_one;
255 p = enc64(p, (u64) fhp->fh_pre_size);
256 p = encode_time3(p, fhp->fh_pre_mtime);
257 p = encode_time3(p, fhp->fh_pre_ctime);
258 } else {
259 *p++ = xdr_zero;
261 return encode_post_op_attr(rqstp, p, inode);
265 * Check buffer bounds after decoding arguments
267 static inline int
268 xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
270 struct svc_buf *buf = &rqstp->rq_argbuf;
272 return p - buf->base <= buf->buflen;
275 static inline int
276 xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
278 struct svc_buf *buf = &rqstp->rq_resbuf;
280 buf->len = p - buf->base;
281 dprintk("nfsd: ressize_check p %p base %p len %d\n",
282 p, buf->base, buf->buflen);
283 return (buf->len <= buf->buflen);
287 * XDR decode functions
290 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
292 if (!(p = decode_fh(p, fhp)))
293 return 0;
294 return xdr_argsize_check(rqstp, p);
298 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
299 struct nfsd3_sattrargs *args)
301 if (!(p = decode_fh(p, &args->fh))
302 || !(p = decode_sattr3(p, &args->attrs))
303 || (*p++ && !(p = decode_time3(p, &args->guardtime))))
304 return 0;
306 return xdr_argsize_check(rqstp, p);
310 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
311 struct nfsd3_diropargs *args)
313 if (!(p = decode_fh(p, &args->fh))
314 || !(p = decode_filename(p, &args->name, &args->len)))
315 return 0;
317 return xdr_argsize_check(rqstp, p);
321 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
322 struct nfsd3_accessargs *args)
324 if (!(p = decode_fh(p, &args->fh)))
325 return 0;
326 args->access = ntohl(*p++);
328 return xdr_argsize_check(rqstp, p);
332 nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
333 struct nfsd3_readargs *args)
335 if (!(p = decode_fh(p, &args->fh))
336 || !(p = dec64(p, &args->offset))
337 || !(p = dec64(p, &args->count)))
338 return 0;
340 return xdr_argsize_check(rqstp, p);
344 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
345 struct nfsd3_writeargs *args)
347 if (!(p = decode_fh(p, &args->fh))
348 || !(p = dec64(p, &args->offset))
349 || !(p = dec64(p, &args->count)))
350 return 0;
352 args->stable = ntohl(*p++);
353 args->len = ntohl(*p++);
354 args->data = (char *) p;
355 p += (args->len + 3) >> 2;
357 return xdr_argsize_check(rqstp, p);
361 nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
362 struct nfsd3_createargs *args)
364 if (!(p = decode_fh(p, &args->fh))
365 || !(p = decode_filename(p, &args->name, &args->len)))
366 return 0;
368 switch (args->createmode = ntohl(*p++)) {
369 case 0: case 1:
370 if (!(p = decode_sattr3(p, &args->attrs)))
371 return 0;
372 break;
373 case 2:
374 args->verf = p;
375 p += 2;
376 break;
377 default:
378 return 0;
381 return xdr_argsize_check(rqstp, p);
384 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p,
385 struct nfsd3_createargs *args)
387 if (!(p = decode_fh(p, &args->fh))
388 || !(p = decode_filename(p, &args->name, &args->len))
389 || !(p = decode_sattr3(p, &args->attrs)))
390 return 0;
392 return xdr_argsize_check(rqstp, p);
396 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
397 struct nfsd3_symlinkargs *args)
399 if (!(p = decode_fh(p, &args->ffh))
400 || !(p = decode_filename(p, &args->fname, &args->flen))
401 || !(p = decode_sattr3(p, &args->attrs))
402 || !(p = decode_pathname(p, &args->tname, &args->tlen)))
403 return 0;
405 return xdr_argsize_check(rqstp, p);
409 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p,
410 struct nfsd3_mknodargs *args)
412 if (!(p = decode_fh(p, &args->fh))
413 || !(p = decode_filename(p, &args->name, &args->len)))
414 return 0;
416 args->ftype = ntohl(*p++);
418 if (args->ftype == NF3BLK || args->ftype == NF3CHR
419 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
420 if (!(p = decode_sattr3(p, &args->attrs)))
421 return 0;
424 if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
425 args->major = ntohl(*p++);
426 args->minor = ntohl(*p++);
429 return xdr_argsize_check(rqstp, p);
433 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
434 struct nfsd3_renameargs *args)
436 if (!(p = decode_fh(p, &args->ffh))
437 || !(p = decode_filename(p, &args->fname, &args->flen))
438 || !(p = decode_fh(p, &args->tfh))
439 || !(p = decode_filename(p, &args->tname, &args->tlen)))
440 return 0;
442 return xdr_argsize_check(rqstp, p);
446 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
447 struct nfsd3_linkargs *args)
449 if (!(p = decode_fh(p, &args->ffh))
450 || !(p = decode_fh(p, &args->tfh))
451 || !(p = decode_filename(p, &args->tname, &args->tlen)))
452 return 0;
454 return xdr_argsize_check(rqstp, p);
458 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
459 struct nfsd3_readdirargs *args)
461 if (!(p = decode_fh(p, &args->fh)))
462 return 0;
463 args->cookie = ntohl(*p++);
464 args->verf = p; p += 2;
465 args->count = ntohl(*p++);
467 return xdr_argsize_check(rqstp, p);
471 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
472 struct nfsd3_readdirargs *args)
474 if (!(p = decode_fh(p, &args->fh)))
475 return 0;
476 args->cookie = ntohl(*p++);
477 args->verf = p; p += 2;
478 args->dircount = ntohl(*p++);
479 args->count = ntohl(*p++);
481 return xdr_argsize_check(rqstp, p);
485 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
486 struct nfsd3_commitargs *args)
488 if (!(p = decode_fh(p, &args->fh))
489 || !(p = dec64(p, &args->offset)))
490 return 0;
491 args->count = ntohl(*p++);
493 return xdr_argsize_check(rqstp, p);
497 * XDR encode functions
499 /* GETATTR */
501 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
502 struct nfsd3_attrstat *resp)
504 if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
505 return 0;
506 return xdr_ressize_check(rqstp, p);
509 /* SETATTR, REMOVE, RMDIR */
511 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
512 struct nfsd3_attrstat *resp)
514 if (!(p = encode_wcc_data(rqstp, p, &resp->fh)))
515 return 0;
516 return xdr_ressize_check(rqstp, p);
519 /* LOOKUP */
521 nfs3svc_encode_lookupres(struct svc_rqst *rqstp, u32 *p,
522 struct nfsd3_lookupres *resp)
524 if (resp->status == 0) {
525 p = encode_fh(p, &resp->fh);
526 if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
527 return 0;
529 p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_inode);
530 return xdr_ressize_check(rqstp, p);
533 /* ACCESS */
535 nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
536 struct nfsd3_accessres *resp)
538 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
539 if (resp->status == 0)
540 *p++ = htonl(resp->access);
541 return xdr_ressize_check(rqstp, p);
544 /* READLINK */
546 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
547 struct nfsd3_readlinkres *resp)
549 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
550 if (resp->status == 0) {
551 *p++ = htonl(resp->len);
552 p += XDR_QUADLEN(resp->len);
554 return xdr_ressize_check(rqstp, p);
557 /* READ */
559 nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
560 struct nfsd3_readres *resp)
562 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
563 if (resp->status == 0) {
564 *p++ = htonl(resp->count);
565 *p++ = htonl(resp->eof);
566 *p++ = htonl(resp->count); /* xdr opaque count */
567 p += XDR_QUADLEN(resp->count);
569 return xdr_ressize_check(rqstp, p);
572 /* WRITE */
574 nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
575 struct nfsd3_writeres *resp)
577 p = encode_wcc_data(rqstp, p, &resp->fh);
578 if (resp->status == 0) {
579 *p++ = htonl(resp->count);
580 *p++ = htonl(resp->committed);
581 *p++ = htonl(nfssvc_boot.tv_sec);
582 *p++ = htonl(nfssvc_boot.tv_usec);
584 return xdr_ressize_check(rqstp, p);
587 /* CREATE, MKDIR, SYMLINK, MKNOD */
589 nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
590 struct nfsd3_createres *resp)
592 if (resp->status == 0) {
593 p = encode_fh(p, &resp->fh);
594 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
596 p = encode_wcc_data(rqstp, p, &resp->dirfh);
597 return xdr_ressize_check(rqstp, p);
600 /* RENAME */
602 nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
603 struct nfsd3_renameres *resp)
605 p = encode_wcc_data(rqstp, p, &resp->ffh);
606 p = encode_wcc_data(rqstp, p, &resp->tfh);
607 return xdr_ressize_check(rqstp, p);
610 /* LINK */
612 nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
613 struct nfsd3_linkres *resp)
615 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
616 p = encode_wcc_data(rqstp, p, &resp->tfh);
617 return xdr_ressize_check(rqstp, p);
620 /* READDIR */
622 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
623 struct nfsd3_readdirres *resp)
625 p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
626 if (resp->status == 0) {
627 /* stupid readdir cookie */
628 *p++ = ntohl(resp->fh.fh_inode->i_mtime);
629 *p++ = xdr_zero;
630 p = resp->list_end;
633 return xdr_ressize_check(rqstp, p);
636 #define NFS3_ENTRYPLUS_BAGGAGE ((1 + 20 + 1 + NFS3_FHSIZE) << 2)
638 nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
639 int namlen, unsigned long offset, ino_t ino)
641 u32 *p = cd->buffer;
642 int buflen, slen, elen;
643 struct svc_fh fh;
645 if (offset > ~((u64) 0))
646 return -EINVAL;
647 if (cd->offset)
648 *cd->offset = htonl(offset);
650 /* For readdirplus, look up the inode */
651 if (cd->plus && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh))
652 return 0;
654 /* truncate filename if too long */
655 if (namlen > NFS3_MAXNAMLEN)
656 namlen = NFS3_MAXNAMLEN;
658 slen = XDR_QUADLEN(namlen);
659 elen = slen + (cd->plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
660 if ((buflen = cd->buflen - elen - 4) < 0) {
661 cd->eob = 1;
662 if (cd->plus)
663 fh_put(&fh);
664 return -EINVAL;
666 *p++ = xdr_one; /* mark entry present */
667 *p++ = xdr_zero; /* file id (64 bit) */
668 *p++ = htonl((u32) ino);
669 *p++ = htonl((u32) namlen); /* name length & name */
670 memcpy(p, name, namlen);
671 p += slen;
673 /* throw in readdirplus baggage */
674 if (cd->plus) {
675 p = encode_post_op_attr(cd->rqstp, p, fh.fh_inode);
676 p = encode_fh(p, &fh);
677 fh_put(&fh);
680 cd->offset = p; /* remember pointer */
681 p = enc64(p, ~(u64) 0); /* offset of next entry */
683 cd->buflen = buflen;
684 cd->buffer = p;
685 return 0;
688 /* FSSTAT */
690 nfs3svc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
691 struct nfsd3_statfsres *resp)
693 struct statfs *s = &resp->stats;
694 u64 bs = s->f_bsize;
696 *p++ = xdr_zero; /* no post_op_attr */
698 if (resp->status == 0) {
699 p = enc64(p, bs * s->f_blocks); /* total bytes */
700 p = enc64(p, bs * s->f_bfree); /* free bytes */
701 p = enc64(p, bs * s->f_bavail); /* user available bytes */
702 p = enc64(p, s->f_files); /* total inodes */
703 p = enc64(p, s->f_ffree); /* free inodes */
704 p = enc64(p, s->f_ffree); /* user available inodes */
705 *p++ = htonl(resp->invarsec); /* mean unchanged time */
707 return xdr_ressize_check(rqstp, p);
710 /* FSINFO */
712 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
713 struct nfsd3_fsinfores *resp)
715 *p++ = xdr_zero; /* no post_op_attr */
717 if (resp->status == 0) {
718 *p++ = htonl(resp->f_rtmax);
719 *p++ = htonl(resp->f_rtpref);
720 *p++ = htonl(resp->f_rtmult);
721 *p++ = htonl(resp->f_wtmax);
722 *p++ = htonl(resp->f_wtpref);
723 *p++ = htonl(resp->f_wtmult);
724 *p++ = htonl(resp->f_dtpref);
725 *p++ = htonl(resp->f_maxfilesize);
726 *p++ = xdr_zero;
727 *p++ = htonl(1000000000 / HZ);
728 *p++ = htonl(resp->f_properties);
731 return xdr_ressize_check(rqstp, p);
734 /* PATHCONF */
736 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
737 struct nfsd3_pathconfres *resp)
739 *p++ = xdr_zero; /* no post_op_attr */
741 if (resp->status == 0) {
742 *p++ = htonl(resp->p_link_max);
743 *p++ = htonl(resp->p_name_max);
744 *p++ = xdr_one; /* always reject long file names */
745 *p++ = xdr_one; /* chown restricted */
746 *p++ = htonl(resp->p_case_insensitive);
747 *p++ = htonl(resp->p_case_preserving);
750 return xdr_ressize_check(rqstp, p);
753 /* COMMIT */
755 nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
756 struct nfsd3_commitres *resp)
758 p = encode_wcc_data(rqstp, p, &resp->fh);
759 /* Write verifier */
760 if (resp->status == 0) {
761 *p++ = htonl(nfssvc_boot.tv_sec);
762 *p++ = htonl(nfssvc_boot.tv_usec);
764 return xdr_ressize_check(rqstp, p);
768 * XDR release functions
771 nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
772 struct nfsd_fhandle *resp)
774 fh_put(&resp->fh);
775 return 1;
779 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
780 struct nfsd3_fhandle2 *resp)
782 fh_put(&resp->fh1);
783 fh_put(&resp->fh2);
784 return 1;