xref: /dragonfly/sys/vfs/nfs/nfs_serv.c (revision f8f04fe3)
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.46 2007/11/20 21:36:08 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 			vn_unlock(dvp);
1663 			error = VOP_NCREATE(&nd.nl_nch, dvp, &vp,
1664 					    nd.nl_cred, vap);
1665 			vrele(dvp);
1666 			dvp = NULL;
1667 			if (error == 0) {
1668 				if (exclusive_flag) {
1669 					exclusive_flag = 0;
1670 					VATTR_NULL(vap);
1671 					bcopy(cverf, (caddr_t)&vap->va_atime,
1672 						NFSX_V3CREATEVERF);
1673 					error = VOP_SETATTR(vp, vap, cred);
1674 				}
1675 			}
1676 		} else if (
1677 			vap->va_type == VCHR ||
1678 			vap->va_type == VBLK ||
1679 			vap->va_type == VFIFO
1680 		) {
1681 			/*
1682 			 * Handle SysV FIFO node special cases.  All other
1683 			 * devices require super user to access.
1684 			 */
1685 			if (vap->va_type == VCHR && rdev == 0xffffffff)
1686 				vap->va_type = VFIFO;
1687                         if (vap->va_type != VFIFO &&
1688                             (error = suser_cred(cred, 0))) {
1689 				goto nfsmreply0;
1690                         }
1691 			vap->va_rmajor = umajor(rdev);
1692 			vap->va_rminor = uminor(rdev);
1693 
1694 			vn_unlock(dvp);
1695 			error = VOP_NMKNOD(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1696 			vrele(dvp);
1697 			dvp = NULL;
1698 			if (error)
1699 				goto nfsmreply0;
1700 #if 0
1701 			/*
1702 			 * XXX what is this junk supposed to do ?
1703 			 */
1704 
1705 			vput(vp);
1706 			vp = NULL;
1707 
1708 			/*
1709 			 * release dvp prior to lookup
1710 			 */
1711 			vput(dvp);
1712 			dvp = NULL;
1713 
1714 			/*
1715 			 * Setup for lookup.
1716 			 *
1717 			 * Even though LOCKPARENT was cleared, ni_dvp may
1718 			 * be garbage.
1719 			 */
1720 			nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
1721 			nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT);
1722 			nd.ni_cnd.cn_td = td;
1723 			nd.ni_cnd.cn_cred = cred;
1724 
1725 			error = lookup(&nd);
1726 			nd.ni_dvp = NULL;
1727 
1728 			if (error != 0) {
1729 				nfsm_reply(0);
1730 				/* fall through on certain errors */
1731 			}
1732 			nfsrv_object_create(nd.ni_vp);
1733 			if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) {
1734 				error = EINVAL;
1735 				goto nfsmreply0;
1736 			}
1737 #endif
1738 		} else {
1739 			error = ENXIO;
1740 		}
1741 	} else {
1742 		if (vap->va_size != -1) {
1743 			error = nfsrv_access(vp, VWRITE, cred,
1744 			    (nd.nl_flags & NLC_NFS_RDONLY), td, 0);
1745 			if (!error) {
1746 				tempsize = vap->va_size;
1747 				VATTR_NULL(vap);
1748 				vap->va_size = tempsize;
1749 				error = VOP_SETATTR(vp, vap, cred);
1750 			}
1751 		}
1752 	}
1753 
1754 	if (!error) {
1755 		bzero((caddr_t)fhp, sizeof(nfh));
1756 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1757 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
1758 		if (!error)
1759 			error = VOP_GETATTR(vp, vap);
1760 	}
1761 	if (v3) {
1762 		if (exclusive_flag && !error &&
1763 			bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
1764 			error = EEXIST;
1765 		diraft_ret = VOP_GETATTR(dirp, &diraft);
1766 		vrele(dirp);
1767 		dirp = NULL;
1768 	}
1769 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1770 	if (v3) {
1771 		if (!error) {
1772 			nfsm_srvpostop_fh(fhp);
1773 			nfsm_srvpostop_attr(0, vap);
1774 		}
1775 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1776 		error = 0;
1777 	} else {
1778 		nfsm_srvfhtom(fhp, v3);
1779 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1780 		nfsm_srvfillattr(vap, fp);
1781 	}
1782 	goto nfsmout;
1783 
1784 nfsmreply0:
1785 	nfsm_reply(0);
1786 	error = 0;
1787 	/* fall through */
1788 
1789 nfsmout:
1790 	if (dirp)
1791 		vrele(dirp);
1792 	nlookup_done(&nd);
1793 	if (dvp) {
1794 		if (dvp == vp)
1795 			vrele(dvp);
1796 		else
1797 			vput(dvp);
1798 	}
1799 	if (vp)
1800 		vput(vp);
1801 	return (error);
1802 }
1803 
1804 /*
1805  * nfs v3 mknod service
1806  */
1807 int
1808 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1809 	    struct thread *td, struct mbuf **mrq)
1810 {
1811 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1812 	struct sockaddr *nam = nfsd->nd_nam;
1813 	caddr_t dpos = nfsd->nd_dpos;
1814 	struct ucred *cred = &nfsd->nd_cr;
1815 	struct vattr va, dirfor, diraft;
1816 	struct vattr *vap = &va;
1817 	u_int32_t *tl;
1818 	struct nlookupdata nd;
1819 	int32_t t1;
1820 	caddr_t bpos;
1821 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1822 	enum vtype vtyp;
1823 	char *cp2;
1824 	struct mbuf *mb, *mb2, *mreq;
1825 	struct vnode *dirp;
1826 	struct vnode *dvp;
1827 	struct vnode *vp;
1828 	nfsfh_t nfh;
1829 	fhandle_t *fhp;
1830 
1831 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1832 	nlookup_zero(&nd);
1833 	dirp = NULL;
1834 	dvp = NULL;
1835 	vp = NULL;
1836 
1837 	fhp = &nfh.fh_generic;
1838 	nfsm_srvmtofh(fhp);
1839 	nfsm_srvnamesiz(len);
1840 
1841 	/*
1842 	 * Handle nfs_namei() call.  If an error occurs, the nd structure
1843 	 * is not valid.  However, nfsm_*() routines may still jump to
1844 	 * nfsmout.
1845 	 */
1846 
1847 	error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp,
1848 			  fhp, len, slp, nam, &md, &dpos, &dirp,
1849 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1850 	if (dirp)
1851 		dirfor_ret = VOP_GETATTR(dirp, &dirfor);
1852 	if (error) {
1853 		nfsm_reply(NFSX_WCCDATA(1));
1854 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1855 		error = 0;
1856 		goto nfsmout;
1857 	}
1858 	nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1859 	vtyp = nfsv3tov_type(*tl);
1860 	if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1861 		error = NFSERR_BADTYPE;
1862 		goto out;
1863 	}
1864 	VATTR_NULL(vap);
1865 	nfsm_srvsattr(vap);
1866 	if (vtyp == VCHR || vtyp == VBLK) {
1867 		nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1868 		vap->va_rmajor = fxdr_unsigned(u_int32_t, *tl++);
1869 		vap->va_rminor = fxdr_unsigned(u_int32_t, *tl);
1870 	}
1871 
1872 	/*
1873 	 * Iff doesn't exist, create it.
1874 	 */
1875 	if (vp) {
1876 		error = EEXIST;
1877 		goto out;
1878 	}
1879 	vap->va_type = vtyp;
1880 	if (vap->va_mode == (mode_t)VNOVAL)
1881 		vap->va_mode = 0;
1882 	if (vtyp == VSOCK) {
1883 		vn_unlock(dvp);
1884 		error = VOP_NCREATE(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1885 		vrele(dvp);
1886 		dvp = NULL;
1887 	} else {
1888 		if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
1889 			goto out;
1890 
1891 		vn_unlock(dvp);
1892 		error = VOP_NMKNOD(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1893 		vrele(dvp);
1894 		dvp = NULL;
1895 		if (error)
1896 			goto out;
1897 	}
1898 
1899 	/*
1900 	 * send response, cleanup, return.
1901 	 */
1902 out:
1903 	nlookup_done(&nd);
1904 	if (dvp) {
1905 		if (dvp == vp)
1906 			vrele(dvp);
1907 		else
1908 			vput(dvp);
1909 		dvp = NULL;
1910 	}
1911 	if (!error) {
1912 		bzero((caddr_t)fhp, sizeof(nfh));
1913 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1914 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
1915 		if (!error)
1916 			error = VOP_GETATTR(vp, vap);
1917 	}
1918 	if (vp) {
1919 		vput(vp);
1920 		vp = NULL;
1921 	}
1922 	diraft_ret = VOP_GETATTR(dirp, &diraft);
1923 	if (dirp) {
1924 		vrele(dirp);
1925 		dirp = NULL;
1926 	}
1927 	nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1928 	if (!error) {
1929 		nfsm_srvpostop_fh(fhp);
1930 		nfsm_srvpostop_attr(0, vap);
1931 	}
1932 	nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1933 	return (0);
1934 nfsmout:
1935 	if (dirp)
1936 		vrele(dirp);
1937 	nlookup_done(&nd);
1938 	if (dvp) {
1939 		if (dvp == vp)
1940 			vrele(dvp);
1941 		else
1942 			vput(dvp);
1943 	}
1944 	if (vp)
1945 		vput(vp);
1946 	return (error);
1947 }
1948 
1949 /*
1950  * nfs remove service
1951  */
1952 int
1953 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1954 	     struct thread *td, struct mbuf **mrq)
1955 {
1956 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1957 	struct sockaddr *nam = nfsd->nd_nam;
1958 	caddr_t dpos = nfsd->nd_dpos;
1959 	struct ucred *cred = &nfsd->nd_cr;
1960 	struct nlookupdata nd;
1961 	u_int32_t *tl;
1962 	int32_t t1;
1963 	caddr_t bpos;
1964 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1965 	int v3 = (nfsd->nd_flag & ND_NFSV3);
1966 	char *cp2;
1967 	struct mbuf *mb, *mreq;
1968 	struct vnode *dirp;
1969 	struct vnode *dvp;
1970 	struct vnode *vp;
1971 	struct vattr dirfor, diraft;
1972 	nfsfh_t nfh;
1973 	fhandle_t *fhp;
1974 
1975 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1976 	nlookup_zero(&nd);
1977 	dirp = NULL;
1978 	dvp = NULL;
1979 	vp = NULL;
1980 
1981 	fhp = &nfh.fh_generic;
1982 	nfsm_srvmtofh(fhp);
1983 	nfsm_srvnamesiz(len);
1984 
1985 	error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp,
1986 			  fhp, len, slp, nam, &md, &dpos, &dirp,
1987 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1988 	if (dirp) {
1989 		if (v3)
1990 			dirfor_ret = VOP_GETATTR(dirp, &dirfor);
1991 	}
1992 	if (error == 0) {
1993 		if (vp->v_type == VDIR) {
1994 			error = EPERM;		/* POSIX */
1995 			goto out;
1996 		}
1997 		/*
1998 		 * The root of a mounted filesystem cannot be deleted.
1999 		 */
2000 		if (vp->v_flag & VROOT) {
2001 			error = EBUSY;
2002 			goto out;
2003 		}
2004 out:
2005 		if (!error) {
2006 			if (dvp != vp)
2007 				vn_unlock(dvp);
2008 			if (vp) {
2009 				vput(vp);
2010 				vp = NULL;
2011 			}
2012 			error = VOP_NREMOVE(&nd.nl_nch, dvp, nd.nl_cred);
2013 			vrele(dvp);
2014 			dvp = NULL;
2015 		}
2016 	}
2017 	if (dirp && v3)
2018 		diraft_ret = VOP_GETATTR(dirp, &diraft);
2019 	nfsm_reply(NFSX_WCCDATA(v3));
2020 	if (v3) {
2021 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2022 		error = 0;
2023 	}
2024 nfsmout:
2025 	nlookup_done(&nd);
2026 	if (dirp)
2027 		vrele(dirp);
2028 	if (dvp) {
2029 		if (dvp == vp)
2030 			vrele(dvp);
2031 		else
2032 			vput(dvp);
2033 	}
2034 	if (vp)
2035 		vput(vp);
2036 	return(error);
2037 }
2038 
2039 /*
2040  * nfs rename service
2041  */
2042 int
2043 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2044 	     struct thread *td, struct mbuf **mrq)
2045 {
2046 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2047 	struct sockaddr *nam = nfsd->nd_nam;
2048 	caddr_t dpos = nfsd->nd_dpos;
2049 	struct ucred *cred = &nfsd->nd_cr;
2050 	u_int32_t *tl;
2051 	int32_t t1;
2052 	caddr_t bpos;
2053 	int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2054 	int tdirfor_ret = 1, tdiraft_ret = 1;
2055 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2056 	char *cp2;
2057 	struct mbuf *mb, *mreq;
2058 	struct nlookupdata fromnd, tond;
2059 	struct vnode *fvp, *fdirp, *fdvp;
2060 	struct vnode *tvp, *tdirp, *tdvp;
2061 	struct namecache *ncp;
2062 	struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2063 	nfsfh_t fnfh, tnfh;
2064 	fhandle_t *ffhp, *tfhp;
2065 	uid_t saved_uid;
2066 
2067 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2068 #ifndef nolint
2069 	fvp = (struct vnode *)0;
2070 #endif
2071 	ffhp = &fnfh.fh_generic;
2072 	tfhp = &tnfh.fh_generic;
2073 
2074 	/*
2075 	 * Clear fields incase goto nfsmout occurs from macro.
2076 	 */
2077 
2078 	nlookup_zero(&fromnd);
2079 	nlookup_zero(&tond);
2080 	fdirp = NULL;
2081 	tdirp = NULL;
2082 
2083 	nfsm_srvmtofh(ffhp);
2084 	nfsm_srvnamesiz(len);
2085 	/*
2086 	 * Remember our original uid so that we can reset cr_uid before
2087 	 * the second nfs_namei() call, in case it is remapped.
2088 	 */
2089 	saved_uid = cred->cr_uid;
2090 	error = nfs_namei(&fromnd, cred, NAMEI_DELETE, NULL, NULL,
2091 			  ffhp, len, slp, nam, &md, &dpos, &fdirp,
2092 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2093 	if (fdirp) {
2094 		if (v3)
2095 			fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor);
2096 	}
2097 	if (error) {
2098 		nfsm_reply(2 * NFSX_WCCDATA(v3));
2099 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2100 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2101 		error = 0;
2102 		goto nfsmout;
2103 	}
2104 
2105 	/*
2106 	 * We have to unlock the from ncp before we can safely lookup
2107 	 * the target ncp.
2108 	 */
2109 	KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED);
2110 	cache_unlock(&fromnd.nl_nch);
2111 	fromnd.nl_flags &= ~NLC_NCPISLOCKED;
2112 	nfsm_srvmtofh(tfhp);
2113 	nfsm_strsiz(len2, NFS_MAXNAMLEN);
2114 	cred->cr_uid = saved_uid;
2115 
2116 	error = nfs_namei(&tond, cred, NAMEI_RENAME, NULL, NULL,
2117 			  tfhp, len2, slp, nam, &md, &dpos, &tdirp,
2118 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2119 	if (tdirp) {
2120 		if (v3)
2121 			tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor);
2122 	}
2123 	if (error)
2124 		goto out1;
2125 
2126 	/*
2127 	 * relock the source
2128 	 */
2129 	if (cache_lock_nonblock(&fromnd.nl_nch) == 0) {
2130 		cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2131 	} else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) {
2132 		cache_lock(&fromnd.nl_nch);
2133 		cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2134 	} else {
2135 		cache_unlock(&tond.nl_nch);
2136 		cache_lock(&fromnd.nl_nch);
2137 		cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2138 		cache_lock(&tond.nl_nch);
2139 		cache_resolve(&tond.nl_nch, tond.nl_cred);
2140 	}
2141 	fromnd.nl_flags |= NLC_NCPISLOCKED;
2142 
2143 	fvp = fromnd.nl_nch.ncp->nc_vp;
2144 	tvp = tond.nl_nch.ncp->nc_vp;
2145 
2146 	/*
2147 	 * Set fdvp and tdvp.  We haven't done all the topology checks
2148 	 * so these can wind up NULL (e.g. if either fvp or tvp is a mount
2149 	 * point).  If we get through the checks these will be guarenteed
2150 	 * to be non-NULL.
2151 	 *
2152 	 * Holding the children ncp's should be sufficient to prevent
2153 	 * fdvp and tdvp ripouts.
2154 	 */
2155 	if (fromnd.nl_nch.ncp->nc_parent)
2156 		fdvp = fromnd.nl_nch.ncp->nc_parent->nc_vp;
2157 	else
2158 		fdvp = NULL;
2159 	if (tond.nl_nch.ncp->nc_parent)
2160 		tdvp = tond.nl_nch.ncp->nc_parent->nc_vp;
2161 	else
2162 		tdvp = NULL;
2163 
2164 	if (tvp != NULL) {
2165 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2166 			if (v3)
2167 				error = EEXIST;
2168 			else
2169 				error = EISDIR;
2170 			goto out;
2171 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2172 			if (v3)
2173 				error = EEXIST;
2174 			else
2175 				error = ENOTDIR;
2176 			goto out;
2177 		}
2178 		if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
2179 			if (v3)
2180 				error = EXDEV;
2181 			else
2182 				error = ENOTEMPTY;
2183 			goto out;
2184 		}
2185 	}
2186 	if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
2187 		if (v3)
2188 			error = EXDEV;
2189 		else
2190 			error = ENOTEMPTY;
2191 		goto out;
2192 	}
2193 	if (fromnd.nl_nch.mount != tond.nl_nch.mount) {
2194 		if (v3)
2195 			error = EXDEV;
2196 		else
2197 			error = ENOTEMPTY;
2198 		goto out;
2199 	}
2200 	if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) {
2201 		if (v3)
2202 			error = EINVAL;
2203 		else
2204 			error = ENOTEMPTY;
2205 	}
2206 
2207 	/*
2208 	 * You cannot rename a source into itself or a subdirectory of itself.
2209 	 * We check this by travsering the target directory upwards looking
2210 	 * for a match against the source.
2211 	 */
2212 	if (error == 0) {
2213 		for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) {
2214 			if (fromnd.nl_nch.ncp == ncp) {
2215 				error = EINVAL;
2216 				break;
2217 			}
2218 		}
2219 	}
2220 
2221 	/*
2222 	 * If source is the same as the destination (that is the
2223 	 * same vnode with the same name in the same directory),
2224 	 * then there is nothing to do.
2225 	 */
2226 	if (fromnd.nl_nch.ncp == tond.nl_nch.ncp)
2227 		error = -1;
2228 out:
2229 	if (!error) {
2230 		/*
2231 		 * The VOP_NRENAME function releases all vnode references &
2232 		 * locks prior to returning so we need to clear the pointers
2233 		 * to bypass cleanup code later on.
2234 		 */
2235 		error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch,
2236 				    fdvp, tdvp, tond.nl_cred);
2237 	} else {
2238 		if (error == -1)
2239 			error = 0;
2240 	}
2241 	/* fall through */
2242 
2243 out1:
2244 	if (fdirp)
2245 		fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft);
2246 	if (tdirp)
2247 		tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft);
2248 	nfsm_reply(2 * NFSX_WCCDATA(v3));
2249 	if (v3) {
2250 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2251 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2252 	}
2253 	error = 0;
2254 	/* fall through */
2255 
2256 nfsmout:
2257 	if (tdirp)
2258 		vrele(tdirp);
2259 	nlookup_done(&tond);
2260 	if (fdirp)
2261 		vrele(fdirp);
2262 	nlookup_done(&fromnd);
2263 	return (error);
2264 }
2265 
2266 /*
2267  * nfs link service
2268  */
2269 int
2270 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2271 	   struct thread *td, struct mbuf **mrq)
2272 {
2273 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2274 	struct sockaddr *nam = nfsd->nd_nam;
2275 	caddr_t dpos = nfsd->nd_dpos;
2276 	struct ucred *cred = &nfsd->nd_cr;
2277 	struct nlookupdata nd;
2278 	u_int32_t *tl;
2279 	int32_t t1;
2280 	caddr_t bpos;
2281 	int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2282 	int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2283 	char *cp2;
2284 	struct mbuf *mb, *mreq;
2285 	struct vnode *dirp;
2286 	struct vnode *dvp;
2287 	struct vnode *vp;
2288 	struct vnode *xp;
2289 	struct vattr dirfor, diraft, at;
2290 	nfsfh_t nfh, dnfh;
2291 	fhandle_t *fhp, *dfhp;
2292 
2293 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2294 	nlookup_zero(&nd);
2295 	dirp = dvp = vp = xp = NULL;
2296 
2297 	fhp = &nfh.fh_generic;
2298 	dfhp = &dnfh.fh_generic;
2299 	nfsm_srvmtofh(fhp);
2300 	nfsm_srvmtofh(dfhp);
2301 	nfsm_srvnamesiz(len);
2302 
2303 	error = nfsrv_fhtovp(fhp, FALSE, &xp, cred, slp, nam,
2304 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2305 	if (error) {
2306 		nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2307 		nfsm_srvpostop_attr(getret, &at);
2308 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2309 		xp = NULL;
2310 		error = 0;
2311 		goto nfsmout;
2312 	}
2313 	if (xp->v_type == VDIR) {
2314 		error = EPERM;		/* POSIX */
2315 		goto out1;
2316 	}
2317 
2318 	error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp,
2319 			  dfhp, len, slp, nam, &md, &dpos, &dirp,
2320 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2321 	if (dirp) {
2322 		if (v3)
2323 			dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2324 	}
2325 	if (error)
2326 		goto out1;
2327 
2328 	if (vp != NULL) {
2329 		error = EEXIST;
2330 		goto out;
2331 	}
2332 	if (xp->v_mount != dvp->v_mount)
2333 		error = EXDEV;
2334 out:
2335 	if (!error) {
2336 		vn_unlock(dvp);
2337 		error = VOP_NLINK(&nd.nl_nch, dvp, xp, nd.nl_cred);
2338 		vrele(dvp);
2339 		dvp = NULL;
2340 	}
2341 	/* fall through */
2342 
2343 out1:
2344 	if (v3)
2345 		getret = VOP_GETATTR(xp, &at);
2346 	if (dirp)
2347 		diraft_ret = VOP_GETATTR(dirp, &diraft);
2348 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2349 	if (v3) {
2350 		nfsm_srvpostop_attr(getret, &at);
2351 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2352 		error = 0;
2353 	}
2354 	/* fall through */
2355 
2356 nfsmout:
2357 	nlookup_done(&nd);
2358 	if (dirp)
2359 		vrele(dirp);
2360 	if (xp)
2361 		vrele(xp);
2362 	if (dvp) {
2363 		if (dvp == vp)
2364 			vrele(dvp);
2365 		else
2366 			vput(dvp);
2367 	}
2368 	if (vp)
2369 		vput(vp);
2370 	return(error);
2371 }
2372 
2373 /*
2374  * nfs symbolic link service
2375  */
2376 int
2377 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2378 	      struct thread *td, struct mbuf **mrq)
2379 {
2380 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2381 	struct sockaddr *nam = nfsd->nd_nam;
2382 	caddr_t dpos = nfsd->nd_dpos;
2383 	struct ucred *cred = &nfsd->nd_cr;
2384 	struct vattr va, dirfor, diraft;
2385 	struct nlookupdata nd;
2386 	struct vattr *vap = &va;
2387 	u_int32_t *tl;
2388 	int32_t t1;
2389 	struct nfsv2_sattr *sp;
2390 	char *bpos, *pathcp = (char *)0, *cp2;
2391 	struct uio io;
2392 	struct iovec iv;
2393 	int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2394 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2395 	struct mbuf *mb, *mreq, *mb2;
2396 	struct vnode *dirp;
2397 	struct vnode *vp;
2398 	struct vnode *dvp;
2399 	nfsfh_t nfh;
2400 	fhandle_t *fhp;
2401 
2402 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2403 	nlookup_zero(&nd);
2404 	dirp = NULL;
2405 	dvp = NULL;
2406 	vp = NULL;
2407 
2408 	fhp = &nfh.fh_generic;
2409 	nfsm_srvmtofh(fhp);
2410 	nfsm_srvnamesiz(len);
2411 
2412 	error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp,
2413 			fhp, len, slp, nam, &md, &dpos, &dirp,
2414 			td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2415 	if (dirp) {
2416 		if (v3)
2417 			dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2418 	}
2419 	if (error)
2420 		goto out;
2421 
2422 	VATTR_NULL(vap);
2423 	if (v3)
2424 		nfsm_srvsattr(vap);
2425 	nfsm_strsiz(len2, NFS_MAXPATHLEN);
2426 	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2427 	iv.iov_base = pathcp;
2428 	iv.iov_len = len2;
2429 	io.uio_resid = len2;
2430 	io.uio_offset = 0;
2431 	io.uio_iov = &iv;
2432 	io.uio_iovcnt = 1;
2433 	io.uio_segflg = UIO_SYSSPACE;
2434 	io.uio_rw = UIO_READ;
2435 	io.uio_td = NULL;
2436 	nfsm_mtouio(&io, len2);
2437 	if (!v3) {
2438 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2439 		vap->va_mode = nfstov_mode(sp->sa_mode);
2440 	}
2441 	*(pathcp + len2) = '\0';
2442 	if (vp) {
2443 		error = EEXIST;
2444 		goto out;
2445 	}
2446 
2447 	if (vap->va_mode == (mode_t)VNOVAL)
2448 		vap->va_mode = 0;
2449 	if (dvp != vp)
2450 		vn_unlock(dvp);
2451 	error = VOP_NSYMLINK(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap, pathcp);
2452 	vrele(dvp);
2453 	dvp = NULL;
2454 	if (error == 0) {
2455 		bzero((caddr_t)fhp, sizeof(nfh));
2456 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2457 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
2458 		if (!error)
2459 			error = VOP_GETATTR(vp, vap);
2460 	}
2461 
2462 out:
2463 	if (dvp) {
2464 		if (dvp == vp)
2465 			vrele(dvp);
2466 		else
2467 			vput(dvp);
2468 	}
2469 	if (vp) {
2470 		vput(vp);
2471 		vp = NULL;
2472 	}
2473 	if (pathcp) {
2474 		FREE(pathcp, M_TEMP);
2475 		pathcp = NULL;
2476 	}
2477 	if (dirp) {
2478 		diraft_ret = VOP_GETATTR(dirp, &diraft);
2479 		vrele(dirp);
2480 		dirp = NULL;
2481 	}
2482 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2483 	if (v3) {
2484 		if (!error) {
2485 			nfsm_srvpostop_fh(fhp);
2486 			nfsm_srvpostop_attr(0, vap);
2487 		}
2488 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2489 	}
2490 	error = 0;
2491 	/* fall through */
2492 
2493 nfsmout:
2494 	nlookup_done(&nd);
2495 	if (vp)
2496 		vput(vp);
2497 	if (dirp)
2498 		vrele(dirp);
2499 	if (pathcp)
2500 		FREE(pathcp, M_TEMP);
2501 	return (error);
2502 }
2503 
2504 /*
2505  * nfs mkdir service
2506  */
2507 int
2508 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2509 	    struct thread *td, struct mbuf **mrq)
2510 {
2511 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2512 	struct sockaddr *nam = nfsd->nd_nam;
2513 	caddr_t dpos = nfsd->nd_dpos;
2514 	struct ucred *cred = &nfsd->nd_cr;
2515 	struct vattr va, dirfor, diraft;
2516 	struct vattr *vap = &va;
2517 	struct nfs_fattr *fp;
2518 	struct nlookupdata nd;
2519 	caddr_t cp;
2520 	u_int32_t *tl;
2521 	int32_t t1;
2522 	caddr_t bpos;
2523 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2524 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2525 	char *cp2;
2526 	struct mbuf *mb, *mb2, *mreq;
2527 	struct vnode *dirp;
2528 	struct vnode *dvp;
2529 	struct vnode *vp;
2530 	nfsfh_t nfh;
2531 	fhandle_t *fhp;
2532 
2533 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2534 	nlookup_zero(&nd);
2535 	dirp = NULL;
2536 	dvp = NULL;
2537 	vp = NULL;
2538 
2539 	fhp = &nfh.fh_generic;
2540 	nfsm_srvmtofh(fhp);
2541 	nfsm_srvnamesiz(len);
2542 
2543 	error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp,
2544 			  fhp, len, slp, nam, &md, &dpos, &dirp,
2545 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2546 	if (dirp) {
2547 		if (v3)
2548 			dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2549 	}
2550 	if (error) {
2551 		nfsm_reply(NFSX_WCCDATA(v3));
2552 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2553 		error = 0;
2554 		goto nfsmout;
2555 	}
2556 	VATTR_NULL(vap);
2557 	if (v3) {
2558 		nfsm_srvsattr(vap);
2559 	} else {
2560 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2561 		vap->va_mode = nfstov_mode(*tl++);
2562 	}
2563 
2564 	/*
2565 	 * At this point nd.ni_dvp is referenced and exclusively locked and
2566 	 * nd.ni_vp, if it exists, is referenced but not locked.
2567 	 */
2568 
2569 	vap->va_type = VDIR;
2570 	if (vp != NULL) {
2571 		error = EEXIST;
2572 		goto out;
2573 	}
2574 
2575 	/*
2576 	 * Issue mkdir op.  Since SAVESTART is not set, the pathname
2577 	 * component is freed by the VOP call.  This will fill-in
2578 	 * nd.ni_vp, reference, and exclusively lock it.
2579 	 */
2580 	if (vap->va_mode == (mode_t)VNOVAL)
2581 		vap->va_mode = 0;
2582 	vn_unlock(dvp);
2583 	error = VOP_NMKDIR(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
2584 	vrele(dvp);
2585 	dvp = NULL;
2586 
2587 	if (error == 0) {
2588 		bzero((caddr_t)fhp, sizeof(nfh));
2589 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2590 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
2591 		if (error == 0)
2592 			error = VOP_GETATTR(vp, vap);
2593 	}
2594 out:
2595 	if (dirp)
2596 		diraft_ret = VOP_GETATTR(dirp, &diraft);
2597 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2598 	if (v3) {
2599 		if (!error) {
2600 			nfsm_srvpostop_fh(fhp);
2601 			nfsm_srvpostop_attr(0, vap);
2602 		}
2603 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2604 	} else {
2605 		nfsm_srvfhtom(fhp, v3);
2606 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
2607 		nfsm_srvfillattr(vap, fp);
2608 	}
2609 	error = 0;
2610 	/* fall through */
2611 
2612 nfsmout:
2613 	nlookup_done(&nd);
2614 	if (dirp)
2615 		vrele(dirp);
2616 	if (dvp) {
2617 		if (dvp == vp)
2618 			vrele(dvp);
2619 		else
2620 			vput(dvp);
2621 	}
2622 	if (vp)
2623 		vput(vp);
2624 	return (error);
2625 }
2626 
2627 /*
2628  * nfs rmdir service
2629  */
2630 int
2631 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2632 	    struct thread *td, struct mbuf **mrq)
2633 {
2634 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2635 	struct sockaddr *nam = nfsd->nd_nam;
2636 	caddr_t dpos = nfsd->nd_dpos;
2637 	struct ucred *cred = &nfsd->nd_cr;
2638 	u_int32_t *tl;
2639 	int32_t t1;
2640 	caddr_t bpos;
2641 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2642 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2643 	char *cp2;
2644 	struct mbuf *mb, *mreq;
2645 	struct vnode *dirp;
2646 	struct vnode *dvp;
2647 	struct vnode *vp;
2648 	struct vattr dirfor, diraft;
2649 	nfsfh_t nfh;
2650 	fhandle_t *fhp;
2651 	struct nlookupdata nd;
2652 
2653 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2654 	nlookup_zero(&nd);
2655 	dirp = NULL;
2656 	dvp = NULL;
2657 	vp = NULL;
2658 
2659 	fhp = &nfh.fh_generic;
2660 	nfsm_srvmtofh(fhp);
2661 	nfsm_srvnamesiz(len);
2662 
2663 	error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp,
2664 			  fhp, len, slp, nam, &md, &dpos, &dirp,
2665 			  td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2666 	if (dirp) {
2667 		if (v3)
2668 			dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2669 	}
2670 	if (error) {
2671 		nfsm_reply(NFSX_WCCDATA(v3));
2672 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2673 		error = 0;
2674 		goto nfsmout;
2675 	}
2676 	if (vp->v_type != VDIR) {
2677 		error = ENOTDIR;
2678 		goto out;
2679 	}
2680 
2681 	/*
2682 	 * The root of a mounted filesystem cannot be deleted.
2683 	 */
2684 	if (vp->v_flag & VROOT)
2685 		error = EBUSY;
2686 out:
2687 	/*
2688 	 * Issue or abort op.  Since SAVESTART is not set, path name
2689 	 * component is freed by the VOP after either.
2690 	 */
2691 	if (!error) {
2692 		if (dvp != vp)
2693 			vn_unlock(dvp);
2694 		vput(vp);
2695 		vp = NULL;
2696 		error = VOP_NRMDIR(&nd.nl_nch, dvp, nd.nl_cred);
2697 		vrele(dvp);
2698 		dvp = NULL;
2699 	}
2700 	nlookup_done(&nd);
2701 
2702 	if (dirp)
2703 		diraft_ret = VOP_GETATTR(dirp, &diraft);
2704 	nfsm_reply(NFSX_WCCDATA(v3));
2705 	if (v3) {
2706 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2707 		error = 0;
2708 	}
2709 	/* fall through */
2710 
2711 nfsmout:
2712 	if (dvp) {
2713 		if (dvp == vp)
2714 			vrele(dvp);
2715 		else
2716 			vput(dvp);
2717 	}
2718 	nlookup_done(&nd);
2719 	if (dirp)
2720 		vrele(dirp);
2721 	if (vp)
2722 		vput(vp);
2723 	return(error);
2724 }
2725 
2726 /*
2727  * nfs readdir service
2728  * - mallocs what it thinks is enough to read
2729  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2730  * - calls VOP_READDIR()
2731  * - loops around building the reply
2732  *	if the output generated exceeds count break out of loop
2733  *	The nfsm_clget macro is used here so that the reply will be packed
2734  *	tightly in mbuf clusters.
2735  * - it only knows that it has encountered eof when the VOP_READDIR()
2736  *	reads nothing
2737  * - as such one readdir rpc will return eof false although you are there
2738  *	and then the next will return eof
2739  * - it trims out records with d_fileno == 0
2740  *	this doesn't matter for Unix clients, but they might confuse clients
2741  *	for other os'.
2742  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2743  *	than requested, but this may not apply to all filesystems. For
2744  *	example, client NFS does not { although it is never remote mounted
2745  *	anyhow }
2746  *     The alternate call nfsrv_readdirplus() does lookups as well.
2747  * PS: The NFS protocol spec. does not clarify what the "count" byte
2748  *	argument is a count of.. just name strings and file id's or the
2749  *	entire reply rpc or ...
2750  *	I tried just file name and id sizes and it confused the Sun client,
2751  *	so I am using the full rpc size now. The "paranoia.." comment refers
2752  *	to including the status longwords that are not a part of the dir.
2753  *	"entry" structures, but are in the rpc.
2754  */
2755 struct flrep {
2756 	nfsuint64	fl_off;
2757 	u_int32_t	fl_postopok;
2758 	u_int32_t	fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2759 	u_int32_t	fl_fhok;
2760 	u_int32_t	fl_fhsize;
2761 	u_int32_t	fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2762 };
2763 
2764 int
2765 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2766 	      struct thread *td, struct mbuf **mrq)
2767 {
2768 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2769 	struct sockaddr *nam = nfsd->nd_nam;
2770 	caddr_t dpos = nfsd->nd_dpos;
2771 	struct ucred *cred = &nfsd->nd_cr;
2772 	char *bp, *be;
2773 	struct mbuf *mp;
2774 	struct dirent *dp;
2775 	caddr_t cp;
2776 	u_int32_t *tl;
2777 	int32_t t1;
2778 	caddr_t bpos;
2779 	struct mbuf *mb, *mb2, *mreq, *mp2;
2780 	char *cpos, *cend, *cp2, *rbuf;
2781 	struct vnode *vp = NULL;
2782 	struct vattr at;
2783 	nfsfh_t nfh;
2784 	fhandle_t *fhp;
2785 	struct uio io;
2786 	struct iovec iv;
2787 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2788 	int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2789 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2790 	u_quad_t off, toff, verf;
2791 	off_t *cookies = NULL, *cookiep;
2792 
2793 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2794 	fhp = &nfh.fh_generic;
2795 	nfsm_srvmtofh(fhp);
2796 	if (v3) {
2797 		nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2798 		toff = fxdr_hyper(tl);
2799 		tl += 2;
2800 		verf = fxdr_hyper(tl);
2801 		tl += 2;
2802 	} else {
2803 		nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2804 		toff = fxdr_unsigned(u_quad_t, *tl++);
2805 		verf = 0;	/* shut up gcc */
2806 	}
2807 	off = toff;
2808 	cnt = fxdr_unsigned(int, *tl);
2809 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2810 	xfer = NFS_SRVMAXDATA(nfsd);
2811 	if (cnt > xfer)
2812 		cnt = xfer;
2813 	if (siz > xfer)
2814 		siz = xfer;
2815 	fullsiz = siz;
2816 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2817 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2818 	if (!error && vp->v_type != VDIR) {
2819 		error = ENOTDIR;
2820 		vput(vp);
2821 		vp = NULL;
2822 	}
2823 	if (error) {
2824 		nfsm_reply(NFSX_UNSIGNED);
2825 		nfsm_srvpostop_attr(getret, &at);
2826 		error = 0;
2827 		goto nfsmout;
2828 	}
2829 
2830 	/*
2831 	 * Obtain lock on vnode for this section of the code
2832 	 */
2833 
2834 	if (v3) {
2835 		error = getret = VOP_GETATTR(vp, &at);
2836 #if 0
2837 		/*
2838 		 * XXX This check may be too strict for Solaris 2.5 clients.
2839 		 */
2840 		if (!error && toff && verf && verf != at.va_filerev)
2841 			error = NFSERR_BAD_COOKIE;
2842 #endif
2843 	}
2844 	if (!error)
2845 		error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
2846 	if (error) {
2847 		vput(vp);
2848 		vp = NULL;
2849 		nfsm_reply(NFSX_POSTOPATTR(v3));
2850 		nfsm_srvpostop_attr(getret, &at);
2851 		error = 0;
2852 		goto nfsmout;
2853 	}
2854 	vn_unlock(vp);
2855 
2856 	/*
2857 	 * end section.  Allocate rbuf and continue
2858 	 */
2859 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
2860 again:
2861 	iv.iov_base = rbuf;
2862 	iv.iov_len = fullsiz;
2863 	io.uio_iov = &iv;
2864 	io.uio_iovcnt = 1;
2865 	io.uio_offset = (off_t)off;
2866 	io.uio_resid = fullsiz;
2867 	io.uio_segflg = UIO_SYSSPACE;
2868 	io.uio_rw = UIO_READ;
2869 	io.uio_td = NULL;
2870 	eofflag = 0;
2871 	if (cookies) {
2872 		kfree((caddr_t)cookies, M_TEMP);
2873 		cookies = NULL;
2874 	}
2875 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2876 	off = (off_t)io.uio_offset;
2877 	if (!cookies && !error)
2878 		error = NFSERR_PERM;
2879 	if (v3) {
2880 		getret = VOP_GETATTR(vp, &at);
2881 		if (!error)
2882 			error = getret;
2883 	}
2884 	if (error) {
2885 		vrele(vp);
2886 		vp = NULL;
2887 		kfree((caddr_t)rbuf, M_TEMP);
2888 		if (cookies)
2889 			kfree((caddr_t)cookies, M_TEMP);
2890 		nfsm_reply(NFSX_POSTOPATTR(v3));
2891 		nfsm_srvpostop_attr(getret, &at);
2892 		error = 0;
2893 		goto nfsmout;
2894 	}
2895 	if (io.uio_resid) {
2896 		siz -= io.uio_resid;
2897 
2898 		/*
2899 		 * If nothing read, return eof
2900 		 * rpc reply
2901 		 */
2902 		if (siz == 0) {
2903 			vrele(vp);
2904 			vp = NULL;
2905 			nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2906 				2 * NFSX_UNSIGNED);
2907 			if (v3) {
2908 				nfsm_srvpostop_attr(getret, &at);
2909 				nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2910 				txdr_hyper(at.va_filerev, tl);
2911 				tl += 2;
2912 			} else
2913 				nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2914 			*tl++ = nfs_false;
2915 			*tl = nfs_true;
2916 			FREE((caddr_t)rbuf, M_TEMP);
2917 			FREE((caddr_t)cookies, M_TEMP);
2918 			error = 0;
2919 			goto nfsmout;
2920 		}
2921 	}
2922 
2923 	/*
2924 	 * Check for degenerate cases of nothing useful read.
2925 	 * If so go try again
2926 	 */
2927 	cpos = rbuf;
2928 	cend = rbuf + siz;
2929 	dp = (struct dirent *)cpos;
2930 	cookiep = cookies;
2931 	/*
2932 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
2933 	 * directory offset up to a block boundary, so it is necessary to
2934 	 * skip over the records that preceed the requested offset. This
2935 	 * requires the assumption that file offset cookies monotonically
2936 	 * increase.
2937 	 */
2938 	while (cpos < cend && ncookies > 0 &&
2939 		(dp->d_ino == 0 || dp->d_type == DT_WHT ||
2940 		 ((u_quad_t)(*cookiep)) <= toff)) {
2941 		dp = _DIRENT_NEXT(dp);
2942 		cpos = (char *)dp;
2943 		cookiep++;
2944 		ncookies--;
2945 	}
2946 	if (cpos >= cend || ncookies == 0) {
2947 		toff = off;
2948 		siz = fullsiz;
2949 		goto again;
2950 	}
2951 
2952 	len = 3 * NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
2953 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2954 	if (v3) {
2955 		nfsm_srvpostop_attr(getret, &at);
2956 		nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2957 		txdr_hyper(at.va_filerev, tl);
2958 	}
2959 	mp = mp2 = mb;
2960 	bp = bpos;
2961 	be = bp + M_TRAILINGSPACE(mp);
2962 
2963 	/* Loop through the records and build reply */
2964 	while (cpos < cend && ncookies > 0) {
2965 		if (dp->d_ino != 0 && dp->d_type != DT_WHT) {
2966 			nlen = dp->d_namlen;
2967 			rem = nfsm_rndup(nlen) - nlen;
2968 			len += (4 * NFSX_UNSIGNED + nlen + rem);
2969 			if (v3)
2970 				len += 2 * NFSX_UNSIGNED;
2971 			if (len > cnt) {
2972 				eofflag = 0;
2973 				break;
2974 			}
2975 			/*
2976 			 * Build the directory record xdr from
2977 			 * the dirent entry.
2978 			 */
2979 			nfsm_clget;
2980 			*tl = nfs_true;
2981 			bp += NFSX_UNSIGNED;
2982 			if (v3) {
2983 				nfsm_clget;
2984 				*tl = 0;
2985 				bp += NFSX_UNSIGNED;
2986 			}
2987 			nfsm_clget;
2988 			*tl = txdr_unsigned(dp->d_ino);
2989 			bp += NFSX_UNSIGNED;
2990 			nfsm_clget;
2991 			*tl = txdr_unsigned(nlen);
2992 			bp += NFSX_UNSIGNED;
2993 
2994 			/* And loop around copying the name */
2995 			xfer = nlen;
2996 			cp = dp->d_name;
2997 			while (xfer > 0) {
2998 				nfsm_clget;
2999 				if ((bp+xfer) > be)
3000 					tsiz = be-bp;
3001 				else
3002 					tsiz = xfer;
3003 				bcopy(cp, bp, tsiz);
3004 				bp += tsiz;
3005 				xfer -= tsiz;
3006 				if (xfer > 0)
3007 					cp += tsiz;
3008 			}
3009 			/* And null pad to a int32_t boundary */
3010 			for (i = 0; i < rem; i++)
3011 				*bp++ = '\0';
3012 			nfsm_clget;
3013 
3014 			/* Finish off the record */
3015 			if (v3) {
3016 				*tl = txdr_unsigned(*cookiep >> 32);
3017 				bp += NFSX_UNSIGNED;
3018 				nfsm_clget;
3019 			}
3020 			*tl = txdr_unsigned(*cookiep);
3021 			bp += NFSX_UNSIGNED;
3022 		}
3023 		dp = _DIRENT_NEXT(dp);
3024 		cpos = (char *)dp;
3025 		cookiep++;
3026 		ncookies--;
3027 	}
3028 	vrele(vp);
3029 	vp = NULL;
3030 	nfsm_clget;
3031 	*tl = nfs_false;
3032 	bp += NFSX_UNSIGNED;
3033 	nfsm_clget;
3034 	if (eofflag)
3035 		*tl = nfs_true;
3036 	else
3037 		*tl = nfs_false;
3038 	bp += NFSX_UNSIGNED;
3039 	if (mp != mb) {
3040 		if (bp < be)
3041 			mp->m_len = bp - mtod(mp, caddr_t);
3042 	} else
3043 		mp->m_len += bp - bpos;
3044 	FREE((caddr_t)rbuf, M_TEMP);
3045 	FREE((caddr_t)cookies, M_TEMP);
3046 
3047 nfsmout:
3048 	if (vp)
3049 		vrele(vp);
3050 	return(error);
3051 }
3052 
3053 int
3054 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3055 		  struct thread *td, struct mbuf **mrq)
3056 {
3057 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3058 	struct sockaddr *nam = nfsd->nd_nam;
3059 	caddr_t dpos = nfsd->nd_dpos;
3060 	struct ucred *cred = &nfsd->nd_cr;
3061 	char *bp, *be;
3062 	struct mbuf *mp;
3063 	struct dirent *dp;
3064 	caddr_t cp;
3065 	u_int32_t *tl;
3066 	int32_t t1;
3067 	caddr_t bpos;
3068 	struct mbuf *mb, *mb2, *mreq, *mp2;
3069 	char *cpos, *cend, *cp2, *rbuf;
3070 	struct vnode *vp = NULL, *nvp;
3071 	struct flrep fl;
3072 	nfsfh_t nfh;
3073 	fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3074 	struct uio io;
3075 	struct iovec iv;
3076 	struct vattr va, at, *vap = &va;
3077 	struct nfs_fattr *fp;
3078 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3079 	int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3080 	u_quad_t off, toff, verf;
3081 	off_t *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3082 
3083 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3084 	fhp = &nfh.fh_generic;
3085 	nfsm_srvmtofh(fhp);
3086 	nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
3087 	toff = fxdr_hyper(tl);
3088 	tl += 2;
3089 	verf = fxdr_hyper(tl);
3090 	tl += 2;
3091 	siz = fxdr_unsigned(int, *tl++);
3092 	cnt = fxdr_unsigned(int, *tl);
3093 	off = toff;
3094 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3095 	xfer = NFS_SRVMAXDATA(nfsd);
3096 	if (cnt > xfer)
3097 		cnt = xfer;
3098 	if (siz > xfer)
3099 		siz = xfer;
3100 	fullsiz = siz;
3101 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3102 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3103 	if (!error && vp->v_type != VDIR) {
3104 		error = ENOTDIR;
3105 		vput(vp);
3106 		vp = NULL;
3107 	}
3108 	if (error) {
3109 		nfsm_reply(NFSX_UNSIGNED);
3110 		nfsm_srvpostop_attr(getret, &at);
3111 		error = 0;
3112 		goto nfsmout;
3113 	}
3114 	error = getret = VOP_GETATTR(vp, &at);
3115 #if 0
3116 	/*
3117 	 * XXX This check may be too strict for Solaris 2.5 clients.
3118 	 */
3119 	if (!error && toff && verf && verf != at.va_filerev)
3120 		error = NFSERR_BAD_COOKIE;
3121 #endif
3122 	if (!error) {
3123 		error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
3124 	}
3125 	if (error) {
3126 		vput(vp);
3127 		vp = NULL;
3128 		nfsm_reply(NFSX_V3POSTOPATTR);
3129 		nfsm_srvpostop_attr(getret, &at);
3130 		error = 0;
3131 		goto nfsmout;
3132 	}
3133 	vn_unlock(vp);
3134 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3135 again:
3136 	iv.iov_base = rbuf;
3137 	iv.iov_len = fullsiz;
3138 	io.uio_iov = &iv;
3139 	io.uio_iovcnt = 1;
3140 	io.uio_offset = (off_t)off;
3141 	io.uio_resid = fullsiz;
3142 	io.uio_segflg = UIO_SYSSPACE;
3143 	io.uio_rw = UIO_READ;
3144 	io.uio_td = NULL;
3145 	eofflag = 0;
3146 	if (cookies) {
3147 		kfree((caddr_t)cookies, M_TEMP);
3148 		cookies = NULL;
3149 	}
3150 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3151 	off = (u_quad_t)io.uio_offset;
3152 	getret = VOP_GETATTR(vp, &at);
3153 	if (!cookies && !error)
3154 		error = NFSERR_PERM;
3155 	if (!error)
3156 		error = getret;
3157 	if (error) {
3158 		vrele(vp);
3159 		vp = NULL;
3160 		if (cookies)
3161 			kfree((caddr_t)cookies, M_TEMP);
3162 		kfree((caddr_t)rbuf, M_TEMP);
3163 		nfsm_reply(NFSX_V3POSTOPATTR);
3164 		nfsm_srvpostop_attr(getret, &at);
3165 		error = 0;
3166 		goto nfsmout;
3167 	}
3168 	if (io.uio_resid) {
3169 		siz -= io.uio_resid;
3170 
3171 		/*
3172 		 * If nothing read, return eof
3173 		 * rpc reply
3174 		 */
3175 		if (siz == 0) {
3176 			vrele(vp);
3177 			vp = NULL;
3178 			nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3179 				2 * NFSX_UNSIGNED);
3180 			nfsm_srvpostop_attr(getret, &at);
3181 			nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
3182 			txdr_hyper(at.va_filerev, tl);
3183 			tl += 2;
3184 			*tl++ = nfs_false;
3185 			*tl = nfs_true;
3186 			FREE((caddr_t)cookies, M_TEMP);
3187 			FREE((caddr_t)rbuf, M_TEMP);
3188 			error = 0;
3189 			goto nfsmout;
3190 		}
3191 	}
3192 
3193 	/*
3194 	 * Check for degenerate cases of nothing useful read.
3195 	 * If so go try again
3196 	 */
3197 	cpos = rbuf;
3198 	cend = rbuf + siz;
3199 	dp = (struct dirent *)cpos;
3200 	cookiep = cookies;
3201 	/*
3202 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
3203 	 * directory offset up to a block boundary, so it is necessary to
3204 	 * skip over the records that preceed the requested offset. This
3205 	 * requires the assumption that file offset cookies monotonically
3206 	 * increase.
3207 	 */
3208 	while (cpos < cend && ncookies > 0 &&
3209 		(dp->d_ino == 0 || dp->d_type == DT_WHT ||
3210 		 ((u_quad_t)(*cookiep)) <= toff)) {
3211 		dp = _DIRENT_NEXT(dp);
3212 		cpos = (char *)dp;
3213 		cookiep++;
3214 		ncookies--;
3215 	}
3216 	if (cpos >= cend || ncookies == 0) {
3217 		toff = off;
3218 		siz = fullsiz;
3219 		goto again;
3220 	}
3221 
3222 	/*
3223 	 * Probe one of the directory entries to see if the filesystem
3224 	 * supports VGET.
3225 	 */
3226 	if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp) == EOPNOTSUPP) {
3227 		error = NFSERR_NOTSUPP;
3228 		vrele(vp);
3229 		vp = NULL;
3230 		kfree((caddr_t)cookies, M_TEMP);
3231 		kfree((caddr_t)rbuf, M_TEMP);
3232 		nfsm_reply(NFSX_V3POSTOPATTR);
3233 		nfsm_srvpostop_attr(getret, &at);
3234 		error = 0;
3235 		goto nfsmout;
3236 	}
3237 	if (nvp) {
3238 		vput(nvp);
3239 		nvp = NULL;
3240 	}
3241 
3242 	dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
3243 	nfsm_reply(cnt);
3244 	nfsm_srvpostop_attr(getret, &at);
3245 	nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3246 	txdr_hyper(at.va_filerev, tl);
3247 	mp = mp2 = mb;
3248 	bp = bpos;
3249 	be = bp + M_TRAILINGSPACE(mp);
3250 
3251 	/* Loop through the records and build reply */
3252 	while (cpos < cend && ncookies > 0) {
3253 		if (dp->d_ino != 0 && dp->d_type != DT_WHT) {
3254 			nlen = dp->d_namlen;
3255 			rem = nfsm_rndup(nlen)-nlen;
3256 
3257 			/*
3258 			 * For readdir_and_lookup get the vnode using
3259 			 * the file number.
3260 			 */
3261 			if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp))
3262 				goto invalid;
3263 			bzero((caddr_t)nfhp, NFSX_V3FH);
3264 			nfhp->fh_fsid =
3265 				nvp->v_mount->mnt_stat.f_fsid;
3266 			if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3267 				vput(nvp);
3268 				nvp = NULL;
3269 				goto invalid;
3270 			}
3271 			if (VOP_GETATTR(nvp, vap)) {
3272 				vput(nvp);
3273 				nvp = NULL;
3274 				goto invalid;
3275 			}
3276 			vput(nvp);
3277 			nvp = NULL;
3278 
3279 			/*
3280 			 * If either the dircount or maxcount will be
3281 			 * exceeded, get out now. Both of these lengths
3282 			 * are calculated conservatively, including all
3283 			 * XDR overheads.
3284 			 */
3285 			len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3286 				NFSX_V3POSTOPATTR);
3287 			dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3288 			if (len > cnt || dirlen > fullsiz) {
3289 				eofflag = 0;
3290 				break;
3291 			}
3292 
3293 			/*
3294 			 * Build the directory record xdr from
3295 			 * the dirent entry.
3296 			 */
3297 			fp = (struct nfs_fattr *)&fl.fl_fattr;
3298 			nfsm_srvfillattr(vap, fp);
3299 			fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3300 			fl.fl_fhok = nfs_true;
3301 			fl.fl_postopok = nfs_true;
3302 			fl.fl_off.nfsuquad[0] = txdr_unsigned(*cookiep >> 32);
3303 			fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3304 
3305 			nfsm_clget;
3306 			*tl = nfs_true;
3307 			bp += NFSX_UNSIGNED;
3308 			nfsm_clget;
3309 			*tl = 0;
3310 			bp += NFSX_UNSIGNED;
3311 			nfsm_clget;
3312 			*tl = txdr_unsigned(dp->d_ino);
3313 			bp += NFSX_UNSIGNED;
3314 			nfsm_clget;
3315 			*tl = txdr_unsigned(nlen);
3316 			bp += NFSX_UNSIGNED;
3317 
3318 			/* And loop around copying the name */
3319 			xfer = nlen;
3320 			cp = dp->d_name;
3321 			while (xfer > 0) {
3322 				nfsm_clget;
3323 				if ((bp + xfer) > be)
3324 					tsiz = be - bp;
3325 				else
3326 					tsiz = xfer;
3327 				bcopy(cp, bp, tsiz);
3328 				bp += tsiz;
3329 				xfer -= tsiz;
3330 				if (xfer > 0)
3331 					cp += tsiz;
3332 			}
3333 			/* And null pad to a int32_t boundary */
3334 			for (i = 0; i < rem; i++)
3335 				*bp++ = '\0';
3336 
3337 			/*
3338 			 * Now copy the flrep structure out.
3339 			 */
3340 			xfer = sizeof (struct flrep);
3341 			cp = (caddr_t)&fl;
3342 			while (xfer > 0) {
3343 				nfsm_clget;
3344 				if ((bp + xfer) > be)
3345 					tsiz = be - bp;
3346 				else
3347 					tsiz = xfer;
3348 				bcopy(cp, bp, tsiz);
3349 				bp += tsiz;
3350 				xfer -= tsiz;
3351 				if (xfer > 0)
3352 					cp += tsiz;
3353 			}
3354 		}
3355 invalid:
3356 		dp = _DIRENT_NEXT(dp);
3357 		cpos = (char *)dp;
3358 		cookiep++;
3359 		ncookies--;
3360 	}
3361 	vrele(vp);
3362 	vp = NULL;
3363 	nfsm_clget;
3364 	*tl = nfs_false;
3365 	bp += NFSX_UNSIGNED;
3366 	nfsm_clget;
3367 	if (eofflag)
3368 		*tl = nfs_true;
3369 	else
3370 		*tl = nfs_false;
3371 	bp += NFSX_UNSIGNED;
3372 	if (mp != mb) {
3373 		if (bp < be)
3374 			mp->m_len = bp - mtod(mp, caddr_t);
3375 	} else
3376 		mp->m_len += bp - bpos;
3377 	FREE((caddr_t)cookies, M_TEMP);
3378 	FREE((caddr_t)rbuf, M_TEMP);
3379 nfsmout:
3380 	if (vp)
3381 		vrele(vp);
3382 	return(error);
3383 }
3384 
3385 /*
3386  * nfs commit service
3387  */
3388 int
3389 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3390 	     struct thread *td, struct mbuf **mrq)
3391 {
3392 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3393 	struct sockaddr *nam = nfsd->nd_nam;
3394 	caddr_t dpos = nfsd->nd_dpos;
3395 	struct ucred *cred = &nfsd->nd_cr;
3396 	struct vattr bfor, aft;
3397 	struct vnode *vp = NULL;
3398 	nfsfh_t nfh;
3399 	fhandle_t *fhp;
3400 	u_int32_t *tl;
3401 	int32_t t1;
3402 	caddr_t bpos;
3403 	int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
3404 	char *cp2;
3405 	struct mbuf *mb, *mb2, *mreq;
3406 	u_quad_t off;
3407 
3408 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3409 	fhp = &nfh.fh_generic;
3410 	nfsm_srvmtofh(fhp);
3411 	nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3412 
3413 	/*
3414 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
3415 	 * count parameters, so these arguments are useless (someday maybe).
3416 	 */
3417 	off = fxdr_hyper(tl);
3418 	tl += 2;
3419 	cnt = fxdr_unsigned(int, *tl);
3420 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3421 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3422 	if (error) {
3423 		nfsm_reply(2 * NFSX_UNSIGNED);
3424 		nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3425 		error = 0;
3426 		goto nfsmout;
3427 	}
3428 	for_ret = VOP_GETATTR(vp, &bfor);
3429 
3430 	if (cnt > MAX_COMMIT_COUNT) {
3431 		/*
3432 		 * Give up and do the whole thing
3433 		 */
3434 		if (vp->v_object &&
3435 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3436 			vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3437 		}
3438 		error = VOP_FSYNC(vp, MNT_WAIT);
3439 	} else {
3440 		/*
3441 		 * Locate and synchronously write any buffers that fall
3442 		 * into the requested range.  Note:  we are assuming that
3443 		 * f_iosize is a power of 2.
3444 		 */
3445 		int iosize = vp->v_mount->mnt_stat.f_iosize;
3446 		int iomask = iosize - 1;
3447 		off_t loffset;
3448 
3449 		/*
3450 		 * Align to iosize boundry, super-align to page boundry.
3451 		 */
3452 		if (off & iomask) {
3453 			cnt += off & iomask;
3454 			off &= ~(u_quad_t)iomask;
3455 		}
3456 		if (off & PAGE_MASK) {
3457 			cnt += off & PAGE_MASK;
3458 			off &= ~(u_quad_t)PAGE_MASK;
3459 		}
3460 		loffset = off;
3461 
3462 		if (vp->v_object &&
3463 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3464 			vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
3465 		}
3466 
3467 		crit_enter();
3468 		while (cnt > 0) {
3469 			struct buf *bp;
3470 
3471 			/*
3472 			 * If we have a buffer and it is marked B_DELWRI we
3473 			 * have to lock and write it.  Otherwise the prior
3474 			 * write is assumed to have already been committed.
3475 			 */
3476 			if ((bp = findblk(vp, loffset)) != NULL && (bp->b_flags & B_DELWRI)) {
3477 				if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
3478 					if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL) == 0)
3479 						BUF_UNLOCK(bp);
3480 					continue; /* retry */
3481 				}
3482 				bremfree(bp);
3483 				bp->b_flags &= ~B_ASYNC;
3484 				bwrite(bp);
3485 				++nfs_commit_miss;
3486 			}
3487 			++nfs_commit_blks;
3488 			if (cnt < iosize)
3489 				break;
3490 			cnt -= iosize;
3491 			loffset += iosize;
3492 		}
3493 		crit_exit();
3494 	}
3495 
3496 	aft_ret = VOP_GETATTR(vp, &aft);
3497 	vput(vp);
3498 	vp = NULL;
3499 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3500 	nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3501 	if (!error) {
3502 		nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
3503 		if (nfsver.tv_sec == 0)
3504 			nfsver = boottime;
3505 		*tl++ = txdr_unsigned(nfsver.tv_sec);
3506 		*tl = txdr_unsigned(nfsver.tv_nsec / 1000);
3507 	} else {
3508 		error = 0;
3509 	}
3510 nfsmout:
3511 	if (vp)
3512 		vput(vp);
3513 	return(error);
3514 }
3515 
3516 /*
3517  * nfs statfs service
3518  */
3519 int
3520 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3521 	     struct thread *td, struct mbuf **mrq)
3522 {
3523 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3524 	struct sockaddr *nam = nfsd->nd_nam;
3525 	caddr_t dpos = nfsd->nd_dpos;
3526 	struct ucred *cred = &nfsd->nd_cr;
3527 	struct statfs *sf;
3528 	struct nfs_statfs *sfp;
3529 	u_int32_t *tl;
3530 	int32_t t1;
3531 	caddr_t bpos;
3532 	int error = 0, rdonly, getret = 1;
3533 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3534 	char *cp2;
3535 	struct mbuf *mb, *mb2, *mreq;
3536 	struct vnode *vp = NULL;
3537 	struct vattr at;
3538 	nfsfh_t nfh;
3539 	fhandle_t *fhp;
3540 	struct statfs statfs;
3541 	u_quad_t tval;
3542 
3543 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3544 	fhp = &nfh.fh_generic;
3545 	nfsm_srvmtofh(fhp);
3546 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3547 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3548 	if (error) {
3549 		nfsm_reply(NFSX_UNSIGNED);
3550 		nfsm_srvpostop_attr(getret, &at);
3551 		error = 0;
3552 		goto nfsmout;
3553 	}
3554 	sf = &statfs;
3555 	error = VFS_STATFS(vp->v_mount, sf, proc0.p_ucred);
3556 	getret = VOP_GETATTR(vp, &at);
3557 	vput(vp);
3558 	vp = NULL;
3559 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3560 	if (v3)
3561 		nfsm_srvpostop_attr(getret, &at);
3562 	if (error) {
3563 		error = 0;
3564 		goto nfsmout;
3565 	}
3566 	nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
3567 	if (v3) {
3568 		tval = (u_quad_t)sf->f_blocks;
3569 		tval *= (u_quad_t)sf->f_bsize;
3570 		txdr_hyper(tval, &sfp->sf_tbytes);
3571 		tval = (u_quad_t)sf->f_bfree;
3572 		tval *= (u_quad_t)sf->f_bsize;
3573 		txdr_hyper(tval, &sfp->sf_fbytes);
3574 		tval = (u_quad_t)sf->f_bavail;
3575 		tval *= (u_quad_t)sf->f_bsize;
3576 		txdr_hyper(tval, &sfp->sf_abytes);
3577 		sfp->sf_tfiles.nfsuquad[0] = 0;
3578 		sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3579 		sfp->sf_ffiles.nfsuquad[0] = 0;
3580 		sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3581 		sfp->sf_afiles.nfsuquad[0] = 0;
3582 		sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3583 		sfp->sf_invarsec = 0;
3584 	} else {
3585 		sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3586 		sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3587 		sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3588 		sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3589 		sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3590 	}
3591 nfsmout:
3592 	if (vp)
3593 		vput(vp);
3594 	return(error);
3595 }
3596 
3597 /*
3598  * nfs fsinfo service
3599  */
3600 int
3601 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3602 	     struct thread *td, struct mbuf **mrq)
3603 {
3604 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3605 	struct sockaddr *nam = nfsd->nd_nam;
3606 	caddr_t dpos = nfsd->nd_dpos;
3607 	struct ucred *cred = &nfsd->nd_cr;
3608 	u_int32_t *tl;
3609 	struct nfsv3_fsinfo *sip;
3610 	int32_t t1;
3611 	caddr_t bpos;
3612 	int error = 0, rdonly, getret = 1, pref;
3613 	char *cp2;
3614 	struct mbuf *mb, *mb2, *mreq;
3615 	struct vnode *vp = NULL;
3616 	struct vattr at;
3617 	nfsfh_t nfh;
3618 	fhandle_t *fhp;
3619 	u_quad_t maxfsize;
3620 	struct statfs sb;
3621 
3622 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3623 	fhp = &nfh.fh_generic;
3624 	nfsm_srvmtofh(fhp);
3625 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3626 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3627 	if (error) {
3628 		nfsm_reply(NFSX_UNSIGNED);
3629 		nfsm_srvpostop_attr(getret, &at);
3630 		error = 0;
3631 		goto nfsmout;
3632 	}
3633 
3634 	/* XXX Try to make a guess on the max file size. */
3635 	VFS_STATFS(vp->v_mount, &sb, proc0.p_ucred);
3636 	maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3637 
3638 	getret = VOP_GETATTR(vp, &at);
3639 	vput(vp);
3640 	vp = NULL;
3641 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3642 	nfsm_srvpostop_attr(getret, &at);
3643 	nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3644 
3645 	/*
3646 	 * XXX
3647 	 * There should be file system VFS OP(s) to get this information.
3648 	 * For now, assume ufs.
3649 	 */
3650 	if (slp->ns_so->so_type == SOCK_DGRAM)
3651 		pref = NFS_MAXDGRAMDATA;
3652 	else
3653 		pref = NFS_MAXDATA;
3654 	sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
3655 	sip->fs_rtpref = txdr_unsigned(pref);
3656 	sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3657 	sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
3658 	sip->fs_wtpref = txdr_unsigned(pref);
3659 	sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3660 	sip->fs_dtpref = txdr_unsigned(pref);
3661 	txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3662 	sip->fs_timedelta.nfsv3_sec = 0;
3663 	sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3664 	sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3665 		NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3666 		NFSV3FSINFO_CANSETTIME);
3667 nfsmout:
3668 	if (vp)
3669 		vput(vp);
3670 	return(error);
3671 }
3672 
3673 /*
3674  * nfs pathconf service
3675  */
3676 int
3677 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3678 	       struct thread *td, struct mbuf **mrq)
3679 {
3680 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3681 	struct sockaddr *nam = nfsd->nd_nam;
3682 	caddr_t dpos = nfsd->nd_dpos;
3683 	struct ucred *cred = &nfsd->nd_cr;
3684 	u_int32_t *tl;
3685 	struct nfsv3_pathconf *pc;
3686 	int32_t t1;
3687 	caddr_t bpos;
3688 	int error = 0, rdonly, getret = 1;
3689 	register_t linkmax, namemax, chownres, notrunc;
3690 	char *cp2;
3691 	struct mbuf *mb, *mb2, *mreq;
3692 	struct vnode *vp = NULL;
3693 	struct vattr at;
3694 	nfsfh_t nfh;
3695 	fhandle_t *fhp;
3696 
3697 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3698 	fhp = &nfh.fh_generic;
3699 	nfsm_srvmtofh(fhp);
3700 	error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3701 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3702 	if (error) {
3703 		nfsm_reply(NFSX_UNSIGNED);
3704 		nfsm_srvpostop_attr(getret, &at);
3705 		error = 0;
3706 		goto nfsmout;
3707 	}
3708 	error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3709 	if (!error)
3710 		error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3711 	if (!error)
3712 		error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3713 	if (!error)
3714 		error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
3715 	getret = VOP_GETATTR(vp, &at);
3716 	vput(vp);
3717 	vp = NULL;
3718 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3719 	nfsm_srvpostop_attr(getret, &at);
3720 	if (error) {
3721 		error = 0;
3722 		goto nfsmout;
3723 	}
3724 	nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3725 
3726 	pc->pc_linkmax = txdr_unsigned(linkmax);
3727 	pc->pc_namemax = txdr_unsigned(namemax);
3728 	pc->pc_notrunc = txdr_unsigned(notrunc);
3729 	pc->pc_chownrestricted = txdr_unsigned(chownres);
3730 
3731 	/*
3732 	 * These should probably be supported by VOP_PATHCONF(), but
3733 	 * until msdosfs is exportable (why would you want to?), the
3734 	 * Unix defaults should be ok.
3735 	 */
3736 	pc->pc_caseinsensitive = nfs_false;
3737 	pc->pc_casepreserving = nfs_true;
3738 nfsmout:
3739 	if (vp)
3740 		vput(vp);
3741 	return(error);
3742 }
3743 
3744 /*
3745  * Null operation, used by clients to ping server
3746  */
3747 /* ARGSUSED */
3748 int
3749 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3750 	   struct thread *td, struct mbuf **mrq)
3751 {
3752 	struct mbuf *mrep = nfsd->nd_mrep;
3753 	caddr_t bpos;
3754 	int error = NFSERR_RETVOID;
3755 	struct mbuf *mb, *mreq;
3756 
3757 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3758 	nfsm_reply(0);
3759 	nfsm_srvdone;
3760 }
3761 
3762 /*
3763  * No operation, used for obsolete procedures
3764  */
3765 /* ARGSUSED */
3766 int
3767 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3768 	   struct thread *td, struct mbuf **mrq)
3769 {
3770 	struct mbuf *mrep = nfsd->nd_mrep;
3771 	caddr_t bpos;
3772 	int error;
3773 	struct mbuf *mb, *mreq;
3774 
3775 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3776 	if (nfsd->nd_repstat)
3777 		error = nfsd->nd_repstat;
3778 	else
3779 		error = EPROCUNAVAIL;
3780 	nfsm_reply(0);
3781 	error = 0;
3782 	nfsm_srvdone;
3783 }
3784 
3785 /*
3786  * Perform access checking for vnodes obtained from file handles that would
3787  * refer to files already opened by a Unix client. You cannot just use
3788  * vn_writechk() and VOP_ACCESS() for two reasons.
3789  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3790  * 2 - The owner is to be given access irrespective of mode bits for some
3791  *     operations, so that processes that chmod after opening a file don't
3792  *     break. I don't like this because it opens a security hole, but since
3793  *     the nfs server opens a security hole the size of a barn door anyhow,
3794  *     what the heck.
3795  *
3796  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3797  * will return EPERM instead of EACCESS. EPERM is always an error.
3798  */
3799 static int
3800 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred,
3801 	     int rdonly, struct thread *td, int override)
3802 {
3803 	struct vattr vattr;
3804 	int error;
3805 
3806 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3807 	if (flags & VWRITE) {
3808 		/* Just vn_writechk() changed to check rdonly */
3809 		/*
3810 		 * Disallow write attempts on read-only file systems;
3811 		 * unless the file is a socket or a block or character
3812 		 * device resident on the file system.
3813 		 */
3814 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3815 			switch (vp->v_type) {
3816 			case VREG:
3817 			case VDIR:
3818 			case VLNK:
3819 				return (EROFS);
3820 			default:
3821 				break;
3822 			}
3823 		}
3824 		/*
3825 		 * If there's shared text associated with
3826 		 * the inode, we can't allow writing.
3827 		 */
3828 		if (vp->v_flag & VTEXT)
3829 			return (ETXTBSY);
3830 	}
3831 	error = VOP_GETATTR(vp, &vattr);
3832 	if (error)
3833 		return (error);
3834 	error = VOP_ACCESS(vp, flags, cred);
3835 	/*
3836 	 * Allow certain operations for the owner (reads and writes
3837 	 * on files that are already open).
3838 	 */
3839 	if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3840 		error = 0;
3841 	return error;
3842 }
3843 #endif /* NFS_NOSERVER */
3844 
3845