4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
10 #define NFSDDBG_FACILITY NFSDDBG_XDR
13 * Mapping of S_IF* types to NFS file types
15 static u32 nfs_ftypes
[] = {
16 NFNON
, NFCHR
, NFCHR
, NFBAD
,
17 NFDIR
, NFBAD
, NFBLK
, NFBAD
,
18 NFREG
, NFBAD
, NFLNK
, NFBAD
,
19 NFSOCK
, NFBAD
, NFLNK
, NFBAD
,
24 * XDR functions for basic NFS types
27 decode_fh(__be32
*p
, struct svc_fh
*fhp
)
29 fh_init(fhp
, NFS_FHSIZE
);
30 memcpy(&fhp
->fh_handle
.fh_base
, p
, NFS_FHSIZE
);
31 fhp
->fh_handle
.fh_size
= NFS_FHSIZE
;
33 /* FIXME: Look up export pointer here and verify
34 * Sun Secure RPC if requested */
35 return p
+ (NFS_FHSIZE
>> 2);
38 /* Helper function for NFSv2 ACL code */
39 __be32
*nfs2svc_decode_fh(__be32
*p
, struct svc_fh
*fhp
)
41 return decode_fh(p
, fhp
);
45 encode_fh(__be32
*p
, struct svc_fh
*fhp
)
47 memcpy(p
, &fhp
->fh_handle
.fh_base
, NFS_FHSIZE
);
48 return p
+ (NFS_FHSIZE
>> 2);
52 * Decode a file name and make sure that the path contains
53 * no slashes or null bytes.
56 decode_filename(__be32
*p
, char **namp
, unsigned int *lenp
)
61 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXNAMLEN
)) != NULL
) {
62 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
63 if (*name
== '\0' || *name
== '/')
72 decode_pathname(__be32
*p
, char **namp
, unsigned int *lenp
)
77 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXPATHLEN
)) != NULL
) {
78 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
88 decode_sattr(__be32
*p
, struct iattr
*iap
)
94 /* Sun client bug compatibility check: some sun clients seem to
95 * put 0xffff in the mode field when they mean 0xffffffff.
96 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
98 if ((tmp
= ntohl(*p
++)) != (u32
)-1 && tmp
!= 0xffff) {
99 iap
->ia_valid
|= ATTR_MODE
;
102 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
103 iap
->ia_valid
|= ATTR_UID
;
106 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
107 iap
->ia_valid
|= ATTR_GID
;
110 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
111 iap
->ia_valid
|= ATTR_SIZE
;
114 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
115 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
116 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
117 iap
->ia_atime
.tv_sec
= tmp
;
118 iap
->ia_atime
.tv_nsec
= tmp1
* 1000;
120 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
121 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
122 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
123 iap
->ia_mtime
.tv_sec
= tmp
;
124 iap
->ia_mtime
.tv_nsec
= tmp1
* 1000;
126 * Passing the invalid value useconds=1000000 for mtime
127 * is a Sun convention for "set both mtime and atime to
128 * current server time". It's needed to make permissions
129 * checks for the "touch" program across v2 mounts to
130 * Solaris and Irix boxes work correctly. See description of
131 * sattr in section 6.1 of "NFS Illustrated" by
132 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
135 iap
->ia_valid
&= ~(ATTR_ATIME_SET
|ATTR_MTIME_SET
);
141 encode_fattr(struct svc_rqst
*rqstp
, __be32
*p
, struct svc_fh
*fhp
,
144 struct dentry
*dentry
= fhp
->fh_dentry
;
146 struct timespec time
;
149 type
= (stat
->mode
& S_IFMT
);
151 *p
++ = htonl(nfs_ftypes
[type
>> 12]);
152 *p
++ = htonl((u32
) stat
->mode
);
153 *p
++ = htonl((u32
) stat
->nlink
);
154 *p
++ = htonl((u32
) nfsd_ruid(rqstp
, stat
->uid
));
155 *p
++ = htonl((u32
) nfsd_rgid(rqstp
, stat
->gid
));
157 if (S_ISLNK(type
) && stat
->size
> NFS_MAXPATHLEN
) {
158 *p
++ = htonl(NFS_MAXPATHLEN
);
160 *p
++ = htonl((u32
) stat
->size
);
162 *p
++ = htonl((u32
) stat
->blksize
);
163 if (S_ISCHR(type
) || S_ISBLK(type
))
164 *p
++ = htonl(new_encode_dev(stat
->rdev
));
166 *p
++ = htonl(0xffffffff);
167 *p
++ = htonl((u32
) stat
->blocks
);
168 switch (fsid_source(fhp
)) {
171 *p
++ = htonl(new_encode_dev(stat
->dev
));
173 case FSIDSOURCE_FSID
:
174 *p
++ = htonl((u32
) fhp
->fh_export
->ex_fsid
);
176 case FSIDSOURCE_UUID
:
177 f
= ((u32
*)fhp
->fh_export
->ex_uuid
)[0];
178 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[1];
179 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[2];
180 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[3];
184 *p
++ = htonl((u32
) stat
->ino
);
185 *p
++ = htonl((u32
) stat
->atime
.tv_sec
);
186 *p
++ = htonl(stat
->atime
.tv_nsec
? stat
->atime
.tv_nsec
/ 1000 : 0);
187 lease_get_mtime(dentry
->d_inode
, &time
);
188 *p
++ = htonl((u32
) time
.tv_sec
);
189 *p
++ = htonl(time
.tv_nsec
? time
.tv_nsec
/ 1000 : 0);
190 *p
++ = htonl((u32
) stat
->ctime
.tv_sec
);
191 *p
++ = htonl(stat
->ctime
.tv_nsec
? stat
->ctime
.tv_nsec
/ 1000 : 0);
196 /* Helper function for NFSv2 ACL code */
197 __be32
*nfs2svc_encode_fattr(struct svc_rqst
*rqstp
, __be32
*p
, struct svc_fh
*fhp
)
200 vfs_getattr(fhp
->fh_export
->ex_path
.mnt
, fhp
->fh_dentry
, &stat
);
201 return encode_fattr(rqstp
, p
, fhp
, &stat
);
205 * XDR decode functions
208 nfssvc_decode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
210 return xdr_argsize_check(rqstp
, p
);
214 nfssvc_decode_fhandle(struct svc_rqst
*rqstp
, __be32
*p
, struct nfsd_fhandle
*args
)
216 if (!(p
= decode_fh(p
, &args
->fh
)))
218 return xdr_argsize_check(rqstp
, p
);
222 nfssvc_decode_sattrargs(struct svc_rqst
*rqstp
, __be32
*p
,
223 struct nfsd_sattrargs
*args
)
225 p
= decode_fh(p
, &args
->fh
);
228 p
= decode_sattr(p
, &args
->attrs
);
230 return xdr_argsize_check(rqstp
, p
);
234 nfssvc_decode_diropargs(struct svc_rqst
*rqstp
, __be32
*p
,
235 struct nfsd_diropargs
*args
)
237 if (!(p
= decode_fh(p
, &args
->fh
))
238 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
241 return xdr_argsize_check(rqstp
, p
);
245 nfssvc_decode_readargs(struct svc_rqst
*rqstp
, __be32
*p
,
246 struct nfsd_readargs
*args
)
250 if (!(p
= decode_fh(p
, &args
->fh
)))
253 args
->offset
= ntohl(*p
++);
254 len
= args
->count
= ntohl(*p
++);
255 p
++; /* totalcount - unused */
257 if (len
> NFSSVC_MAXBLKSIZE_V2
)
258 len
= NFSSVC_MAXBLKSIZE_V2
;
260 /* set up somewhere to store response.
261 * We take pages, put them on reslist and include in iovec
265 pn
= rqstp
->rq_resused
++;
266 rqstp
->rq_vec
[v
].iov_base
= page_address(rqstp
->rq_respages
[pn
]);
267 rqstp
->rq_vec
[v
].iov_len
= len
< PAGE_SIZE
?len
:PAGE_SIZE
;
268 len
-= rqstp
->rq_vec
[v
].iov_len
;
272 return xdr_argsize_check(rqstp
, p
);
276 nfssvc_decode_writeargs(struct svc_rqst
*rqstp
, __be32
*p
,
277 struct nfsd_writeargs
*args
)
279 unsigned int len
, hdr
, dlen
;
282 if (!(p
= decode_fh(p
, &args
->fh
)))
285 p
++; /* beginoffset */
286 args
->offset
= ntohl(*p
++); /* offset */
287 p
++; /* totalcount */
288 len
= args
->len
= ntohl(*p
++);
290 * The protocol specifies a maximum of 8192 bytes.
292 if (len
> NFSSVC_MAXBLKSIZE_V2
)
296 * Check to make sure that we got the right number of
299 hdr
= (void*)p
- rqstp
->rq_arg
.head
[0].iov_base
;
300 dlen
= rqstp
->rq_arg
.head
[0].iov_len
+ rqstp
->rq_arg
.page_len
304 * Round the length of the data which was specified up to
305 * the next multiple of XDR units and then compare that
306 * against the length which was actually received.
307 * Note that when RPCSEC/GSS (for example) is used, the
308 * data buffer can be padded so dlen might be larger
309 * than required. It must never be smaller.
311 if (dlen
< XDR_QUADLEN(len
)*4)
314 rqstp
->rq_vec
[0].iov_base
= (void*)p
;
315 rqstp
->rq_vec
[0].iov_len
= rqstp
->rq_arg
.head
[0].iov_len
- hdr
;
317 while (len
> rqstp
->rq_vec
[v
].iov_len
) {
318 len
-= rqstp
->rq_vec
[v
].iov_len
;
320 rqstp
->rq_vec
[v
].iov_base
= page_address(rqstp
->rq_pages
[v
]);
321 rqstp
->rq_vec
[v
].iov_len
= PAGE_SIZE
;
323 rqstp
->rq_vec
[v
].iov_len
= len
;
329 nfssvc_decode_createargs(struct svc_rqst
*rqstp
, __be32
*p
,
330 struct nfsd_createargs
*args
)
332 if ( !(p
= decode_fh(p
, &args
->fh
))
333 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
335 p
= decode_sattr(p
, &args
->attrs
);
337 return xdr_argsize_check(rqstp
, p
);
341 nfssvc_decode_renameargs(struct svc_rqst
*rqstp
, __be32
*p
,
342 struct nfsd_renameargs
*args
)
344 if (!(p
= decode_fh(p
, &args
->ffh
))
345 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
346 || !(p
= decode_fh(p
, &args
->tfh
))
347 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
350 return xdr_argsize_check(rqstp
, p
);
354 nfssvc_decode_readlinkargs(struct svc_rqst
*rqstp
, __be32
*p
, struct nfsd_readlinkargs
*args
)
356 if (!(p
= decode_fh(p
, &args
->fh
)))
358 args
->buffer
= page_address(rqstp
->rq_respages
[rqstp
->rq_resused
++]);
360 return xdr_argsize_check(rqstp
, p
);
364 nfssvc_decode_linkargs(struct svc_rqst
*rqstp
, __be32
*p
,
365 struct nfsd_linkargs
*args
)
367 if (!(p
= decode_fh(p
, &args
->ffh
))
368 || !(p
= decode_fh(p
, &args
->tfh
))
369 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
372 return xdr_argsize_check(rqstp
, p
);
376 nfssvc_decode_symlinkargs(struct svc_rqst
*rqstp
, __be32
*p
,
377 struct nfsd_symlinkargs
*args
)
379 if ( !(p
= decode_fh(p
, &args
->ffh
))
380 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
381 || !(p
= decode_pathname(p
, &args
->tname
, &args
->tlen
)))
383 p
= decode_sattr(p
, &args
->attrs
);
385 return xdr_argsize_check(rqstp
, p
);
389 nfssvc_decode_readdirargs(struct svc_rqst
*rqstp
, __be32
*p
,
390 struct nfsd_readdirargs
*args
)
392 if (!(p
= decode_fh(p
, &args
->fh
)))
394 args
->cookie
= ntohl(*p
++);
395 args
->count
= ntohl(*p
++);
396 if (args
->count
> PAGE_SIZE
)
397 args
->count
= PAGE_SIZE
;
399 args
->buffer
= page_address(rqstp
->rq_respages
[rqstp
->rq_resused
++]);
401 return xdr_argsize_check(rqstp
, p
);
405 * XDR encode functions
408 nfssvc_encode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
410 return xdr_ressize_check(rqstp
, p
);
414 nfssvc_encode_attrstat(struct svc_rqst
*rqstp
, __be32
*p
,
415 struct nfsd_attrstat
*resp
)
417 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
418 return xdr_ressize_check(rqstp
, p
);
422 nfssvc_encode_diropres(struct svc_rqst
*rqstp
, __be32
*p
,
423 struct nfsd_diropres
*resp
)
425 p
= encode_fh(p
, &resp
->fh
);
426 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
427 return xdr_ressize_check(rqstp
, p
);
431 nfssvc_encode_readlinkres(struct svc_rqst
*rqstp
, __be32
*p
,
432 struct nfsd_readlinkres
*resp
)
434 *p
++ = htonl(resp
->len
);
435 xdr_ressize_check(rqstp
, p
);
436 rqstp
->rq_res
.page_len
= resp
->len
;
438 /* need to pad the tail */
439 rqstp
->rq_res
.tail
[0].iov_base
= p
;
441 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->len
&3);
447 nfssvc_encode_readres(struct svc_rqst
*rqstp
, __be32
*p
,
448 struct nfsd_readres
*resp
)
450 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
451 *p
++ = htonl(resp
->count
);
452 xdr_ressize_check(rqstp
, p
);
454 /* now update rqstp->rq_res to reflect data as well */
455 rqstp
->rq_res
.page_len
= resp
->count
;
456 if (resp
->count
& 3) {
457 /* need to pad the tail */
458 rqstp
->rq_res
.tail
[0].iov_base
= p
;
460 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->count
&3);
466 nfssvc_encode_readdirres(struct svc_rqst
*rqstp
, __be32
*p
,
467 struct nfsd_readdirres
*resp
)
469 xdr_ressize_check(rqstp
, p
);
471 *p
++ = 0; /* no more entries */
472 *p
++ = htonl((resp
->common
.err
== nfserr_eof
));
473 rqstp
->rq_res
.page_len
= (((unsigned long)p
-1) & ~PAGE_MASK
)+1;
479 nfssvc_encode_statfsres(struct svc_rqst
*rqstp
, __be32
*p
,
480 struct nfsd_statfsres
*resp
)
482 struct kstatfs
*stat
= &resp
->stats
;
484 *p
++ = htonl(NFSSVC_MAXBLKSIZE_V2
); /* max transfer size */
485 *p
++ = htonl(stat
->f_bsize
);
486 *p
++ = htonl(stat
->f_blocks
);
487 *p
++ = htonl(stat
->f_bfree
);
488 *p
++ = htonl(stat
->f_bavail
);
489 return xdr_ressize_check(rqstp
, p
);
493 nfssvc_encode_entry(void *ccdv
, const char *name
,
494 int namlen
, loff_t offset
, u64 ino
, unsigned int d_type
)
496 struct readdir_cd
*ccd
= ccdv
;
497 struct nfsd_readdirres
*cd
= container_of(ccd
, struct nfsd_readdirres
, common
);
498 __be32
*p
= cd
->buffer
;
502 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
503 namlen, name, offset, ino);
506 if (offset
> ~((u32
) 0)) {
507 cd
->common
.err
= nfserr_fbig
;
511 *cd
->offset
= htonl(offset
);
512 if (namlen
> NFS2_MAXNAMLEN
)
513 namlen
= NFS2_MAXNAMLEN
;/* truncate filename */
515 slen
= XDR_QUADLEN(namlen
);
516 if ((buflen
= cd
->buflen
- slen
- 4) < 0) {
517 cd
->common
.err
= nfserr_toosmall
;
520 if (ino
> ~((u32
) 0)) {
521 cd
->common
.err
= nfserr_fbig
;
524 *p
++ = xdr_one
; /* mark entry present */
525 *p
++ = htonl((u32
) ino
); /* file id */
526 p
= xdr_encode_array(p
, name
, namlen
);/* name length & name */
527 cd
->offset
= p
; /* remember pointer */
528 *p
++ = htonl(~0U); /* offset of next entry */
532 cd
->common
.err
= nfs_ok
;
537 * XDR release functions
540 nfssvc_release_fhandle(struct svc_rqst
*rqstp
, __be32
*p
,
541 struct nfsd_fhandle
*resp
)