2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
37 * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $
38 * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.48 2008/09/17 21:44:24 dillon Exp $
42 * nfs version 2 and 3 server calls to vnode ops
43 * - these routines generally have 3 phases
44 * 1 - break down and validate rpc request in mbuf list
45 * 2 - do the vnode ops for the request
46 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
47 * 3 - build the rpc reply in an mbuf list
49 * - do not mix the phases, since the nfsm_?? macros can return failures
50 * on a bad rpc or similar and do not do any vrele() or vput()'s
52 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
53 * error number iff error != 0 whereas
54 * returning an error from the server function implies a fatal error
55 * such as a badly constructed rpc request that should be dropped without
57 * For Version 3, nfsm_reply() does not return for the error case, since
58 * most version 3 rpcs return more than the status for error cases.
61 * Warning: always pay careful attention to resource cleanup on return
62 * and note that nfsm_*() macros can terminate a procedure on certain
66 #include <sys/param.h>
67 #include <sys/systm.h>
70 #include <sys/nlookup.h>
71 #include <sys/namei.h>
72 #include <sys/unistd.h>
73 #include <sys/vnode.h>
74 #include <sys/mount.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/malloc.h>
79 #include <sys/dirent.h>
81 #include <sys/kernel.h>
82 #include <sys/sysctl.h>
86 #include <vm/vm_extern.h>
87 #include <vm/vm_zone.h>
88 #include <vm/vm_object.h>
92 #include <sys/thread2.h>
98 #include "nfsm_subs.h"
101 #define nfsdbprintf(info) kprintf info
103 #define nfsdbprintf(info)
106 #define MAX_COMMIT_COUNT (1024 * 1024)
108 #define NUM_HEURISTIC 1017
109 #define NHUSE_INIT 64
111 #define NHUSE_MAX 2048
113 static struct nfsheur
{
114 struct vnode
*nh_vp
; /* vp to match (unreferenced pointer) */
115 off_t nh_nextr
; /* next offset for sequential detection */
116 int nh_use
; /* use count for selection */
117 int nh_seqcount
; /* heuristic */
118 } nfsheur
[NUM_HEURISTIC
];
120 nfstype nfsv3_type
[9] = { NFNON
, NFREG
, NFDIR
, NFBLK
, NFCHR
, NFLNK
, NFSOCK
,
123 nfstype nfsv2_type
[9] = { NFNON
, NFREG
, NFDIR
, NFBLK
, NFCHR
, NFLNK
, NFNON
,
126 extern u_int32_t nfs_xdrneg1
;
127 extern u_int32_t nfs_false
, nfs_true
;
128 extern enum vtype nv3tov_type
[8];
129 extern struct nfsstats nfsstats
;
131 int nfsrvw_procrastinate
= NFS_GATHERDELAY
* 1000;
132 int nfsrvw_procrastinate_v3
= 0;
134 static struct timespec nfsver
;
136 SYSCTL_DECL(_vfs_nfs
);
139 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, async
, CTLFLAG_RW
, &nfs_async
, 0, "");
140 static int nfs_commit_blks
;
141 static int nfs_commit_miss
;
142 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, commit_blks
, CTLFLAG_RW
, &nfs_commit_blks
, 0, "");
143 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, commit_miss
, CTLFLAG_RW
, &nfs_commit_miss
, 0, "");
145 static int nfsrv_access (struct mount
*, struct vnode
*, int,
146 struct ucred
*, int, struct thread
*, int);
147 static void nfsrvw_coalesce (struct nfsrv_descript
*,
148 struct nfsrv_descript
*);
151 * nfs v3 access service
154 nfsrv3_access(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
155 struct thread
*td
, struct mbuf
**mrq
)
157 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
158 struct sockaddr
*nam
= nfsd
->nd_nam
;
159 caddr_t dpos
= nfsd
->nd_dpos
;
160 struct ucred
*cred
= &nfsd
->nd_cr
;
161 struct vnode
*vp
= NULL
;
162 struct mount
*mp
= NULL
;
168 int error
= 0, rdonly
, getret
;
170 struct mbuf
*mb
, *mreq
, *mb2
;
171 struct vattr vattr
, *vap
= &vattr
;
172 u_long testmode
, nfsmode
;
174 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
175 fhp
= &nfh
.fh_generic
;
177 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
178 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
, &rdonly
,
179 (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
181 nfsm_reply(NFSX_UNSIGNED
);
182 nfsm_srvpostop_attr(1, NULL
);
186 nfsmode
= fxdr_unsigned(u_int32_t
, *tl
);
187 if ((nfsmode
& NFSV3ACCESS_READ
) &&
188 nfsrv_access(mp
, vp
, VREAD
, cred
, rdonly
, td
, 0))
189 nfsmode
&= ~NFSV3ACCESS_READ
;
190 if (vp
->v_type
== VDIR
)
191 testmode
= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
|
194 testmode
= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
);
195 if ((nfsmode
& testmode
) &&
196 nfsrv_access(mp
, vp
, VWRITE
, cred
, rdonly
, td
, 0))
197 nfsmode
&= ~testmode
;
198 if (vp
->v_type
== VDIR
)
199 testmode
= NFSV3ACCESS_LOOKUP
;
201 testmode
= NFSV3ACCESS_EXECUTE
;
202 if ((nfsmode
& testmode
) &&
203 nfsrv_access(mp
, vp
, VEXEC
, cred
, rdonly
, td
, 0))
204 nfsmode
&= ~testmode
;
205 getret
= VOP_GETATTR(vp
, vap
);
208 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED
);
209 nfsm_srvpostop_attr(getret
, vap
);
210 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
211 *tl
= txdr_unsigned(nfsmode
);
219 * nfs getattr service
222 nfsrv_getattr(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
223 struct thread
*td
, struct mbuf
**mrq
)
225 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
226 struct sockaddr
*nam
= nfsd
->nd_nam
;
227 caddr_t dpos
= nfsd
->nd_dpos
;
228 struct ucred
*cred
= &nfsd
->nd_cr
;
229 struct nfs_fattr
*fp
;
231 struct vattr
*vap
= &va
;
232 struct vnode
*vp
= NULL
;
233 struct mount
*mp
= NULL
;
239 int error
= 0, rdonly
;
241 struct mbuf
*mb
, *mb2
, *mreq
;
243 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
244 fhp
= &nfh
.fh_generic
;
246 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
247 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
253 error
= VOP_GETATTR(vp
, vap
);
256 nfsm_reply(NFSX_FATTR(nfsd
->nd_flag
& ND_NFSV3
));
261 nfsm_build(fp
, struct nfs_fattr
*, NFSX_FATTR(nfsd
->nd_flag
& ND_NFSV3
));
262 nfsm_srvfillattr(vap
, fp
);
272 * nfs setattr service
275 nfsrv_setattr(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
276 struct thread
*td
, struct mbuf
**mrq
)
278 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
279 struct sockaddr
*nam
= nfsd
->nd_nam
;
280 caddr_t dpos
= nfsd
->nd_dpos
;
281 struct ucred
*cred
= &nfsd
->nd_cr
;
282 struct vattr va
, preat
;
283 struct vattr
*vap
= &va
;
284 struct nfsv2_sattr
*sp
;
285 struct nfs_fattr
*fp
;
286 struct vnode
*vp
= NULL
;
287 struct mount
*mp
= NULL
;
293 int error
= 0, rdonly
, preat_ret
= 1, postat_ret
= 1;
294 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), gcheck
= 0;
296 struct mbuf
*mb
, *mb2
, *mreq
;
297 struct timespec guard
;
299 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
300 fhp
= &nfh
.fh_generic
;
305 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
306 gcheck
= fxdr_unsigned(int, *tl
);
308 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
309 fxdr_nfsv3time(tl
, &guard
);
312 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
314 * Nah nah nah nah na nah
315 * There is a bug in the Sun client that puts 0xffff in the mode
316 * field of sattr when it should put in 0xffffffff. The u_short
317 * doesn't sign extend.
318 * --> check the low order 2 bytes for 0xffff
320 if ((fxdr_unsigned(int, sp
->sa_mode
) & 0xffff) != 0xffff)
321 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
322 if (sp
->sa_uid
!= nfs_xdrneg1
)
323 vap
->va_uid
= fxdr_unsigned(uid_t
, sp
->sa_uid
);
324 if (sp
->sa_gid
!= nfs_xdrneg1
)
325 vap
->va_gid
= fxdr_unsigned(gid_t
, sp
->sa_gid
);
326 if (sp
->sa_size
!= nfs_xdrneg1
)
327 vap
->va_size
= fxdr_unsigned(u_quad_t
, sp
->sa_size
);
328 if (sp
->sa_atime
.nfsv2_sec
!= nfs_xdrneg1
) {
330 fxdr_nfsv2time(&sp
->sa_atime
, &vap
->va_atime
);
332 vap
->va_atime
.tv_sec
=
333 fxdr_unsigned(int32_t, sp
->sa_atime
.nfsv2_sec
);
334 vap
->va_atime
.tv_nsec
= 0;
337 if (sp
->sa_mtime
.nfsv2_sec
!= nfs_xdrneg1
)
338 fxdr_nfsv2time(&sp
->sa_mtime
, &vap
->va_mtime
);
343 * Now that we have all the fields, lets do it.
345 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
, &rdonly
,
346 (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
348 nfsm_reply(2 * NFSX_UNSIGNED
);
349 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
355 * vp now an active resource, pay careful attention to cleanup
359 error
= preat_ret
= VOP_GETATTR(vp
, &preat
);
360 if (!error
&& gcheck
&&
361 (preat
.va_ctime
.tv_sec
!= guard
.tv_sec
||
362 preat
.va_ctime
.tv_nsec
!= guard
.tv_nsec
))
363 error
= NFSERR_NOT_SYNC
;
367 nfsm_reply(NFSX_WCCDATA(v3
));
368 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
375 * If the size is being changed write acces is required, otherwise
376 * just check for a read only file system.
378 if (vap
->va_size
== ((u_quad_t
)((quad_t
) -1))) {
379 if (rdonly
|| (mp
->mnt_flag
& MNT_RDONLY
)) {
384 if (vp
->v_type
== VDIR
) {
387 } else if ((error
= nfsrv_access(mp
, vp
, VWRITE
, cred
, rdonly
,
392 error
= VOP_SETATTR(vp
, vap
, cred
);
393 postat_ret
= VOP_GETATTR(vp
, vap
);
399 nfsm_reply(NFSX_WCCORFATTR(v3
));
401 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
405 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
406 nfsm_srvfillattr(vap
, fp
);
420 nfsrv_lookup(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
421 struct thread
*td
, struct mbuf
**mrq
)
423 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
424 struct sockaddr
*nam
= nfsd
->nd_nam
;
425 caddr_t dpos
= nfsd
->nd_dpos
;
426 struct ucred
*cred
= &nfsd
->nd_cr
;
427 struct nfs_fattr
*fp
;
428 struct nlookupdata nd
;
438 int error
= 0, len
, dirattr_ret
= 1;
439 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), pubflag
;
441 struct mbuf
*mb
, *mb2
, *mreq
;
442 struct vattr va
, dirattr
, *vap
= &va
;
444 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
449 fhp
= &nfh
.fh_generic
;
451 nfsm_srvnamesiz(len
);
453 pubflag
= nfs_ispublicfh(fhp
);
455 error
= nfs_namei(&nd
, cred
, 0, NULL
, &vp
,
456 fhp
, len
, slp
, nam
, &md
, &dpos
,
457 &dirp
, td
, (nfsd
->nd_flag
& ND_KERBAUTH
), pubflag
);
460 * namei failure, only dirp to cleanup. Clear out garbarge from
461 * structure in case macros jump to nfsmout.
467 dirattr_ret
= VOP_GETATTR(dirp
, &dirattr
);
471 nfsm_reply(NFSX_POSTOPATTR(v3
));
472 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
478 * Locate index file for public filehandle
480 * error is 0 on entry and 0 on exit from this block.
484 if (vp
->v_type
== VDIR
&& nfs_pub
.np_index
!= NULL
) {
486 * Setup call to lookup() to see if we can find
487 * the index file. Arguably, this doesn't belong
488 * in a kernel.. Ugh. If an error occurs, do not
489 * try to install an index file and then clear the
492 * When we replace nd with ind and redirect ndp,
493 * maintenance of ni_startdir and ni_vp shift to
494 * ind and we have to clean them up in the old nd.
495 * However, the cnd resource continues to be maintained
496 * via the original nd. Confused? You aren't alone!
499 cache_copy(&nd
.nl_nch
, &nch
);
501 error
= nlookup_init_raw(&nd
, nfs_pub
.np_index
,
502 UIO_SYSSPACE
, 0, cred
, &nch
);
505 error
= nlookup(&nd
);
509 * Found an index file. Get rid of
510 * the old references. transfer vp and
511 * load up the new vp. Fortunately we do
512 * not have to deal with dvp, that would be
519 error
= cache_vget(&nd
.nl_nch
, nd
.nl_cred
,
521 KKASSERT(error
== 0);
526 * If the public filehandle was used, check that this lookup
527 * didn't result in a filehandle outside the publicly exported
528 * filesystem. We clear the poor vp here to avoid lockups due
532 if (vp
->v_mount
!= nfs_pub
.np_mount
) {
541 dirattr_ret
= VOP_GETATTR(dirp
, &dirattr
);
547 * Resources at this point:
548 * ndp->ni_vp may not be NULL
553 nfsm_reply(NFSX_POSTOPATTR(v3
));
554 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
560 * Clear out some resources prior to potentially blocking. This
561 * is not as critical as ni_dvp resources in other routines, but
567 * Get underlying attribute, then release remaining resources ( for
568 * the same potential blocking reason ) and reply.
570 bzero(&fhp
->fh_fid
, sizeof(fhp
->fh_fid
));
571 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
573 error
= VOP_GETATTR(vp
, vap
);
577 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPORFATTR(v3
) + NFSX_POSTOPATTR(v3
));
579 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
583 nfsm_srvfhtom(fhp
, v3
);
585 nfsm_srvpostop_attr(0, vap
);
586 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
588 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
589 nfsm_srvfillattr(vap
, fp
);
595 nlookup_done(&nd
); /* may be called twice */
602 * nfs readlink service
605 nfsrv_readlink(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
606 struct thread
*td
, struct mbuf
**mrq
)
608 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
609 struct sockaddr
*nam
= nfsd
->nd_nam
;
610 caddr_t dpos
= nfsd
->nd_dpos
;
611 struct ucred
*cred
= &nfsd
->nd_cr
;
612 struct iovec iv
[(NFS_MAXPATHLEN
+MLEN
-1)/MLEN
];
613 struct iovec
*ivp
= iv
;
617 int error
= 0, rdonly
, i
, tlen
, len
, getret
;
618 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
620 struct mbuf
*mb
, *mb2
, *mp1
, *mp2
, *mp3
, *mreq
;
621 struct vnode
*vp
= NULL
;
622 struct mount
*mp
= NULL
;
626 struct uio io
, *uiop
= &io
;
628 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
633 fhp
= &nfh
.fh_generic
;
637 while (len
< NFS_MAXPATHLEN
) {
638 mp1
= m_getcl(MB_WAIT
, MT_DATA
, 0);
639 mp1
->m_len
= MCLBYTES
;
646 if ((len
+ mp1
->m_len
) > NFS_MAXPATHLEN
) {
647 mp1
->m_len
= NFS_MAXPATHLEN
-len
;
648 len
= NFS_MAXPATHLEN
;
651 ivp
->iov_base
= mtod(mp1
, caddr_t
);
652 ivp
->iov_len
= mp1
->m_len
;
657 uiop
->uio_iovcnt
= i
;
658 uiop
->uio_offset
= 0;
659 uiop
->uio_resid
= len
;
660 uiop
->uio_rw
= UIO_READ
;
661 uiop
->uio_segflg
= UIO_SYSSPACE
;
663 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
664 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
666 nfsm_reply(2 * NFSX_UNSIGNED
);
667 nfsm_srvpostop_attr(1, NULL
);
671 if (vp
->v_type
!= VLNK
) {
678 error
= VOP_READLINK(vp
, uiop
, cred
);
680 getret
= VOP_GETATTR(vp
, &attr
);
683 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_UNSIGNED
);
685 nfsm_srvpostop_attr(getret
, &attr
);
691 if (uiop
->uio_resid
> 0) {
692 len
-= uiop
->uio_resid
;
693 tlen
= nfsm_rndup(len
);
694 nfsm_adj(mp3
, NFS_MAXPATHLEN
-tlen
, tlen
-len
);
696 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
697 *tl
= txdr_unsigned(len
);
712 nfsrv_read(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
713 struct thread
*td
, struct mbuf
**mrq
)
715 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
716 struct sockaddr
*nam
= nfsd
->nd_nam
;
717 caddr_t dpos
= nfsd
->nd_dpos
;
718 struct ucred
*cred
= &nfsd
->nd_cr
;
722 struct nfs_fattr
*fp
;
727 int error
= 0, rdonly
, cnt
, len
, left
, siz
, tlen
, getret
;
728 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), reqlen
;
730 struct mbuf
*mb
, *mb2
, *mreq
;
732 struct vnode
*vp
= NULL
;
733 struct mount
*mp
= NULL
;
736 struct uio io
, *uiop
= &io
;
737 struct vattr va
, *vap
= &va
;
742 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
743 fhp
= &nfh
.fh_generic
;
746 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
747 off
= fxdr_hyper(tl
);
749 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
750 off
= (off_t
)fxdr_unsigned(u_int32_t
, *tl
);
752 nfsm_srvstrsiz(reqlen
, NFS_SRVMAXDATA(nfsd
));
755 * Reference vp. If an error occurs, vp will be invalid, but we
756 * have to NULL it just in case. The macros might goto nfsmout
760 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
761 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
764 nfsm_reply(2 * NFSX_UNSIGNED
);
765 nfsm_srvpostop_attr(1, NULL
);
770 if (vp
->v_type
!= VREG
) {
774 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
777 if ((error
= nfsrv_access(mp
, vp
, VREAD
, cred
, rdonly
, td
, 1)) != 0)
778 error
= nfsrv_access(mp
, vp
, VEXEC
, cred
, rdonly
, td
, 1);
780 getret
= VOP_GETATTR(vp
, vap
);
786 nfsm_reply(NFSX_POSTOPATTR(v3
));
787 nfsm_srvpostop_attr(getret
, vap
);
793 * Calculate byte count to read
796 if (off
>= vap
->va_size
)
798 else if ((off
+ reqlen
) > vap
->va_size
)
799 cnt
= vap
->va_size
- off
;
804 * Calculate seqcount for heuristic
812 * Locate best candidate
815 hi
= ((int)(vm_offset_t
)vp
/ sizeof(struct vnode
)) % NUM_HEURISTIC
;
819 if (nfsheur
[hi
].nh_vp
== vp
) {
823 if (nfsheur
[hi
].nh_use
> 0)
824 --nfsheur
[hi
].nh_use
;
825 hi
= (hi
+ 1) % NUM_HEURISTIC
;
826 if (nfsheur
[hi
].nh_use
< nh
->nh_use
)
830 if (nh
->nh_vp
!= vp
) {
833 nh
->nh_use
= NHUSE_INIT
;
841 * Calculate heuristic
844 if ((off
== 0 && nh
->nh_seqcount
> 0) || off
== nh
->nh_nextr
) {
845 if (++nh
->nh_seqcount
> IO_SEQMAX
)
846 nh
->nh_seqcount
= IO_SEQMAX
;
847 } else if (nh
->nh_seqcount
> 1) {
852 nh
->nh_use
+= NHUSE_INC
;
853 if (nh
->nh_use
> NHUSE_MAX
)
854 nh
->nh_use
= NHUSE_MAX
;
855 ioflag
|= nh
->nh_seqcount
<< IO_SEQSHIFT
;
858 nfsm_reply(NFSX_POSTOPORFATTR(v3
) + 3 * NFSX_UNSIGNED
+nfsm_rndup(cnt
));
860 nfsm_build(tl
, u_int32_t
*, NFSX_V3FATTR
+ 4 * NFSX_UNSIGNED
);
862 fp
= (struct nfs_fattr
*)tl
;
863 tl
+= (NFSX_V3FATTR
/ sizeof (u_int32_t
));
865 nfsm_build(tl
, u_int32_t
*, NFSX_V2FATTR
+ NFSX_UNSIGNED
);
866 fp
= (struct nfs_fattr
*)tl
;
867 tl
+= (NFSX_V2FATTR
/ sizeof (u_int32_t
));
869 len
= left
= nfsm_rndup(cnt
);
872 * Generate the mbuf list with the uio_iov ref. to it.
877 siz
= min(M_TRAILINGSPACE(m
), left
);
883 m
= m_getcl(MB_WAIT
, MT_DATA
, 0);
889 MALLOC(iv
, struct iovec
*, i
* sizeof (struct iovec
),
891 uiop
->uio_iov
= iv2
= iv
;
897 panic("nfsrv_read iov");
898 siz
= min(M_TRAILINGSPACE(m
), left
);
900 iv
->iov_base
= mtod(m
, caddr_t
) + m
->m_len
;
909 uiop
->uio_iovcnt
= i
;
910 uiop
->uio_offset
= off
;
911 uiop
->uio_resid
= len
;
912 uiop
->uio_rw
= UIO_READ
;
913 uiop
->uio_segflg
= UIO_SYSSPACE
;
914 error
= VOP_READ(vp
, uiop
, IO_NODELOCKED
| ioflag
, cred
);
915 off
= uiop
->uio_offset
;
917 FREE((caddr_t
)iv2
, M_TEMP
);
918 if (error
|| (getret
= VOP_GETATTR(vp
, vap
))) {
924 nfsm_reply(NFSX_POSTOPATTR(v3
));
925 nfsm_srvpostop_attr(getret
, vap
);
934 nfsm_srvfillattr(vap
, fp
);
935 tlen
= len
- uiop
->uio_resid
;
936 cnt
= cnt
< tlen
? cnt
: tlen
;
937 tlen
= nfsm_rndup(cnt
);
938 if (len
!= tlen
|| tlen
!= cnt
)
939 nfsm_adj(mb
, len
- tlen
, tlen
- cnt
);
941 *tl
++ = txdr_unsigned(cnt
);
947 *tl
= txdr_unsigned(cnt
);
958 nfsrv_write(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
959 struct thread
*td
, struct mbuf
**mrq
)
961 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
962 struct sockaddr
*nam
= nfsd
->nd_nam
;
963 caddr_t dpos
= nfsd
->nd_dpos
;
964 struct ucred
*cred
= &nfsd
->nd_cr
;
968 struct nfs_fattr
*fp
;
970 struct vattr va
, forat
;
971 struct vattr
*vap
= &va
;
975 int error
= 0, rdonly
, len
, forat_ret
= 1;
976 int ioflags
, aftat_ret
= 1, retlen
, zeroing
, adjust
;
977 int stable
= NFSV3WRITE_FILESYNC
;
978 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
980 struct mbuf
*mb
, *mb2
, *mreq
;
981 struct vnode
*vp
= NULL
;
982 struct mount
*mp
= NULL
;
985 struct uio io
, *uiop
= &io
;
988 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
994 fhp
= &nfh
.fh_generic
;
997 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
998 off
= fxdr_hyper(tl
);
1000 stable
= fxdr_unsigned(int, *tl
++);
1002 nfsm_dissect(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1003 off
= (off_t
)fxdr_unsigned(u_int32_t
, *++tl
);
1006 stable
= NFSV3WRITE_UNSTABLE
;
1008 retlen
= len
= fxdr_unsigned(int32_t, *tl
);
1012 * For NFS Version 2, it is not obvious what a write of zero length
1013 * should do, but I might as well be consistent with Version 3,
1014 * which is to return ok so long as there are no permission problems.
1022 adjust
= dpos
- mtod(mp1
, caddr_t
);
1023 mp1
->m_len
-= adjust
;
1024 if (mp1
->m_len
> 0 && adjust
> 0)
1025 NFSMADV(mp1
, adjust
);
1029 else if (mp1
->m_len
> 0) {
1032 mp1
->m_len
-= (i
- len
);
1041 if (len
> NFS_MAXDATA
|| len
< 0 || i
< len
) {
1043 nfsm_reply(2 * NFSX_UNSIGNED
);
1044 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1048 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
1049 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
1052 nfsm_reply(2 * NFSX_UNSIGNED
);
1053 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1058 forat_ret
= VOP_GETATTR(vp
, &forat
);
1059 if (vp
->v_type
!= VREG
) {
1063 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
1066 error
= nfsrv_access(mp
, vp
, VWRITE
, cred
, rdonly
, td
, 1);
1071 nfsm_reply(NFSX_WCCDATA(v3
));
1072 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1078 MALLOC(ivp
, struct iovec
*, cnt
* sizeof (struct iovec
), M_TEMP
,
1080 uiop
->uio_iov
= iv
= ivp
;
1081 uiop
->uio_iovcnt
= cnt
;
1084 if (mp1
->m_len
> 0) {
1085 ivp
->iov_base
= mtod(mp1
, caddr_t
);
1086 ivp
->iov_len
= mp1
->m_len
;
1094 * The IO_METASYNC flag indicates that all metadata (and not just
1095 * enough to ensure data integrity) mus be written to stable storage
1097 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1099 if (stable
== NFSV3WRITE_UNSTABLE
)
1100 ioflags
= IO_NODELOCKED
;
1101 else if (stable
== NFSV3WRITE_DATASYNC
)
1102 ioflags
= (IO_SYNC
| IO_NODELOCKED
);
1104 ioflags
= (IO_METASYNC
| IO_SYNC
| IO_NODELOCKED
);
1105 uiop
->uio_resid
= len
;
1106 uiop
->uio_rw
= UIO_WRITE
;
1107 uiop
->uio_segflg
= UIO_SYSSPACE
;
1108 uiop
->uio_td
= NULL
;
1109 uiop
->uio_offset
= off
;
1110 error
= VOP_WRITE(vp
, uiop
, ioflags
, cred
);
1111 nfsstats
.srvvop_writes
++;
1112 FREE((caddr_t
)iv
, M_TEMP
);
1114 aftat_ret
= VOP_GETATTR(vp
, vap
);
1119 nfsm_reply(NFSX_PREOPATTR(v3
) + NFSX_POSTOPORFATTR(v3
) +
1120 2 * NFSX_UNSIGNED
+ NFSX_WRITEVERF(v3
));
1122 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1127 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1128 *tl
++ = txdr_unsigned(retlen
);
1130 * If nfs_async is set, then pretend the write was FILESYNC.
1132 if (stable
== NFSV3WRITE_UNSTABLE
&& !nfs_async
)
1133 *tl
++ = txdr_unsigned(stable
);
1135 *tl
++ = txdr_unsigned(NFSV3WRITE_FILESYNC
);
1137 * Actually, there is no need to txdr these fields,
1138 * but it may make the values more human readable,
1139 * for debugging purposes.
1141 if (nfsver
.tv_sec
== 0)
1143 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
1144 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
1146 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1147 nfsm_srvfillattr(vap
, fp
);
1156 * NFS write service with write gathering support. Called when
1157 * nfsrvw_procrastinate > 0.
1158 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1159 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1163 nfsrv_writegather(struct nfsrv_descript
**ndp
, struct nfssvc_sock
*slp
,
1164 struct thread
*td
, struct mbuf
**mrq
)
1167 struct nfsrv_descript
*wp
, *nfsd
, *owp
, *swp
;
1168 struct nfs_fattr
*fp
;
1171 struct nfsrvw_delayhash
*wpp
;
1173 struct vattr va
, forat
;
1177 int error
= 0, rdonly
, len
, forat_ret
= 1;
1178 int ioflags
, aftat_ret
= 1, adjust
, v3
, zeroing
;
1180 struct mbuf
*mb
, *mb2
, *mreq
, *mrep
, *md
, *mp1
;
1181 struct vnode
*vp
= NULL
;
1182 struct mount
*mp
= NULL
;
1183 struct uio io
, *uiop
= &io
;
1186 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1195 mrep
= nfsd
->nd_mrep
;
1197 dpos
= nfsd
->nd_dpos
;
1198 cred
= &nfsd
->nd_cr
;
1199 v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1200 LIST_INIT(&nfsd
->nd_coalesce
);
1201 nfsd
->nd_mreq
= NULL
;
1202 nfsd
->nd_stable
= NFSV3WRITE_FILESYNC
;
1203 cur_usec
= nfs_curusec();
1204 nfsd
->nd_time
= cur_usec
+
1205 (v3
? nfsrvw_procrastinate_v3
: nfsrvw_procrastinate
);
1208 * Now, get the write header..
1210 nfsm_srvmtofh(&nfsd
->nd_fh
);
1212 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
1213 nfsd
->nd_off
= fxdr_hyper(tl
);
1215 nfsd
->nd_stable
= fxdr_unsigned(int, *tl
++);
1217 nfsm_dissect(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1218 nfsd
->nd_off
= (off_t
)fxdr_unsigned(u_int32_t
, *++tl
);
1221 nfsd
->nd_stable
= NFSV3WRITE_UNSTABLE
;
1223 len
= fxdr_unsigned(int32_t, *tl
);
1225 nfsd
->nd_eoff
= nfsd
->nd_off
+ len
;
1228 * Trim the header out of the mbuf list and trim off any trailing
1229 * junk so that the mbuf list has only the write data.
1237 adjust
= dpos
- mtod(mp1
, caddr_t
);
1238 mp1
->m_len
-= adjust
;
1239 if (mp1
->m_len
> 0 && adjust
> 0)
1240 NFSMADV(mp1
, adjust
);
1247 mp1
->m_len
-= (i
- len
);
1253 if (len
> NFS_MAXDATA
|| len
< 0 || i
< len
) {
1257 nfsm_writereply(2 * NFSX_UNSIGNED
, v3
);
1259 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1260 nfsd
->nd_mreq
= mreq
;
1261 nfsd
->nd_mrep
= NULL
;
1266 * Add this entry to the hash and time queues.
1270 wp
= slp
->ns_tq
.lh_first
;
1271 while (wp
&& wp
->nd_time
< nfsd
->nd_time
) {
1273 wp
= wp
->nd_tq
.le_next
;
1275 NFS_DPF(WG
, ("Q%03x", nfsd
->nd_retxid
& 0xfff));
1277 LIST_INSERT_AFTER(owp
, nfsd
, nd_tq
);
1279 LIST_INSERT_HEAD(&slp
->ns_tq
, nfsd
, nd_tq
);
1281 if (nfsd
->nd_mrep
) {
1282 wpp
= NWDELAYHASH(slp
, nfsd
->nd_fh
.fh_fid
.fid_data
);
1286 bcmp((caddr_t
)&nfsd
->nd_fh
,(caddr_t
)&wp
->nd_fh
,NFSX_V3FH
)) {
1288 wp
= wp
->nd_hash
.le_next
;
1290 while (wp
&& wp
->nd_off
< nfsd
->nd_off
&&
1291 !bcmp((caddr_t
)&nfsd
->nd_fh
,(caddr_t
)&wp
->nd_fh
,NFSX_V3FH
)) {
1293 wp
= wp
->nd_hash
.le_next
;
1296 LIST_INSERT_AFTER(owp
, nfsd
, nd_hash
);
1299 * Search the hash list for overlapping entries and
1302 for(; nfsd
&& NFSW_CONTIG(owp
, nfsd
); nfsd
= wp
) {
1303 wp
= nfsd
->nd_hash
.le_next
;
1304 if (NFSW_SAMECRED(owp
, nfsd
))
1305 nfsrvw_coalesce(owp
, nfsd
);
1308 LIST_INSERT_HEAD(wpp
, nfsd
, nd_hash
);
1315 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1316 * and generate the associated reply mbuf list(s).
1319 cur_usec
= nfs_curusec();
1321 for (nfsd
= slp
->ns_tq
.lh_first
; nfsd
; nfsd
= owp
) {
1322 owp
= nfsd
->nd_tq
.le_next
;
1323 if (nfsd
->nd_time
> cur_usec
)
1327 NFS_DPF(WG
, ("P%03x", nfsd
->nd_retxid
& 0xfff));
1328 LIST_REMOVE(nfsd
, nd_tq
);
1329 LIST_REMOVE(nfsd
, nd_hash
);
1331 mrep
= nfsd
->nd_mrep
;
1332 nfsd
->nd_mrep
= NULL
;
1333 cred
= &nfsd
->nd_cr
;
1334 v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1335 forat_ret
= aftat_ret
= 1;
1336 error
= nfsrv_fhtovp(&nfsd
->nd_fh
, 1, &mp
, &vp
, cred
, slp
,
1337 nfsd
->nd_nam
, &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
1340 forat_ret
= VOP_GETATTR(vp
, &forat
);
1341 if (vp
->v_type
!= VREG
) {
1345 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
1351 error
= nfsrv_access(mp
, vp
, VWRITE
, cred
, rdonly
, td
, 1);
1354 if (nfsd
->nd_stable
== NFSV3WRITE_UNSTABLE
)
1355 ioflags
= IO_NODELOCKED
;
1356 else if (nfsd
->nd_stable
== NFSV3WRITE_DATASYNC
)
1357 ioflags
= (IO_SYNC
| IO_NODELOCKED
);
1359 ioflags
= (IO_METASYNC
| IO_SYNC
| IO_NODELOCKED
);
1360 uiop
->uio_rw
= UIO_WRITE
;
1361 uiop
->uio_segflg
= UIO_SYSSPACE
;
1362 uiop
->uio_td
= NULL
;
1363 uiop
->uio_offset
= nfsd
->nd_off
;
1364 uiop
->uio_resid
= nfsd
->nd_eoff
- nfsd
->nd_off
;
1365 if (uiop
->uio_resid
> 0) {
1373 uiop
->uio_iovcnt
= i
;
1374 MALLOC(iov
, struct iovec
*, i
* sizeof (struct iovec
),
1376 uiop
->uio_iov
= ivp
= iov
;
1379 if (mp1
->m_len
> 0) {
1380 ivp
->iov_base
= mtod(mp1
, caddr_t
);
1381 ivp
->iov_len
= mp1
->m_len
;
1387 error
= VOP_WRITE(vp
, uiop
, ioflags
, cred
);
1388 nfsstats
.srvvop_writes
++;
1390 FREE((caddr_t
)iov
, M_TEMP
);
1394 aftat_ret
= VOP_GETATTR(vp
, &va
);
1400 * Loop around generating replies for all write rpcs that have
1401 * now been completed.
1405 NFS_DPF(WG
, ("R%03x", nfsd
->nd_retxid
& 0xfff));
1407 nfsm_writereply(NFSX_WCCDATA(v3
), v3
);
1409 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1412 nfsm_writereply(NFSX_PREOPATTR(v3
) +
1413 NFSX_POSTOPORFATTR(v3
) + 2 * NFSX_UNSIGNED
+
1414 NFSX_WRITEVERF(v3
), v3
);
1416 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1417 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1418 *tl
++ = txdr_unsigned(nfsd
->nd_len
);
1419 *tl
++ = txdr_unsigned(swp
->nd_stable
);
1421 * Actually, there is no need to txdr these fields,
1422 * but it may make the values more human readable,
1423 * for debugging purposes.
1425 if (nfsver
.tv_sec
== 0)
1427 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
1428 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
1430 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1431 nfsm_srvfillattr(&va
, fp
);
1434 nfsd
->nd_mreq
= mreq
;
1436 panic("nfsrv_write: nd_mrep not free");
1439 * Done. Put it at the head of the timer queue so that
1440 * the final phase can return the reply.
1445 LIST_INSERT_HEAD(&slp
->ns_tq
, nfsd
, nd_tq
);
1447 nfsd
= swp
->nd_coalesce
.lh_first
;
1449 LIST_REMOVE(nfsd
, nd_tq
);
1455 LIST_INSERT_HEAD(&slp
->ns_tq
, swp
, nd_tq
);
1462 * Search for a reply to return.
1465 for (nfsd
= slp
->ns_tq
.lh_first
; nfsd
; nfsd
= nfsd
->nd_tq
.le_next
)
1466 if (nfsd
->nd_mreq
) {
1467 NFS_DPF(WG
, ("X%03x", nfsd
->nd_retxid
& 0xfff));
1468 LIST_REMOVE(nfsd
, nd_tq
);
1469 *mrq
= nfsd
->nd_mreq
;
1478 * Coalesce the write request nfsd into owp. To do this we must:
1479 * - remove nfsd from the queues
1480 * - merge nfsd->nd_mrep into owp->nd_mrep
1481 * - update the nd_eoff and nd_stable for owp
1482 * - put nfsd on owp's nd_coalesce list
1483 * NB: Must be called at splsoftclock().
1486 nfsrvw_coalesce(struct nfsrv_descript
*owp
, struct nfsrv_descript
*nfsd
)
1490 struct nfsrv_descript
*p
;
1492 NFS_DPF(WG
, ("C%03x-%03x",
1493 nfsd
->nd_retxid
& 0xfff, owp
->nd_retxid
& 0xfff));
1494 LIST_REMOVE(nfsd
, nd_hash
);
1495 LIST_REMOVE(nfsd
, nd_tq
);
1496 if (owp
->nd_eoff
< nfsd
->nd_eoff
) {
1497 overlap
= owp
->nd_eoff
- nfsd
->nd_off
;
1499 panic("nfsrv_coalesce: bad off");
1501 m_adj(nfsd
->nd_mrep
, overlap
);
1505 mp1
->m_next
= nfsd
->nd_mrep
;
1506 owp
->nd_eoff
= nfsd
->nd_eoff
;
1508 m_freem(nfsd
->nd_mrep
);
1509 nfsd
->nd_mrep
= NULL
;
1510 if (nfsd
->nd_stable
== NFSV3WRITE_FILESYNC
)
1511 owp
->nd_stable
= NFSV3WRITE_FILESYNC
;
1512 else if (nfsd
->nd_stable
== NFSV3WRITE_DATASYNC
&&
1513 owp
->nd_stable
== NFSV3WRITE_UNSTABLE
)
1514 owp
->nd_stable
= NFSV3WRITE_DATASYNC
;
1515 LIST_INSERT_HEAD(&owp
->nd_coalesce
, nfsd
, nd_tq
);
1518 * If nfsd had anything else coalesced into it, transfer them
1519 * to owp, otherwise their replies will never get sent.
1521 for (p
= nfsd
->nd_coalesce
.lh_first
; p
;
1522 p
= nfsd
->nd_coalesce
.lh_first
) {
1523 LIST_REMOVE(p
, nd_tq
);
1524 LIST_INSERT_HEAD(&owp
->nd_coalesce
, p
, nd_tq
);
1529 * nfs create service
1530 * now does a truncate to 0 length via. setattr if it already exists
1533 nfsrv_create(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1534 struct thread
*td
, struct mbuf
**mrq
)
1536 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1537 struct sockaddr
*nam
= nfsd
->nd_nam
;
1538 caddr_t dpos
= nfsd
->nd_dpos
;
1539 struct ucred
*cred
= &nfsd
->nd_cr
;
1540 struct nfs_fattr
*fp
;
1541 struct vattr va
, dirfor
, diraft
;
1542 struct vattr
*vap
= &va
;
1543 struct nfsv2_sattr
*sp
;
1545 struct nlookupdata nd
;
1548 int error
= 0, len
, tsize
, dirfor_ret
= 1, diraft_ret
= 1;
1549 udev_t rdev
= NOUDEV
;
1550 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), how
, exclusive_flag
= 0;
1553 struct mbuf
*mb
, *mb2
, *mreq
;
1561 u_char cverf
[NFSX_V3CREATEVERF
];
1563 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1569 fhp
= &nfh
.fh_generic
;
1571 nfsm_srvnamesiz(len
);
1574 * Call namei and do initial cleanup to get a few things
1575 * out of the way. If we get an initial error we cleanup
1576 * and return here to avoid special-casing the invalid nd
1577 * structure through the rest of the case. dirp may be
1578 * set even if an error occurs, but the nd structure will not
1579 * be valid at all if an error occurs so we have to invalidate it
1580 * prior to calling nfsm_reply ( which might goto nfsmout ).
1582 error
= nfs_namei(&nd
, cred
, NLC_CREATE
, &dvp
, &vp
,
1583 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1584 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1585 mp
= vfs_getvfs(&fhp
->fh_fsid
);
1589 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1596 nfsm_reply(NFSX_WCCDATA(v3
));
1597 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1603 * No error. Continue. State:
1606 * vp may be valid or NULL if the target does not
1610 * The error state is set through the code and we may also do some
1611 * opportunistic releasing of vnodes to avoid holding locks through
1612 * NFS I/O. The cleanup at the end is a catch-all
1617 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
1618 how
= fxdr_unsigned(int, *tl
);
1620 case NFSV3CREATE_GUARDED
:
1626 case NFSV3CREATE_UNCHECKED
:
1629 case NFSV3CREATE_EXCLUSIVE
:
1630 nfsm_dissect(cp
, caddr_t
, NFSX_V3CREATEVERF
);
1631 bcopy(cp
, cverf
, NFSX_V3CREATEVERF
);
1635 vap
->va_type
= VREG
;
1637 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1638 vap
->va_type
= IFTOVT(fxdr_unsigned(u_int32_t
, sp
->sa_mode
));
1639 if (vap
->va_type
== VNON
)
1640 vap
->va_type
= VREG
;
1641 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
1642 switch (vap
->va_type
) {
1644 tsize
= fxdr_unsigned(int32_t, sp
->sa_size
);
1646 vap
->va_size
= (u_quad_t
)tsize
;
1651 rdev
= fxdr_unsigned(long, sp
->sa_size
);
1659 * Iff doesn't exist, create it
1660 * otherwise just truncate to 0 length
1661 * should I set the mode too ?
1663 * The only possible error we can have at this point is EEXIST.
1664 * nd.ni_vp will also be non-NULL in that case.
1667 if (vap
->va_mode
== (mode_t
)VNOVAL
)
1669 if (vap
->va_type
== VREG
|| vap
->va_type
== VSOCK
) {
1671 error
= VOP_NCREATE(&nd
.nl_nch
, dvp
, &vp
,
1676 if (exclusive_flag
) {
1679 bcopy(cverf
, (caddr_t
)&vap
->va_atime
,
1681 error
= VOP_SETATTR(vp
, vap
, cred
);
1685 vap
->va_type
== VCHR
||
1686 vap
->va_type
== VBLK
||
1687 vap
->va_type
== VFIFO
1690 * Handle SysV FIFO node special cases. All other
1691 * devices require super user to access.
1693 if (vap
->va_type
== VCHR
&& rdev
== 0xffffffff)
1694 vap
->va_type
= VFIFO
;
1695 if (vap
->va_type
!= VFIFO
&&
1696 (error
= priv_check_cred(cred
, PRIV_ROOT
, 0))) {
1699 vap
->va_rmajor
= umajor(rdev
);
1700 vap
->va_rminor
= uminor(rdev
);
1703 error
= VOP_NMKNOD(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1710 * XXX what is this junk supposed to do ?
1717 * release dvp prior to lookup
1725 * Even though LOCKPARENT was cleared, ni_dvp may
1728 nd
.ni_cnd
.cn_nameiop
= NAMEI_LOOKUP
;
1729 nd
.ni_cnd
.cn_flags
&= ~(CNP_LOCKPARENT
);
1730 nd
.ni_cnd
.cn_td
= td
;
1731 nd
.ni_cnd
.cn_cred
= cred
;
1733 error
= lookup(&nd
);
1738 /* fall through on certain errors */
1740 nfsrv_object_create(nd
.ni_vp
);
1741 if (nd
.ni_cnd
.cn_flags
& CNP_ISSYMLINK
) {
1750 if (vap
->va_size
!= -1) {
1751 error
= nfsrv_access(mp
, vp
, VWRITE
, cred
,
1752 (nd
.nl_flags
& NLC_NFS_RDONLY
), td
, 0);
1754 tempsize
= vap
->va_size
;
1756 vap
->va_size
= tempsize
;
1757 error
= VOP_SETATTR(vp
, vap
, cred
);
1763 bzero(&fhp
->fh_fid
, sizeof(fhp
->fh_fid
));
1764 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
1766 error
= VOP_GETATTR(vp
, vap
);
1769 if (exclusive_flag
&& !error
&&
1770 bcmp(cverf
, (caddr_t
)&vap
->va_atime
, NFSX_V3CREATEVERF
))
1772 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
1776 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_FATTR(v3
) + NFSX_WCCDATA(v3
));
1779 nfsm_srvpostop_fh(fhp
);
1780 nfsm_srvpostop_attr(0, vap
);
1782 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1785 nfsm_srvfhtom(fhp
, v3
);
1786 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1787 nfsm_srvfillattr(vap
, fp
);
1812 * nfs v3 mknod service
1815 nfsrv_mknod(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1816 struct thread
*td
, struct mbuf
**mrq
)
1818 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1819 struct sockaddr
*nam
= nfsd
->nd_nam
;
1820 caddr_t dpos
= nfsd
->nd_dpos
;
1821 struct ucred
*cred
= &nfsd
->nd_cr
;
1822 struct vattr va
, dirfor
, diraft
;
1823 struct vattr
*vap
= &va
;
1825 struct nlookupdata nd
;
1828 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
1831 struct mbuf
*mb
, *mb2
, *mreq
;
1838 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1844 fhp
= &nfh
.fh_generic
;
1846 nfsm_srvnamesiz(len
);
1849 * Handle nfs_namei() call. If an error occurs, the nd structure
1850 * is not valid. However, nfsm_*() routines may still jump to
1854 error
= nfs_namei(&nd
, cred
, NLC_CREATE
, &dvp
, &vp
,
1855 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1856 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1858 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1860 nfsm_reply(NFSX_WCCDATA(1));
1861 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1865 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
1866 vtyp
= nfsv3tov_type(*tl
);
1867 if (vtyp
!= VCHR
&& vtyp
!= VBLK
&& vtyp
!= VSOCK
&& vtyp
!= VFIFO
) {
1868 error
= NFSERR_BADTYPE
;
1873 if (vtyp
== VCHR
|| vtyp
== VBLK
) {
1874 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
1875 vap
->va_rmajor
= fxdr_unsigned(u_int32_t
, *tl
++);
1876 vap
->va_rminor
= fxdr_unsigned(u_int32_t
, *tl
);
1880 * Iff doesn't exist, create it.
1886 vap
->va_type
= vtyp
;
1887 if (vap
->va_mode
== (mode_t
)VNOVAL
)
1889 if (vtyp
== VSOCK
) {
1891 error
= VOP_NCREATE(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1895 if (vtyp
!= VFIFO
&& (error
= priv_check_cred(cred
, PRIV_ROOT
, 0)))
1899 error
= VOP_NMKNOD(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1907 * send response, cleanup, return.
1919 bzero(&fhp
->fh_fid
, sizeof(fhp
->fh_fid
));
1920 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
1922 error
= VOP_GETATTR(vp
, vap
);
1928 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
1933 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1935 nfsm_srvpostop_fh(fhp
);
1936 nfsm_srvpostop_attr(0, vap
);
1938 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1956 * nfs remove service
1959 nfsrv_remove(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1960 struct thread
*td
, struct mbuf
**mrq
)
1962 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1963 struct sockaddr
*nam
= nfsd
->nd_nam
;
1964 caddr_t dpos
= nfsd
->nd_dpos
;
1965 struct ucred
*cred
= &nfsd
->nd_cr
;
1966 struct nlookupdata nd
;
1970 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
1971 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1973 struct mbuf
*mb
, *mreq
;
1977 struct vattr dirfor
, diraft
;
1981 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1987 fhp
= &nfh
.fh_generic
;
1989 nfsm_srvnamesiz(len
);
1991 error
= nfs_namei(&nd
, cred
, NLC_DELETE
, &dvp
, &vp
,
1992 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1993 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1996 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1999 if (vp
->v_type
== VDIR
) {
2000 error
= EPERM
; /* POSIX */
2004 * The root of a mounted filesystem cannot be deleted.
2006 if (vp
->v_flag
& VROOT
) {
2018 error
= VOP_NREMOVE(&nd
.nl_nch
, dvp
, nd
.nl_cred
);
2024 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2025 nfsm_reply(NFSX_WCCDATA(v3
));
2027 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2046 * nfs rename service
2049 nfsrv_rename(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2050 struct thread
*td
, struct mbuf
**mrq
)
2052 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2053 struct sockaddr
*nam
= nfsd
->nd_nam
;
2054 caddr_t dpos
= nfsd
->nd_dpos
;
2055 struct ucred
*cred
= &nfsd
->nd_cr
;
2059 int error
= 0, len
, len2
, fdirfor_ret
= 1, fdiraft_ret
= 1;
2060 int tdirfor_ret
= 1, tdiraft_ret
= 1;
2061 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2063 struct mbuf
*mb
, *mreq
;
2064 struct nlookupdata fromnd
, tond
;
2065 struct vnode
*fvp
, *fdirp
, *fdvp
;
2066 struct vnode
*tvp
, *tdirp
, *tdvp
;
2067 struct namecache
*ncp
;
2068 struct vattr fdirfor
, fdiraft
, tdirfor
, tdiraft
;
2070 fhandle_t
*ffhp
, *tfhp
;
2073 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2077 ffhp
= &fnfh
.fh_generic
;
2078 tfhp
= &tnfh
.fh_generic
;
2081 * Clear fields incase goto nfsmout occurs from macro.
2084 nlookup_zero(&fromnd
);
2085 nlookup_zero(&tond
);
2089 nfsm_srvmtofh(ffhp
);
2090 nfsm_srvnamesiz(len
);
2092 * Remember our original uid so that we can reset cr_uid before
2093 * the second nfs_namei() call, in case it is remapped.
2095 saved_uid
= cred
->cr_uid
;
2096 error
= nfs_namei(&fromnd
, cred
, NLC_RENAME_SRC
,
2098 ffhp
, len
, slp
, nam
, &md
, &dpos
, &fdirp
,
2099 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2102 fdirfor_ret
= VOP_GETATTR(fdirp
, &fdirfor
);
2105 nfsm_reply(2 * NFSX_WCCDATA(v3
));
2106 nfsm_srvwcc_data(fdirfor_ret
, &fdirfor
, fdiraft_ret
, &fdiraft
);
2107 nfsm_srvwcc_data(tdirfor_ret
, &tdirfor
, tdiraft_ret
, &tdiraft
);
2113 * We have to unlock the from ncp before we can safely lookup
2116 KKASSERT(fromnd
.nl_flags
& NLC_NCPISLOCKED
);
2117 cache_unlock(&fromnd
.nl_nch
);
2118 fromnd
.nl_flags
&= ~NLC_NCPISLOCKED
;
2119 nfsm_srvmtofh(tfhp
);
2120 nfsm_strsiz(len2
, NFS_MAXNAMLEN
);
2121 cred
->cr_uid
= saved_uid
;
2123 error
= nfs_namei(&tond
, cred
, NLC_RENAME_DST
, NULL
, NULL
,
2124 tfhp
, len2
, slp
, nam
, &md
, &dpos
, &tdirp
,
2125 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2128 tdirfor_ret
= VOP_GETATTR(tdirp
, &tdirfor
);
2136 if (cache_lock_nonblock(&fromnd
.nl_nch
) == 0) {
2137 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2138 } else if (fromnd
.nl_nch
.ncp
> tond
.nl_nch
.ncp
) {
2139 cache_lock(&fromnd
.nl_nch
);
2140 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2142 cache_unlock(&tond
.nl_nch
);
2143 cache_lock(&fromnd
.nl_nch
);
2144 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2145 cache_lock(&tond
.nl_nch
);
2146 cache_resolve(&tond
.nl_nch
, tond
.nl_cred
);
2148 fromnd
.nl_flags
|= NLC_NCPISLOCKED
;
2150 fvp
= fromnd
.nl_nch
.ncp
->nc_vp
;
2151 tvp
= tond
.nl_nch
.ncp
->nc_vp
;
2154 * Set fdvp and tdvp. We haven't done all the topology checks
2155 * so these can wind up NULL (e.g. if either fvp or tvp is a mount
2156 * point). If we get through the checks these will be guarenteed
2159 * Holding the children ncp's should be sufficient to prevent
2160 * fdvp and tdvp ripouts.
2162 if (fromnd
.nl_nch
.ncp
->nc_parent
)
2163 fdvp
= fromnd
.nl_nch
.ncp
->nc_parent
->nc_vp
;
2166 if (tond
.nl_nch
.ncp
->nc_parent
)
2167 tdvp
= tond
.nl_nch
.ncp
->nc_parent
->nc_vp
;
2172 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
2178 } else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
2185 if (tvp
->v_type
== VDIR
&& (tond
.nl_nch
.ncp
->nc_flag
& NCF_ISMOUNTPT
)) {
2193 if (fvp
->v_type
== VDIR
&& (fromnd
.nl_nch
.ncp
->nc_flag
& NCF_ISMOUNTPT
)) {
2200 if (fromnd
.nl_nch
.mount
!= tond
.nl_nch
.mount
) {
2207 if (fromnd
.nl_nch
.ncp
== tond
.nl_nch
.ncp
->nc_parent
) {
2215 * You cannot rename a source into itself or a subdirectory of itself.
2216 * We check this by travsering the target directory upwards looking
2217 * for a match against the source.
2220 for (ncp
= tond
.nl_nch
.ncp
; ncp
; ncp
= ncp
->nc_parent
) {
2221 if (fromnd
.nl_nch
.ncp
== ncp
) {
2229 * If source is the same as the destination (that is the
2230 * same vnode with the same name in the same directory),
2231 * then there is nothing to do.
2233 if (fromnd
.nl_nch
.ncp
== tond
.nl_nch
.ncp
)
2238 * The VOP_NRENAME function releases all vnode references &
2239 * locks prior to returning so we need to clear the pointers
2240 * to bypass cleanup code later on.
2242 error
= VOP_NRENAME(&fromnd
.nl_nch
, &tond
.nl_nch
,
2243 fdvp
, tdvp
, tond
.nl_cred
);
2252 fdiraft_ret
= VOP_GETATTR(fdirp
, &fdiraft
);
2254 tdiraft_ret
= VOP_GETATTR(tdirp
, &tdiraft
);
2255 nfsm_reply(2 * NFSX_WCCDATA(v3
));
2257 nfsm_srvwcc_data(fdirfor_ret
, &fdirfor
, fdiraft_ret
, &fdiraft
);
2258 nfsm_srvwcc_data(tdirfor_ret
, &tdirfor
, tdiraft_ret
, &tdiraft
);
2266 nlookup_done(&tond
);
2269 nlookup_done(&fromnd
);
2277 nfsrv_link(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2278 struct thread
*td
, struct mbuf
**mrq
)
2280 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2281 struct sockaddr
*nam
= nfsd
->nd_nam
;
2282 caddr_t dpos
= nfsd
->nd_dpos
;
2283 struct ucred
*cred
= &nfsd
->nd_cr
;
2284 struct nlookupdata nd
;
2288 int error
= 0, rdonly
, len
, dirfor_ret
= 1, diraft_ret
= 1;
2289 int getret
= 1, v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2291 struct mbuf
*mb
, *mreq
;
2298 struct vattr dirfor
, diraft
, at
;
2300 fhandle_t
*fhp
, *dfhp
;
2302 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2304 dirp
= dvp
= vp
= xp
= NULL
;
2307 fhp
= &nfh
.fh_generic
;
2308 dfhp
= &dnfh
.fh_generic
;
2310 nfsm_srvmtofh(dfhp
);
2311 nfsm_srvnamesiz(len
);
2313 error
= nfsrv_fhtovp(fhp
, FALSE
, &xmp
, &xp
, cred
, slp
, nam
,
2314 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
2316 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2317 nfsm_srvpostop_attr(getret
, &at
);
2318 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2323 if (xp
->v_type
== VDIR
) {
2324 error
= EPERM
; /* POSIX */
2328 error
= nfs_namei(&nd
, cred
, NLC_CREATE
, &dvp
, &vp
,
2329 dfhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2330 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2333 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2342 if (xp
->v_mount
!= dvp
->v_mount
)
2347 error
= VOP_NLINK(&nd
.nl_nch
, dvp
, xp
, nd
.nl_cred
);
2355 getret
= VOP_GETATTR(xp
, &at
);
2357 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2358 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2360 nfsm_srvpostop_attr(getret
, &at
);
2361 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2384 * nfs symbolic link service
2387 nfsrv_symlink(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2388 struct thread
*td
, struct mbuf
**mrq
)
2390 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2391 struct sockaddr
*nam
= nfsd
->nd_nam
;
2392 caddr_t dpos
= nfsd
->nd_dpos
;
2393 struct ucred
*cred
= &nfsd
->nd_cr
;
2394 struct vattr va
, dirfor
, diraft
;
2395 struct nlookupdata nd
;
2396 struct vattr
*vap
= &va
;
2399 struct nfsv2_sattr
*sp
;
2400 char *bpos
, *pathcp
= NULL
, *cp2
;
2403 int error
= 0, len
, len2
, dirfor_ret
= 1, diraft_ret
= 1;
2404 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2405 struct mbuf
*mb
, *mreq
, *mb2
;
2412 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2418 fhp
= &nfh
.fh_generic
;
2420 nfsm_srvnamesiz(len
);
2422 error
= nfs_namei(&nd
, cred
, NLC_CREATE
, &dvp
, &vp
,
2423 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2424 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2427 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2435 nfsm_strsiz(len2
, NFS_MAXPATHLEN
);
2436 MALLOC(pathcp
, caddr_t
, len2
+ 1, M_TEMP
, M_WAITOK
);
2437 iv
.iov_base
= pathcp
;
2439 io
.uio_resid
= len2
;
2443 io
.uio_segflg
= UIO_SYSSPACE
;
2444 io
.uio_rw
= UIO_READ
;
2446 nfsm_mtouio(&io
, len2
);
2448 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2449 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
2451 *(pathcp
+ len2
) = '\0';
2457 if (vap
->va_mode
== (mode_t
)VNOVAL
)
2461 error
= VOP_NSYMLINK(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
, pathcp
);
2465 bzero(&fhp
->fh_fid
, sizeof(fhp
->fh_fid
));
2466 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
2468 error
= VOP_GETATTR(vp
, vap
);
2483 FREE(pathcp
, M_TEMP
);
2487 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2491 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2494 nfsm_srvpostop_fh(fhp
);
2495 nfsm_srvpostop_attr(0, vap
);
2497 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2509 FREE(pathcp
, M_TEMP
);
2517 nfsrv_mkdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2518 struct thread
*td
, struct mbuf
**mrq
)
2520 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2521 struct sockaddr
*nam
= nfsd
->nd_nam
;
2522 caddr_t dpos
= nfsd
->nd_dpos
;
2523 struct ucred
*cred
= &nfsd
->nd_cr
;
2524 struct vattr va
, dirfor
, diraft
;
2525 struct vattr
*vap
= &va
;
2526 struct nfs_fattr
*fp
;
2527 struct nlookupdata nd
;
2532 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
2533 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2535 struct mbuf
*mb
, *mb2
, *mreq
;
2542 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2548 fhp
= &nfh
.fh_generic
;
2550 nfsm_srvnamesiz(len
);
2552 error
= nfs_namei(&nd
, cred
, NLC_CREATE
, &dvp
, &vp
,
2553 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2554 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2557 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2560 nfsm_reply(NFSX_WCCDATA(v3
));
2561 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2569 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
2570 vap
->va_mode
= nfstov_mode(*tl
++);
2574 * At this point nd.ni_dvp is referenced and exclusively locked and
2575 * nd.ni_vp, if it exists, is referenced but not locked.
2578 vap
->va_type
= VDIR
;
2585 * Issue mkdir op. Since SAVESTART is not set, the pathname
2586 * component is freed by the VOP call. This will fill-in
2587 * nd.ni_vp, reference, and exclusively lock it.
2589 if (vap
->va_mode
== (mode_t
)VNOVAL
)
2592 error
= VOP_NMKDIR(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
2597 bzero(&fhp
->fh_fid
, sizeof(fhp
->fh_fid
));
2598 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
2600 error
= VOP_GETATTR(vp
, vap
);
2604 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2605 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2608 nfsm_srvpostop_fh(fhp
);
2609 nfsm_srvpostop_attr(0, vap
);
2611 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2613 nfsm_srvfhtom(fhp
, v3
);
2614 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
2615 nfsm_srvfillattr(vap
, fp
);
2639 nfsrv_rmdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2640 struct thread
*td
, struct mbuf
**mrq
)
2642 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2643 struct sockaddr
*nam
= nfsd
->nd_nam
;
2644 caddr_t dpos
= nfsd
->nd_dpos
;
2645 struct ucred
*cred
= &nfsd
->nd_cr
;
2649 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
2650 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2652 struct mbuf
*mb
, *mreq
;
2656 struct vattr dirfor
, diraft
;
2659 struct nlookupdata nd
;
2661 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2667 fhp
= &nfh
.fh_generic
;
2669 nfsm_srvnamesiz(len
);
2671 error
= nfs_namei(&nd
, cred
, NLC_DELETE
, &dvp
, &vp
,
2672 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2673 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2676 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2679 nfsm_reply(NFSX_WCCDATA(v3
));
2680 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2684 if (vp
->v_type
!= VDIR
) {
2690 * The root of a mounted filesystem cannot be deleted.
2692 if (vp
->v_flag
& VROOT
)
2696 * Issue or abort op. Since SAVESTART is not set, path name
2697 * component is freed by the VOP after either.
2704 error
= VOP_NRMDIR(&nd
.nl_nch
, dvp
, nd
.nl_cred
);
2711 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2712 nfsm_reply(NFSX_WCCDATA(v3
));
2714 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2735 * nfs readdir service
2736 * - mallocs what it thinks is enough to read
2737 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2738 * - calls VOP_READDIR()
2739 * - loops around building the reply
2740 * if the output generated exceeds count break out of loop
2741 * The nfsm_clget macro is used here so that the reply will be packed
2742 * tightly in mbuf clusters.
2743 * - it only knows that it has encountered eof when the VOP_READDIR()
2745 * - as such one readdir rpc will return eof false although you are there
2746 * and then the next will return eof
2747 * - it trims out records with d_fileno == 0
2748 * this doesn't matter for Unix clients, but they might confuse clients
2750 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2751 * than requested, but this may not apply to all filesystems. For
2752 * example, client NFS does not { although it is never remote mounted
2754 * The alternate call nfsrv_readdirplus() does lookups as well.
2755 * PS: The NFS protocol spec. does not clarify what the "count" byte
2756 * argument is a count of.. just name strings and file id's or the
2757 * entire reply rpc or ...
2758 * I tried just file name and id sizes and it confused the Sun client,
2759 * so I am using the full rpc size now. The "paranoia.." comment refers
2760 * to including the status longwords that are not a part of the dir.
2761 * "entry" structures, but are in the rpc.
2765 u_int32_t fl_postopok
;
2766 u_int32_t fl_fattr
[NFSX_V3FATTR
/ sizeof (u_int32_t
)];
2768 u_int32_t fl_fhsize
;
2769 u_int32_t fl_nfh
[NFSX_V3FH
/ sizeof (u_int32_t
)];
2773 nfsrv_readdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2774 struct thread
*td
, struct mbuf
**mrq
)
2776 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2777 struct sockaddr
*nam
= nfsd
->nd_nam
;
2778 caddr_t dpos
= nfsd
->nd_dpos
;
2779 struct ucred
*cred
= &nfsd
->nd_cr
;
2786 struct mbuf
*mb
, *mb2
, *mreq
, *mp1
, *mp2
;
2787 char *cpos
, *cend
, *cp2
, *rbuf
;
2788 struct vnode
*vp
= NULL
;
2789 struct mount
*mp
= NULL
;
2795 int len
, nlen
, rem
, xfer
, tsiz
, i
, error
= 0, getret
= 1;
2796 int siz
, cnt
, fullsiz
, eofflag
, rdonly
, ncookies
;
2797 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2798 u_quad_t off
, toff
, verf
;
2799 off_t
*cookies
= NULL
, *cookiep
;
2801 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2802 fhp
= &nfh
.fh_generic
;
2805 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
2806 toff
= fxdr_hyper(tl
);
2808 verf
= fxdr_hyper(tl
);
2811 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2812 toff
= fxdr_unsigned(u_quad_t
, *tl
++);
2813 verf
= 0; /* shut up gcc */
2816 cnt
= fxdr_unsigned(int, *tl
);
2817 siz
= ((cnt
+ DIRBLKSIZ
- 1) & ~(DIRBLKSIZ
- 1));
2818 xfer
= NFS_SRVMAXDATA(nfsd
);
2824 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
2825 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
2826 if (!error
&& vp
->v_type
!= VDIR
) {
2832 nfsm_reply(NFSX_UNSIGNED
);
2833 nfsm_srvpostop_attr(getret
, &at
);
2839 * Obtain lock on vnode for this section of the code
2843 error
= getret
= VOP_GETATTR(vp
, &at
);
2846 * XXX This check may be too strict for Solaris 2.5 clients.
2848 if (!error
&& toff
&& verf
&& verf
!= at
.va_filerev
)
2849 error
= NFSERR_BAD_COOKIE
;
2853 error
= nfsrv_access(mp
, vp
, VEXEC
, cred
, rdonly
, td
, 0);
2857 nfsm_reply(NFSX_POSTOPATTR(v3
));
2858 nfsm_srvpostop_attr(getret
, &at
);
2865 * end section. Allocate rbuf and continue
2867 MALLOC(rbuf
, caddr_t
, siz
, M_TEMP
, M_WAITOK
);
2870 iv
.iov_len
= fullsiz
;
2873 io
.uio_offset
= (off_t
)off
;
2874 io
.uio_resid
= fullsiz
;
2875 io
.uio_segflg
= UIO_SYSSPACE
;
2876 io
.uio_rw
= UIO_READ
;
2880 kfree((caddr_t
)cookies
, M_TEMP
);
2883 error
= VOP_READDIR(vp
, &io
, cred
, &eofflag
, &ncookies
, &cookies
);
2884 off
= (off_t
)io
.uio_offset
;
2885 if (!cookies
&& !error
)
2886 error
= NFSERR_PERM
;
2888 getret
= VOP_GETATTR(vp
, &at
);
2895 kfree((caddr_t
)rbuf
, M_TEMP
);
2897 kfree((caddr_t
)cookies
, M_TEMP
);
2898 nfsm_reply(NFSX_POSTOPATTR(v3
));
2899 nfsm_srvpostop_attr(getret
, &at
);
2904 siz
-= io
.uio_resid
;
2907 * If nothing read, return eof
2913 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_COOKIEVERF(v3
) +
2916 nfsm_srvpostop_attr(getret
, &at
);
2917 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
2918 txdr_hyper(at
.va_filerev
, tl
);
2921 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2924 FREE((caddr_t
)rbuf
, M_TEMP
);
2925 FREE((caddr_t
)cookies
, M_TEMP
);
2932 * Check for degenerate cases of nothing useful read.
2933 * If so go try again
2937 dp
= (struct dirent
*)cpos
;
2940 * For some reason FreeBSD's ufs_readdir() chooses to back the
2941 * directory offset up to a block boundary, so it is necessary to
2942 * skip over the records that preceed the requested offset. This
2943 * requires the assumption that file offset cookies monotonically
2946 while (cpos
< cend
&& ncookies
> 0 &&
2947 (dp
->d_ino
== 0 || dp
->d_type
== DT_WHT
||
2948 ((u_quad_t
)(*cookiep
)) <= toff
)) {
2949 dp
= _DIRENT_NEXT(dp
);
2954 if (cpos
>= cend
|| ncookies
== 0) {
2960 len
= 3 * NFSX_UNSIGNED
; /* paranoia, probably can be 0 */
2961 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_COOKIEVERF(v3
) + siz
);
2963 nfsm_srvpostop_attr(getret
, &at
);
2964 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2965 txdr_hyper(at
.va_filerev
, tl
);
2969 be
= bp
+ M_TRAILINGSPACE(mp1
);
2971 /* Loop through the records and build reply */
2972 while (cpos
< cend
&& ncookies
> 0) {
2973 if (dp
->d_ino
!= 0 && dp
->d_type
!= DT_WHT
) {
2974 nlen
= dp
->d_namlen
;
2975 rem
= nfsm_rndup(nlen
) - nlen
;
2976 len
+= (4 * NFSX_UNSIGNED
+ nlen
+ rem
);
2978 len
+= 2 * NFSX_UNSIGNED
;
2984 * Build the directory record xdr from
2987 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
2989 bp
+= NFSX_UNSIGNED
;
2991 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
2993 bp
+= NFSX_UNSIGNED
;
2995 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
2996 *tl
= txdr_unsigned(dp
->d_ino
);
2997 bp
+= NFSX_UNSIGNED
;
2998 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
2999 *tl
= txdr_unsigned(nlen
);
3000 bp
+= NFSX_UNSIGNED
;
3002 /* And loop around copying the name */
3006 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3011 bcopy(cp
, bp
, tsiz
);
3017 /* And null pad to a int32_t boundary */
3018 for (i
= 0; i
< rem
; i
++)
3020 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3022 /* Finish off the record */
3024 *tl
= txdr_unsigned(*cookiep
>> 32);
3025 bp
+= NFSX_UNSIGNED
;
3026 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3028 *tl
= txdr_unsigned(*cookiep
);
3029 bp
+= NFSX_UNSIGNED
;
3031 dp
= _DIRENT_NEXT(dp
);
3038 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3040 bp
+= NFSX_UNSIGNED
;
3041 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3046 bp
+= NFSX_UNSIGNED
;
3049 mp1
->m_len
= bp
- mtod(mp1
, caddr_t
);
3051 mp1
->m_len
+= bp
- bpos
;
3052 FREE((caddr_t
)rbuf
, M_TEMP
);
3053 FREE((caddr_t
)cookies
, M_TEMP
);
3062 nfsrv_readdirplus(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3063 struct thread
*td
, struct mbuf
**mrq
)
3065 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3066 struct sockaddr
*nam
= nfsd
->nd_nam
;
3067 caddr_t dpos
= nfsd
->nd_dpos
;
3068 struct ucred
*cred
= &nfsd
->nd_cr
;
3075 struct mbuf
*mb
, *mb2
, *mreq
, *mp1
, *mp2
;
3076 char *cpos
, *cend
, *cp2
, *rbuf
;
3077 struct vnode
*vp
= NULL
, *nvp
;
3078 struct mount
*mp
= NULL
;
3081 fhandle_t
*fhp
, *nfhp
= (fhandle_t
*)fl
.fl_nfh
;
3084 struct vattr va
, at
, *vap
= &va
;
3085 struct nfs_fattr
*fp
;
3086 int len
, nlen
, rem
, xfer
, tsiz
, i
, error
= 0, getret
= 1;
3087 int siz
, cnt
, fullsiz
, eofflag
, rdonly
, dirlen
, ncookies
;
3088 u_quad_t off
, toff
, verf
;
3089 off_t
*cookies
= NULL
, *cookiep
; /* needs to be int64_t or off_t */
3091 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3092 fhp
= &nfh
.fh_generic
;
3094 nfsm_dissect(tl
, u_int32_t
*, 6 * NFSX_UNSIGNED
);
3095 toff
= fxdr_hyper(tl
);
3097 verf
= fxdr_hyper(tl
);
3099 siz
= fxdr_unsigned(int, *tl
++);
3100 cnt
= fxdr_unsigned(int, *tl
);
3102 siz
= ((siz
+ DIRBLKSIZ
- 1) & ~(DIRBLKSIZ
- 1));
3103 xfer
= NFS_SRVMAXDATA(nfsd
);
3109 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
3110 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3111 if (!error
&& vp
->v_type
!= VDIR
) {
3117 nfsm_reply(NFSX_UNSIGNED
);
3118 nfsm_srvpostop_attr(getret
, &at
);
3122 error
= getret
= VOP_GETATTR(vp
, &at
);
3125 * XXX This check may be too strict for Solaris 2.5 clients.
3127 if (!error
&& toff
&& verf
&& verf
!= at
.va_filerev
)
3128 error
= NFSERR_BAD_COOKIE
;
3131 error
= nfsrv_access(mp
, vp
, VEXEC
, cred
, rdonly
, td
, 0);
3136 nfsm_reply(NFSX_V3POSTOPATTR
);
3137 nfsm_srvpostop_attr(getret
, &at
);
3142 MALLOC(rbuf
, caddr_t
, siz
, M_TEMP
, M_WAITOK
);
3145 iv
.iov_len
= fullsiz
;
3148 io
.uio_offset
= (off_t
)off
;
3149 io
.uio_resid
= fullsiz
;
3150 io
.uio_segflg
= UIO_SYSSPACE
;
3151 io
.uio_rw
= UIO_READ
;
3155 kfree((caddr_t
)cookies
, M_TEMP
);
3158 error
= VOP_READDIR(vp
, &io
, cred
, &eofflag
, &ncookies
, &cookies
);
3159 off
= (u_quad_t
)io
.uio_offset
;
3160 getret
= VOP_GETATTR(vp
, &at
);
3161 if (!cookies
&& !error
)
3162 error
= NFSERR_PERM
;
3169 kfree((caddr_t
)cookies
, M_TEMP
);
3170 kfree((caddr_t
)rbuf
, M_TEMP
);
3171 nfsm_reply(NFSX_V3POSTOPATTR
);
3172 nfsm_srvpostop_attr(getret
, &at
);
3177 siz
-= io
.uio_resid
;
3180 * If nothing read, return eof
3186 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3COOKIEVERF
+
3188 nfsm_srvpostop_attr(getret
, &at
);
3189 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
3190 txdr_hyper(at
.va_filerev
, tl
);
3194 FREE((caddr_t
)cookies
, M_TEMP
);
3195 FREE((caddr_t
)rbuf
, M_TEMP
);
3202 * Check for degenerate cases of nothing useful read.
3203 * If so go try again
3207 dp
= (struct dirent
*)cpos
;
3210 * For some reason FreeBSD's ufs_readdir() chooses to back the
3211 * directory offset up to a block boundary, so it is necessary to
3212 * skip over the records that preceed the requested offset. This
3213 * requires the assumption that file offset cookies monotonically
3216 while (cpos
< cend
&& ncookies
> 0 &&
3217 (dp
->d_ino
== 0 || dp
->d_type
== DT_WHT
||
3218 ((u_quad_t
)(*cookiep
)) <= toff
)) {
3219 dp
= _DIRENT_NEXT(dp
);
3224 if (cpos
>= cend
|| ncookies
== 0) {
3231 * Probe one of the directory entries to see if the filesystem
3234 if (VFS_VGET(vp
->v_mount
, dp
->d_ino
, &nvp
) == EOPNOTSUPP
) {
3235 error
= NFSERR_NOTSUPP
;
3238 kfree((caddr_t
)cookies
, M_TEMP
);
3239 kfree((caddr_t
)rbuf
, M_TEMP
);
3240 nfsm_reply(NFSX_V3POSTOPATTR
);
3241 nfsm_srvpostop_attr(getret
, &at
);
3250 dirlen
= len
= NFSX_V3POSTOPATTR
+ NFSX_V3COOKIEVERF
+ 2 * NFSX_UNSIGNED
;
3252 nfsm_srvpostop_attr(getret
, &at
);
3253 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
3254 txdr_hyper(at
.va_filerev
, tl
);
3257 be
= bp
+ M_TRAILINGSPACE(mp1
);
3259 /* Loop through the records and build reply */
3260 while (cpos
< cend
&& ncookies
> 0) {
3261 if (dp
->d_ino
!= 0 && dp
->d_type
!= DT_WHT
) {
3262 nlen
= dp
->d_namlen
;
3263 rem
= nfsm_rndup(nlen
)-nlen
;
3266 * For readdir_and_lookup get the vnode using
3269 if (VFS_VGET(vp
->v_mount
, dp
->d_ino
, &nvp
))
3271 bzero((caddr_t
)nfhp
, NFSX_V3FH
);
3272 nfhp
->fh_fsid
= fhp
->fh_fsid
;
3273 if (VFS_VPTOFH(nvp
, &nfhp
->fh_fid
)) {
3278 if (VOP_GETATTR(nvp
, vap
)) {
3287 * If either the dircount or maxcount will be
3288 * exceeded, get out now. Both of these lengths
3289 * are calculated conservatively, including all
3292 len
+= (8 * NFSX_UNSIGNED
+ nlen
+ rem
+ NFSX_V3FH
+
3294 dirlen
+= (6 * NFSX_UNSIGNED
+ nlen
+ rem
);
3295 if (len
> cnt
|| dirlen
> fullsiz
) {
3301 * Build the directory record xdr from
3304 fp
= (struct nfs_fattr
*)&fl
.fl_fattr
;
3305 nfsm_srvfillattr(vap
, fp
);
3306 fl
.fl_fhsize
= txdr_unsigned(NFSX_V3FH
);
3307 fl
.fl_fhok
= nfs_true
;
3308 fl
.fl_postopok
= nfs_true
;
3309 fl
.fl_off
.nfsuquad
[0] = txdr_unsigned(*cookiep
>> 32);
3310 fl
.fl_off
.nfsuquad
[1] = txdr_unsigned(*cookiep
);
3312 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3314 bp
+= NFSX_UNSIGNED
;
3315 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3317 bp
+= NFSX_UNSIGNED
;
3318 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3319 *tl
= txdr_unsigned(dp
->d_ino
);
3320 bp
+= NFSX_UNSIGNED
;
3321 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3322 *tl
= txdr_unsigned(nlen
);
3323 bp
+= NFSX_UNSIGNED
;
3325 /* And loop around copying the name */
3329 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3330 if ((bp
+ xfer
) > be
)
3334 bcopy(cp
, bp
, tsiz
);
3340 /* And null pad to a int32_t boundary */
3341 for (i
= 0; i
< rem
; i
++)
3345 * Now copy the flrep structure out.
3347 xfer
= sizeof (struct flrep
);
3350 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3351 if ((bp
+ xfer
) > be
)
3355 bcopy(cp
, bp
, tsiz
);
3363 dp
= _DIRENT_NEXT(dp
);
3370 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3372 bp
+= NFSX_UNSIGNED
;
3373 nfsm_clget(mp1
, mp2
, mb
, bp
, be
, tl
);
3378 bp
+= NFSX_UNSIGNED
;
3381 mp1
->m_len
= bp
- mtod(mp1
, caddr_t
);
3383 mp1
->m_len
+= bp
- bpos
;
3384 FREE((caddr_t
)cookies
, M_TEMP
);
3385 FREE((caddr_t
)rbuf
, M_TEMP
);
3393 * nfs commit service
3396 nfsrv_commit(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3397 struct thread
*td
, struct mbuf
**mrq
)
3399 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3400 struct sockaddr
*nam
= nfsd
->nd_nam
;
3401 caddr_t dpos
= nfsd
->nd_dpos
;
3402 struct ucred
*cred
= &nfsd
->nd_cr
;
3403 struct vattr bfor
, aft
;
3404 struct vnode
*vp
= NULL
;
3405 struct mount
*mp
= NULL
;
3411 int error
= 0, rdonly
, for_ret
= 1, aft_ret
= 1, cnt
;
3413 struct mbuf
*mb
, *mb2
, *mreq
;
3416 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3417 fhp
= &nfh
.fh_generic
;
3419 nfsm_dissect(tl
, u_int32_t
*, 3 * NFSX_UNSIGNED
);
3422 * XXX At this time VOP_FSYNC() does not accept offset and byte
3423 * count parameters, so these arguments are useless (someday maybe).
3425 off
= fxdr_hyper(tl
);
3427 cnt
= fxdr_unsigned(int, *tl
);
3428 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
3429 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3431 nfsm_reply(2 * NFSX_UNSIGNED
);
3432 nfsm_srvwcc_data(for_ret
, &bfor
, aft_ret
, &aft
);
3436 for_ret
= VOP_GETATTR(vp
, &bfor
);
3438 if (cnt
> MAX_COMMIT_COUNT
) {
3440 * Give up and do the whole thing
3443 (vp
->v_object
->flags
& OBJ_MIGHTBEDIRTY
)) {
3444 vm_object_page_clean(vp
->v_object
, 0, 0, OBJPC_SYNC
);
3446 error
= VOP_FSYNC(vp
, MNT_WAIT
);
3449 * Locate and synchronously write any buffers that fall
3450 * into the requested range. Note: we are assuming that
3451 * f_iosize is a power of 2.
3453 int iosize
= vp
->v_mount
->mnt_stat
.f_iosize
;
3454 int iomask
= iosize
- 1;
3458 * Align to iosize boundry, super-align to page boundry.
3461 cnt
+= off
& iomask
;
3462 off
&= ~(u_quad_t
)iomask
;
3464 if (off
& PAGE_MASK
) {
3465 cnt
+= off
& PAGE_MASK
;
3466 off
&= ~(u_quad_t
)PAGE_MASK
;
3471 (vp
->v_object
->flags
& OBJ_MIGHTBEDIRTY
)) {
3472 vm_object_page_clean(vp
->v_object
, off
/ PAGE_SIZE
, (cnt
+ PAGE_MASK
) / PAGE_SIZE
, OBJPC_SYNC
);
3480 * If we have a buffer and it is marked B_DELWRI we
3481 * have to lock and write it. Otherwise the prior
3482 * write is assumed to have already been committed.
3484 if ((bp
= findblk(vp
, loffset
)) != NULL
&& (bp
->b_flags
& B_DELWRI
)) {
3485 if (BUF_LOCK(bp
, LK_EXCLUSIVE
| LK_NOWAIT
)) {
3486 if (BUF_LOCK(bp
, LK_EXCLUSIVE
| LK_SLEEPFAIL
) == 0)
3488 continue; /* retry */
3491 bp
->b_flags
&= ~B_ASYNC
;
3504 aft_ret
= VOP_GETATTR(vp
, &aft
);
3507 nfsm_reply(NFSX_V3WCCDATA
+ NFSX_V3WRITEVERF
);
3508 nfsm_srvwcc_data(for_ret
, &bfor
, aft_ret
, &aft
);
3510 nfsm_build(tl
, u_int32_t
*, NFSX_V3WRITEVERF
);
3511 if (nfsver
.tv_sec
== 0)
3513 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
3514 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
3525 * nfs statfs service
3528 nfsrv_statfs(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3529 struct thread
*td
, struct mbuf
**mrq
)
3531 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3532 struct sockaddr
*nam
= nfsd
->nd_nam
;
3533 caddr_t dpos
= nfsd
->nd_dpos
;
3534 struct ucred
*cred
= &nfsd
->nd_cr
;
3536 struct nfs_statfs
*sfp
;
3540 int error
= 0, rdonly
, getret
= 1;
3541 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
3543 struct mbuf
*mb
, *mb2
, *mreq
;
3544 struct vnode
*vp
= NULL
;
3545 struct mount
*mp
= NULL
;
3549 struct statfs statfs
;
3552 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3553 fhp
= &nfh
.fh_generic
;
3555 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
3556 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3558 nfsm_reply(NFSX_UNSIGNED
);
3559 nfsm_srvpostop_attr(getret
, &at
);
3564 error
= VFS_STATFS(vp
->v_mount
, sf
, proc0
.p_ucred
);
3565 getret
= VOP_GETATTR(vp
, &at
);
3568 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_STATFS(v3
));
3570 nfsm_srvpostop_attr(getret
, &at
);
3575 nfsm_build(sfp
, struct nfs_statfs
*, NFSX_STATFS(v3
));
3577 tval
= (u_quad_t
)sf
->f_blocks
;
3578 tval
*= (u_quad_t
)sf
->f_bsize
;
3579 txdr_hyper(tval
, &sfp
->sf_tbytes
);
3580 tval
= (u_quad_t
)sf
->f_bfree
;
3581 tval
*= (u_quad_t
)sf
->f_bsize
;
3582 txdr_hyper(tval
, &sfp
->sf_fbytes
);
3583 tval
= (u_quad_t
)sf
->f_bavail
;
3584 tval
*= (u_quad_t
)sf
->f_bsize
;
3585 txdr_hyper(tval
, &sfp
->sf_abytes
);
3586 sfp
->sf_tfiles
.nfsuquad
[0] = 0;
3587 sfp
->sf_tfiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_files
);
3588 sfp
->sf_ffiles
.nfsuquad
[0] = 0;
3589 sfp
->sf_ffiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_ffree
);
3590 sfp
->sf_afiles
.nfsuquad
[0] = 0;
3591 sfp
->sf_afiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_ffree
);
3592 sfp
->sf_invarsec
= 0;
3594 sfp
->sf_tsize
= txdr_unsigned(NFS_MAXDGRAMDATA
);
3595 sfp
->sf_bsize
= txdr_unsigned(sf
->f_bsize
);
3596 sfp
->sf_blocks
= txdr_unsigned(sf
->f_blocks
);
3597 sfp
->sf_bfree
= txdr_unsigned(sf
->f_bfree
);
3598 sfp
->sf_bavail
= txdr_unsigned(sf
->f_bavail
);
3607 * nfs fsinfo service
3610 nfsrv_fsinfo(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3611 struct thread
*td
, struct mbuf
**mrq
)
3613 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3614 struct sockaddr
*nam
= nfsd
->nd_nam
;
3615 caddr_t dpos
= nfsd
->nd_dpos
;
3616 struct ucred
*cred
= &nfsd
->nd_cr
;
3618 struct nfsv3_fsinfo
*sip
;
3621 int error
= 0, rdonly
, getret
= 1, pref
;
3623 struct mbuf
*mb
, *mb2
, *mreq
;
3624 struct vnode
*vp
= NULL
;
3625 struct mount
*mp
= NULL
;
3632 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3633 fhp
= &nfh
.fh_generic
;
3635 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
3636 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3638 nfsm_reply(NFSX_UNSIGNED
);
3639 nfsm_srvpostop_attr(getret
, &at
);
3644 /* XXX Try to make a guess on the max file size. */
3645 VFS_STATFS(vp
->v_mount
, &sb
, proc0
.p_ucred
);
3646 maxfsize
= (u_quad_t
)0x80000000 * sb
.f_bsize
- 1;
3648 getret
= VOP_GETATTR(vp
, &at
);
3651 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3FSINFO
);
3652 nfsm_srvpostop_attr(getret
, &at
);
3653 nfsm_build(sip
, struct nfsv3_fsinfo
*, NFSX_V3FSINFO
);
3657 * There should be file system VFS OP(s) to get this information.
3658 * For now, assume ufs.
3660 if (slp
->ns_so
->so_type
== SOCK_DGRAM
)
3661 pref
= NFS_MAXDGRAMDATA
;
3664 sip
->fs_rtmax
= txdr_unsigned(NFS_MAXDATA
);
3665 sip
->fs_rtpref
= txdr_unsigned(pref
);
3666 sip
->fs_rtmult
= txdr_unsigned(NFS_FABLKSIZE
);
3667 sip
->fs_wtmax
= txdr_unsigned(NFS_MAXDATA
);
3668 sip
->fs_wtpref
= txdr_unsigned(pref
);
3669 sip
->fs_wtmult
= txdr_unsigned(NFS_FABLKSIZE
);
3670 sip
->fs_dtpref
= txdr_unsigned(pref
);
3671 txdr_hyper(maxfsize
, &sip
->fs_maxfilesize
);
3672 sip
->fs_timedelta
.nfsv3_sec
= 0;
3673 sip
->fs_timedelta
.nfsv3_nsec
= txdr_unsigned(1);
3674 sip
->fs_properties
= txdr_unsigned(NFSV3FSINFO_LINK
|
3675 NFSV3FSINFO_SYMLINK
| NFSV3FSINFO_HOMOGENEOUS
|
3676 NFSV3FSINFO_CANSETTIME
);
3684 * nfs pathconf service
3687 nfsrv_pathconf(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3688 struct thread
*td
, struct mbuf
**mrq
)
3690 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3691 struct sockaddr
*nam
= nfsd
->nd_nam
;
3692 caddr_t dpos
= nfsd
->nd_dpos
;
3693 struct ucred
*cred
= &nfsd
->nd_cr
;
3695 struct nfsv3_pathconf
*pc
;
3698 int error
= 0, rdonly
, getret
= 1;
3699 register_t linkmax
, namemax
, chownres
, notrunc
;
3701 struct mbuf
*mb
, *mb2
, *mreq
;
3702 struct vnode
*vp
= NULL
;
3703 struct mount
*mp
= NULL
;
3708 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3709 fhp
= &nfh
.fh_generic
;
3711 error
= nfsrv_fhtovp(fhp
, 1, &mp
, &vp
, cred
, slp
, nam
,
3712 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3714 nfsm_reply(NFSX_UNSIGNED
);
3715 nfsm_srvpostop_attr(getret
, &at
);
3719 error
= VOP_PATHCONF(vp
, _PC_LINK_MAX
, &linkmax
);
3721 error
= VOP_PATHCONF(vp
, _PC_NAME_MAX
, &namemax
);
3723 error
= VOP_PATHCONF(vp
, _PC_CHOWN_RESTRICTED
, &chownres
);
3725 error
= VOP_PATHCONF(vp
, _PC_NO_TRUNC
, ¬runc
);
3726 getret
= VOP_GETATTR(vp
, &at
);
3729 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3PATHCONF
);
3730 nfsm_srvpostop_attr(getret
, &at
);
3735 nfsm_build(pc
, struct nfsv3_pathconf
*, NFSX_V3PATHCONF
);
3737 pc
->pc_linkmax
= txdr_unsigned(linkmax
);
3738 pc
->pc_namemax
= txdr_unsigned(namemax
);
3739 pc
->pc_notrunc
= txdr_unsigned(notrunc
);
3740 pc
->pc_chownrestricted
= txdr_unsigned(chownres
);
3743 * These should probably be supported by VOP_PATHCONF(), but
3744 * until msdosfs is exportable (why would you want to?), the
3745 * Unix defaults should be ok.
3747 pc
->pc_caseinsensitive
= nfs_false
;
3748 pc
->pc_casepreserving
= nfs_true
;
3756 * Null operation, used by clients to ping server
3760 nfsrv_null(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3761 struct thread
*td
, struct mbuf
**mrq
)
3763 struct mbuf
*mrep
= nfsd
->nd_mrep
;
3765 int error
= NFSERR_RETVOID
;
3766 struct mbuf
*mb
, *mreq
;
3768 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3774 * No operation, used for obsolete procedures
3778 nfsrv_noop(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3779 struct thread
*td
, struct mbuf
**mrq
)
3781 struct mbuf
*mrep
= nfsd
->nd_mrep
;
3784 struct mbuf
*mb
, *mreq
;
3786 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3787 if (nfsd
->nd_repstat
)
3788 error
= nfsd
->nd_repstat
;
3790 error
= EPROCUNAVAIL
;
3797 * Perform access checking for vnodes obtained from file handles that would
3798 * refer to files already opened by a Unix client. You cannot just use
3799 * vn_writechk() and VOP_ACCESS() for two reasons.
3800 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3801 * 2 - The owner is to be given access irrespective of mode bits for some
3802 * operations, so that processes that chmod after opening a file don't
3803 * break. I don't like this because it opens a security hole, but since
3804 * the nfs server opens a security hole the size of a barn door anyhow,
3807 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3808 * will return EPERM instead of EACCESS. EPERM is always an error.
3811 nfsrv_access(struct mount
*mp
, struct vnode
*vp
, int flags
, struct ucred
*cred
,
3812 int rdonly
, struct thread
*td
, int override
)
3817 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3818 if (flags
& VWRITE
) {
3819 /* Just vn_writechk() changed to check rdonly */
3821 * Disallow write attempts on read-only file systems;
3822 * unless the file is a socket or a block or character
3823 * device resident on the file system.
3826 ((mp
->mnt_flag
| vp
->v_mount
->mnt_flag
) & MNT_RDONLY
)) {
3827 switch (vp
->v_type
) {
3837 * If there's shared text associated with
3838 * the inode, we can't allow writing.
3840 if (vp
->v_flag
& VTEXT
)
3843 error
= VOP_GETATTR(vp
, &vattr
);
3846 error
= VOP_ACCESS(vp
, flags
, cred
);
3848 * Allow certain operations for the owner (reads and writes
3849 * on files that are already open).
3851 if (override
&& error
== EACCES
&& cred
->cr_uid
== vattr
.va_uid
)
3855 #endif /* NFS_NOSERVER */