2 * linux/fs/nfsd/nfs3xdr.c
4 * XDR support for nfsd/protocol version 3.
6 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
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 #ifdef NFSD_OPTIMIZE_SPACE
26 * Mapping of S_IF* types to NFS file types
28 static u32 nfs3_ftypes
[] = {
29 NF3NON
, NF3FIFO
, NF3CHR
, NF3BAD
,
30 NF3DIR
, NF3BAD
, NF3BLK
, NF3BAD
,
31 NF3REG
, NF3BAD
, NF3LNK
, NF3BAD
,
32 NF3SOCK
, NF3BAD
, NF3LNK
, NF3BAD
,
36 * XDR functions for basic NFS types
39 encode_time3(u32
*p
, time_t secs
)
41 *p
++ = htonl((u32
) secs
); *p
++ = 0;
46 decode_time3(u32
*p
, time_t *secp
)
53 decode_fh(u32
*p
, struct svc_fh
*fhp
)
56 fh_init(fhp
, NFS3_FHSIZE
);
58 if (size
> NFS3_FHSIZE
)
61 memcpy(&fhp
->fh_handle
.fh_base
, p
, size
);
62 fhp
->fh_handle
.fh_size
= size
;
63 return p
+ XDR_QUADLEN(size
);
67 encode_fh(u32
*p
, struct svc_fh
*fhp
)
69 int size
= fhp
->fh_handle
.fh_size
;
71 if (size
) p
[XDR_QUADLEN(size
)-1]=0;
72 memcpy(p
, &fhp
->fh_handle
.fh_base
, size
);
73 return p
+ XDR_QUADLEN(size
);
77 * Decode a file name and make sure that the path contains
78 * no slashes or null bytes.
81 decode_filename(u32
*p
, char **namp
, int *lenp
)
86 if ((p
= xdr_decode_string(p
, namp
, lenp
, NFS3_MAXNAMLEN
)) != NULL
) {
87 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
88 if (*name
== '\0' || *name
== '/')
98 decode_pathname(u32
*p
, char **namp
, int *lenp
)
103 if ((p
= xdr_decode_string(p
, namp
, lenp
, NFS3_MAXPATHLEN
)) != NULL
) {
104 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
115 decode_sattr3(u32
*p
, struct iattr
*iap
)
122 iap
->ia_valid
|= ATTR_MODE
;
123 iap
->ia_mode
= ntohl(*p
++);
126 iap
->ia_valid
|= ATTR_UID
;
127 iap
->ia_uid
= ntohl(*p
++);
130 iap
->ia_valid
|= ATTR_GID
;
131 iap
->ia_gid
= ntohl(*p
++);
136 iap
->ia_valid
|= ATTR_SIZE
;
137 p
= xdr_decode_hyper(p
, &newsize
);
138 if (newsize
<= NFS_OFFSET_MAX
)
139 iap
->ia_size
= newsize
;
141 iap
->ia_size
= NFS_OFFSET_MAX
;
143 if ((tmp
= ntohl(*p
++)) == 1) { /* set to server time */
144 iap
->ia_valid
|= ATTR_ATIME
;
145 } else if (tmp
== 2) { /* set to client time */
146 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
147 iap
->ia_atime
= ntohl(*p
++), p
++;
149 if ((tmp
= ntohl(*p
++)) == 1) { /* set to server time */
150 iap
->ia_valid
|= ATTR_MTIME
;
151 } else if (tmp
== 2) { /* set to client time */
152 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
153 iap
->ia_mtime
= ntohl(*p
++), p
++;
159 encode_fattr3(struct svc_rqst
*rqstp
, u32
*p
, struct dentry
*dentry
)
161 struct inode
*inode
= dentry
->d_inode
;
164 printk("nfsd: NULL inode in %s:%d", __FILE__
, __LINE__
);
168 *p
++ = htonl(nfs3_ftypes
[(inode
->i_mode
& S_IFMT
) >> 12]);
169 *p
++ = htonl((u32
) inode
->i_mode
);
170 *p
++ = htonl((u32
) inode
->i_nlink
);
171 *p
++ = htonl((u32
) nfsd_ruid(rqstp
, inode
->i_uid
));
172 *p
++ = htonl((u32
) nfsd_rgid(rqstp
, inode
->i_gid
));
173 if (S_ISLNK(inode
->i_mode
) && inode
->i_size
> NFS3_MAXPATHLEN
) {
174 p
= xdr_encode_hyper(p
, (u64
) NFS3_MAXPATHLEN
);
176 p
= xdr_encode_hyper(p
, (u64
) inode
->i_size
);
178 if (inode
->i_blksize
== 0 && inode
->i_blocks
== 0)
179 /* Minix file system(?) i_size is (hopefully) close enough */
180 p
= xdr_encode_hyper(p
, (u64
)(inode
->i_size
+511)& ~511);
182 p
= xdr_encode_hyper(p
, ((u64
)inode
->i_blocks
) << 9);
183 *p
++ = htonl((u32
) MAJOR(inode
->i_rdev
));
184 *p
++ = htonl((u32
) MINOR(inode
->i_rdev
));
185 p
= xdr_encode_hyper(p
, (u64
) inode
->i_dev
);
186 p
= xdr_encode_hyper(p
, (u64
) inode
->i_ino
);
187 p
= encode_time3(p
, inode
->i_atime
);
188 p
= encode_time3(p
, lease_get_mtime(inode
));
189 p
= encode_time3(p
, inode
->i_ctime
);
195 encode_saved_post_attr(struct svc_rqst
*rqstp
, u32
*p
, struct svc_fh
*fhp
)
197 struct inode
*inode
= fhp
->fh_dentry
->d_inode
;
199 /* Attributes to follow */
202 *p
++ = htonl(nfs3_ftypes
[(fhp
->fh_post_mode
& S_IFMT
) >> 12]);
203 *p
++ = htonl((u32
) fhp
->fh_post_mode
);
204 *p
++ = htonl((u32
) fhp
->fh_post_nlink
);
205 *p
++ = htonl((u32
) nfsd_ruid(rqstp
, fhp
->fh_post_uid
));
206 *p
++ = htonl((u32
) nfsd_rgid(rqstp
, fhp
->fh_post_gid
));
207 if (S_ISLNK(fhp
->fh_post_mode
) && fhp
->fh_post_size
> NFS3_MAXPATHLEN
) {
208 p
= xdr_encode_hyper(p
, (u64
) NFS3_MAXPATHLEN
);
210 p
= xdr_encode_hyper(p
, (u64
) fhp
->fh_post_size
);
212 p
= xdr_encode_hyper(p
, ((u64
)fhp
->fh_post_blocks
) << 9);
213 *p
++ = htonl((u32
) MAJOR(fhp
->fh_post_rdev
));
214 *p
++ = htonl((u32
) MINOR(fhp
->fh_post_rdev
));
215 p
= xdr_encode_hyper(p
, (u64
) inode
->i_dev
);
216 p
= xdr_encode_hyper(p
, (u64
) inode
->i_ino
);
217 p
= encode_time3(p
, fhp
->fh_post_atime
);
218 p
= encode_time3(p
, fhp
->fh_post_mtime
);
219 p
= encode_time3(p
, fhp
->fh_post_ctime
);
225 * Encode post-operation attributes.
226 * The inode may be NULL if the call failed because of a stale file
227 * handle. In this case, no attributes are returned.
230 encode_post_op_attr(struct svc_rqst
*rqstp
, u32
*p
, struct dentry
*dentry
)
232 if (dentry
&& dentry
->d_inode
!= NULL
) {
233 *p
++ = xdr_one
; /* attributes follow */
234 return encode_fattr3(rqstp
, p
, dentry
);
241 * Enocde weak cache consistency data
244 encode_wcc_data(struct svc_rqst
*rqstp
, u32
*p
, struct svc_fh
*fhp
)
246 struct dentry
*dentry
= fhp
->fh_dentry
;
248 if (dentry
&& dentry
->d_inode
&& fhp
->fh_post_saved
) {
249 if (fhp
->fh_pre_saved
) {
251 p
= xdr_encode_hyper(p
, (u64
) fhp
->fh_pre_size
);
252 p
= encode_time3(p
, fhp
->fh_pre_mtime
);
253 p
= encode_time3(p
, fhp
->fh_pre_ctime
);
257 return encode_saved_post_attr(rqstp
, p
, fhp
);
259 /* no pre- or post-attrs */
261 return encode_post_op_attr(rqstp
, p
, dentry
);
265 * Check buffer bounds after decoding arguments
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
;
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
)))
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
)))
305 if ((args
->check_guard
= ntohl(*p
++)) != 0)
306 p
= decode_time3(p
, &args
->guardtime
);
308 return xdr_argsize_check(rqstp
, p
);
312 nfs3svc_decode_diropargs(struct svc_rqst
*rqstp
, u32
*p
,
313 struct nfsd3_diropargs
*args
)
315 if (!(p
= decode_fh(p
, &args
->fh
))
316 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
319 return xdr_argsize_check(rqstp
, p
);
323 nfs3svc_decode_accessargs(struct svc_rqst
*rqstp
, u32
*p
,
324 struct nfsd3_accessargs
*args
)
326 if (!(p
= decode_fh(p
, &args
->fh
)))
328 args
->access
= ntohl(*p
++);
330 return xdr_argsize_check(rqstp
, p
);
334 nfs3svc_decode_readargs(struct svc_rqst
*rqstp
, u32
*p
,
335 struct nfsd3_readargs
*args
)
337 if (!(p
= decode_fh(p
, &args
->fh
))
338 || !(p
= xdr_decode_hyper(p
, &args
->offset
)))
341 args
->count
= ntohl(*p
++);
342 return xdr_argsize_check(rqstp
, p
);
346 nfs3svc_decode_writeargs(struct svc_rqst
*rqstp
, u32
*p
,
347 struct nfsd3_writeargs
*args
)
349 if (!(p
= decode_fh(p
, &args
->fh
))
350 || !(p
= xdr_decode_hyper(p
, &args
->offset
)))
353 args
->count
= ntohl(*p
++);
354 args
->stable
= ntohl(*p
++);
355 args
->len
= ntohl(*p
++);
356 args
->data
= (char *) p
;
357 p
+= XDR_QUADLEN(args
->len
);
359 return xdr_argsize_check(rqstp
, p
);
363 nfs3svc_decode_createargs(struct svc_rqst
*rqstp
, u32
*p
,
364 struct nfsd3_createargs
*args
)
366 if (!(p
= decode_fh(p
, &args
->fh
))
367 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
370 switch (args
->createmode
= ntohl(*p
++)) {
371 case NFS3_CREATE_UNCHECKED
:
372 case NFS3_CREATE_GUARDED
:
373 if (!(p
= decode_sattr3(p
, &args
->attrs
)))
376 case NFS3_CREATE_EXCLUSIVE
:
384 return xdr_argsize_check(rqstp
, p
);
387 nfs3svc_decode_mkdirargs(struct svc_rqst
*rqstp
, u32
*p
,
388 struct nfsd3_createargs
*args
)
390 if (!(p
= decode_fh(p
, &args
->fh
))
391 || !(p
= decode_filename(p
, &args
->name
, &args
->len
))
392 || !(p
= decode_sattr3(p
, &args
->attrs
)))
395 return xdr_argsize_check(rqstp
, p
);
399 nfs3svc_decode_symlinkargs(struct svc_rqst
*rqstp
, u32
*p
,
400 struct nfsd3_symlinkargs
*args
)
402 if (!(p
= decode_fh(p
, &args
->ffh
))
403 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
404 || !(p
= decode_sattr3(p
, &args
->attrs
))
405 || !(p
= decode_pathname(p
, &args
->tname
, &args
->tlen
)))
408 return xdr_argsize_check(rqstp
, p
);
412 nfs3svc_decode_mknodargs(struct svc_rqst
*rqstp
, u32
*p
,
413 struct nfsd3_mknodargs
*args
)
415 if (!(p
= decode_fh(p
, &args
->fh
))
416 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
419 args
->ftype
= ntohl(*p
++);
421 if (args
->ftype
== NF3BLK
|| args
->ftype
== NF3CHR
422 || args
->ftype
== NF3SOCK
|| args
->ftype
== NF3FIFO
) {
423 if (!(p
= decode_sattr3(p
, &args
->attrs
)))
427 if (args
->ftype
== NF3BLK
|| args
->ftype
== NF3CHR
) {
428 args
->major
= ntohl(*p
++);
429 args
->minor
= ntohl(*p
++);
432 return xdr_argsize_check(rqstp
, p
);
436 nfs3svc_decode_renameargs(struct svc_rqst
*rqstp
, u32
*p
,
437 struct nfsd3_renameargs
*args
)
439 if (!(p
= decode_fh(p
, &args
->ffh
))
440 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
441 || !(p
= decode_fh(p
, &args
->tfh
))
442 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
445 return xdr_argsize_check(rqstp
, p
);
449 nfs3svc_decode_linkargs(struct svc_rqst
*rqstp
, u32
*p
,
450 struct nfsd3_linkargs
*args
)
452 if (!(p
= decode_fh(p
, &args
->ffh
))
453 || !(p
= decode_fh(p
, &args
->tfh
))
454 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
457 return xdr_argsize_check(rqstp
, p
);
461 nfs3svc_decode_readdirargs(struct svc_rqst
*rqstp
, u32
*p
,
462 struct nfsd3_readdirargs
*args
)
464 if (!(p
= decode_fh(p
, &args
->fh
)))
466 p
= xdr_decode_hyper(p
, &args
->cookie
);
467 args
->verf
= p
; p
+= 2;
469 args
->count
= ntohl(*p
++);
471 return xdr_argsize_check(rqstp
, p
);
475 nfs3svc_decode_readdirplusargs(struct svc_rqst
*rqstp
, u32
*p
,
476 struct nfsd3_readdirargs
*args
)
478 if (!(p
= decode_fh(p
, &args
->fh
)))
480 p
= xdr_decode_hyper(p
, &args
->cookie
);
481 args
->verf
= p
; p
+= 2;
482 args
->dircount
= ntohl(*p
++);
483 args
->count
= ntohl(*p
++);
485 return xdr_argsize_check(rqstp
, p
);
489 nfs3svc_decode_commitargs(struct svc_rqst
*rqstp
, u32
*p
,
490 struct nfsd3_commitargs
*args
)
492 if (!(p
= decode_fh(p
, &args
->fh
)))
494 p
= xdr_decode_hyper(p
, &args
->offset
);
495 args
->count
= ntohl(*p
++);
497 return xdr_argsize_check(rqstp
, p
);
501 * XDR encode functions
504 * There must be an encoding function for void results so svc_process
505 * will work properly.
508 nfs3svc_encode_voidres(struct svc_rqst
*rqstp
, u32
*p
, void *dummy
)
510 return xdr_ressize_check(rqstp
, p
);
515 nfs3svc_encode_attrstat(struct svc_rqst
*rqstp
, u32
*p
,
516 struct nfsd3_attrstat
*resp
)
518 if (resp
->status
== 0
519 && !(p
= encode_fattr3(rqstp
, p
, resp
->fh
.fh_dentry
)))
521 return xdr_ressize_check(rqstp
, p
);
524 /* SETATTR, REMOVE, RMDIR */
526 nfs3svc_encode_wccstat(struct svc_rqst
*rqstp
, u32
*p
,
527 struct nfsd3_attrstat
*resp
)
529 if (!(p
= encode_wcc_data(rqstp
, p
, &resp
->fh
)))
531 return xdr_ressize_check(rqstp
, p
);
536 nfs3svc_encode_diropres(struct svc_rqst
*rqstp
, u32
*p
,
537 struct nfsd3_diropres
*resp
)
539 if (resp
->status
== 0) {
540 p
= encode_fh(p
, &resp
->fh
);
541 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
543 p
= encode_post_op_attr(rqstp
, p
, resp
->dirfh
.fh_dentry
);
544 return xdr_ressize_check(rqstp
, p
);
549 nfs3svc_encode_accessres(struct svc_rqst
*rqstp
, u32
*p
,
550 struct nfsd3_accessres
*resp
)
552 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
553 if (resp
->status
== 0)
554 *p
++ = htonl(resp
->access
);
555 return xdr_ressize_check(rqstp
, p
);
560 nfs3svc_encode_readlinkres(struct svc_rqst
*rqstp
, u32
*p
,
561 struct nfsd3_readlinkres
*resp
)
563 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
564 if (resp
->status
== 0) {
565 *p
++ = htonl(resp
->len
);
566 p
+= XDR_QUADLEN(resp
->len
);
568 return xdr_ressize_check(rqstp
, p
);
573 nfs3svc_encode_readres(struct svc_rqst
*rqstp
, u32
*p
,
574 struct nfsd3_readres
*resp
)
576 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
577 if (resp
->status
== 0) {
578 *p
++ = htonl(resp
->count
);
579 *p
++ = htonl(resp
->eof
);
580 *p
++ = htonl(resp
->count
); /* xdr opaque count */
581 p
+= XDR_QUADLEN(resp
->count
);
583 return xdr_ressize_check(rqstp
, p
);
588 nfs3svc_encode_writeres(struct svc_rqst
*rqstp
, u32
*p
,
589 struct nfsd3_writeres
*resp
)
591 p
= encode_wcc_data(rqstp
, p
, &resp
->fh
);
592 if (resp
->status
== 0) {
593 *p
++ = htonl(resp
->count
);
594 *p
++ = htonl(resp
->committed
);
595 *p
++ = htonl(nfssvc_boot
.tv_sec
);
596 *p
++ = htonl(nfssvc_boot
.tv_usec
);
598 return xdr_ressize_check(rqstp
, p
);
601 /* CREATE, MKDIR, SYMLINK, MKNOD */
603 nfs3svc_encode_createres(struct svc_rqst
*rqstp
, u32
*p
,
604 struct nfsd3_diropres
*resp
)
606 if (resp
->status
== 0) {
608 p
= encode_fh(p
, &resp
->fh
);
609 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
611 p
= encode_wcc_data(rqstp
, p
, &resp
->dirfh
);
612 return xdr_ressize_check(rqstp
, p
);
617 nfs3svc_encode_renameres(struct svc_rqst
*rqstp
, u32
*p
,
618 struct nfsd3_renameres
*resp
)
620 p
= encode_wcc_data(rqstp
, p
, &resp
->ffh
);
621 p
= encode_wcc_data(rqstp
, p
, &resp
->tfh
);
622 return xdr_ressize_check(rqstp
, p
);
627 nfs3svc_encode_linkres(struct svc_rqst
*rqstp
, u32
*p
,
628 struct nfsd3_linkres
*resp
)
630 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
631 p
= encode_wcc_data(rqstp
, p
, &resp
->tfh
);
632 return xdr_ressize_check(rqstp
, p
);
637 nfs3svc_encode_readdirres(struct svc_rqst
*rqstp
, u32
*p
,
638 struct nfsd3_readdirres
*resp
)
640 p
= encode_post_op_attr(rqstp
, p
, resp
->fh
.fh_dentry
);
641 if (resp
->status
== 0) {
642 /* stupid readdir cookie */
643 memcpy(p
, resp
->verf
, 8); p
+= 2;
644 p
+= XDR_QUADLEN(resp
->count
);
647 return xdr_ressize_check(rqstp
, p
);
651 * Encode a directory entry. This one works for both normal readdir
653 * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
654 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
656 * The readdirplus baggage is 1+21 words for post_op_attr, plus the
660 #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1)
661 #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
663 encode_entry(struct readdir_cd
*cd
, const char *name
,
664 int namlen
, off_t offset
, ino_t ino
, unsigned int d_type
, int plus
)
667 int buflen
, slen
, elen
;
670 xdr_encode_hyper(cd
->offset
, (u64
) offset
);
672 /* nfsd_readdir calls us with name == 0 when it wants us to
673 * set the last offset entry. */
678 dprintk("encode_entry(%.*s @%ld%s)\n",
679 namlen, name, (long) offset, plus? " plus" : "");
682 /* truncate filename if too long */
683 if (namlen
> NFS3_MAXNAMLEN
)
684 namlen
= NFS3_MAXNAMLEN
;
686 slen
= XDR_QUADLEN(namlen
);
687 elen
= slen
+ NFS3_ENTRY_BAGGAGE
688 + (plus
? NFS3_ENTRYPLUS_BAGGAGE
: 0);
689 if ((buflen
= cd
->buflen
- elen
) < 0) {
693 *p
++ = xdr_one
; /* mark entry present */
694 p
= xdr_encode_hyper(p
, ino
); /* file id */
695 p
= xdr_encode_array(p
, name
, namlen
);/* name length & name */
697 cd
->offset
= p
; /* remember pointer */
698 p
= xdr_encode_hyper(p
, NFS_OFFSET_MAX
); /* offset of next entry */
700 /* throw in readdirplus baggage */
703 struct svc_export
*exp
;
704 struct dentry
*dparent
, *dchild
;
706 dparent
= cd
->dirfh
->fh_dentry
;
707 exp
= cd
->dirfh
->fh_export
;
709 fh_init(&fh
, NFS3_FHSIZE
);
710 if (fh_verify(cd
->rqstp
, cd
->dirfh
, S_IFDIR
, MAY_EXEC
) != 0)
712 if (isdotent(name
, namlen
)) {
715 dchild
= dchild
->d_parent
;
716 dchild
= dget(dchild
);
718 dchild
= lookup_one(name
, dparent
);
721 if (fh_compose(&fh
, exp
, dchild
) != 0 || !dchild
->d_inode
)
723 p
= encode_post_op_attr(cd
->rqstp
, p
, fh
.fh_dentry
);
724 *p
++ = xdr_one
; /* yes, a file handle follows */
725 p
= encode_fh(p
, &fh
);
741 nfs3svc_encode_entry(struct readdir_cd
*cd
, const char *name
,
742 int namlen
, off_t offset
, ino_t ino
, unsigned int d_type
)
744 return encode_entry(cd
, name
, namlen
, offset
, ino
, d_type
, 0);
748 nfs3svc_encode_entry_plus(struct readdir_cd
*cd
, const char *name
,
749 int namlen
, off_t offset
, ino_t ino
, unsigned int d_type
)
751 return encode_entry(cd
, name
, namlen
, offset
, ino
, d_type
, 1);
756 nfs3svc_encode_fsstatres(struct svc_rqst
*rqstp
, u32
*p
,
757 struct nfsd3_fsstatres
*resp
)
759 struct statfs
*s
= &resp
->stats
;
762 *p
++ = xdr_zero
; /* no post_op_attr */
764 if (resp
->status
== 0) {
765 p
= xdr_encode_hyper(p
, bs
* s
->f_blocks
); /* total bytes */
766 p
= xdr_encode_hyper(p
, bs
* s
->f_bfree
); /* free bytes */
767 p
= xdr_encode_hyper(p
, bs
* s
->f_bavail
); /* user available bytes */
768 p
= xdr_encode_hyper(p
, s
->f_files
); /* total inodes */
769 p
= xdr_encode_hyper(p
, s
->f_ffree
); /* free inodes */
770 p
= xdr_encode_hyper(p
, s
->f_ffree
); /* user available inodes */
771 *p
++ = htonl(resp
->invarsec
); /* mean unchanged time */
773 return xdr_ressize_check(rqstp
, p
);
778 nfs3svc_encode_fsinfores(struct svc_rqst
*rqstp
, u32
*p
,
779 struct nfsd3_fsinfores
*resp
)
781 *p
++ = xdr_zero
; /* no post_op_attr */
783 if (resp
->status
== 0) {
784 *p
++ = htonl(resp
->f_rtmax
);
785 *p
++ = htonl(resp
->f_rtpref
);
786 *p
++ = htonl(resp
->f_rtmult
);
787 *p
++ = htonl(resp
->f_wtmax
);
788 *p
++ = htonl(resp
->f_wtpref
);
789 *p
++ = htonl(resp
->f_wtmult
);
790 *p
++ = htonl(resp
->f_dtpref
);
791 p
= xdr_encode_hyper(p
, resp
->f_maxfilesize
);
794 *p
++ = htonl(resp
->f_properties
);
797 return xdr_ressize_check(rqstp
, p
);
802 nfs3svc_encode_pathconfres(struct svc_rqst
*rqstp
, u32
*p
,
803 struct nfsd3_pathconfres
*resp
)
805 *p
++ = xdr_zero
; /* no post_op_attr */
807 if (resp
->status
== 0) {
808 *p
++ = htonl(resp
->p_link_max
);
809 *p
++ = htonl(resp
->p_name_max
);
810 *p
++ = htonl(resp
->p_no_trunc
);
811 *p
++ = htonl(resp
->p_chown_restricted
);
812 *p
++ = htonl(resp
->p_case_insensitive
);
813 *p
++ = htonl(resp
->p_case_preserving
);
816 return xdr_ressize_check(rqstp
, p
);
821 nfs3svc_encode_commitres(struct svc_rqst
*rqstp
, u32
*p
,
822 struct nfsd3_commitres
*resp
)
824 p
= encode_wcc_data(rqstp
, p
, &resp
->fh
);
826 if (resp
->status
== 0) {
827 *p
++ = htonl(nfssvc_boot
.tv_sec
);
828 *p
++ = htonl(nfssvc_boot
.tv_usec
);
830 return xdr_ressize_check(rqstp
, p
);
834 * XDR release functions
837 nfs3svc_release_fhandle(struct svc_rqst
*rqstp
, u32
*p
,
838 struct nfsd3_attrstat
*resp
)
845 nfs3svc_release_fhandle2(struct svc_rqst
*rqstp
, u32
*p
,
846 struct nfsd3_fhandle_pair
*resp
)