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