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