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