6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
9 #include <linux/types.h>
10 #include <linux/time.h>
11 #include <linux/nfs.h>
12 #include <linux/vfs.h>
13 #include <linux/sunrpc/xdr.h>
14 #include <linux/sunrpc/svc.h>
15 #include <linux/nfsd/nfsd.h>
16 #include <linux/nfsd/xdr.h>
19 #define NFSDDBG_FACILITY NFSDDBG_XDR
22 #ifdef NFSD_OPTIMIZE_SPACE
27 * Mapping of S_IF* types to NFS file types
29 static u32 nfs_ftypes
[] = {
30 NFNON
, NFCHR
, NFCHR
, NFBAD
,
31 NFDIR
, NFBAD
, NFBLK
, NFBAD
,
32 NFREG
, NFBAD
, NFLNK
, NFBAD
,
33 NFSOCK
, NFBAD
, NFLNK
, NFBAD
,
38 * XDR functions for basic NFS types
41 decode_fh(u32
*p
, struct svc_fh
*fhp
)
43 fh_init(fhp
, NFS_FHSIZE
);
44 memcpy(&fhp
->fh_handle
.fh_base
, p
, NFS_FHSIZE
);
45 fhp
->fh_handle
.fh_size
= NFS_FHSIZE
;
47 /* FIXME: Look up export pointer here and verify
48 * Sun Secure RPC if requested */
49 return p
+ (NFS_FHSIZE
>> 2);
53 encode_fh(u32
*p
, struct svc_fh
*fhp
)
55 memcpy(p
, &fhp
->fh_handle
.fh_base
, NFS_FHSIZE
);
56 return p
+ (NFS_FHSIZE
>> 2);
60 * Decode a file name and make sure that the path contains
61 * no slashes or null bytes.
64 decode_filename(u32
*p
, char **namp
, int *lenp
)
69 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXNAMLEN
)) != NULL
) {
70 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
71 if (*name
== '\0' || *name
== '/')
80 decode_pathname(u32
*p
, char **namp
, int *lenp
)
85 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXPATHLEN
)) != NULL
) {
86 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
96 decode_sattr(u32
*p
, struct iattr
*iap
)
102 /* Sun client bug compatibility check: some sun clients seem to
103 * put 0xffff in the mode field when they mean 0xffffffff.
104 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
106 if ((tmp
= ntohl(*p
++)) != (u32
)-1 && tmp
!= 0xffff) {
107 iap
->ia_valid
|= ATTR_MODE
;
110 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
111 iap
->ia_valid
|= ATTR_UID
;
114 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
115 iap
->ia_valid
|= ATTR_GID
;
118 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
119 iap
->ia_valid
|= ATTR_SIZE
;
122 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
123 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
124 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
125 iap
->ia_atime
.tv_sec
= tmp
;
126 iap
->ia_atime
.tv_nsec
= tmp1
* 1000;
128 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
129 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
130 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
131 iap
->ia_mtime
.tv_sec
= tmp
;
132 iap
->ia_mtime
.tv_nsec
= tmp1
* 1000;
134 * Passing the invalid value useconds=1000000 for mtime
135 * is a Sun convention for "set both mtime and atime to
136 * current server time". It's needed to make permissions
137 * checks for the "touch" program across v2 mounts to
138 * Solaris and Irix boxes work correctly. See description of
139 * sattr in section 6.1 of "NFS Illustrated" by
140 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
143 iap
->ia_valid
&= ~(ATTR_ATIME_SET
|ATTR_MTIME_SET
);
149 encode_fattr(struct svc_rqst
*rqstp
, u32
*p
, struct svc_fh
*fhp
)
151 struct vfsmount
*mnt
= fhp
->fh_export
->ex_mnt
;
152 struct dentry
*dentry
= fhp
->fh_dentry
;
155 struct timespec time
;
157 vfs_getattr(mnt
, dentry
, &stat
);
158 type
= (stat
.mode
& S_IFMT
);
160 *p
++ = htonl(nfs_ftypes
[type
>> 12]);
161 *p
++ = htonl((u32
) stat
.mode
);
162 *p
++ = htonl((u32
) stat
.nlink
);
163 *p
++ = htonl((u32
) nfsd_ruid(rqstp
, stat
.uid
));
164 *p
++ = htonl((u32
) nfsd_rgid(rqstp
, stat
.gid
));
166 if (S_ISLNK(type
) && stat
.size
> NFS_MAXPATHLEN
) {
167 *p
++ = htonl(NFS_MAXPATHLEN
);
169 *p
++ = htonl((u32
) stat
.size
);
171 *p
++ = htonl((u32
) stat
.blksize
);
172 if (S_ISCHR(type
) || S_ISBLK(type
))
173 *p
++ = htonl(new_encode_dev(stat
.rdev
));
175 *p
++ = htonl(0xffffffff);
176 *p
++ = htonl((u32
) stat
.blocks
);
177 if (is_fsid(fhp
, rqstp
->rq_reffh
))
178 *p
++ = htonl((u32
) fhp
->fh_export
->ex_fsid
);
180 *p
++ = htonl(new_encode_dev(stat
.dev
));
181 *p
++ = htonl((u32
) stat
.ino
);
182 *p
++ = htonl((u32
) stat
.atime
.tv_sec
);
183 *p
++ = htonl(stat
.atime
.tv_nsec
? stat
.atime
.tv_nsec
/ 1000 : 0);
184 lease_get_mtime(dentry
->d_inode
, &time
);
185 *p
++ = htonl((u32
) time
.tv_sec
);
186 *p
++ = htonl(time
.tv_nsec
? time
.tv_nsec
/ 1000 : 0);
187 *p
++ = htonl((u32
) stat
.ctime
.tv_sec
);
188 *p
++ = htonl(stat
.ctime
.tv_nsec
? stat
.ctime
.tv_nsec
/ 1000 : 0);
195 * XDR decode functions
198 nfssvc_decode_void(struct svc_rqst
*rqstp
, u32
*p
, void *dummy
)
200 return xdr_argsize_check(rqstp
, p
);
204 nfssvc_decode_fhandle(struct svc_rqst
*rqstp
, u32
*p
, struct nfsd_fhandle
*args
)
206 if (!(p
= decode_fh(p
, &args
->fh
)))
208 return xdr_argsize_check(rqstp
, p
);
212 nfssvc_decode_sattrargs(struct svc_rqst
*rqstp
, u32
*p
,
213 struct nfsd_sattrargs
*args
)
215 if (!(p
= decode_fh(p
, &args
->fh
))
216 || !(p
= decode_sattr(p
, &args
->attrs
)))
219 return xdr_argsize_check(rqstp
, p
);
223 nfssvc_decode_diropargs(struct svc_rqst
*rqstp
, u32
*p
,
224 struct nfsd_diropargs
*args
)
226 if (!(p
= decode_fh(p
, &args
->fh
))
227 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
230 return xdr_argsize_check(rqstp
, p
);
234 nfssvc_decode_readargs(struct svc_rqst
*rqstp
, u32
*p
,
235 struct nfsd_readargs
*args
)
239 if (!(p
= decode_fh(p
, &args
->fh
)))
242 args
->offset
= ntohl(*p
++);
243 len
= args
->count
= ntohl(*p
++);
244 p
++; /* totalcount - unused */
246 if (len
> NFSSVC_MAXBLKSIZE
)
247 len
= NFSSVC_MAXBLKSIZE
;
249 /* set up somewhere to store response.
250 * We take pages, put them on reslist and include in iovec
254 pn
=rqstp
->rq_resused
;
255 svc_take_page(rqstp
);
256 args
->vec
[v
].iov_base
= page_address(rqstp
->rq_respages
[pn
]);
257 args
->vec
[v
].iov_len
= len
< PAGE_SIZE
?len
:PAGE_SIZE
;
258 len
-= args
->vec
[v
].iov_len
;
262 return xdr_argsize_check(rqstp
, p
);
266 nfssvc_decode_writeargs(struct svc_rqst
*rqstp
, u32
*p
,
267 struct nfsd_writeargs
*args
)
271 if (!(p
= decode_fh(p
, &args
->fh
)))
274 p
++; /* beginoffset */
275 args
->offset
= ntohl(*p
++); /* offset */
276 p
++; /* totalcount */
277 len
= args
->len
= ntohl(*p
++);
278 args
->vec
[0].iov_base
= (void*)p
;
279 args
->vec
[0].iov_len
= rqstp
->rq_arg
.head
[0].iov_len
-
280 (((void*)p
) - rqstp
->rq_arg
.head
[0].iov_base
);
281 if (len
> NFSSVC_MAXBLKSIZE
)
282 len
= NFSSVC_MAXBLKSIZE
;
284 while (len
> args
->vec
[v
].iov_len
) {
285 len
-= args
->vec
[v
].iov_len
;
287 args
->vec
[v
].iov_base
= page_address(rqstp
->rq_argpages
[v
]);
288 args
->vec
[v
].iov_len
= PAGE_SIZE
;
290 args
->vec
[v
].iov_len
= len
;
292 return args
->vec
[0].iov_len
> 0;
296 nfssvc_decode_createargs(struct svc_rqst
*rqstp
, u32
*p
,
297 struct nfsd_createargs
*args
)
299 if (!(p
= decode_fh(p
, &args
->fh
))
300 || !(p
= decode_filename(p
, &args
->name
, &args
->len
))
301 || !(p
= decode_sattr(p
, &args
->attrs
)))
304 return xdr_argsize_check(rqstp
, p
);
308 nfssvc_decode_renameargs(struct svc_rqst
*rqstp
, u32
*p
,
309 struct nfsd_renameargs
*args
)
311 if (!(p
= decode_fh(p
, &args
->ffh
))
312 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
313 || !(p
= decode_fh(p
, &args
->tfh
))
314 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
317 return xdr_argsize_check(rqstp
, p
);
321 nfssvc_decode_readlinkargs(struct svc_rqst
*rqstp
, u32
*p
, struct nfsd_readlinkargs
*args
)
323 if (!(p
= decode_fh(p
, &args
->fh
)))
325 svc_take_page(rqstp
);
326 args
->buffer
= page_address(rqstp
->rq_respages
[rqstp
->rq_resused
-1]);
328 return xdr_argsize_check(rqstp
, p
);
332 nfssvc_decode_linkargs(struct svc_rqst
*rqstp
, u32
*p
,
333 struct nfsd_linkargs
*args
)
335 if (!(p
= decode_fh(p
, &args
->ffh
))
336 || !(p
= decode_fh(p
, &args
->tfh
))
337 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
340 return xdr_argsize_check(rqstp
, p
);
344 nfssvc_decode_symlinkargs(struct svc_rqst
*rqstp
, u32
*p
,
345 struct nfsd_symlinkargs
*args
)
347 if (!(p
= decode_fh(p
, &args
->ffh
))
348 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
349 || !(p
= decode_pathname(p
, &args
->tname
, &args
->tlen
))
350 || !(p
= decode_sattr(p
, &args
->attrs
)))
353 return xdr_argsize_check(rqstp
, p
);
357 nfssvc_decode_readdirargs(struct svc_rqst
*rqstp
, u32
*p
,
358 struct nfsd_readdirargs
*args
)
360 if (!(p
= decode_fh(p
, &args
->fh
)))
362 args
->cookie
= ntohl(*p
++);
363 args
->count
= ntohl(*p
++);
364 if (args
->count
> PAGE_SIZE
)
365 args
->count
= PAGE_SIZE
;
367 svc_take_page(rqstp
);
368 args
->buffer
= page_address(rqstp
->rq_respages
[rqstp
->rq_resused
-1]);
370 return xdr_argsize_check(rqstp
, p
);
374 * XDR encode functions
377 nfssvc_encode_void(struct svc_rqst
*rqstp
, u32
*p
, void *dummy
)
379 return xdr_ressize_check(rqstp
, p
);
383 nfssvc_encode_attrstat(struct svc_rqst
*rqstp
, u32
*p
,
384 struct nfsd_attrstat
*resp
)
386 p
= encode_fattr(rqstp
, p
, &resp
->fh
);
387 return xdr_ressize_check(rqstp
, p
);
391 nfssvc_encode_diropres(struct svc_rqst
*rqstp
, u32
*p
,
392 struct nfsd_diropres
*resp
)
394 p
= encode_fh(p
, &resp
->fh
);
395 p
= encode_fattr(rqstp
, p
, &resp
->fh
);
396 return xdr_ressize_check(rqstp
, p
);
400 nfssvc_encode_readlinkres(struct svc_rqst
*rqstp
, u32
*p
,
401 struct nfsd_readlinkres
*resp
)
403 *p
++ = htonl(resp
->len
);
404 xdr_ressize_check(rqstp
, p
);
405 rqstp
->rq_res
.page_len
= resp
->len
;
407 /* need to pad the tail */
408 rqstp
->rq_restailpage
= 0;
409 rqstp
->rq_res
.tail
[0].iov_base
= p
;
411 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->len
&3);
417 nfssvc_encode_readres(struct svc_rqst
*rqstp
, u32
*p
,
418 struct nfsd_readres
*resp
)
420 p
= encode_fattr(rqstp
, p
, &resp
->fh
);
421 *p
++ = htonl(resp
->count
);
422 xdr_ressize_check(rqstp
, p
);
424 /* now update rqstp->rq_res to reflect data aswell */
425 rqstp
->rq_res
.page_len
= resp
->count
;
426 if (resp
->count
& 3) {
427 /* need to pad the tail */
428 rqstp
->rq_restailpage
= 0;
429 rqstp
->rq_res
.tail
[0].iov_base
= p
;
431 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->count
&3);
437 nfssvc_encode_readdirres(struct svc_rqst
*rqstp
, u32
*p
,
438 struct nfsd_readdirres
*resp
)
440 xdr_ressize_check(rqstp
, p
);
442 *p
++ = 0; /* no more entries */
443 *p
++ = htonl((resp
->common
.err
== nfserr_eof
));
444 rqstp
->rq_res
.page_len
= (((unsigned long)p
-1) & ~PAGE_MASK
)+1;
450 nfssvc_encode_statfsres(struct svc_rqst
*rqstp
, u32
*p
,
451 struct nfsd_statfsres
*resp
)
453 struct kstatfs
*stat
= &resp
->stats
;
455 *p
++ = htonl(NFSSVC_MAXBLKSIZE
); /* max transfer size */
456 *p
++ = htonl(stat
->f_bsize
);
457 *p
++ = htonl(stat
->f_blocks
);
458 *p
++ = htonl(stat
->f_bfree
);
459 *p
++ = htonl(stat
->f_bavail
);
460 return xdr_ressize_check(rqstp
, p
);
464 nfssvc_encode_entry(struct readdir_cd
*ccd
, const char *name
,
465 int namlen
, loff_t offset
, ino_t ino
, unsigned int d_type
)
467 struct nfsd_readdirres
*cd
= container_of(ccd
, struct nfsd_readdirres
, common
);
472 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
473 namlen, name, offset, ino);
476 if (offset
> ~((u32
) 0)) {
477 cd
->common
.err
= nfserr_fbig
;
481 *cd
->offset
= htonl(offset
);
482 if (namlen
> NFS2_MAXNAMLEN
)
483 namlen
= NFS2_MAXNAMLEN
;/* truncate filename */
485 slen
= XDR_QUADLEN(namlen
);
486 if ((buflen
= cd
->buflen
- slen
- 4) < 0) {
487 cd
->common
.err
= nfserr_toosmall
;
490 *p
++ = xdr_one
; /* mark entry present */
491 *p
++ = htonl((u32
) ino
); /* file id */
492 p
= xdr_encode_array(p
, name
, namlen
);/* name length & name */
493 cd
->offset
= p
; /* remember pointer */
494 *p
++ = ~(u32
) 0; /* offset of next entry */
498 cd
->common
.err
= nfs_ok
;
503 * XDR release functions
506 nfssvc_release_fhandle(struct svc_rqst
*rqstp
, u32
*p
,
507 struct nfsd_fhandle
*resp
)