xref: /dragonfly/sys/vfs/nfs/nfs_serv.c (revision aa8d5dcb)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
23  *
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
34  * SUCH DAMAGE.
35  *
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.13 2004/03/01 06:33:21 dillon Exp $
39  */
40 
41 /*
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
48  *   nb:
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
51  *
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
56  *	a reply.
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.
59  *
60  * Other notes:
61  *	Warning: always pay careful attention to resource cleanup on return
62  *	and note that nfsm_*() macros can terminate a procedure on certain
63  *	errors.
64  *
65  *	lookup() and namei()
66  *	may return garbage in various structural fields/return elements
67  *	if an error is returned, and may garbage up nd.ni_dvp even if no
68  *	error is returned and you did not request LOCKPARENT or WANTPARENT.
69  *
70  *	We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
71  *	buffer has been freed or not.
72  */
73 
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/proc.h>
77 #include <sys/namei.h>
78 #include <sys/unistd.h>
79 #include <sys/vnode.h>
80 #include <sys/mount.h>
81 #include <sys/socket.h>
82 #include <sys/socketvar.h>
83 #include <sys/malloc.h>
84 #include <sys/mbuf.h>
85 #include <sys/dirent.h>
86 #include <sys/stat.h>
87 #include <sys/kernel.h>
88 #include <sys/sysctl.h>
89 #include <sys/buf.h>
90 
91 #include <vm/vm.h>
92 #include <vm/vm_extern.h>
93 #include <vm/vm_zone.h>
94 #include <vm/vm_object.h>
95 
96 #include <sys/buf2.h>
97 
98 #include "nfsproto.h"
99 #include "rpcv2.h"
100 #include "nfs.h"
101 #include "xdr_subs.h"
102 #include "nfsm_subs.h"
103 #include "nqnfs.h"
104 
105 #ifdef NFSRV_DEBUG
106 #define nfsdbprintf(info)	printf info
107 #else
108 #define nfsdbprintf(info)
109 #endif
110 
111 #define MAX_COMMIT_COUNT	(1024 * 1024)
112 
113 #define NUM_HEURISTIC		64
114 #define NHUSE_INIT		64
115 #define NHUSE_INC		16
116 #define NHUSE_MAX		2048
117 
118 static struct nfsheur {
119     struct vnode *nh_vp;	/* vp to match (unreferenced pointer) */
120     off_t nh_nextr;		/* next offset for sequential detection */
121     int nh_use;			/* use count for selection */
122     int nh_seqcount;		/* heuristic */
123 } nfsheur[NUM_HEURISTIC];
124 
125 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
126 		      NFFIFO, NFNON };
127 #ifndef NFS_NOSERVER
128 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
129 		      NFCHR, NFNON };
130 /* Global vars */
131 extern u_int32_t nfs_xdrneg1;
132 extern u_int32_t nfs_false, nfs_true;
133 extern enum vtype nv3tov_type[8];
134 extern struct nfsstats nfsstats;
135 
136 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
137 int nfsrvw_procrastinate_v3 = 0;
138 
139 static struct timespec	nfsver;
140 
141 SYSCTL_DECL(_vfs_nfs);
142 
143 static int nfs_async;
144 SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
145 static int nfs_commit_blks;
146 static int nfs_commit_miss;
147 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
148 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
149 
150 static int nfsrv_access (struct vnode *,int,struct ucred *,int,
151 		struct thread *, int);
152 static void nfsrvw_coalesce (struct nfsrv_descript *,
153 		struct nfsrv_descript *);
154 
155 /*
156  * Clear nameidata fields that are tested in nsfmout cleanup code prior
157  * to using first nfsm macro (that might jump to the cleanup code).
158  */
159 
160 static __inline
161 void
162 ndclear(struct nameidata *nd)
163 {
164 	nd->ni_cnd.cn_flags = 0;
165 	nd->ni_vp = NULL;
166 	nd->ni_dvp = NULL;
167 	nd->ni_startdir = NULL;
168 }
169 
170 /*
171  * nfs v3 access service
172  */
173 int
174 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
175 	struct thread *td, struct mbuf **mrq)
176 {
177 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
178 	struct sockaddr *nam = nfsd->nd_nam;
179 	caddr_t dpos = nfsd->nd_dpos;
180 	struct ucred *cred = &nfsd->nd_cr;
181 	struct vnode *vp = NULL;
182 	nfsfh_t nfh;
183 	fhandle_t *fhp;
184 	u_int32_t *tl;
185 	int32_t t1;
186 	caddr_t bpos;
187 	int error = 0, rdonly, cache, getret;
188 	char *cp2;
189 	struct mbuf *mb, *mreq, *mb2;
190 	struct vattr vattr, *vap = &vattr;
191 	u_long testmode, nfsmode;
192 	u_quad_t frev;
193 
194 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
195 #ifndef nolint
196 	cache = 0;
197 #endif
198 	fhp = &nfh.fh_generic;
199 	nfsm_srvmtofh(fhp);
200 	nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
201 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
202 	    (nfsd->nd_flag & ND_KERBAUTH), TRUE);
203 	if (error) {
204 		nfsm_reply(NFSX_UNSIGNED);
205 		nfsm_srvpostop_attr(1, (struct vattr *)0);
206 		error = 0;
207 		goto nfsmout;
208 	}
209 	nfsmode = fxdr_unsigned(u_int32_t, *tl);
210 	if ((nfsmode & NFSV3ACCESS_READ) &&
211 		nfsrv_access(vp, VREAD, cred, rdonly, td, 0))
212 		nfsmode &= ~NFSV3ACCESS_READ;
213 	if (vp->v_type == VDIR)
214 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
215 			NFSV3ACCESS_DELETE);
216 	else
217 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
218 	if ((nfsmode & testmode) &&
219 		nfsrv_access(vp, VWRITE, cred, rdonly, td, 0))
220 		nfsmode &= ~testmode;
221 	if (vp->v_type == VDIR)
222 		testmode = NFSV3ACCESS_LOOKUP;
223 	else
224 		testmode = NFSV3ACCESS_EXECUTE;
225 	if ((nfsmode & testmode) &&
226 		nfsrv_access(vp, VEXEC, cred, rdonly, td, 0))
227 		nfsmode &= ~testmode;
228 	getret = VOP_GETATTR(vp, vap, td);
229 	vput(vp);
230 	vp = NULL;
231 	nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
232 	nfsm_srvpostop_attr(getret, vap);
233 	nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
234 	*tl = txdr_unsigned(nfsmode);
235 nfsmout:
236 	if (vp)
237 		vput(vp);
238 	return(error);
239 }
240 
241 /*
242  * nfs getattr service
243  */
244 int
245 nfsrv_getattr(nfsd, slp, td, mrq)
246 	struct nfsrv_descript *nfsd;
247 	struct nfssvc_sock *slp;
248 	struct thread *td;
249 	struct mbuf **mrq;
250 {
251 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
252 	struct sockaddr *nam = nfsd->nd_nam;
253 	caddr_t dpos = nfsd->nd_dpos;
254 	struct ucred *cred = &nfsd->nd_cr;
255 	struct nfs_fattr *fp;
256 	struct vattr va;
257 	struct vattr *vap = &va;
258 	struct vnode *vp = NULL;
259 	nfsfh_t nfh;
260 	fhandle_t *fhp;
261 	u_int32_t *tl;
262 	int32_t t1;
263 	caddr_t bpos;
264 	int error = 0, rdonly, cache;
265 	char *cp2;
266 	struct mbuf *mb, *mb2, *mreq;
267 	u_quad_t frev;
268 
269 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
270 	fhp = &nfh.fh_generic;
271 	nfsm_srvmtofh(fhp);
272 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
273 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
274 	if (error) {
275 		nfsm_reply(0);
276 		error = 0;
277 		goto nfsmout;
278 	}
279 	nqsrv_getl(vp, ND_READ);
280 	error = VOP_GETATTR(vp, vap, td);
281 	vput(vp);
282 	vp = NULL;
283 	nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
284 	if (error) {
285 		error = 0;
286 		goto nfsmout;
287 	}
288 	nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
289 	nfsm_srvfillattr(vap, fp);
290 	/* fall through */
291 
292 nfsmout:
293 	if (vp)
294 		vput(vp);
295 	return(error);
296 }
297 
298 /*
299  * nfs setattr service
300  */
301 int
302 nfsrv_setattr(nfsd, slp, td, mrq)
303 	struct nfsrv_descript *nfsd;
304 	struct nfssvc_sock *slp;
305 	struct thread *td;
306 	struct mbuf **mrq;
307 {
308 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
309 	struct sockaddr *nam = nfsd->nd_nam;
310 	caddr_t dpos = nfsd->nd_dpos;
311 	struct ucred *cred = &nfsd->nd_cr;
312 	struct vattr va, preat;
313 	struct vattr *vap = &va;
314 	struct nfsv2_sattr *sp;
315 	struct nfs_fattr *fp;
316 	struct vnode *vp = NULL;
317 	nfsfh_t nfh;
318 	fhandle_t *fhp;
319 	u_int32_t *tl;
320 	int32_t t1;
321 	caddr_t bpos;
322 	int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
323 	int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
324 	char *cp2;
325 	struct mbuf *mb, *mb2, *mreq;
326 	u_quad_t frev;
327 	struct timespec guard;
328 
329 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
330 	fhp = &nfh.fh_generic;
331 	nfsm_srvmtofh(fhp);
332 	VATTR_NULL(vap);
333 	if (v3) {
334 		nfsm_srvsattr(vap);
335 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
336 		gcheck = fxdr_unsigned(int, *tl);
337 		if (gcheck) {
338 			nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
339 			fxdr_nfsv3time(tl, &guard);
340 		}
341 	} else {
342 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
343 		/*
344 		 * Nah nah nah nah na nah
345 		 * There is a bug in the Sun client that puts 0xffff in the mode
346 		 * field of sattr when it should put in 0xffffffff. The u_short
347 		 * doesn't sign extend.
348 		 * --> check the low order 2 bytes for 0xffff
349 		 */
350 		if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
351 			vap->va_mode = nfstov_mode(sp->sa_mode);
352 		if (sp->sa_uid != nfs_xdrneg1)
353 			vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
354 		if (sp->sa_gid != nfs_xdrneg1)
355 			vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
356 		if (sp->sa_size != nfs_xdrneg1)
357 			vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
358 		if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
359 #ifdef notyet
360 			fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
361 #else
362 			vap->va_atime.tv_sec =
363 				fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
364 			vap->va_atime.tv_nsec = 0;
365 #endif
366 		}
367 		if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
368 			fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
369 
370 	}
371 
372 	/*
373 	 * Now that we have all the fields, lets do it.
374 	 */
375 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
376 		(nfsd->nd_flag & ND_KERBAUTH), TRUE);
377 	if (error) {
378 		nfsm_reply(2 * NFSX_UNSIGNED);
379 		nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
380 		error = 0;
381 		goto nfsmout;
382 	}
383 
384 	/*
385 	 * vp now an active resource, pay careful attention to cleanup
386 	 */
387 
388 	nqsrv_getl(vp, ND_WRITE);
389 	if (v3) {
390 		error = preat_ret = VOP_GETATTR(vp, &preat, td);
391 		if (!error && gcheck &&
392 			(preat.va_ctime.tv_sec != guard.tv_sec ||
393 			 preat.va_ctime.tv_nsec != guard.tv_nsec))
394 			error = NFSERR_NOT_SYNC;
395 		if (error) {
396 			vput(vp);
397 			vp = NULL;
398 			nfsm_reply(NFSX_WCCDATA(v3));
399 			nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
400 			error = 0;
401 			goto nfsmout;
402 		}
403 	}
404 
405 	/*
406 	 * If the size is being changed write acces is required, otherwise
407 	 * just check for a read only file system.
408 	 */
409 	if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
410 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
411 			error = EROFS;
412 			goto out;
413 		}
414 	} else {
415 		if (vp->v_type == VDIR) {
416 			error = EISDIR;
417 			goto out;
418 		} else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
419 			    td, 0)) != 0){
420 			goto out;
421 		}
422 	}
423 	error = VOP_SETATTR(vp, vap, cred, td);
424 	postat_ret = VOP_GETATTR(vp, vap, td);
425 	if (!error)
426 		error = postat_ret;
427 out:
428 	vput(vp);
429 	vp = NULL;
430 	nfsm_reply(NFSX_WCCORFATTR(v3));
431 	if (v3) {
432 		nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
433 		error = 0;
434 		goto nfsmout;
435 	} else {
436 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
437 		nfsm_srvfillattr(vap, fp);
438 	}
439 	/* fall through */
440 
441 nfsmout:
442 	if (vp)
443 		vput(vp);
444 	return(error);
445 }
446 
447 /*
448  * nfs lookup rpc
449  */
450 int
451 nfsrv_lookup(nfsd, slp, td, mrq)
452 	struct nfsrv_descript *nfsd;
453 	struct nfssvc_sock *slp;
454 	struct thread *td;
455 	struct mbuf **mrq;
456 {
457 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
458 	struct sockaddr *nam = nfsd->nd_nam;
459 	caddr_t dpos = nfsd->nd_dpos;
460 	struct ucred *cred = &nfsd->nd_cr;
461 	struct nfs_fattr *fp;
462 	struct nameidata nd, ind, *ndp = &nd;
463 	struct vnode *vp, *dirp = NULL;
464 	nfsfh_t nfh;
465 	fhandle_t *fhp;
466 	caddr_t cp;
467 	u_int32_t *tl;
468 	int32_t t1;
469 	caddr_t bpos;
470 	int error = 0, cache, len, dirattr_ret = 1;
471 	int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
472 	char *cp2;
473 	struct mbuf *mb, *mb2, *mreq;
474 	struct vattr va, dirattr, *vap = &va;
475 	u_quad_t frev;
476 
477 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
478 	ndclear(&nd);
479 
480 	fhp = &nfh.fh_generic;
481 	nfsm_srvmtofh(fhp);
482 	nfsm_srvnamesiz(len);
483 
484 	pubflag = nfs_ispublicfh(fhp);
485 
486 	nd.ni_cnd.cn_cred = cred;
487 	nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
488 	nd.ni_cnd.cn_flags = CNP_LOCKLEAF | CNP_SAVESTART;
489 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
490 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
491 
492 	/*
493 	 * namei failure, only dirp to cleanup.  Clear out garbarge from
494 	 * structure in case macros jump to nfsmout.
495 	 */
496 
497 	if (error) {
498 		if (dirp) {
499 			if (v3)
500 				dirattr_ret = VOP_GETATTR(dirp, &dirattr, td);
501 			vrele(dirp);
502 			dirp = NULL;
503 		}
504 		nfsm_reply(NFSX_POSTOPATTR(v3));
505 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
506 		error = 0;
507 		goto nfsmout;
508 	}
509 
510 	/*
511 	 * Locate index file for public filehandle
512 	 *
513 	 * error is 0 on entry and 0 on exit from this block.
514 	 */
515 
516 	if (pubflag) {
517 		if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
518 			/*
519 			 * Setup call to lookup() to see if we can find
520 			 * the index file. Arguably, this doesn't belong
521 			 * in a kernel.. Ugh.  If an error occurs, do not
522 			 * try to install an index file and then clear the
523 			 * error.
524 			 *
525 			 * When we replace nd with ind and redirect ndp,
526 			 * maintenance of ni_startdir and ni_vp shift to
527 			 * ind and we have to clean them up in the old nd.
528 			 * However, the cnd resource continues to be maintained
529 			 * via the original nd.  Confused?  You aren't alone!
530 			 */
531 			ind = nd;
532 			VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
533 			ind.ni_pathlen = strlen(nfs_pub.np_index);
534 			ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
535 			    nfs_pub.np_index;
536 			ind.ni_startdir = nd.ni_vp;
537 			VREF(ind.ni_startdir);
538 
539 			error = lookup(&ind);
540 			ind.ni_dvp = NULL;
541 
542 			if (error == 0) {
543 				/*
544 				 * Found an index file. Get rid of
545 				 * the old references.  transfer nd.ni_vp'
546 				 */
547 				if (dirp)
548 					vrele(dirp);
549 				dirp = nd.ni_vp;
550 				nd.ni_vp = NULL;
551 				vrele(nd.ni_startdir);
552 				nd.ni_startdir = NULL;
553 				ndp = &ind;
554 			}
555 			error = 0;
556 		}
557 		/*
558 		 * If the public filehandle was used, check that this lookup
559 		 * didn't result in a filehandle outside the publicly exported
560 		 * filesystem.  We clear the poor vp here to avoid lockups due
561 		 * to NFS I/O.
562 		 */
563 
564 		if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
565 			vput(nd.ni_vp);
566 			nd.ni_vp = NULL;
567 			error = EPERM;
568 		}
569 	}
570 
571 	if (dirp) {
572 		if (v3)
573 			dirattr_ret = VOP_GETATTR(dirp, &dirattr, td);
574 		vrele(dirp);
575 		dirp = NULL;
576 	}
577 
578 	/*
579 	 * Resources at this point:
580 	 *	ndp->ni_vp	may not be NULL
581 	 *
582 	 */
583 
584 	if (error) {
585 		nfsm_reply(NFSX_POSTOPATTR(v3));
586 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
587 		error = 0;
588 		goto nfsmout;
589 	}
590 
591 	nqsrv_getl(ndp->ni_startdir, ND_READ);
592 
593 	/*
594 	 * Clear out some resources prior to potentially blocking.  This
595 	 * is not as critical as ni_dvp resources in other routines, but
596 	 * it helps.
597 	 */
598 	vrele(ndp->ni_startdir);
599 	ndp->ni_startdir = NULL;
600 	NDFREE(&nd, NDF_ONLY_PNBUF);
601 
602 	/*
603 	 * Get underlying attribute, then release remaining resources ( for
604 	 * the same potential blocking reason ) and reply.
605 	 */
606 	vp = ndp->ni_vp;
607 	bzero((caddr_t)fhp, sizeof(nfh));
608 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
609 	error = VFS_VPTOFH(vp, &fhp->fh_fid);
610 	if (!error)
611 		error = VOP_GETATTR(vp, vap, td);
612 
613 	vput(vp);
614 	ndp->ni_vp = NULL;
615 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
616 	if (error) {
617 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
618 		error = 0;
619 		goto nfsmout;
620 	}
621 	nfsm_srvfhtom(fhp, v3);
622 	if (v3) {
623 		nfsm_srvpostop_attr(0, vap);
624 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
625 	} else {
626 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
627 		nfsm_srvfillattr(vap, fp);
628 	}
629 
630 nfsmout:
631 	if (dirp)
632 		vrele(dirp);
633 	NDFREE(&nd, NDF_ONLY_PNBUF);
634 	if (ndp->ni_startdir)
635 		vrele(ndp->ni_startdir);
636 	if (ndp->ni_vp)
637 		vput(ndp->ni_vp);
638 	return (error);
639 }
640 
641 /*
642  * nfs readlink service
643  */
644 int
645 nfsrv_readlink(nfsd, slp, td, mrq)
646 	struct nfsrv_descript *nfsd;
647 	struct nfssvc_sock *slp;
648 	struct thread *td;
649 	struct mbuf **mrq;
650 {
651 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
652 	struct sockaddr *nam = nfsd->nd_nam;
653 	caddr_t dpos = nfsd->nd_dpos;
654 	struct ucred *cred = &nfsd->nd_cr;
655 	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
656 	struct iovec *ivp = iv;
657 	struct mbuf *mp;
658 	u_int32_t *tl;
659 	int32_t t1;
660 	caddr_t bpos;
661 	int error = 0, rdonly, cache, i, tlen, len, getret;
662 	int v3 = (nfsd->nd_flag & ND_NFSV3);
663 	char *cp2;
664 	struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
665 	struct vnode *vp = NULL;
666 	struct vattr attr;
667 	nfsfh_t nfh;
668 	fhandle_t *fhp;
669 	struct uio io, *uiop = &io;
670 	u_quad_t frev;
671 
672 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
673 #ifndef nolint
674 	mp2 = (struct mbuf *)0;
675 #endif
676 	mp3 = NULL;
677 	fhp = &nfh.fh_generic;
678 	nfsm_srvmtofh(fhp);
679 	len = 0;
680 	i = 0;
681 	while (len < NFS_MAXPATHLEN) {
682 		MGET(mp, M_WAIT, MT_DATA);
683 		MCLGET(mp, M_WAIT);
684 		mp->m_len = NFSMSIZ(mp);
685 		if (len == 0)
686 			mp3 = mp2 = mp;
687 		else {
688 			mp2->m_next = mp;
689 			mp2 = mp;
690 		}
691 		if ((len+mp->m_len) > NFS_MAXPATHLEN) {
692 			mp->m_len = NFS_MAXPATHLEN-len;
693 			len = NFS_MAXPATHLEN;
694 		} else
695 			len += mp->m_len;
696 		ivp->iov_base = mtod(mp, caddr_t);
697 		ivp->iov_len = mp->m_len;
698 		i++;
699 		ivp++;
700 	}
701 	uiop->uio_iov = iv;
702 	uiop->uio_iovcnt = i;
703 	uiop->uio_offset = 0;
704 	uiop->uio_resid = len;
705 	uiop->uio_rw = UIO_READ;
706 	uiop->uio_segflg = UIO_SYSSPACE;
707 	uiop->uio_td = NULL;
708 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
709 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
710 	if (error) {
711 		nfsm_reply(2 * NFSX_UNSIGNED);
712 		nfsm_srvpostop_attr(1, (struct vattr *)0);
713 		error = 0;
714 		goto nfsmout;
715 	}
716 	if (vp->v_type != VLNK) {
717 		if (v3)
718 			error = EINVAL;
719 		else
720 			error = ENXIO;
721 		goto out;
722 	}
723 	nqsrv_getl(vp, ND_READ);
724 	error = VOP_READLINK(vp, uiop, cred);
725 out:
726 	getret = VOP_GETATTR(vp, &attr, td);
727 	vput(vp);
728 	vp = NULL;
729 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
730 	if (v3) {
731 		nfsm_srvpostop_attr(getret, &attr);
732 		if (error) {
733 			error = 0;
734 			goto nfsmout;
735 		}
736 	}
737 	if (uiop->uio_resid > 0) {
738 		len -= uiop->uio_resid;
739 		tlen = nfsm_rndup(len);
740 		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
741 	}
742 	nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
743 	*tl = txdr_unsigned(len);
744 	mb->m_next = mp3;
745 	mp3 = NULL;
746 nfsmout:
747 	if (mp3)
748 		m_freem(mp3);
749 	if (vp)
750 		vput(vp);
751 	return(error);
752 }
753 
754 /*
755  * nfs read service
756  */
757 int
758 nfsrv_read(nfsd, slp, td, mrq)
759 	struct nfsrv_descript *nfsd;
760 	struct nfssvc_sock *slp;
761 	struct thread *td;
762 	struct mbuf **mrq;
763 {
764 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
765 	struct sockaddr *nam = nfsd->nd_nam;
766 	caddr_t dpos = nfsd->nd_dpos;
767 	struct ucred *cred = &nfsd->nd_cr;
768 	struct iovec *iv;
769 	struct iovec *iv2;
770 	struct mbuf *m;
771 	struct nfs_fattr *fp;
772 	u_int32_t *tl;
773 	int32_t t1;
774 	int i;
775 	caddr_t bpos;
776 	int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret;
777 	int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
778 	char *cp2;
779 	struct mbuf *mb, *mb2, *mreq;
780 	struct mbuf *m2;
781 	struct vnode *vp = NULL;
782 	nfsfh_t nfh;
783 	fhandle_t *fhp;
784 	struct uio io, *uiop = &io;
785 	struct vattr va, *vap = &va;
786 	struct nfsheur *nh;
787 	off_t off;
788 	int ioflag = 0;
789 	u_quad_t frev;
790 
791 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
792 	fhp = &nfh.fh_generic;
793 	nfsm_srvmtofh(fhp);
794 	if (v3) {
795 		nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
796 		off = fxdr_hyper(tl);
797 	} else {
798 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
799 		off = (off_t)fxdr_unsigned(u_int32_t, *tl);
800 	}
801 	nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
802 
803 	/*
804 	 * Reference vp.  If an error occurs, vp will be invalid, but we
805 	 * have to NULL it just in case.  The macros might goto nfsmout
806 	 * as well.
807 	 */
808 
809 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
810 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
811 	if (error) {
812 		vp = NULL;
813 		nfsm_reply(2 * NFSX_UNSIGNED);
814 		nfsm_srvpostop_attr(1, (struct vattr *)0);
815 		error = 0;
816 		goto nfsmout;
817 	}
818 
819 	if (vp->v_type != VREG) {
820 		if (v3)
821 			error = EINVAL;
822 		else
823 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
824 	}
825 	if (!error) {
826 	    nqsrv_getl(vp, ND_READ);
827 	    if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0)
828 		error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1);
829 	}
830 	getret = VOP_GETATTR(vp, vap, td);
831 	if (!error)
832 		error = getret;
833 	if (error) {
834 		vput(vp);
835 		vp = NULL;
836 		nfsm_reply(NFSX_POSTOPATTR(v3));
837 		nfsm_srvpostop_attr(getret, vap);
838 		error = 0;
839 		goto nfsmout;
840 	}
841 
842 	/*
843 	 * Calculate byte count to read
844 	 */
845 
846 	if (off >= vap->va_size)
847 		cnt = 0;
848 	else if ((off + reqlen) > vap->va_size)
849 		cnt = vap->va_size - off;
850 	else
851 		cnt = reqlen;
852 
853 	/*
854 	 * Calculate seqcount for heuristic
855 	 */
856 
857 	{
858 		int hi;
859 		int try = 4;
860 
861 		/*
862 		 * Locate best candidate
863 		 */
864 
865 		hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) & (NUM_HEURISTIC - 1);
866 		nh = &nfsheur[hi];
867 
868 		while (try--) {
869 			if (nfsheur[hi].nh_vp == vp) {
870 				nh = &nfsheur[hi];
871 				break;
872 			}
873 			if (nfsheur[hi].nh_use > 0)
874 				--nfsheur[hi].nh_use;
875 			hi = (hi + 1) & (NUM_HEURISTIC - 1);
876 			if (nfsheur[hi].nh_use < nh->nh_use)
877 				nh = &nfsheur[hi];
878 		}
879 
880 		if (nh->nh_vp != vp) {
881 			nh->nh_vp = vp;
882 			nh->nh_nextr = off;
883 			nh->nh_use = NHUSE_INIT;
884 			if (off == 0)
885 				nh->nh_seqcount = 4;
886 			else
887 				nh->nh_seqcount = 1;
888 		}
889 
890 		/*
891 		 * Calculate heuristic
892 		 */
893 
894 		if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
895 			if (++nh->nh_seqcount > IO_SEQMAX)
896 				nh->nh_seqcount = IO_SEQMAX;
897 		} else if (nh->nh_seqcount > 1) {
898 			nh->nh_seqcount = 1;
899 		} else {
900 			nh->nh_seqcount = 0;
901 		}
902 		nh->nh_use += NHUSE_INC;
903 		if (nh->nh_use > NHUSE_MAX)
904 			nh->nh_use = NHUSE_MAX;
905 		ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
906         }
907 
908 	nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
909 	if (v3) {
910 		nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
911 		*tl++ = nfs_true;
912 		fp = (struct nfs_fattr *)tl;
913 		tl += (NFSX_V3FATTR / sizeof (u_int32_t));
914 	} else {
915 		nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
916 		fp = (struct nfs_fattr *)tl;
917 		tl += (NFSX_V2FATTR / sizeof (u_int32_t));
918 	}
919 	len = left = nfsm_rndup(cnt);
920 	if (cnt > 0) {
921 		/*
922 		 * Generate the mbuf list with the uio_iov ref. to it.
923 		 */
924 		i = 0;
925 		m = m2 = mb;
926 		while (left > 0) {
927 			siz = min(M_TRAILINGSPACE(m), left);
928 			if (siz > 0) {
929 				left -= siz;
930 				i++;
931 			}
932 			if (left > 0) {
933 				MGET(m, M_WAIT, MT_DATA);
934 				MCLGET(m, M_WAIT);
935 				m->m_len = 0;
936 				m2->m_next = m;
937 				m2 = m;
938 			}
939 		}
940 		MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
941 		       M_TEMP, M_WAITOK);
942 		uiop->uio_iov = iv2 = iv;
943 		m = mb;
944 		left = len;
945 		i = 0;
946 		while (left > 0) {
947 			if (m == NULL)
948 				panic("nfsrv_read iov");
949 			siz = min(M_TRAILINGSPACE(m), left);
950 			if (siz > 0) {
951 				iv->iov_base = mtod(m, caddr_t) + m->m_len;
952 				iv->iov_len = siz;
953 				m->m_len += siz;
954 				left -= siz;
955 				iv++;
956 				i++;
957 			}
958 			m = m->m_next;
959 		}
960 		uiop->uio_iovcnt = i;
961 		uiop->uio_offset = off;
962 		uiop->uio_resid = len;
963 		uiop->uio_rw = UIO_READ;
964 		uiop->uio_segflg = UIO_SYSSPACE;
965 		error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
966 		off = uiop->uio_offset;
967 		nh->nh_nextr = off;
968 		FREE((caddr_t)iv2, M_TEMP);
969 		if (error || (getret = VOP_GETATTR(vp, vap, td))) {
970 			if (!error)
971 				error = getret;
972 			m_freem(mreq);
973 			vput(vp);
974 			vp = NULL;
975 			nfsm_reply(NFSX_POSTOPATTR(v3));
976 			nfsm_srvpostop_attr(getret, vap);
977 			error = 0;
978 			goto nfsmout;
979 		}
980 	} else {
981 		uiop->uio_resid = 0;
982 	}
983 	vput(vp);
984 	vp = NULL;
985 	nfsm_srvfillattr(vap, fp);
986 	tlen = len - uiop->uio_resid;
987 	cnt = cnt < tlen ? cnt : tlen;
988 	tlen = nfsm_rndup(cnt);
989 	if (len != tlen || tlen != cnt)
990 		nfsm_adj(mb, len - tlen, tlen - cnt);
991 	if (v3) {
992 		*tl++ = txdr_unsigned(cnt);
993 		if (len < reqlen)
994 			*tl++ = nfs_true;
995 		else
996 			*tl++ = nfs_false;
997 	}
998 	*tl = txdr_unsigned(cnt);
999 nfsmout:
1000 	if (vp)
1001 		vput(vp);
1002 	return(error);
1003 }
1004 
1005 /*
1006  * nfs write service
1007  */
1008 int
1009 nfsrv_write(nfsd, slp, td, mrq)
1010 	struct nfsrv_descript *nfsd;
1011 	struct nfssvc_sock *slp;
1012 	struct thread *td;
1013 	struct mbuf **mrq;
1014 {
1015 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1016 	struct sockaddr *nam = nfsd->nd_nam;
1017 	caddr_t dpos = nfsd->nd_dpos;
1018 	struct ucred *cred = &nfsd->nd_cr;
1019 	struct iovec *ivp;
1020 	int i, cnt;
1021 	struct mbuf *mp;
1022 	struct nfs_fattr *fp;
1023 	struct iovec *iv;
1024 	struct vattr va, forat;
1025 	struct vattr *vap = &va;
1026 	u_int32_t *tl;
1027 	int32_t t1;
1028 	caddr_t bpos;
1029 	int error = 0, rdonly, cache, len, forat_ret = 1;
1030 	int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
1031 	int stable = NFSV3WRITE_FILESYNC;
1032 	int v3 = (nfsd->nd_flag & ND_NFSV3);
1033 	char *cp2;
1034 	struct mbuf *mb, *mb2, *mreq;
1035 	struct vnode *vp = NULL;
1036 	nfsfh_t nfh;
1037 	fhandle_t *fhp;
1038 	struct uio io, *uiop = &io;
1039 	off_t off;
1040 	u_quad_t frev;
1041 
1042 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1043 	if (mrep == NULL) {
1044 		*mrq = NULL;
1045 		error = 0;
1046 		goto nfsmout;
1047 	}
1048 	fhp = &nfh.fh_generic;
1049 	nfsm_srvmtofh(fhp);
1050 	if (v3) {
1051 		nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1052 		off = fxdr_hyper(tl);
1053 		tl += 3;
1054 		stable = fxdr_unsigned(int, *tl++);
1055 	} else {
1056 		nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1057 		off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1058 		tl += 2;
1059 		if (nfs_async)
1060 	    		stable = NFSV3WRITE_UNSTABLE;
1061 	}
1062 	retlen = len = fxdr_unsigned(int32_t, *tl);
1063 	cnt = i = 0;
1064 
1065 	/*
1066 	 * For NFS Version 2, it is not obvious what a write of zero length
1067 	 * should do, but I might as well be consistent with Version 3,
1068 	 * which is to return ok so long as there are no permission problems.
1069 	 */
1070 	if (len > 0) {
1071 	    zeroing = 1;
1072 	    mp = mrep;
1073 	    while (mp) {
1074 		if (mp == md) {
1075 			zeroing = 0;
1076 			adjust = dpos - mtod(mp, caddr_t);
1077 			mp->m_len -= adjust;
1078 			if (mp->m_len > 0 && adjust > 0)
1079 				NFSMADV(mp, adjust);
1080 		}
1081 		if (zeroing)
1082 			mp->m_len = 0;
1083 		else if (mp->m_len > 0) {
1084 			i += mp->m_len;
1085 			if (i > len) {
1086 				mp->m_len -= (i - len);
1087 				zeroing	= 1;
1088 			}
1089 			if (mp->m_len > 0)
1090 				cnt++;
1091 		}
1092 		mp = mp->m_next;
1093 	    }
1094 	}
1095 	if (len > NFS_MAXDATA || len < 0 || i < len) {
1096 		error = EIO;
1097 		nfsm_reply(2 * NFSX_UNSIGNED);
1098 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1099 		error = 0;
1100 		goto nfsmout;
1101 	}
1102 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1103 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
1104 	if (error) {
1105 		vp = NULL;
1106 		nfsm_reply(2 * NFSX_UNSIGNED);
1107 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1108 		error = 0;
1109 		goto nfsmout;
1110 	}
1111 	if (v3)
1112 		forat_ret = VOP_GETATTR(vp, &forat, td);
1113 	if (vp->v_type != VREG) {
1114 		if (v3)
1115 			error = EINVAL;
1116 		else
1117 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1118 	}
1119 	if (!error) {
1120 		nqsrv_getl(vp, ND_WRITE);
1121 		error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
1122 	}
1123 	if (error) {
1124 		vput(vp);
1125 		vp = NULL;
1126 		nfsm_reply(NFSX_WCCDATA(v3));
1127 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1128 		error = 0;
1129 		goto nfsmout;
1130 	}
1131 
1132 	if (len > 0) {
1133 	    MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
1134 		M_WAITOK);
1135 	    uiop->uio_iov = iv = ivp;
1136 	    uiop->uio_iovcnt = cnt;
1137 	    mp = mrep;
1138 	    while (mp) {
1139 		if (mp->m_len > 0) {
1140 			ivp->iov_base = mtod(mp, caddr_t);
1141 			ivp->iov_len = mp->m_len;
1142 			ivp++;
1143 		}
1144 		mp = mp->m_next;
1145 	    }
1146 
1147 	    /*
1148 	     * XXX
1149 	     * The IO_METASYNC flag indicates that all metadata (and not just
1150 	     * enough to ensure data integrity) mus be written to stable storage
1151 	     * synchronously.
1152 	     * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1153 	     */
1154 	    if (stable == NFSV3WRITE_UNSTABLE)
1155 		ioflags = IO_NODELOCKED;
1156 	    else if (stable == NFSV3WRITE_DATASYNC)
1157 		ioflags = (IO_SYNC | IO_NODELOCKED);
1158 	    else
1159 		ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1160 	    uiop->uio_resid = len;
1161 	    uiop->uio_rw = UIO_WRITE;
1162 	    uiop->uio_segflg = UIO_SYSSPACE;
1163 	    uiop->uio_td = NULL;
1164 	    uiop->uio_offset = off;
1165 	    error = VOP_WRITE(vp, uiop, ioflags, cred);
1166 	    nfsstats.srvvop_writes++;
1167 	    FREE((caddr_t)iv, M_TEMP);
1168 	}
1169 	aftat_ret = VOP_GETATTR(vp, vap, td);
1170 	vput(vp);
1171 	vp = NULL;
1172 	if (!error)
1173 		error = aftat_ret;
1174 	nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1175 		2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1176 	if (v3) {
1177 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1178 		if (error) {
1179 			error = 0;
1180 			goto nfsmout;
1181 		}
1182 		nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1183 		*tl++ = txdr_unsigned(retlen);
1184 		/*
1185 		 * If nfs_async is set, then pretend the write was FILESYNC.
1186 		 */
1187 		if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1188 			*tl++ = txdr_unsigned(stable);
1189 		else
1190 			*tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1191 		/*
1192 		 * Actually, there is no need to txdr these fields,
1193 		 * but it may make the values more human readable,
1194 		 * for debugging purposes.
1195 		 */
1196 		if (nfsver.tv_sec == 0)
1197 			nfsver = boottime;
1198 		*tl++ = txdr_unsigned(nfsver.tv_sec);
1199 		*tl = txdr_unsigned(nfsver.tv_nsec / 1000);
1200 	} else {
1201 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1202 		nfsm_srvfillattr(vap, fp);
1203 	}
1204 nfsmout:
1205 	if (vp)
1206 		vput(vp);
1207 	return(error);
1208 }
1209 
1210 /*
1211  * NFS write service with write gathering support. Called when
1212  * nfsrvw_procrastinate > 0.
1213  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1214  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1215  * Jan. 1994.
1216  */
1217 int
1218 nfsrv_writegather(ndp, slp, td, mrq)
1219 	struct nfsrv_descript **ndp;
1220 	struct nfssvc_sock *slp;
1221 	struct thread *td;
1222 	struct mbuf **mrq;
1223 {
1224 	struct iovec *ivp;
1225 	struct mbuf *mp;
1226 	struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1227 	struct nfs_fattr *fp;
1228 	int i;
1229 	struct iovec *iov;
1230 	struct nfsrvw_delayhash *wpp;
1231 	struct ucred *cred;
1232 	struct vattr va, forat;
1233 	u_int32_t *tl;
1234 	int32_t t1;
1235 	caddr_t bpos, dpos;
1236 	int error = 0, rdonly, cache, len, forat_ret = 1;
1237 	int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
1238 	char *cp2;
1239 	struct mbuf *mb, *mb2, *mreq, *mrep, *md;
1240 	struct vnode *vp = NULL;
1241 	struct uio io, *uiop = &io;
1242 	u_quad_t frev, cur_usec;
1243 
1244 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1245 #ifndef nolint
1246 	i = 0;
1247 	len = 0;
1248 #endif
1249 	*mrq = NULL;
1250 	if (*ndp) {
1251 	    nfsd = *ndp;
1252 	    *ndp = NULL;
1253 	    mrep = nfsd->nd_mrep;
1254 	    md = nfsd->nd_md;
1255 	    dpos = nfsd->nd_dpos;
1256 	    cred = &nfsd->nd_cr;
1257 	    v3 = (nfsd->nd_flag & ND_NFSV3);
1258 	    LIST_INIT(&nfsd->nd_coalesce);
1259 	    nfsd->nd_mreq = NULL;
1260 	    nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1261 	    cur_usec = nfs_curusec();
1262 	    nfsd->nd_time = cur_usec +
1263 		(v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
1264 
1265 	    /*
1266 	     * Now, get the write header..
1267 	     */
1268 	    nfsm_srvmtofh(&nfsd->nd_fh);
1269 	    if (v3) {
1270 		nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1271 		nfsd->nd_off = fxdr_hyper(tl);
1272 		tl += 3;
1273 		nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1274 	    } else {
1275 		nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1276 		nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1277 		tl += 2;
1278 		if (nfs_async)
1279 			nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
1280 	    }
1281 	    len = fxdr_unsigned(int32_t, *tl);
1282 	    nfsd->nd_len = len;
1283 	    nfsd->nd_eoff = nfsd->nd_off + len;
1284 
1285 	    /*
1286 	     * Trim the header out of the mbuf list and trim off any trailing
1287 	     * junk so that the mbuf list has only the write data.
1288 	     */
1289 	    zeroing = 1;
1290 	    i = 0;
1291 	    mp = mrep;
1292 	    while (mp) {
1293 		if (mp == md) {
1294 		    zeroing = 0;
1295 		    adjust = dpos - mtod(mp, caddr_t);
1296 		    mp->m_len -= adjust;
1297 		    if (mp->m_len > 0 && adjust > 0)
1298 			NFSMADV(mp, adjust);
1299 		}
1300 		if (zeroing)
1301 		    mp->m_len = 0;
1302 		else {
1303 		    i += mp->m_len;
1304 		    if (i > len) {
1305 			mp->m_len -= (i - len);
1306 			zeroing = 1;
1307 		    }
1308 		}
1309 		mp = mp->m_next;
1310 	    }
1311 	    if (len > NFS_MAXDATA || len < 0  || i < len) {
1312 nfsmout:
1313 		m_freem(mrep);
1314 		error = EIO;
1315 		nfsm_writereply(2 * NFSX_UNSIGNED, v3);
1316 		if (v3)
1317 		    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1318 		nfsd->nd_mreq = mreq;
1319 		nfsd->nd_mrep = NULL;
1320 		nfsd->nd_time = 0;
1321 	    }
1322 
1323 	    /*
1324 	     * Add this entry to the hash and time queues.
1325 	     */
1326 	    s = splsoftclock();
1327 	    owp = NULL;
1328 	    wp = slp->ns_tq.lh_first;
1329 	    while (wp && wp->nd_time < nfsd->nd_time) {
1330 		owp = wp;
1331 		wp = wp->nd_tq.le_next;
1332 	    }
1333 	    NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
1334 	    if (owp) {
1335 		LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1336 	    } else {
1337 		LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1338 	    }
1339 	    if (nfsd->nd_mrep) {
1340 		wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1341 		owp = NULL;
1342 		wp = wpp->lh_first;
1343 		while (wp &&
1344 		    bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
1345 		    owp = wp;
1346 		    wp = wp->nd_hash.le_next;
1347 		}
1348 		while (wp && wp->nd_off < nfsd->nd_off &&
1349 		    !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
1350 		    owp = wp;
1351 		    wp = wp->nd_hash.le_next;
1352 		}
1353 		if (owp) {
1354 		    LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1355 
1356 		    /*
1357 		     * Search the hash list for overlapping entries and
1358 		     * coalesce.
1359 		     */
1360 		    for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1361 			wp = nfsd->nd_hash.le_next;
1362 			if (NFSW_SAMECRED(owp, nfsd))
1363 			    nfsrvw_coalesce(owp, nfsd);
1364 		    }
1365 		} else {
1366 		    LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1367 		}
1368 	    }
1369 	    splx(s);
1370 	}
1371 
1372 	/*
1373 	 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1374 	 * and generate the associated reply mbuf list(s).
1375 	 */
1376 loop1:
1377 	cur_usec = nfs_curusec();
1378 	s = splsoftclock();
1379 	for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
1380 		owp = nfsd->nd_tq.le_next;
1381 		if (nfsd->nd_time > cur_usec)
1382 		    break;
1383 		if (nfsd->nd_mreq)
1384 		    continue;
1385 		NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
1386 		LIST_REMOVE(nfsd, nd_tq);
1387 		LIST_REMOVE(nfsd, nd_hash);
1388 		splx(s);
1389 		mrep = nfsd->nd_mrep;
1390 		nfsd->nd_mrep = NULL;
1391 		cred = &nfsd->nd_cr;
1392 		v3 = (nfsd->nd_flag & ND_NFSV3);
1393 		forat_ret = aftat_ret = 1;
1394 		error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1395 		    nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
1396 		if (!error) {
1397 		    if (v3)
1398 			forat_ret = VOP_GETATTR(vp, &forat, td);
1399 		    if (vp->v_type != VREG) {
1400 			if (v3)
1401 			    error = EINVAL;
1402 			else
1403 			    error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1404 		    }
1405 		} else {
1406 		    vp = NULL;
1407 		}
1408 		if (!error) {
1409 		    nqsrv_getl(vp, ND_WRITE);
1410 		    error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
1411 		}
1412 
1413 		if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1414 		    ioflags = IO_NODELOCKED;
1415 		else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1416 		    ioflags = (IO_SYNC | IO_NODELOCKED);
1417 		else
1418 		    ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1419 		uiop->uio_rw = UIO_WRITE;
1420 		uiop->uio_segflg = UIO_SYSSPACE;
1421 		uiop->uio_td = NULL;
1422 		uiop->uio_offset = nfsd->nd_off;
1423 		uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1424 		if (uiop->uio_resid > 0) {
1425 		    mp = mrep;
1426 		    i = 0;
1427 		    while (mp) {
1428 			if (mp->m_len > 0)
1429 			    i++;
1430 			mp = mp->m_next;
1431 		    }
1432 		    uiop->uio_iovcnt = i;
1433 		    MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
1434 			M_TEMP, M_WAITOK);
1435 		    uiop->uio_iov = ivp = iov;
1436 		    mp = mrep;
1437 		    while (mp) {
1438 			if (mp->m_len > 0) {
1439 			    ivp->iov_base = mtod(mp, caddr_t);
1440 			    ivp->iov_len = mp->m_len;
1441 			    ivp++;
1442 			}
1443 			mp = mp->m_next;
1444 		    }
1445 		    if (!error) {
1446 			error = VOP_WRITE(vp, uiop, ioflags, cred);
1447 			nfsstats.srvvop_writes++;
1448 		    }
1449 		    FREE((caddr_t)iov, M_TEMP);
1450 		}
1451 		m_freem(mrep);
1452 		if (vp) {
1453 		    aftat_ret = VOP_GETATTR(vp, &va, td);
1454 		    vput(vp);
1455 		    vp = NULL;
1456 		}
1457 
1458 		/*
1459 		 * Loop around generating replies for all write rpcs that have
1460 		 * now been completed.
1461 		 */
1462 		swp = nfsd;
1463 		do {
1464 		    NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
1465 		    if (error) {
1466 			nfsm_writereply(NFSX_WCCDATA(v3), v3);
1467 			if (v3) {
1468 			    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1469 			}
1470 		    } else {
1471 			nfsm_writereply(NFSX_PREOPATTR(v3) +
1472 			    NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1473 			    NFSX_WRITEVERF(v3), v3);
1474 			if (v3) {
1475 			    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1476 			    nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1477 			    *tl++ = txdr_unsigned(nfsd->nd_len);
1478 			    *tl++ = txdr_unsigned(swp->nd_stable);
1479 			    /*
1480 			     * Actually, there is no need to txdr these fields,
1481 			     * but it may make the values more human readable,
1482 			     * for debugging purposes.
1483 			     */
1484 			    if (nfsver.tv_sec == 0)
1485 				    nfsver = boottime;
1486 			    *tl++ = txdr_unsigned(nfsver.tv_sec);
1487 			    *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
1488 			} else {
1489 			    nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1490 			    nfsm_srvfillattr(&va, fp);
1491 			}
1492 		    }
1493 		    nfsd->nd_mreq = mreq;
1494 		    if (nfsd->nd_mrep)
1495 			panic("nfsrv_write: nd_mrep not free");
1496 
1497 		    /*
1498 		     * Done. Put it at the head of the timer queue so that
1499 		     * the final phase can return the reply.
1500 		     */
1501 		    s = splsoftclock();
1502 		    if (nfsd != swp) {
1503 			nfsd->nd_time = 0;
1504 			LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1505 		    }
1506 		    nfsd = swp->nd_coalesce.lh_first;
1507 		    if (nfsd) {
1508 			LIST_REMOVE(nfsd, nd_tq);
1509 		    }
1510 		    splx(s);
1511 		} while (nfsd);
1512 		s = splsoftclock();
1513 		swp->nd_time = 0;
1514 		LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1515 		splx(s);
1516 		goto loop1;
1517 	}
1518 	splx(s);
1519 
1520 	/*
1521 	 * Search for a reply to return.
1522 	 */
1523 	s = splsoftclock();
1524 	for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next)
1525 		if (nfsd->nd_mreq) {
1526 		    NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
1527 		    LIST_REMOVE(nfsd, nd_tq);
1528 		    *mrq = nfsd->nd_mreq;
1529 		    *ndp = nfsd;
1530 		    break;
1531 		}
1532 	splx(s);
1533 	return (0);
1534 }
1535 
1536 /*
1537  * Coalesce the write request nfsd into owp. To do this we must:
1538  * - remove nfsd from the queues
1539  * - merge nfsd->nd_mrep into owp->nd_mrep
1540  * - update the nd_eoff and nd_stable for owp
1541  * - put nfsd on owp's nd_coalesce list
1542  * NB: Must be called at splsoftclock().
1543  */
1544 static void
1545 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
1546 {
1547         int overlap;
1548         struct mbuf *mp;
1549 	struct nfsrv_descript *p;
1550 
1551 	NFS_DPF(WG, ("C%03x-%03x",
1552 		     nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
1553         LIST_REMOVE(nfsd, nd_hash);
1554         LIST_REMOVE(nfsd, nd_tq);
1555         if (owp->nd_eoff < nfsd->nd_eoff) {
1556             overlap = owp->nd_eoff - nfsd->nd_off;
1557             if (overlap < 0)
1558                 panic("nfsrv_coalesce: bad off");
1559             if (overlap > 0)
1560                 m_adj(nfsd->nd_mrep, overlap);
1561             mp = owp->nd_mrep;
1562             while (mp->m_next)
1563                 mp = mp->m_next;
1564             mp->m_next = nfsd->nd_mrep;
1565             owp->nd_eoff = nfsd->nd_eoff;
1566         } else
1567             m_freem(nfsd->nd_mrep);
1568         nfsd->nd_mrep = NULL;
1569         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1570             owp->nd_stable = NFSV3WRITE_FILESYNC;
1571         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1572             owp->nd_stable == NFSV3WRITE_UNSTABLE)
1573             owp->nd_stable = NFSV3WRITE_DATASYNC;
1574         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1575 
1576 	/*
1577 	 * If nfsd had anything else coalesced into it, transfer them
1578 	 * to owp, otherwise their replies will never get sent.
1579 	 */
1580 	for (p = nfsd->nd_coalesce.lh_first; p;
1581 	     p = nfsd->nd_coalesce.lh_first) {
1582 	    LIST_REMOVE(p, nd_tq);
1583 	    LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
1584 	}
1585 }
1586 
1587 /*
1588  * nfs create service
1589  * now does a truncate to 0 length via. setattr if it already exists
1590  */
1591 int
1592 nfsrv_create(nfsd, slp, td, mrq)
1593 	struct nfsrv_descript *nfsd;
1594 	struct nfssvc_sock *slp;
1595 	struct thread *td;
1596 	struct mbuf **mrq;
1597 {
1598 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1599 	struct sockaddr *nam = nfsd->nd_nam;
1600 	caddr_t dpos = nfsd->nd_dpos;
1601 	struct ucred *cred = &nfsd->nd_cr;
1602 	struct nfs_fattr *fp;
1603 	struct vattr va, dirfor, diraft;
1604 	struct vattr *vap = &va;
1605 	struct nfsv2_sattr *sp;
1606 	u_int32_t *tl;
1607 	struct nameidata nd;
1608 	int32_t t1;
1609 	caddr_t bpos;
1610 	int error = 0, rdev, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1611 	int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1612 	caddr_t cp;
1613 	char *cp2;
1614 	struct mbuf *mb, *mb2, *mreq;
1615 	struct vnode *dirp = (struct vnode *)0;
1616 	nfsfh_t nfh;
1617 	fhandle_t *fhp;
1618 	u_quad_t frev, tempsize;
1619 	u_char cverf[NFSX_V3CREATEVERF];
1620 
1621 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1622 #ifndef nolint
1623 	rdev = 0;
1624 #endif
1625 	ndclear(&nd);
1626 
1627 	fhp = &nfh.fh_generic;
1628 	nfsm_srvmtofh(fhp);
1629 	nfsm_srvnamesiz(len);
1630 
1631 	nd.ni_cnd.cn_cred = cred;
1632 	nd.ni_cnd.cn_nameiop = NAMEI_CREATE;
1633 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_SAVESTART;
1634 
1635 	/*
1636 	 * Call namei and do initial cleanup to get a few things
1637 	 * out of the way.  If we get an initial error we cleanup
1638 	 * and return here to avoid special-casing the invalid nd
1639 	 * structure through the rest of the case.  dirp may be
1640 	 * set even if an error occurs, but the nd structure will not
1641 	 * be valid at all if an error occurs so we have to invalidate it
1642 	 * prior to calling nfsm_reply ( which might goto nfsmout ).
1643 	 */
1644 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1645 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1646 	if (dirp) {
1647 		if (v3) {
1648 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
1649 		} else {
1650 			vrele(dirp);
1651 			dirp = NULL;
1652 		}
1653 	}
1654 	if (error) {
1655 		nfsm_reply(NFSX_WCCDATA(v3));
1656 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1657 		error = 0;
1658 		goto nfsmout;
1659 	}
1660 
1661 	/*
1662 	 * No error.  Continue.  State:
1663 	 *
1664 	 *	startdir	is valid ( we release this immediately )
1665 	 *	dirp 		may be valid
1666 	 *	nd.ni_vp	may be valid
1667 	 *	nd.ni_dvp	is valid
1668 	 *
1669 	 * The error state is set through the code and we may also do some
1670 	 * opportunistic releasing of vnodes to avoid holding locks through
1671 	 * NFS I/O.  The cleanup at the end is a catch-all
1672 	 */
1673 
1674 	VATTR_NULL(vap);
1675 	if (v3) {
1676 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1677 		how = fxdr_unsigned(int, *tl);
1678 		switch (how) {
1679 		case NFSV3CREATE_GUARDED:
1680 			if (nd.ni_vp) {
1681 				error = EEXIST;
1682 				break;
1683 			}
1684 			/* fall through */
1685 		case NFSV3CREATE_UNCHECKED:
1686 			nfsm_srvsattr(vap);
1687 			break;
1688 		case NFSV3CREATE_EXCLUSIVE:
1689 			nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1690 			bcopy(cp, cverf, NFSX_V3CREATEVERF);
1691 			exclusive_flag = 1;
1692 			break;
1693 		};
1694 		vap->va_type = VREG;
1695 	} else {
1696 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1697 		vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1698 		if (vap->va_type == VNON)
1699 			vap->va_type = VREG;
1700 		vap->va_mode = nfstov_mode(sp->sa_mode);
1701 		switch (vap->va_type) {
1702 		case VREG:
1703 			tsize = fxdr_unsigned(int32_t, sp->sa_size);
1704 			if (tsize != -1)
1705 				vap->va_size = (u_quad_t)tsize;
1706 			break;
1707 		case VCHR:
1708 		case VBLK:
1709 		case VFIFO:
1710 			rdev = fxdr_unsigned(long, sp->sa_size);
1711 			break;
1712 		default:
1713 			break;
1714 		};
1715 	}
1716 
1717 	/*
1718 	 * Iff doesn't exist, create it
1719 	 * otherwise just truncate to 0 length
1720 	 *   should I set the mode too ?
1721 	 *
1722 	 * The only possible error we can have at this point is EEXIST.
1723 	 * nd.ni_vp will also be non-NULL in that case.
1724 	 */
1725 	if (nd.ni_vp == NULL) {
1726 		if (vap->va_mode == (mode_t)VNOVAL)
1727 			vap->va_mode = 0;
1728 		if (vap->va_type == VREG || vap->va_type == VSOCK) {
1729 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
1730 			error = VOP_CREATE(nd.ni_dvp, NCPNULL, &nd.ni_vp,
1731 					    &nd.ni_cnd, vap);
1732 			if (error)
1733 				NDFREE(&nd, NDF_ONLY_PNBUF);
1734 			else {
1735 			    	nfsrv_object_create(nd.ni_vp);
1736 				if (exclusive_flag) {
1737 					exclusive_flag = 0;
1738 					VATTR_NULL(vap);
1739 					bcopy(cverf, (caddr_t)&vap->va_atime,
1740 						NFSX_V3CREATEVERF);
1741 					error = VOP_SETATTR(nd.ni_vp, vap, cred,
1742 						td);
1743 				}
1744 			}
1745 		} else if (
1746 			vap->va_type == VCHR ||
1747 			vap->va_type == VBLK ||
1748 			vap->va_type == VFIFO
1749 		) {
1750 			/*
1751 			 * Handle SysV FIFO node special cases.  All other
1752 			 * devices require super user to access.
1753 			 */
1754 			if (vap->va_type == VCHR && rdev == 0xffffffff)
1755 				vap->va_type = VFIFO;
1756                         if (vap->va_type != VFIFO &&
1757                             (error = suser_cred(cred, 0))) {
1758 				goto nfsmreply0;
1759                         }
1760 			vap->va_rdev = rdev;
1761 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
1762 
1763 			error = VOP_MKNOD(nd.ni_dvp, NCPNULL, &nd.ni_vp,
1764 					    &nd.ni_cnd, vap);
1765 			if (error) {
1766 				NDFREE(&nd, NDF_ONLY_PNBUF);
1767 				goto nfsmreply0;
1768 			}
1769 			vput(nd.ni_vp);
1770 			nd.ni_vp = NULL;
1771 
1772 			/*
1773 			 * release dvp prior to lookup
1774 			 */
1775 			vput(nd.ni_dvp);
1776 			nd.ni_dvp = NULL;
1777 
1778 			/*
1779 			 * Setup for lookup.
1780 			 *
1781 			 * Even though LOCKPARENT was cleared, ni_dvp may
1782 			 * be garbage.
1783 			 */
1784 			nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
1785 			nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT);
1786 			nd.ni_cnd.cn_td = td;
1787 			nd.ni_cnd.cn_cred = cred;
1788 
1789 			error = lookup(&nd);
1790 			nd.ni_dvp = NULL;
1791 
1792 			if (error != 0) {
1793 				nfsm_reply(0);
1794 				/* fall through on certain errors */
1795 			}
1796 			nfsrv_object_create(nd.ni_vp);
1797 			if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) {
1798 				error = EINVAL;
1799 				goto nfsmreply0;
1800 			}
1801 		} else {
1802 			error = ENXIO;
1803 		}
1804 	} else {
1805 		if (vap->va_size != -1) {
1806 			error = nfsrv_access(nd.ni_vp, VWRITE, cred,
1807 			    (nd.ni_cnd.cn_flags & CNP_RDONLY), td, 0);
1808 			if (!error) {
1809 				nqsrv_getl(nd.ni_vp, ND_WRITE);
1810 				tempsize = vap->va_size;
1811 				VATTR_NULL(vap);
1812 				vap->va_size = tempsize;
1813 				error = VOP_SETATTR(nd.ni_vp, vap, cred, td);
1814 			}
1815 		}
1816 	}
1817 
1818 	if (!error) {
1819 		bzero((caddr_t)fhp, sizeof(nfh));
1820 		fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1821 		error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1822 		if (!error)
1823 			error = VOP_GETATTR(nd.ni_vp, vap, td);
1824 	}
1825 	if (v3) {
1826 		if (exclusive_flag && !error &&
1827 			bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
1828 			error = EEXIST;
1829 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
1830 		vrele(dirp);
1831 		dirp = NULL;
1832 	}
1833 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1834 	if (v3) {
1835 		if (!error) {
1836 			nfsm_srvpostop_fh(fhp);
1837 			nfsm_srvpostop_attr(0, vap);
1838 		}
1839 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1840 		error = 0;
1841 	} else {
1842 		nfsm_srvfhtom(fhp, v3);
1843 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1844 		nfsm_srvfillattr(vap, fp);
1845 	}
1846 	goto nfsmout;
1847 
1848 nfsmreply0:
1849 	nfsm_reply(0);
1850 	error = 0;
1851 	/* fall through */
1852 
1853 nfsmout:
1854 	if (nd.ni_startdir) {
1855 		vrele(nd.ni_startdir);
1856 		nd.ni_startdir = NULL;
1857 	}
1858 	if (dirp)
1859 		vrele(dirp);
1860 	NDFREE(&nd, NDF_ONLY_PNBUF);
1861 	if (nd.ni_dvp) {
1862 		if (nd.ni_dvp == nd.ni_vp)
1863 			vrele(nd.ni_dvp);
1864 		else
1865 			vput(nd.ni_dvp);
1866 	}
1867 	if (nd.ni_vp)
1868 		vput(nd.ni_vp);
1869 	return (error);
1870 }
1871 
1872 /*
1873  * nfs v3 mknod service
1874  */
1875 int
1876 nfsrv_mknod(nfsd, slp, td, mrq)
1877 	struct nfsrv_descript *nfsd;
1878 	struct nfssvc_sock *slp;
1879 	struct thread *td;
1880 	struct mbuf **mrq;
1881 {
1882 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1883 	struct sockaddr *nam = nfsd->nd_nam;
1884 	caddr_t dpos = nfsd->nd_dpos;
1885 	struct ucred *cred = &nfsd->nd_cr;
1886 	struct vattr va, dirfor, diraft;
1887 	struct vattr *vap = &va;
1888 	u_int32_t *tl;
1889 	struct nameidata nd;
1890 	int32_t t1;
1891 	caddr_t bpos;
1892 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
1893 	u_int32_t major, minor;
1894 	enum vtype vtyp;
1895 	char *cp2;
1896 	struct mbuf *mb, *mb2, *mreq;
1897 	struct vnode *vp, *dirp = (struct vnode *)0;
1898 	nfsfh_t nfh;
1899 	fhandle_t *fhp;
1900 	u_quad_t frev;
1901 
1902 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1903 	ndclear(&nd);
1904 
1905 	fhp = &nfh.fh_generic;
1906 	nfsm_srvmtofh(fhp);
1907 	nfsm_srvnamesiz(len);
1908 
1909 	nd.ni_cnd.cn_cred = cred;
1910 	nd.ni_cnd.cn_nameiop = NAMEI_CREATE;
1911 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_SAVESTART;
1912 
1913 	/*
1914 	 * Handle nfs_namei() call.  If an error occurs, the nd structure
1915 	 * is not valid.  However, nfsm_*() routines may still jump to
1916 	 * nfsmout.
1917 	 */
1918 
1919 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1920 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1921 	if (dirp)
1922 		dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
1923 	if (error) {
1924 		nfsm_reply(NFSX_WCCDATA(1));
1925 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1926 		error = 0;
1927 		goto nfsmout;
1928 	}
1929 	nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1930 	vtyp = nfsv3tov_type(*tl);
1931 	if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1932 		error = NFSERR_BADTYPE;
1933 		goto out;
1934 	}
1935 	VATTR_NULL(vap);
1936 	nfsm_srvsattr(vap);
1937 	if (vtyp == VCHR || vtyp == VBLK) {
1938 		nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1939 		major = fxdr_unsigned(u_int32_t, *tl++);
1940 		minor = fxdr_unsigned(u_int32_t, *tl);
1941 		vap->va_rdev = makeudev(major, minor);
1942 	}
1943 
1944 	/*
1945 	 * Iff doesn't exist, create it.
1946 	 */
1947 	if (nd.ni_vp) {
1948 		error = EEXIST;
1949 		goto out;
1950 	}
1951 	vap->va_type = vtyp;
1952 	if (vap->va_mode == (mode_t)VNOVAL)
1953 		vap->va_mode = 0;
1954 	if (vtyp == VSOCK) {
1955 		vrele(nd.ni_startdir);
1956 		nd.ni_startdir = NULL;
1957 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
1958 		error = VOP_CREATE(nd.ni_dvp, NCPNULL, &nd.ni_vp,
1959 				&nd.ni_cnd, vap);
1960 		if (error)
1961 			NDFREE(&nd, NDF_ONLY_PNBUF);
1962 	} else {
1963 		if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
1964 			goto out;
1965 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
1966 
1967 		error = VOP_MKNOD(nd.ni_dvp, NCPNULL, &nd.ni_vp,
1968 				&nd.ni_cnd, vap);
1969 		if (error) {
1970 			NDFREE(&nd, NDF_ONLY_PNBUF);
1971 			goto out;
1972 		}
1973 		vput(nd.ni_vp);
1974 		nd.ni_vp = NULL;
1975 
1976 		/*
1977 		 * Release dvp prior to lookup
1978 		 */
1979 		vput(nd.ni_dvp);
1980 		nd.ni_dvp = NULL;
1981 
1982 		KKASSERT(td->td_proc);
1983 		nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
1984 		nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT);
1985 		nd.ni_cnd.cn_td = td;
1986 		nd.ni_cnd.cn_cred = td->td_proc->p_ucred;
1987 
1988 		error = lookup(&nd);
1989 		nd.ni_dvp = NULL;
1990 
1991 		if (error)
1992 			goto out;
1993 		if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK)
1994 			error = EINVAL;
1995 	}
1996 
1997 	/*
1998 	 * send response, cleanup, return.
1999 	 */
2000 out:
2001 	if (nd.ni_startdir) {
2002 		vrele(nd.ni_startdir);
2003 		nd.ni_startdir = NULL;
2004 	}
2005 	NDFREE(&nd, NDF_ONLY_PNBUF);
2006 	if (nd.ni_dvp) {
2007 		if (nd.ni_dvp == nd.ni_vp)
2008 			vrele(nd.ni_dvp);
2009 		else
2010 			vput(nd.ni_dvp);
2011 		nd.ni_dvp = NULL;
2012 	}
2013 	vp = nd.ni_vp;
2014 	if (!error) {
2015 		bzero((caddr_t)fhp, sizeof(nfh));
2016 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2017 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
2018 		if (!error)
2019 			error = VOP_GETATTR(vp, vap, td);
2020 	}
2021 	if (vp) {
2022 		vput(vp);
2023 		vp = NULL;
2024 		nd.ni_vp = NULL;
2025 	}
2026 	diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2027 	if (dirp) {
2028 		vrele(dirp);
2029 		dirp = NULL;
2030 	}
2031 	nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
2032 	if (!error) {
2033 		nfsm_srvpostop_fh(fhp);
2034 		nfsm_srvpostop_attr(0, vap);
2035 	}
2036 	nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2037 	return (0);
2038 nfsmout:
2039 	if (dirp)
2040 		vrele(dirp);
2041 	if (nd.ni_startdir)
2042 		vrele(nd.ni_startdir);
2043 	NDFREE(&nd, NDF_ONLY_PNBUF);
2044 	if (nd.ni_dvp) {
2045 		if (nd.ni_dvp == nd.ni_vp)
2046 			vrele(nd.ni_dvp);
2047 		else
2048 			vput(nd.ni_dvp);
2049 	}
2050 	if (nd.ni_vp)
2051 		vput(nd.ni_vp);
2052 	return (error);
2053 }
2054 
2055 /*
2056  * nfs remove service
2057  */
2058 int
2059 nfsrv_remove(nfsd, slp, td, mrq)
2060 	struct nfsrv_descript *nfsd;
2061 	struct nfssvc_sock *slp;
2062 	struct thread *td;
2063 	struct mbuf **mrq;
2064 {
2065 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2066 	struct sockaddr *nam = nfsd->nd_nam;
2067 	caddr_t dpos = nfsd->nd_dpos;
2068 	struct ucred *cred = &nfsd->nd_cr;
2069 	struct nameidata nd;
2070 	u_int32_t *tl;
2071 	int32_t t1;
2072 	caddr_t bpos;
2073 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2074 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2075 	char *cp2;
2076 	struct mbuf *mb, *mreq;
2077 	struct vnode *dirp;
2078 	struct vattr dirfor, diraft;
2079 	nfsfh_t nfh;
2080 	fhandle_t *fhp;
2081 	u_quad_t frev;
2082 
2083 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2084 	ndclear(&nd);
2085 
2086 	fhp = &nfh.fh_generic;
2087 	nfsm_srvmtofh(fhp);
2088 	nfsm_srvnamesiz(len);
2089 
2090 	nd.ni_cnd.cn_cred = cred;
2091 	nd.ni_cnd.cn_nameiop = NAMEI_DELETE;
2092 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF;
2093 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2094 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2095 	if (dirp) {
2096 		if (v3) {
2097 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
2098 		} else {
2099 			vrele(dirp);
2100 			dirp = NULL;
2101 		}
2102 	}
2103 	if (error == 0) {
2104 		if (nd.ni_vp->v_type == VDIR) {
2105 			error = EPERM;		/* POSIX */
2106 			goto out;
2107 		}
2108 		/*
2109 		 * The root of a mounted filesystem cannot be deleted.
2110 		 */
2111 		if (nd.ni_vp->v_flag & VROOT) {
2112 			error = EBUSY;
2113 			goto out;
2114 		}
2115 out:
2116 		if (!error) {
2117 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
2118 			nqsrv_getl(nd.ni_vp, ND_WRITE);
2119 			error = VOP_REMOVE(nd.ni_dvp, NCPNULL, nd.ni_vp, &nd.ni_cnd);
2120 			NDFREE(&nd, NDF_ONLY_PNBUF);
2121 		}
2122 	}
2123 	if (dirp && v3) {
2124 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2125 		vrele(dirp);
2126 		dirp = NULL;
2127 	}
2128 	nfsm_reply(NFSX_WCCDATA(v3));
2129 	if (v3) {
2130 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2131 		error = 0;
2132 	}
2133 nfsmout:
2134 	NDFREE(&nd, NDF_ONLY_PNBUF);
2135 	if (nd.ni_dvp) {
2136 		if (nd.ni_dvp == nd.ni_vp)
2137 			vrele(nd.ni_dvp);
2138 		else
2139 			vput(nd.ni_dvp);
2140 	}
2141 	if (nd.ni_vp)
2142 		vput(nd.ni_vp);
2143 	return(error);
2144 }
2145 
2146 /*
2147  * nfs rename service
2148  */
2149 int
2150 nfsrv_rename(nfsd, slp, td, mrq)
2151 	struct nfsrv_descript *nfsd;
2152 	struct nfssvc_sock *slp;
2153 	struct thread *td;
2154 	struct mbuf **mrq;
2155 {
2156 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2157 	struct sockaddr *nam = nfsd->nd_nam;
2158 	caddr_t dpos = nfsd->nd_dpos;
2159 	struct ucred *cred = &nfsd->nd_cr;
2160 	u_int32_t *tl;
2161 	int32_t t1;
2162 	caddr_t bpos;
2163 	int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2164 	int tdirfor_ret = 1, tdiraft_ret = 1;
2165 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2166 	char *cp2;
2167 	struct mbuf *mb, *mreq;
2168 	struct nameidata fromnd, tond;
2169 	struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
2170 	struct vnode *tdirp = (struct vnode *)0;
2171 	struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2172 	nfsfh_t fnfh, tnfh;
2173 	fhandle_t *ffhp, *tfhp;
2174 	u_quad_t frev;
2175 	uid_t saved_uid;
2176 
2177 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2178 #ifndef nolint
2179 	fvp = (struct vnode *)0;
2180 #endif
2181 	ffhp = &fnfh.fh_generic;
2182 	tfhp = &tnfh.fh_generic;
2183 
2184 	/*
2185 	 * Clear fields incase goto nfsmout occurs from macro.
2186 	 */
2187 
2188 	ndclear(&fromnd);
2189 	ndclear(&tond);
2190 
2191 	nfsm_srvmtofh(ffhp);
2192 	nfsm_srvnamesiz(len);
2193 	/*
2194 	 * Remember our original uid so that we can reset cr_uid before
2195 	 * the second nfs_namei() call, in case it is remapped.
2196 	 */
2197 	saved_uid = cred->cr_uid;
2198 	fromnd.ni_cnd.cn_cred = cred;
2199 	fromnd.ni_cnd.cn_nameiop = NAMEI_DELETE;
2200 	fromnd.ni_cnd.cn_flags = CNP_WANTPARENT | CNP_SAVESTART;
2201 	error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
2202 		&dpos, &fdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2203 	if (fdirp) {
2204 		if (v3) {
2205 			fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, td);
2206 		} else {
2207 			vrele(fdirp);
2208 			fdirp = NULL;
2209 		}
2210 	}
2211 	if (error) {
2212 		nfsm_reply(2 * NFSX_WCCDATA(v3));
2213 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2214 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2215 		error = 0;
2216 		goto nfsmout;
2217 	}
2218 	fvp = fromnd.ni_vp;
2219 	nfsm_srvmtofh(tfhp);
2220 	nfsm_strsiz(len2, NFS_MAXNAMLEN);
2221 	cred->cr_uid = saved_uid;
2222 	tond.ni_cnd.cn_cred = cred;
2223 	tond.ni_cnd.cn_nameiop = NAMEI_RENAME;
2224 	tond.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF |
2225 		CNP_NOCACHE | CNP_SAVESTART;
2226 	error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
2227 		&dpos, &tdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2228 	if (tdirp) {
2229 		if (v3) {
2230 			tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, td);
2231 		} else {
2232 			vrele(tdirp);
2233 			tdirp = NULL;
2234 		}
2235 	}
2236 	if (error)
2237 		goto out1;
2238 
2239 	tdvp = tond.ni_dvp;
2240 	tvp = tond.ni_vp;
2241 	if (tvp != NULL) {
2242 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2243 			if (v3)
2244 				error = EEXIST;
2245 			else
2246 				error = EISDIR;
2247 			goto out;
2248 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2249 			if (v3)
2250 				error = EEXIST;
2251 			else
2252 				error = ENOTDIR;
2253 			goto out;
2254 		}
2255 		if (tvp->v_type == VDIR && tvp->v_mountedhere) {
2256 			if (v3)
2257 				error = EXDEV;
2258 			else
2259 				error = ENOTEMPTY;
2260 			goto out;
2261 		}
2262 	}
2263 	if (fvp->v_type == VDIR && fvp->v_mountedhere) {
2264 		if (v3)
2265 			error = EXDEV;
2266 		else
2267 			error = ENOTEMPTY;
2268 		goto out;
2269 	}
2270 	if (fvp->v_mount != tdvp->v_mount) {
2271 		if (v3)
2272 			error = EXDEV;
2273 		else
2274 			error = ENOTEMPTY;
2275 		goto out;
2276 	}
2277 	if (fvp == tdvp) {
2278 		if (v3)
2279 			error = EINVAL;
2280 		else
2281 			error = ENOTEMPTY;
2282 	}
2283 	/*
2284 	 * If source is the same as the destination (that is the
2285 	 * same vnode with the same name in the same directory),
2286 	 * then there is nothing to do.
2287 	 */
2288 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2289 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2290 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2291 	      fromnd.ni_cnd.cn_namelen))
2292 		error = -1;
2293 out:
2294 	if (!error) {
2295 		/*
2296 		 * The VOP_RENAME function releases all vnode references &
2297 		 * locks prior to returning so we need to clear the pointers
2298 		 * to bypass cleanup code later on.
2299 		 */
2300 		nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
2301 		nqsrv_getl(tdvp, ND_WRITE);
2302 		if (tvp) {
2303 			nqsrv_getl(tvp, ND_WRITE);
2304 		}
2305 		error = VOP_RENAME(fromnd.ni_dvp, NCPNULL, fromnd.ni_vp, &fromnd.ni_cnd,
2306 				   tond.ni_dvp, NCPNULL, tond.ni_vp, &tond.ni_cnd);
2307 		fromnd.ni_dvp = NULL;
2308 		fromnd.ni_vp = NULL;
2309 		tond.ni_dvp = NULL;
2310 		tond.ni_vp = NULL;
2311 		if (error) {
2312 			fromnd.ni_cnd.cn_flags &= ~CNP_HASBUF;
2313 			tond.ni_cnd.cn_flags &= ~CNP_HASBUF;
2314 		}
2315 	} else {
2316 		if (error == -1)
2317 			error = 0;
2318 	}
2319 	/* fall through */
2320 
2321 out1:
2322 	if (fdirp)
2323 		fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, td);
2324 	if (tdirp)
2325 		tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, td);
2326 	nfsm_reply(2 * NFSX_WCCDATA(v3));
2327 	if (v3) {
2328 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2329 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2330 	}
2331 	error = 0;
2332 	/* fall through */
2333 
2334 nfsmout:
2335 	/*
2336 	 * Clear out tond related fields
2337 	 */
2338 	if (tdirp)
2339 		vrele(tdirp);
2340 	if (tond.ni_startdir)
2341 		vrele(tond.ni_startdir);
2342 	NDFREE(&tond, NDF_ONLY_PNBUF);
2343 	if (tond.ni_dvp) {
2344 		if (tond.ni_dvp == tond.ni_vp)
2345 			vrele(tond.ni_dvp);
2346 		else
2347 			vput(tond.ni_dvp);
2348 	}
2349 	if (tond.ni_vp)
2350 		vput(tond.ni_vp);
2351 
2352 	/*
2353 	 * Clear out fromnd related fields
2354 	 */
2355 	if (fdirp)
2356 		vrele(fdirp);
2357 	if (fromnd.ni_startdir)
2358 		vrele(fromnd.ni_startdir);
2359 	NDFREE(&fromnd, NDF_ONLY_PNBUF);
2360 	if (fromnd.ni_dvp)
2361 		vrele(fromnd.ni_dvp);
2362 	if (fromnd.ni_vp)
2363 		vrele(fromnd.ni_vp);
2364 
2365 	return (error);
2366 }
2367 
2368 /*
2369  * nfs link service
2370  */
2371 int
2372 nfsrv_link(nfsd, slp, td, mrq)
2373 	struct nfsrv_descript *nfsd;
2374 	struct nfssvc_sock *slp;
2375 	struct thread *td;
2376 	struct mbuf **mrq;
2377 {
2378 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2379 	struct sockaddr *nam = nfsd->nd_nam;
2380 	caddr_t dpos = nfsd->nd_dpos;
2381 	struct ucred *cred = &nfsd->nd_cr;
2382 	struct nameidata nd;
2383 	u_int32_t *tl;
2384 	int32_t t1;
2385 	caddr_t bpos;
2386 	int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
2387 	int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2388 	char *cp2;
2389 	struct mbuf *mb, *mreq;
2390 	struct vnode *vp = NULL, *xp, *dirp = (struct vnode *)0;
2391 	struct vattr dirfor, diraft, at;
2392 	nfsfh_t nfh, dnfh;
2393 	fhandle_t *fhp, *dfhp;
2394 	u_quad_t frev;
2395 
2396 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2397 	ndclear(&nd);
2398 
2399 	fhp = &nfh.fh_generic;
2400 	dfhp = &dnfh.fh_generic;
2401 	nfsm_srvmtofh(fhp);
2402 	nfsm_srvmtofh(dfhp);
2403 	nfsm_srvnamesiz(len);
2404 
2405 	error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
2406 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2407 	if (error) {
2408 		nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2409 		nfsm_srvpostop_attr(getret, &at);
2410 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2411 		vp = NULL;
2412 		error = 0;
2413 		goto nfsmout;
2414 	}
2415 	if (vp->v_type == VDIR) {
2416 		error = EPERM;		/* POSIX */
2417 		goto out1;
2418 	}
2419 	nd.ni_cnd.cn_cred = cred;
2420 	nd.ni_cnd.cn_nameiop = NAMEI_CREATE;
2421 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT;
2422 	error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2423 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2424 	if (dirp) {
2425 		if (v3) {
2426 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
2427 		} else {
2428 			vrele(dirp);
2429 			dirp = NULL;
2430 		}
2431 	}
2432 	if (error)
2433 		goto out1;
2434 
2435 	xp = nd.ni_vp;
2436 	if (xp != NULL) {
2437 		error = EEXIST;
2438 		goto out;
2439 	}
2440 	xp = nd.ni_dvp;
2441 	if (vp->v_mount != xp->v_mount)
2442 		error = EXDEV;
2443 out:
2444 	if (!error) {
2445 		nqsrv_getl(vp, ND_WRITE);
2446 		nqsrv_getl(xp, ND_WRITE);
2447 		error = VOP_LINK(nd.ni_dvp, NCPNULL, vp, &nd.ni_cnd);
2448 		NDFREE(&nd, NDF_ONLY_PNBUF);
2449 	}
2450 	/* fall through */
2451 
2452 out1:
2453 	if (v3)
2454 		getret = VOP_GETATTR(vp, &at, td);
2455 	if (dirp)
2456 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2457 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2458 	if (v3) {
2459 		nfsm_srvpostop_attr(getret, &at);
2460 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2461 		error = 0;
2462 	}
2463 	/* fall through */
2464 
2465 nfsmout:
2466 	NDFREE(&nd, NDF_ONLY_PNBUF);
2467 	if (dirp)
2468 		vrele(dirp);
2469 	if (vp)
2470 		vrele(vp);
2471 	if (nd.ni_dvp) {
2472 		if (nd.ni_dvp == nd.ni_vp)
2473 			vrele(nd.ni_dvp);
2474 		else
2475 			vput(nd.ni_dvp);
2476 	}
2477 	if (nd.ni_vp)
2478 		vrele(nd.ni_vp);
2479 	return(error);
2480 }
2481 
2482 /*
2483  * nfs symbolic link service
2484  */
2485 int
2486 nfsrv_symlink(nfsd, slp, td, mrq)
2487 	struct nfsrv_descript *nfsd;
2488 	struct nfssvc_sock *slp;
2489 	struct thread *td;
2490 	struct mbuf **mrq;
2491 {
2492 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2493 	struct sockaddr *nam = nfsd->nd_nam;
2494 	caddr_t dpos = nfsd->nd_dpos;
2495 	struct ucred *cred = &nfsd->nd_cr;
2496 	struct vattr va, dirfor, diraft;
2497 	struct nameidata nd;
2498 	struct vattr *vap = &va;
2499 	u_int32_t *tl;
2500 	int32_t t1;
2501 	struct nfsv2_sattr *sp;
2502 	char *bpos, *pathcp = (char *)0, *cp2;
2503 	struct uio io;
2504 	struct iovec iv;
2505 	int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1;
2506 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2507 	struct mbuf *mb, *mreq, *mb2;
2508 	struct vnode *dirp = (struct vnode *)0;
2509 	nfsfh_t nfh;
2510 	fhandle_t *fhp;
2511 	u_quad_t frev;
2512 
2513 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2514 	ndclear(&nd);
2515 
2516 	fhp = &nfh.fh_generic;
2517 	nfsm_srvmtofh(fhp);
2518 	nfsm_srvnamesiz(len);
2519 	nd.ni_cnd.cn_cred = cred;
2520 	nd.ni_cnd.cn_nameiop = NAMEI_CREATE;
2521 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_SAVESTART;
2522 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2523 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2524 	if (dirp) {
2525 		if (v3) {
2526 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
2527 		} else {
2528 			vrele(dirp);
2529 			dirp = NULL;
2530 		}
2531 	}
2532 	if (error)
2533 		goto out;
2534 
2535 	VATTR_NULL(vap);
2536 	if (v3)
2537 		nfsm_srvsattr(vap);
2538 	nfsm_strsiz(len2, NFS_MAXPATHLEN);
2539 	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2540 	iv.iov_base = pathcp;
2541 	iv.iov_len = len2;
2542 	io.uio_resid = len2;
2543 	io.uio_offset = 0;
2544 	io.uio_iov = &iv;
2545 	io.uio_iovcnt = 1;
2546 	io.uio_segflg = UIO_SYSSPACE;
2547 	io.uio_rw = UIO_READ;
2548 	io.uio_td = NULL;
2549 	nfsm_mtouio(&io, len2);
2550 	if (!v3) {
2551 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2552 		vap->va_mode = nfstov_mode(sp->sa_mode);
2553 	}
2554 	*(pathcp + len2) = '\0';
2555 	if (nd.ni_vp) {
2556 		error = EEXIST;
2557 		goto out;
2558 	}
2559 
2560 	/*
2561 	 * issue symlink op.  SAVESTART is set so the underlying path component
2562 	 * is only freed by the VOP if an error occurs.
2563 	 */
2564 	if (vap->va_mode == (mode_t)VNOVAL)
2565 		vap->va_mode = 0;
2566 	nqsrv_getl(nd.ni_dvp, ND_WRITE);
2567 	error = VOP_SYMLINK(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2568 	if (error)
2569 		NDFREE(&nd, NDF_ONLY_PNBUF);
2570 	else
2571 		vput(nd.ni_vp);
2572 	nd.ni_vp = NULL;
2573 	/*
2574 	 * releases directory prior to potential lookup op.
2575 	 */
2576 	vput(nd.ni_dvp);
2577 	nd.ni_dvp = NULL;
2578 
2579 	if (error == 0) {
2580 	    if (v3) {
2581 		/*
2582 		 * Issue lookup.  Leave SAVESTART set so we can easily free
2583 		 * the name buffer later on.
2584 		 *
2585 		 * since LOCKPARENT is not set, ni_dvp will be garbage on
2586 		 * return whether an error occurs or not.
2587 		 */
2588 		nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
2589 		nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT | CNP_FOLLOW);
2590 		nd.ni_cnd.cn_flags |= CNP_LOCKLEAF;
2591 		nd.ni_cnd.cn_td = td;
2592 		nd.ni_cnd.cn_cred = cred;
2593 
2594 		error = lookup(&nd);
2595 		nd.ni_dvp = NULL;
2596 
2597 		if (error == 0) {
2598 			bzero((caddr_t)fhp, sizeof(nfh));
2599 			fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2600 			error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2601 			if (!error)
2602 				error = VOP_GETATTR(nd.ni_vp, vap, td);
2603 			vput(nd.ni_vp);
2604 			nd.ni_vp = NULL;
2605 		}
2606 	    }
2607 	}
2608 out:
2609 	/*
2610 	 * These releases aren't strictly required, does even doing them
2611 	 * make any sense? XXX can nfsm_reply() block?
2612 	 */
2613 	if (pathcp) {
2614 		FREE(pathcp, M_TEMP);
2615 		pathcp = NULL;
2616 	}
2617 	if (dirp) {
2618 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2619 		vrele(dirp);
2620 		dirp = NULL;
2621 	}
2622 	if (nd.ni_startdir) {
2623 		vrele(nd.ni_startdir);
2624 		nd.ni_startdir = NULL;
2625 	}
2626 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2627 	if (v3) {
2628 		if (!error) {
2629 			nfsm_srvpostop_fh(fhp);
2630 			nfsm_srvpostop_attr(0, vap);
2631 		}
2632 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2633 	}
2634 	error = 0;
2635 	/* fall through */
2636 
2637 nfsmout:
2638 	NDFREE(&nd, NDF_ONLY_PNBUF);
2639 	if (nd.ni_dvp) {
2640 		if (nd.ni_dvp == nd.ni_vp)
2641 			vrele(nd.ni_dvp);
2642 		else
2643 			vput(nd.ni_dvp);
2644 	}
2645 	if (nd.ni_vp)
2646 		vrele(nd.ni_vp);
2647 	if (nd.ni_startdir)
2648 		vrele(nd.ni_startdir);
2649 	if (dirp)
2650 		vrele(dirp);
2651 	if (pathcp)
2652 		FREE(pathcp, M_TEMP);
2653 
2654 	return (error);
2655 }
2656 
2657 /*
2658  * nfs mkdir service
2659  */
2660 int
2661 nfsrv_mkdir(nfsd, slp, td, mrq)
2662 	struct nfsrv_descript *nfsd;
2663 	struct nfssvc_sock *slp;
2664 	struct thread *td;
2665 	struct mbuf **mrq;
2666 {
2667 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2668 	struct sockaddr *nam = nfsd->nd_nam;
2669 	caddr_t dpos = nfsd->nd_dpos;
2670 	struct ucred *cred = &nfsd->nd_cr;
2671 	struct vattr va, dirfor, diraft;
2672 	struct vattr *vap = &va;
2673 	struct nfs_fattr *fp;
2674 	struct nameidata nd;
2675 	caddr_t cp;
2676 	u_int32_t *tl;
2677 	int32_t t1;
2678 	caddr_t bpos;
2679 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2680 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2681 	char *cp2;
2682 	struct mbuf *mb, *mb2, *mreq;
2683 	struct vnode *dirp = NULL;
2684 	int vpexcl = 0;
2685 	nfsfh_t nfh;
2686 	fhandle_t *fhp;
2687 	u_quad_t frev;
2688 
2689 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2690 	ndclear(&nd);
2691 
2692 	fhp = &nfh.fh_generic;
2693 	nfsm_srvmtofh(fhp);
2694 	nfsm_srvnamesiz(len);
2695 	nd.ni_cnd.cn_cred = cred;
2696 	nd.ni_cnd.cn_nameiop = NAMEI_CREATE;
2697 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT;
2698 
2699 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2700 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2701 	if (dirp) {
2702 		if (v3) {
2703 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
2704 		} else {
2705 			vrele(dirp);
2706 			dirp = NULL;
2707 		}
2708 	}
2709 	if (error) {
2710 		nfsm_reply(NFSX_WCCDATA(v3));
2711 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2712 		error = 0;
2713 		goto nfsmout;
2714 	}
2715 	VATTR_NULL(vap);
2716 	if (v3) {
2717 		nfsm_srvsattr(vap);
2718 	} else {
2719 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2720 		vap->va_mode = nfstov_mode(*tl++);
2721 	}
2722 
2723 	/*
2724 	 * At this point nd.ni_dvp is referenced and exclusively locked and
2725 	 * nd.ni_vp, if it exists, is referenced but not locked.
2726 	 */
2727 
2728 	vap->va_type = VDIR;
2729 	if (nd.ni_vp != NULL) {
2730 		NDFREE(&nd, NDF_ONLY_PNBUF);
2731 		error = EEXIST;
2732 		goto out;
2733 	}
2734 
2735 	/*
2736 	 * Issue mkdir op.  Since SAVESTART is not set, the pathname
2737 	 * component is freed by the VOP call.  This will fill-in
2738 	 * nd.ni_vp, reference, and exclusively lock it.
2739 	 */
2740 	if (vap->va_mode == (mode_t)VNOVAL)
2741 		vap->va_mode = 0;
2742 	nqsrv_getl(nd.ni_dvp, ND_WRITE);
2743 	error = VOP_MKDIR(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, vap);
2744 	NDFREE(&nd, NDF_ONLY_PNBUF);
2745 	vpexcl = 1;
2746 
2747 	vput(nd.ni_dvp);
2748 	nd.ni_dvp = NULL;
2749 
2750 	if (!error) {
2751 		bzero((caddr_t)fhp, sizeof(nfh));
2752 		fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2753 		error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2754 		if (!error)
2755 			error = VOP_GETATTR(nd.ni_vp, vap, td);
2756 	}
2757 out:
2758 	if (dirp)
2759 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2760 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2761 	if (v3) {
2762 		if (!error) {
2763 			nfsm_srvpostop_fh(fhp);
2764 			nfsm_srvpostop_attr(0, vap);
2765 		}
2766 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2767 	} else {
2768 		nfsm_srvfhtom(fhp, v3);
2769 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
2770 		nfsm_srvfillattr(vap, fp);
2771 	}
2772 	error = 0;
2773 	/* fall through */
2774 
2775 nfsmout:
2776 	if (dirp)
2777 		vrele(dirp);
2778 	if (nd.ni_dvp) {
2779 		NDFREE(&nd, NDF_ONLY_PNBUF);
2780 		if (nd.ni_dvp == nd.ni_vp && vpexcl)
2781 			vrele(nd.ni_dvp);
2782 		else
2783 			vput(nd.ni_dvp);
2784 	}
2785 	if (nd.ni_vp) {
2786 		if (vpexcl)
2787 			vput(nd.ni_vp);
2788 		else
2789 			vrele(nd.ni_vp);
2790 	}
2791 	return (error);
2792 }
2793 
2794 /*
2795  * nfs rmdir service
2796  */
2797 int
2798 nfsrv_rmdir(nfsd, slp, td, mrq)
2799 	struct nfsrv_descript *nfsd;
2800 	struct nfssvc_sock *slp;
2801 	struct thread *td;
2802 	struct mbuf **mrq;
2803 {
2804 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2805 	struct sockaddr *nam = nfsd->nd_nam;
2806 	caddr_t dpos = nfsd->nd_dpos;
2807 	struct ucred *cred = &nfsd->nd_cr;
2808 	u_int32_t *tl;
2809 	int32_t t1;
2810 	caddr_t bpos;
2811 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2812 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2813 	char *cp2;
2814 	struct mbuf *mb, *mreq;
2815 	struct vnode *vp, *dirp = (struct vnode *)0;
2816 	struct vattr dirfor, diraft;
2817 	nfsfh_t nfh;
2818 	fhandle_t *fhp;
2819 	struct nameidata nd;
2820 	u_quad_t frev;
2821 
2822 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2823 	ndclear(&nd);
2824 
2825 	fhp = &nfh.fh_generic;
2826 	nfsm_srvmtofh(fhp);
2827 	nfsm_srvnamesiz(len);
2828 	nd.ni_cnd.cn_cred = cred;
2829 	nd.ni_cnd.cn_nameiop = NAMEI_DELETE;
2830 	nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF;
2831 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2832 		&dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2833 	if (dirp) {
2834 		if (v3) {
2835 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, td);
2836 		} else {
2837 			vrele(dirp);
2838 			dirp = NULL;
2839 		}
2840 	}
2841 	if (error) {
2842 		nfsm_reply(NFSX_WCCDATA(v3));
2843 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2844 		error = 0;
2845 		goto nfsmout;
2846 	}
2847 	vp = nd.ni_vp;
2848 	if (vp->v_type != VDIR) {
2849 		error = ENOTDIR;
2850 		goto out;
2851 	}
2852 	/*
2853 	 * No rmdir "." please.
2854 	 */
2855 	if (nd.ni_dvp == vp) {
2856 		error = EINVAL;
2857 		goto out;
2858 	}
2859 	/*
2860 	 * The root of a mounted filesystem cannot be deleted.
2861 	 */
2862 	if (vp->v_flag & VROOT)
2863 		error = EBUSY;
2864 out:
2865 	/*
2866 	 * Issue or abort op.  Since SAVESTART is not set, path name
2867 	 * component is freed by the VOP after either.
2868 	 */
2869 	if (!error) {
2870 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
2871 		nqsrv_getl(vp, ND_WRITE);
2872 		error = VOP_RMDIR(nd.ni_dvp, NCPNULL, nd.ni_vp, &nd.ni_cnd);
2873 	}
2874 	NDFREE(&nd, NDF_ONLY_PNBUF);
2875 
2876 	if (dirp)
2877 		diraft_ret = VOP_GETATTR(dirp, &diraft, td);
2878 	nfsm_reply(NFSX_WCCDATA(v3));
2879 	if (v3) {
2880 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2881 		error = 0;
2882 	}
2883 	/* fall through */
2884 
2885 nfsmout:
2886 	NDFREE(&nd, NDF_ONLY_PNBUF);
2887 	if (dirp)
2888 		vrele(dirp);
2889 	if (nd.ni_dvp) {
2890 		if (nd.ni_dvp == nd.ni_vp)
2891 			vrele(nd.ni_dvp);
2892 		else
2893 			vput(nd.ni_dvp);
2894 	}
2895 	if (nd.ni_vp)
2896 		vput(nd.ni_vp);
2897 
2898 	return(error);
2899 }
2900 
2901 /*
2902  * nfs readdir service
2903  * - mallocs what it thinks is enough to read
2904  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2905  * - calls VOP_READDIR()
2906  * - loops around building the reply
2907  *	if the output generated exceeds count break out of loop
2908  *	The nfsm_clget macro is used here so that the reply will be packed
2909  *	tightly in mbuf clusters.
2910  * - it only knows that it has encountered eof when the VOP_READDIR()
2911  *	reads nothing
2912  * - as such one readdir rpc will return eof false although you are there
2913  *	and then the next will return eof
2914  * - it trims out records with d_fileno == 0
2915  *	this doesn't matter for Unix clients, but they might confuse clients
2916  *	for other os'.
2917  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2918  *	than requested, but this may not apply to all filesystems. For
2919  *	example, client NFS does not { although it is never remote mounted
2920  *	anyhow }
2921  *     The alternate call nfsrv_readdirplus() does lookups as well.
2922  * PS: The NFS protocol spec. does not clarify what the "count" byte
2923  *	argument is a count of.. just name strings and file id's or the
2924  *	entire reply rpc or ...
2925  *	I tried just file name and id sizes and it confused the Sun client,
2926  *	so I am using the full rpc size now. The "paranoia.." comment refers
2927  *	to including the status longwords that are not a part of the dir.
2928  *	"entry" structures, but are in the rpc.
2929  */
2930 struct flrep {
2931 	nfsuint64	fl_off;
2932 	u_int32_t	fl_postopok;
2933 	u_int32_t	fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2934 	u_int32_t	fl_fhok;
2935 	u_int32_t	fl_fhsize;
2936 	u_int32_t	fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2937 };
2938 
2939 int
2940 nfsrv_readdir(nfsd, slp, td, mrq)
2941 	struct nfsrv_descript *nfsd;
2942 	struct nfssvc_sock *slp;
2943 	struct thread *td;
2944 	struct mbuf **mrq;
2945 {
2946 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2947 	struct sockaddr *nam = nfsd->nd_nam;
2948 	caddr_t dpos = nfsd->nd_dpos;
2949 	struct ucred *cred = &nfsd->nd_cr;
2950 	char *bp, *be;
2951 	struct mbuf *mp;
2952 	struct dirent *dp;
2953 	caddr_t cp;
2954 	u_int32_t *tl;
2955 	int32_t t1;
2956 	caddr_t bpos;
2957 	struct mbuf *mb, *mb2, *mreq, *mp2;
2958 	char *cpos, *cend, *cp2, *rbuf;
2959 	struct vnode *vp = NULL;
2960 	struct vattr at;
2961 	nfsfh_t nfh;
2962 	fhandle_t *fhp;
2963 	struct uio io;
2964 	struct iovec iv;
2965 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2966 	int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
2967 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2968 	u_quad_t frev, off, toff, verf;
2969 	u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
2970 
2971 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2972 	fhp = &nfh.fh_generic;
2973 	nfsm_srvmtofh(fhp);
2974 	if (v3) {
2975 		nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2976 		toff = fxdr_hyper(tl);
2977 		tl += 2;
2978 		verf = fxdr_hyper(tl);
2979 		tl += 2;
2980 	} else {
2981 		nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2982 		toff = fxdr_unsigned(u_quad_t, *tl++);
2983 		verf = 0;	/* shut up gcc */
2984 	}
2985 	off = toff;
2986 	cnt = fxdr_unsigned(int, *tl);
2987 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2988 	xfer = NFS_SRVMAXDATA(nfsd);
2989 	if (cnt > xfer)
2990 		cnt = xfer;
2991 	if (siz > xfer)
2992 		siz = xfer;
2993 	fullsiz = siz;
2994 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2995 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2996 	if (!error && vp->v_type != VDIR) {
2997 		error = ENOTDIR;
2998 		vput(vp);
2999 		vp = NULL;
3000 	}
3001 	if (error) {
3002 		nfsm_reply(NFSX_UNSIGNED);
3003 		nfsm_srvpostop_attr(getret, &at);
3004 		error = 0;
3005 		goto nfsmout;
3006 	}
3007 
3008 	/*
3009 	 * Obtain lock on vnode for this section of the code
3010 	 */
3011 
3012 	nqsrv_getl(vp, ND_READ);
3013 	if (v3) {
3014 		error = getret = VOP_GETATTR(vp, &at, td);
3015 #if 0
3016 		/*
3017 		 * XXX This check may be too strict for Solaris 2.5 clients.
3018 		 */
3019 		if (!error && toff && verf && verf != at.va_filerev)
3020 			error = NFSERR_BAD_COOKIE;
3021 #endif
3022 	}
3023 	if (!error)
3024 		error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
3025 	if (error) {
3026 		vput(vp);
3027 		vp = NULL;
3028 		nfsm_reply(NFSX_POSTOPATTR(v3));
3029 		nfsm_srvpostop_attr(getret, &at);
3030 		error = 0;
3031 		goto nfsmout;
3032 	}
3033 	VOP_UNLOCK(vp, NULL, 0, td);
3034 
3035 	/*
3036 	 * end section.  Allocate rbuf and continue
3037 	 */
3038 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3039 again:
3040 	iv.iov_base = rbuf;
3041 	iv.iov_len = fullsiz;
3042 	io.uio_iov = &iv;
3043 	io.uio_iovcnt = 1;
3044 	io.uio_offset = (off_t)off;
3045 	io.uio_resid = fullsiz;
3046 	io.uio_segflg = UIO_SYSSPACE;
3047 	io.uio_rw = UIO_READ;
3048 	io.uio_td = NULL;
3049 	eofflag = 0;
3050 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
3051 	if (cookies) {
3052 		free((caddr_t)cookies, M_TEMP);
3053 		cookies = NULL;
3054 	}
3055 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3056 	off = (off_t)io.uio_offset;
3057 	if (!cookies && !error)
3058 		error = NFSERR_PERM;
3059 	if (v3) {
3060 		getret = VOP_GETATTR(vp, &at, td);
3061 		if (!error)
3062 			error = getret;
3063 	}
3064 	VOP_UNLOCK(vp, NULL, 0, td);
3065 	if (error) {
3066 		vrele(vp);
3067 		vp = NULL;
3068 		free((caddr_t)rbuf, M_TEMP);
3069 		if (cookies)
3070 			free((caddr_t)cookies, M_TEMP);
3071 		nfsm_reply(NFSX_POSTOPATTR(v3));
3072 		nfsm_srvpostop_attr(getret, &at);
3073 		error = 0;
3074 		goto nfsmout;
3075 	}
3076 	if (io.uio_resid) {
3077 		siz -= io.uio_resid;
3078 
3079 		/*
3080 		 * If nothing read, return eof
3081 		 * rpc reply
3082 		 */
3083 		if (siz == 0) {
3084 			vrele(vp);
3085 			vp = NULL;
3086 			nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
3087 				2 * NFSX_UNSIGNED);
3088 			if (v3) {
3089 				nfsm_srvpostop_attr(getret, &at);
3090 				nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
3091 				txdr_hyper(at.va_filerev, tl);
3092 				tl += 2;
3093 			} else
3094 				nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3095 			*tl++ = nfs_false;
3096 			*tl = nfs_true;
3097 			FREE((caddr_t)rbuf, M_TEMP);
3098 			FREE((caddr_t)cookies, M_TEMP);
3099 			error = 0;
3100 			goto nfsmout;
3101 		}
3102 	}
3103 
3104 	/*
3105 	 * Check for degenerate cases of nothing useful read.
3106 	 * If so go try again
3107 	 */
3108 	cpos = rbuf;
3109 	cend = rbuf + siz;
3110 	dp = (struct dirent *)cpos;
3111 	cookiep = cookies;
3112 	/*
3113 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
3114 	 * directory offset up to a block boundary, so it is necessary to
3115 	 * skip over the records that preceed the requested offset. This
3116 	 * requires the assumption that file offset cookies monotonically
3117 	 * increase.
3118 	 */
3119 	while (cpos < cend && ncookies > 0 &&
3120 		(dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3121 		 ((u_quad_t)(*cookiep)) <= toff)) {
3122 		cpos += dp->d_reclen;
3123 		dp = (struct dirent *)cpos;
3124 		cookiep++;
3125 		ncookies--;
3126 	}
3127 	if (cpos >= cend || ncookies == 0) {
3128 		toff = off;
3129 		siz = fullsiz;
3130 		goto again;
3131 	}
3132 
3133 	len = 3 * NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
3134 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
3135 	if (v3) {
3136 		nfsm_srvpostop_attr(getret, &at);
3137 		nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3138 		txdr_hyper(at.va_filerev, tl);
3139 	}
3140 	mp = mp2 = mb;
3141 	bp = bpos;
3142 	be = bp + M_TRAILINGSPACE(mp);
3143 
3144 	/* Loop through the records and build reply */
3145 	while (cpos < cend && ncookies > 0) {
3146 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3147 			nlen = dp->d_namlen;
3148 			rem = nfsm_rndup(nlen) - nlen;
3149 			len += (4 * NFSX_UNSIGNED + nlen + rem);
3150 			if (v3)
3151 				len += 2 * NFSX_UNSIGNED;
3152 			if (len > cnt) {
3153 				eofflag = 0;
3154 				break;
3155 			}
3156 			/*
3157 			 * Build the directory record xdr from
3158 			 * the dirent entry.
3159 			 */
3160 			nfsm_clget;
3161 			*tl = nfs_true;
3162 			bp += NFSX_UNSIGNED;
3163 			if (v3) {
3164 				nfsm_clget;
3165 				*tl = 0;
3166 				bp += NFSX_UNSIGNED;
3167 			}
3168 			nfsm_clget;
3169 			*tl = txdr_unsigned(dp->d_fileno);
3170 			bp += NFSX_UNSIGNED;
3171 			nfsm_clget;
3172 			*tl = txdr_unsigned(nlen);
3173 			bp += NFSX_UNSIGNED;
3174 
3175 			/* And loop around copying the name */
3176 			xfer = nlen;
3177 			cp = dp->d_name;
3178 			while (xfer > 0) {
3179 				nfsm_clget;
3180 				if ((bp+xfer) > be)
3181 					tsiz = be-bp;
3182 				else
3183 					tsiz = xfer;
3184 				bcopy(cp, bp, tsiz);
3185 				bp += tsiz;
3186 				xfer -= tsiz;
3187 				if (xfer > 0)
3188 					cp += tsiz;
3189 			}
3190 			/* And null pad to a int32_t boundary */
3191 			for (i = 0; i < rem; i++)
3192 				*bp++ = '\0';
3193 			nfsm_clget;
3194 
3195 			/* Finish off the record */
3196 			if (v3) {
3197 				*tl = 0;
3198 				bp += NFSX_UNSIGNED;
3199 				nfsm_clget;
3200 			}
3201 			*tl = txdr_unsigned(*cookiep);
3202 			bp += NFSX_UNSIGNED;
3203 		}
3204 		cpos += dp->d_reclen;
3205 		dp = (struct dirent *)cpos;
3206 		cookiep++;
3207 		ncookies--;
3208 	}
3209 	vrele(vp);
3210 	vp = NULL;
3211 	nfsm_clget;
3212 	*tl = nfs_false;
3213 	bp += NFSX_UNSIGNED;
3214 	nfsm_clget;
3215 	if (eofflag)
3216 		*tl = nfs_true;
3217 	else
3218 		*tl = nfs_false;
3219 	bp += NFSX_UNSIGNED;
3220 	if (mp != mb) {
3221 		if (bp < be)
3222 			mp->m_len = bp - mtod(mp, caddr_t);
3223 	} else
3224 		mp->m_len += bp - bpos;
3225 	FREE((caddr_t)rbuf, M_TEMP);
3226 	FREE((caddr_t)cookies, M_TEMP);
3227 
3228 nfsmout:
3229 	if (vp)
3230 		vrele(vp);
3231 	return(error);
3232 }
3233 
3234 int
3235 nfsrv_readdirplus(nfsd, slp, td, mrq)
3236 	struct nfsrv_descript *nfsd;
3237 	struct nfssvc_sock *slp;
3238 	struct thread *td;
3239 	struct mbuf **mrq;
3240 {
3241 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3242 	struct sockaddr *nam = nfsd->nd_nam;
3243 	caddr_t dpos = nfsd->nd_dpos;
3244 	struct ucred *cred = &nfsd->nd_cr;
3245 	char *bp, *be;
3246 	struct mbuf *mp;
3247 	struct dirent *dp;
3248 	caddr_t cp;
3249 	u_int32_t *tl;
3250 	int32_t t1;
3251 	caddr_t bpos;
3252 	struct mbuf *mb, *mb2, *mreq, *mp2;
3253 	char *cpos, *cend, *cp2, *rbuf;
3254 	struct vnode *vp = NULL, *nvp;
3255 	struct flrep fl;
3256 	nfsfh_t nfh;
3257 	fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3258 	struct uio io;
3259 	struct iovec iv;
3260 	struct vattr va, at, *vap = &va;
3261 	struct nfs_fattr *fp;
3262 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3263 	int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
3264 	u_quad_t frev, off, toff, verf;
3265 	u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3266 
3267 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3268 	fhp = &nfh.fh_generic;
3269 	nfsm_srvmtofh(fhp);
3270 	nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
3271 	toff = fxdr_hyper(tl);
3272 	tl += 2;
3273 	verf = fxdr_hyper(tl);
3274 	tl += 2;
3275 	siz = fxdr_unsigned(int, *tl++);
3276 	cnt = fxdr_unsigned(int, *tl);
3277 	off = toff;
3278 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3279 	xfer = NFS_SRVMAXDATA(nfsd);
3280 	if (cnt > xfer)
3281 		cnt = xfer;
3282 	if (siz > xfer)
3283 		siz = xfer;
3284 	fullsiz = siz;
3285 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3286 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3287 	if (!error && vp->v_type != VDIR) {
3288 		error = ENOTDIR;
3289 		vput(vp);
3290 		vp = NULL;
3291 	}
3292 	if (error) {
3293 		nfsm_reply(NFSX_UNSIGNED);
3294 		nfsm_srvpostop_attr(getret, &at);
3295 		error = 0;
3296 		goto nfsmout;
3297 	}
3298 	error = getret = VOP_GETATTR(vp, &at, td);
3299 #if 0
3300 	/*
3301 	 * XXX This check may be too strict for Solaris 2.5 clients.
3302 	 */
3303 	if (!error && toff && verf && verf != at.va_filerev)
3304 		error = NFSERR_BAD_COOKIE;
3305 #endif
3306 	if (!error) {
3307 		nqsrv_getl(vp, ND_READ);
3308 		error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
3309 	}
3310 	if (error) {
3311 		vput(vp);
3312 		vp = NULL;
3313 		nfsm_reply(NFSX_V3POSTOPATTR);
3314 		nfsm_srvpostop_attr(getret, &at);
3315 		error = 0;
3316 		goto nfsmout;
3317 	}
3318 	VOP_UNLOCK(vp, NULL, 0, td);
3319 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3320 again:
3321 	iv.iov_base = rbuf;
3322 	iv.iov_len = fullsiz;
3323 	io.uio_iov = &iv;
3324 	io.uio_iovcnt = 1;
3325 	io.uio_offset = (off_t)off;
3326 	io.uio_resid = fullsiz;
3327 	io.uio_segflg = UIO_SYSSPACE;
3328 	io.uio_rw = UIO_READ;
3329 	io.uio_td = NULL;
3330 	eofflag = 0;
3331 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
3332 	if (cookies) {
3333 		free((caddr_t)cookies, M_TEMP);
3334 		cookies = NULL;
3335 	}
3336 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3337 	off = (u_quad_t)io.uio_offset;
3338 	getret = VOP_GETATTR(vp, &at, td);
3339 	VOP_UNLOCK(vp, NULL, 0, td);
3340 	if (!cookies && !error)
3341 		error = NFSERR_PERM;
3342 	if (!error)
3343 		error = getret;
3344 	if (error) {
3345 		vrele(vp);
3346 		vp = NULL;
3347 		if (cookies)
3348 			free((caddr_t)cookies, M_TEMP);
3349 		free((caddr_t)rbuf, M_TEMP);
3350 		nfsm_reply(NFSX_V3POSTOPATTR);
3351 		nfsm_srvpostop_attr(getret, &at);
3352 		error = 0;
3353 		goto nfsmout;
3354 	}
3355 	if (io.uio_resid) {
3356 		siz -= io.uio_resid;
3357 
3358 		/*
3359 		 * If nothing read, return eof
3360 		 * rpc reply
3361 		 */
3362 		if (siz == 0) {
3363 			vrele(vp);
3364 			vp = NULL;
3365 			nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3366 				2 * NFSX_UNSIGNED);
3367 			nfsm_srvpostop_attr(getret, &at);
3368 			nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
3369 			txdr_hyper(at.va_filerev, tl);
3370 			tl += 2;
3371 			*tl++ = nfs_false;
3372 			*tl = nfs_true;
3373 			FREE((caddr_t)cookies, M_TEMP);
3374 			FREE((caddr_t)rbuf, M_TEMP);
3375 			error = 0;
3376 			goto nfsmout;
3377 		}
3378 	}
3379 
3380 	/*
3381 	 * Check for degenerate cases of nothing useful read.
3382 	 * If so go try again
3383 	 */
3384 	cpos = rbuf;
3385 	cend = rbuf + siz;
3386 	dp = (struct dirent *)cpos;
3387 	cookiep = cookies;
3388 	/*
3389 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
3390 	 * directory offset up to a block boundary, so it is necessary to
3391 	 * skip over the records that preceed the requested offset. This
3392 	 * requires the assumption that file offset cookies monotonically
3393 	 * increase.
3394 	 */
3395 	while (cpos < cend && ncookies > 0 &&
3396 		(dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3397 		 ((u_quad_t)(*cookiep)) <= toff)) {
3398 		cpos += dp->d_reclen;
3399 		dp = (struct dirent *)cpos;
3400 		cookiep++;
3401 		ncookies--;
3402 	}
3403 	if (cpos >= cend || ncookies == 0) {
3404 		toff = off;
3405 		siz = fullsiz;
3406 		goto again;
3407 	}
3408 
3409 	/*
3410 	 * Probe one of the directory entries to see if the filesystem
3411 	 * supports VGET.
3412 	 */
3413 	if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) {
3414 		error = NFSERR_NOTSUPP;
3415 		vrele(vp);
3416 		vp = NULL;
3417 		free((caddr_t)cookies, M_TEMP);
3418 		free((caddr_t)rbuf, M_TEMP);
3419 		nfsm_reply(NFSX_V3POSTOPATTR);
3420 		nfsm_srvpostop_attr(getret, &at);
3421 		error = 0;
3422 		goto nfsmout;
3423 	}
3424 	vput(nvp);
3425 	nvp = NULL;
3426 
3427 	dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
3428 	nfsm_reply(cnt);
3429 	nfsm_srvpostop_attr(getret, &at);
3430 	nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3431 	txdr_hyper(at.va_filerev, tl);
3432 	mp = mp2 = mb;
3433 	bp = bpos;
3434 	be = bp + M_TRAILINGSPACE(mp);
3435 
3436 	/* Loop through the records and build reply */
3437 	while (cpos < cend && ncookies > 0) {
3438 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3439 			nlen = dp->d_namlen;
3440 			rem = nfsm_rndup(nlen)-nlen;
3441 
3442 			/*
3443 			 * For readdir_and_lookup get the vnode using
3444 			 * the file number.
3445 			 */
3446 			if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
3447 				goto invalid;
3448 			bzero((caddr_t)nfhp, NFSX_V3FH);
3449 			nfhp->fh_fsid =
3450 				nvp->v_mount->mnt_stat.f_fsid;
3451 			if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3452 				vput(nvp);
3453 				nvp = NULL;
3454 				goto invalid;
3455 			}
3456 			if (VOP_GETATTR(nvp, vap, td)) {
3457 				vput(nvp);
3458 				nvp = NULL;
3459 				goto invalid;
3460 			}
3461 			vput(nvp);
3462 			nvp = NULL;
3463 
3464 			/*
3465 			 * If either the dircount or maxcount will be
3466 			 * exceeded, get out now. Both of these lengths
3467 			 * are calculated conservatively, including all
3468 			 * XDR overheads.
3469 			 */
3470 			len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3471 				NFSX_V3POSTOPATTR);
3472 			dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3473 			if (len > cnt || dirlen > fullsiz) {
3474 				eofflag = 0;
3475 				break;
3476 			}
3477 
3478 			/*
3479 			 * Build the directory record xdr from
3480 			 * the dirent entry.
3481 			 */
3482 			fp = (struct nfs_fattr *)&fl.fl_fattr;
3483 			nfsm_srvfillattr(vap, fp);
3484 			fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3485 			fl.fl_fhok = nfs_true;
3486 			fl.fl_postopok = nfs_true;
3487 			fl.fl_off.nfsuquad[0] = 0;
3488 			fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3489 
3490 			nfsm_clget;
3491 			*tl = nfs_true;
3492 			bp += NFSX_UNSIGNED;
3493 			nfsm_clget;
3494 			*tl = 0;
3495 			bp += NFSX_UNSIGNED;
3496 			nfsm_clget;
3497 			*tl = txdr_unsigned(dp->d_fileno);
3498 			bp += NFSX_UNSIGNED;
3499 			nfsm_clget;
3500 			*tl = txdr_unsigned(nlen);
3501 			bp += NFSX_UNSIGNED;
3502 
3503 			/* And loop around copying the name */
3504 			xfer = nlen;
3505 			cp = dp->d_name;
3506 			while (xfer > 0) {
3507 				nfsm_clget;
3508 				if ((bp + xfer) > be)
3509 					tsiz = be - bp;
3510 				else
3511 					tsiz = xfer;
3512 				bcopy(cp, bp, tsiz);
3513 				bp += tsiz;
3514 				xfer -= tsiz;
3515 				if (xfer > 0)
3516 					cp += tsiz;
3517 			}
3518 			/* And null pad to a int32_t boundary */
3519 			for (i = 0; i < rem; i++)
3520 				*bp++ = '\0';
3521 
3522 			/*
3523 			 * Now copy the flrep structure out.
3524 			 */
3525 			xfer = sizeof (struct flrep);
3526 			cp = (caddr_t)&fl;
3527 			while (xfer > 0) {
3528 				nfsm_clget;
3529 				if ((bp + xfer) > be)
3530 					tsiz = be - bp;
3531 				else
3532 					tsiz = xfer;
3533 				bcopy(cp, bp, tsiz);
3534 				bp += tsiz;
3535 				xfer -= tsiz;
3536 				if (xfer > 0)
3537 					cp += tsiz;
3538 			}
3539 		}
3540 invalid:
3541 		cpos += dp->d_reclen;
3542 		dp = (struct dirent *)cpos;
3543 		cookiep++;
3544 		ncookies--;
3545 	}
3546 	vrele(vp);
3547 	vp = NULL;
3548 	nfsm_clget;
3549 	*tl = nfs_false;
3550 	bp += NFSX_UNSIGNED;
3551 	nfsm_clget;
3552 	if (eofflag)
3553 		*tl = nfs_true;
3554 	else
3555 		*tl = nfs_false;
3556 	bp += NFSX_UNSIGNED;
3557 	if (mp != mb) {
3558 		if (bp < be)
3559 			mp->m_len = bp - mtod(mp, caddr_t);
3560 	} else
3561 		mp->m_len += bp - bpos;
3562 	FREE((caddr_t)cookies, M_TEMP);
3563 	FREE((caddr_t)rbuf, M_TEMP);
3564 nfsmout:
3565 	if (vp)
3566 		vrele(vp);
3567 	return(error);
3568 }
3569 
3570 /*
3571  * nfs commit service
3572  */
3573 int
3574 nfsrv_commit(nfsd, slp, td, mrq)
3575 	struct nfsrv_descript *nfsd;
3576 	struct nfssvc_sock *slp;
3577 	struct thread *td;
3578 	struct mbuf **mrq;
3579 {
3580 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3581 	struct sockaddr *nam = nfsd->nd_nam;
3582 	caddr_t dpos = nfsd->nd_dpos;
3583 	struct ucred *cred = &nfsd->nd_cr;
3584 	struct vattr bfor, aft;
3585 	struct vnode *vp = NULL;
3586 	nfsfh_t nfh;
3587 	fhandle_t *fhp;
3588 	u_int32_t *tl;
3589 	int32_t t1;
3590 	caddr_t bpos;
3591 	int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
3592 	char *cp2;
3593 	struct mbuf *mb, *mb2, *mreq;
3594 	u_quad_t frev, off;
3595 
3596 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3597 #ifndef nolint
3598 	cache = 0;
3599 #endif
3600 	fhp = &nfh.fh_generic;
3601 	nfsm_srvmtofh(fhp);
3602 	nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3603 
3604 	/*
3605 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
3606 	 * count parameters, so these arguments are useless (someday maybe).
3607 	 */
3608 	off = fxdr_hyper(tl);
3609 	tl += 2;
3610 	cnt = fxdr_unsigned(int, *tl);
3611 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3612 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3613 	if (error) {
3614 		nfsm_reply(2 * NFSX_UNSIGNED);
3615 		nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3616 		error = 0;
3617 		goto nfsmout;
3618 	}
3619 	for_ret = VOP_GETATTR(vp, &bfor, td);
3620 
3621 	if (cnt > MAX_COMMIT_COUNT) {
3622 		/*
3623 		 * Give up and do the whole thing
3624 		 */
3625 		if (vp->v_object &&
3626 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3627 			vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3628 		}
3629 		error = VOP_FSYNC(vp, MNT_WAIT, td);
3630 	} else {
3631 		/*
3632 		 * Locate and synchronously write any buffers that fall
3633 		 * into the requested range.  Note:  we are assuming that
3634 		 * f_iosize is a power of 2.
3635 		 */
3636 		int iosize = vp->v_mount->mnt_stat.f_iosize;
3637 		int iomask = iosize - 1;
3638 		int s;
3639 		daddr_t lblkno;
3640 
3641 		/*
3642 		 * Align to iosize boundry, super-align to page boundry.
3643 		 */
3644 		if (off & iomask) {
3645 			cnt += off & iomask;
3646 			off &= ~(u_quad_t)iomask;
3647 		}
3648 		if (off & PAGE_MASK) {
3649 			cnt += off & PAGE_MASK;
3650 			off &= ~(u_quad_t)PAGE_MASK;
3651 		}
3652 		lblkno = off / iosize;
3653 
3654 		if (vp->v_object &&
3655 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3656 			vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
3657 		}
3658 
3659 		s = splbio();
3660 		while (cnt > 0) {
3661 			struct buf *bp;
3662 
3663 			/*
3664 			 * If we have a buffer and it is marked B_DELWRI we
3665 			 * have to lock and write it.  Otherwise the prior
3666 			 * write is assumed to have already been committed.
3667 			 */
3668 			if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) {
3669 				if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
3670 					BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL);
3671 					continue; /* retry */
3672 				}
3673 				bremfree(bp);
3674 				bp->b_flags &= ~B_ASYNC;
3675 				VOP_BWRITE(bp->b_vp, bp);
3676 				++nfs_commit_miss;
3677 			}
3678 			++nfs_commit_blks;
3679 			if (cnt < iosize)
3680 				break;
3681 			cnt -= iosize;
3682 			++lblkno;
3683 		}
3684 		splx(s);
3685 	}
3686 
3687 	aft_ret = VOP_GETATTR(vp, &aft, td);
3688 	vput(vp);
3689 	vp = NULL;
3690 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3691 	nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3692 	if (!error) {
3693 		nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
3694 		if (nfsver.tv_sec == 0)
3695 			nfsver = boottime;
3696 		*tl++ = txdr_unsigned(nfsver.tv_sec);
3697 		*tl = txdr_unsigned(nfsver.tv_nsec / 1000);
3698 	} else {
3699 		error = 0;
3700 	}
3701 nfsmout:
3702 	if (vp)
3703 		vput(vp);
3704 	return(error);
3705 }
3706 
3707 /*
3708  * nfs statfs service
3709  */
3710 int
3711 nfsrv_statfs(nfsd, slp, td, mrq)
3712 	struct nfsrv_descript *nfsd;
3713 	struct nfssvc_sock *slp;
3714 	struct thread *td;
3715 	struct mbuf **mrq;
3716 {
3717 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3718 	struct sockaddr *nam = nfsd->nd_nam;
3719 	caddr_t dpos = nfsd->nd_dpos;
3720 	struct ucred *cred = &nfsd->nd_cr;
3721 	struct statfs *sf;
3722 	struct nfs_statfs *sfp;
3723 	u_int32_t *tl;
3724 	int32_t t1;
3725 	caddr_t bpos;
3726 	int error = 0, rdonly, cache, getret = 1;
3727 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3728 	char *cp2;
3729 	struct mbuf *mb, *mb2, *mreq;
3730 	struct vnode *vp = NULL;
3731 	struct vattr at;
3732 	nfsfh_t nfh;
3733 	fhandle_t *fhp;
3734 	struct statfs statfs;
3735 	u_quad_t frev, tval;
3736 
3737 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3738 #ifndef nolint
3739 	cache = 0;
3740 #endif
3741 	fhp = &nfh.fh_generic;
3742 	nfsm_srvmtofh(fhp);
3743 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3744 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3745 	if (error) {
3746 		nfsm_reply(NFSX_UNSIGNED);
3747 		nfsm_srvpostop_attr(getret, &at);
3748 		error = 0;
3749 		goto nfsmout;
3750 	}
3751 	sf = &statfs;
3752 	error = VFS_STATFS(vp->v_mount, sf, td);
3753 	getret = VOP_GETATTR(vp, &at, td);
3754 	vput(vp);
3755 	vp = NULL;
3756 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3757 	if (v3)
3758 		nfsm_srvpostop_attr(getret, &at);
3759 	if (error) {
3760 		error = 0;
3761 		goto nfsmout;
3762 	}
3763 	nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
3764 	if (v3) {
3765 		tval = (u_quad_t)sf->f_blocks;
3766 		tval *= (u_quad_t)sf->f_bsize;
3767 		txdr_hyper(tval, &sfp->sf_tbytes);
3768 		tval = (u_quad_t)sf->f_bfree;
3769 		tval *= (u_quad_t)sf->f_bsize;
3770 		txdr_hyper(tval, &sfp->sf_fbytes);
3771 		tval = (u_quad_t)sf->f_bavail;
3772 		tval *= (u_quad_t)sf->f_bsize;
3773 		txdr_hyper(tval, &sfp->sf_abytes);
3774 		sfp->sf_tfiles.nfsuquad[0] = 0;
3775 		sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3776 		sfp->sf_ffiles.nfsuquad[0] = 0;
3777 		sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3778 		sfp->sf_afiles.nfsuquad[0] = 0;
3779 		sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3780 		sfp->sf_invarsec = 0;
3781 	} else {
3782 		sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3783 		sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3784 		sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3785 		sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3786 		sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3787 	}
3788 nfsmout:
3789 	if (vp)
3790 		vput(vp);
3791 	return(error);
3792 }
3793 
3794 /*
3795  * nfs fsinfo service
3796  */
3797 int
3798 nfsrv_fsinfo(nfsd, slp, td, mrq)
3799 	struct nfsrv_descript *nfsd;
3800 	struct nfssvc_sock *slp;
3801 	struct thread *td;
3802 	struct mbuf **mrq;
3803 {
3804 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3805 	struct sockaddr *nam = nfsd->nd_nam;
3806 	caddr_t dpos = nfsd->nd_dpos;
3807 	struct ucred *cred = &nfsd->nd_cr;
3808 	u_int32_t *tl;
3809 	struct nfsv3_fsinfo *sip;
3810 	int32_t t1;
3811 	caddr_t bpos;
3812 	int error = 0, rdonly, cache, getret = 1, pref;
3813 	char *cp2;
3814 	struct mbuf *mb, *mb2, *mreq;
3815 	struct vnode *vp = NULL;
3816 	struct vattr at;
3817 	nfsfh_t nfh;
3818 	fhandle_t *fhp;
3819 	u_quad_t frev, maxfsize;
3820 	struct statfs sb;
3821 
3822 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3823 #ifndef nolint
3824 	cache = 0;
3825 #endif
3826 	fhp = &nfh.fh_generic;
3827 	nfsm_srvmtofh(fhp);
3828 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3829 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3830 	if (error) {
3831 		nfsm_reply(NFSX_UNSIGNED);
3832 		nfsm_srvpostop_attr(getret, &at);
3833 		error = 0;
3834 		goto nfsmout;
3835 	}
3836 
3837 	/* XXX Try to make a guess on the max file size. */
3838 	VFS_STATFS(vp->v_mount, &sb, td);
3839 	maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3840 
3841 	getret = VOP_GETATTR(vp, &at, td);
3842 	vput(vp);
3843 	vp = NULL;
3844 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3845 	nfsm_srvpostop_attr(getret, &at);
3846 	nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3847 
3848 	/*
3849 	 * XXX
3850 	 * There should be file system VFS OP(s) to get this information.
3851 	 * For now, assume ufs.
3852 	 */
3853 	if (slp->ns_so->so_type == SOCK_DGRAM)
3854 		pref = NFS_MAXDGRAMDATA;
3855 	else
3856 		pref = NFS_MAXDATA;
3857 	sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
3858 	sip->fs_rtpref = txdr_unsigned(pref);
3859 	sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3860 	sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
3861 	sip->fs_wtpref = txdr_unsigned(pref);
3862 	sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3863 	sip->fs_dtpref = txdr_unsigned(pref);
3864 	txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3865 	sip->fs_timedelta.nfsv3_sec = 0;
3866 	sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3867 	sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3868 		NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3869 		NFSV3FSINFO_CANSETTIME);
3870 nfsmout:
3871 	if (vp)
3872 		vput(vp);
3873 	return(error);
3874 }
3875 
3876 /*
3877  * nfs pathconf service
3878  */
3879 int
3880 nfsrv_pathconf(nfsd, slp, td, mrq)
3881 	struct nfsrv_descript *nfsd;
3882 	struct nfssvc_sock *slp;
3883 	struct thread *td;
3884 	struct mbuf **mrq;
3885 {
3886 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3887 	struct sockaddr *nam = nfsd->nd_nam;
3888 	caddr_t dpos = nfsd->nd_dpos;
3889 	struct ucred *cred = &nfsd->nd_cr;
3890 	u_int32_t *tl;
3891 	struct nfsv3_pathconf *pc;
3892 	int32_t t1;
3893 	caddr_t bpos;
3894 	int error = 0, rdonly, cache, getret = 1;
3895 	register_t linkmax, namemax, chownres, notrunc;
3896 	char *cp2;
3897 	struct mbuf *mb, *mb2, *mreq;
3898 	struct vnode *vp = NULL;
3899 	struct vattr at;
3900 	nfsfh_t nfh;
3901 	fhandle_t *fhp;
3902 	u_quad_t frev;
3903 
3904 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3905 #ifndef nolint
3906 	cache = 0;
3907 #endif
3908 	fhp = &nfh.fh_generic;
3909 	nfsm_srvmtofh(fhp);
3910 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3911 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3912 	if (error) {
3913 		nfsm_reply(NFSX_UNSIGNED);
3914 		nfsm_srvpostop_attr(getret, &at);
3915 		error = 0;
3916 		goto nfsmout;
3917 	}
3918 	error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3919 	if (!error)
3920 		error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3921 	if (!error)
3922 		error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3923 	if (!error)
3924 		error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
3925 	getret = VOP_GETATTR(vp, &at, td);
3926 	vput(vp);
3927 	vp = NULL;
3928 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3929 	nfsm_srvpostop_attr(getret, &at);
3930 	if (error) {
3931 		error = 0;
3932 		goto nfsmout;
3933 	}
3934 	nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3935 
3936 	pc->pc_linkmax = txdr_unsigned(linkmax);
3937 	pc->pc_namemax = txdr_unsigned(namemax);
3938 	pc->pc_notrunc = txdr_unsigned(notrunc);
3939 	pc->pc_chownrestricted = txdr_unsigned(chownres);
3940 
3941 	/*
3942 	 * These should probably be supported by VOP_PATHCONF(), but
3943 	 * until msdosfs is exportable (why would you want to?), the
3944 	 * Unix defaults should be ok.
3945 	 */
3946 	pc->pc_caseinsensitive = nfs_false;
3947 	pc->pc_casepreserving = nfs_true;
3948 nfsmout:
3949 	if (vp)
3950 		vput(vp);
3951 	return(error);
3952 }
3953 
3954 /*
3955  * Null operation, used by clients to ping server
3956  */
3957 /* ARGSUSED */
3958 int
3959 nfsrv_null(nfsd, slp, td, mrq)
3960 	struct nfsrv_descript *nfsd;
3961 	struct nfssvc_sock *slp;
3962 	struct thread *td;
3963 	struct mbuf **mrq;
3964 {
3965 	struct mbuf *mrep = nfsd->nd_mrep;
3966 	caddr_t bpos;
3967 	int error = NFSERR_RETVOID, cache;
3968 	struct mbuf *mb, *mreq;
3969 	u_quad_t frev;
3970 
3971 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3972 #ifndef nolint
3973 	cache = 0;
3974 #endif
3975 	nfsm_reply(0);
3976 	nfsm_srvdone;
3977 }
3978 
3979 /*
3980  * No operation, used for obsolete procedures
3981  */
3982 /* ARGSUSED */
3983 int
3984 nfsrv_noop(nfsd, slp, td, mrq)
3985 	struct nfsrv_descript *nfsd;
3986 	struct nfssvc_sock *slp;
3987 	struct thread *td;
3988 	struct mbuf **mrq;
3989 {
3990 	struct mbuf *mrep = nfsd->nd_mrep;
3991 	caddr_t bpos;
3992 	int error, cache;
3993 	struct mbuf *mb, *mreq;
3994 	u_quad_t frev;
3995 
3996 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3997 #ifndef nolint
3998 	cache = 0;
3999 #endif
4000 	if (nfsd->nd_repstat)
4001 		error = nfsd->nd_repstat;
4002 	else
4003 		error = EPROCUNAVAIL;
4004 	nfsm_reply(0);
4005 	error = 0;
4006 	nfsm_srvdone;
4007 }
4008 
4009 /*
4010  * Perform access checking for vnodes obtained from file handles that would
4011  * refer to files already opened by a Unix client. You cannot just use
4012  * vn_writechk() and VOP_ACCESS() for two reasons.
4013  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
4014  * 2 - The owner is to be given access irrespective of mode bits for some
4015  *     operations, so that processes that chmod after opening a file don't
4016  *     break. I don't like this because it opens a security hole, but since
4017  *     the nfs server opens a security hole the size of a barn door anyhow,
4018  *     what the heck.
4019  *
4020  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
4021  * will return EPERM instead of EACCESS. EPERM is always an error.
4022  */
4023 static int
4024 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred,
4025 	int rdonly, struct thread *td, int override)
4026 {
4027 	struct vattr vattr;
4028 	int error;
4029 
4030 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4031 	if (flags & VWRITE) {
4032 		/* Just vn_writechk() changed to check rdonly */
4033 		/*
4034 		 * Disallow write attempts on read-only file systems;
4035 		 * unless the file is a socket or a block or character
4036 		 * device resident on the file system.
4037 		 */
4038 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
4039 			switch (vp->v_type) {
4040 			case VREG:
4041 			case VDIR:
4042 			case VLNK:
4043 				return (EROFS);
4044 			default:
4045 				break;
4046 			}
4047 		}
4048 		/*
4049 		 * If there's shared text associated with
4050 		 * the inode, we can't allow writing.
4051 		 */
4052 		if (vp->v_flag & VTEXT)
4053 			return (ETXTBSY);
4054 	}
4055 	error = VOP_GETATTR(vp, &vattr, td);
4056 	if (error)
4057 		return (error);
4058 	error = VOP_ACCESS(vp, flags, cred, td);
4059 	/*
4060 	 * Allow certain operations for the owner (reads and writes
4061 	 * on files that are already open).
4062 	 */
4063 	if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
4064 		error = 0;
4065 	return error;
4066 }
4067 #endif /* NFS_NOSERVER */
4068 
4069