xref: /openbsd-src/sys/nfs/nfs_vnops.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: nfs_vnops.c,v 1.55 2003/06/02 23:28:20 millert Exp $	*/
2 /*	$NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $	*/
3 
4 /*
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Rick Macklem at The University of Guelph.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)nfs_vnops.c	8.16 (Berkeley) 5/27/95
36  */
37 
38 
39 /*
40  * vnode op calls for Sun NFS version 2 and 3
41  */
42 
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/resourcevar.h>
48 #include <sys/proc.h>
49 #include <sys/mount.h>
50 #include <sys/buf.h>
51 #include <sys/malloc.h>
52 #include <sys/mbuf.h>
53 #include <sys/conf.h>
54 #include <sys/namei.h>
55 #include <sys/vnode.h>
56 #include <sys/dirent.h>
57 #include <sys/fcntl.h>
58 #include <sys/lockf.h>
59 
60 #include <uvm/uvm_extern.h>
61 
62 #include <miscfs/specfs/specdev.h>
63 #include <miscfs/fifofs/fifo.h>
64 
65 #include <nfs/rpcv2.h>
66 #include <nfs/nfsproto.h>
67 #include <nfs/nfs.h>
68 #include <nfs/nfsnode.h>
69 #include <nfs/nfsmount.h>
70 #include <nfs/xdr_subs.h>
71 #include <nfs/nfsm_subs.h>
72 #include <nfs/nfs_var.h>
73 
74 #include <net/if.h>
75 #include <netinet/in.h>
76 #include <netinet/in_var.h>
77 
78 /* Defs */
79 #define	TRUE	1
80 #define	FALSE	0
81 
82 /*
83  * Global vfs data structures for nfs
84  */
85 int (**nfsv2_vnodeop_p)(void *);
86 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
87 	{ &vop_default_desc, vn_default_error },
88 	{ &vop_lookup_desc, nfs_lookup },	/* lookup */
89 	{ &vop_create_desc, nfs_create },	/* create */
90 	{ &vop_mknod_desc, nfs_mknod },		/* mknod */
91 	{ &vop_open_desc, nfs_open },		/* open */
92 	{ &vop_close_desc, nfs_close },		/* close */
93 	{ &vop_access_desc, nfs_access },	/* access */
94 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
95 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
96 	{ &vop_read_desc, nfs_read },		/* read */
97 	{ &vop_write_desc, nfs_write },		/* write */
98 	{ &vop_lease_desc, nfs_lease_check },	/* lease */
99 	{ &vop_ioctl_desc, nfs_ioctl },		/* ioctl */
100 	{ &vop_select_desc, nfs_select },	/* select */
101 	{ &vop_kqfilter_desc, vop_generic_kqfilter },	/* kqfilter */
102 	{ &vop_revoke_desc, nfs_revoke },	/* revoke */
103 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
104 	{ &vop_remove_desc, nfs_remove },	/* remove */
105 	{ &vop_link_desc, nfs_link },		/* link */
106 	{ &vop_rename_desc, nfs_rename },	/* rename */
107 	{ &vop_mkdir_desc, nfs_mkdir },		/* mkdir */
108 	{ &vop_rmdir_desc, nfs_rmdir },		/* rmdir */
109 	{ &vop_symlink_desc, nfs_symlink },	/* symlink */
110 	{ &vop_readdir_desc, nfs_readdir },	/* readdir */
111 	{ &vop_readlink_desc, nfs_readlink },	/* readlink */
112 	{ &vop_abortop_desc, vop_generic_abortop },	/* abortop */
113 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
114 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
115 	{ &vop_lock_desc, nfs_lock },		/* lock */
116 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
117 	{ &vop_bmap_desc, nfs_bmap },		/* bmap */
118 	{ &vop_strategy_desc, nfs_strategy },	/* strategy */
119 	{ &vop_print_desc, nfs_print },		/* print */
120 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
121 	{ &vop_pathconf_desc, nfs_pathconf },	/* pathconf */
122 	{ &vop_advlock_desc, nfs_advlock },	/* advlock */
123 	{ &vop_reallocblks_desc, nfs_reallocblks },	/* reallocblks */
124 	{ &vop_bwrite_desc, nfs_bwrite },
125 	{ NULL, NULL }
126 };
127 struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
128 	{ &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
129 
130 /*
131  * Special device vnode ops
132  */
133 int (**spec_nfsv2nodeop_p)(void *);
134 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
135 	{ &vop_default_desc, spec_vnoperate },
136 	{ &vop_close_desc, nfsspec_close },	/* close */
137 	{ &vop_access_desc, nfsspec_access },	/* access */
138 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
139 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
140 	{ &vop_read_desc, nfsspec_read },	/* read */
141 	{ &vop_write_desc, nfsspec_write },	/* write */
142 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
143 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
144 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
145 	{ &vop_lock_desc, nfs_lock },		/* lock */
146 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
147 	{ &vop_print_desc, nfs_print },		/* print */
148 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
149 	{ NULL, NULL }
150 };
151 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
152 	{ &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
153 
154 #ifdef FIFO
155 int (**fifo_nfsv2nodeop_p)(void *);
156 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
157 	{ &vop_default_desc, fifo_vnoperate },
158 	{ &vop_close_desc, nfsfifo_close },	/* close */
159 	{ &vop_access_desc, nfsspec_access },	/* access */
160 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
161 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
162 	{ &vop_read_desc, nfsfifo_read },	/* read */
163 	{ &vop_write_desc, nfsfifo_write },	/* write */
164 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
165 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
166 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
167 	{ &vop_lock_desc, nfs_lock },		/* lock */
168 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
169 	{ &vop_print_desc, nfs_print },		/* print */
170 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
171 	{ &vop_bwrite_desc, vop_generic_bwrite },
172 	{ NULL, NULL }
173 };
174 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
175 	{ &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
176 #endif /* FIFO */
177 
178 /*
179  * Global variables
180  */
181 extern u_int32_t nfs_true, nfs_false;
182 extern u_int32_t nfs_xdrneg1;
183 extern struct nfsstats nfsstats;
184 extern nfstype nfsv3_type[9];
185 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
186 int nfs_numasync = 0;
187 
188 /*
189  * nfs null call from vfs.
190  */
191 int
192 nfs_null(vp, cred, procp)
193 	struct vnode *vp;
194 	struct ucred *cred;
195 	struct proc *procp;
196 {
197 	caddr_t bpos, dpos;
198 	int error = 0;
199 	struct mbuf *mreq, *mrep, *md, *mb;
200 
201 	nfsm_reqhead(vp, NFSPROC_NULL, 0);
202 	nfsm_request(vp, NFSPROC_NULL, procp, cred);
203 	nfsm_reqdone;
204 	return (error);
205 }
206 
207 /*
208  * nfs access vnode op.
209  * For nfs version 2, just return ok. File accesses may fail later.
210  * For nfs version 3, use the access rpc to check accessibility. If file modes
211  * are changed on the server, accesses might still fail later.
212  */
213 int
214 nfs_access(v)
215 	void *v;
216 {
217 	struct vop_access_args /* {
218 		struct vnode *a_vp;
219 		int  a_mode;
220 		struct ucred *a_cred;
221 		struct proc *a_p;
222 	} */ *ap = v;
223 	struct vnode *vp = ap->a_vp;
224 	u_int32_t *tl;
225 	caddr_t cp;
226 	int32_t t1, t2;
227 	caddr_t bpos, dpos, cp2;
228 	int error = 0, attrflag;
229 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
230 	u_int32_t mode, rmode;
231 	int v3 = NFS_ISV3(vp);
232 
233 	/*
234 	 * Disallow write attempts on filesystems mounted read-only;
235 	 * unless the file is a socket, fifo, or a block or character
236 	 * device resident on the filesystem.
237 	 */
238 	if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
239 		switch (vp->v_type) {
240 		case VREG:
241 		case VDIR:
242 		case VLNK:
243 			return (EROFS);
244 		default:
245 			break;
246 		}
247 	}
248 	/*
249 	 * For nfs v3, do an access rpc, otherwise you are stuck emulating
250 	 * ufs_access() locally using the vattr. This may not be correct,
251 	 * since the server may apply other access criteria such as
252 	 * client uid-->server uid mapping that we do not know about, but
253 	 * this is better than just returning anything that is lying about
254 	 * in the cache.
255 	 */
256 	if (v3) {
257 		nfsstats.rpccnt[NFSPROC_ACCESS]++;
258 		nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
259 		nfsm_fhtom(vp, v3);
260 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
261 		if (ap->a_mode & VREAD)
262 			mode = NFSV3ACCESS_READ;
263 		else
264 			mode = 0;
265 		if (vp->v_type == VDIR) {
266 			if (ap->a_mode & VWRITE)
267 				mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
268 					 NFSV3ACCESS_DELETE);
269 			if (ap->a_mode & VEXEC)
270 				mode |= NFSV3ACCESS_LOOKUP;
271 		} else {
272 			if (ap->a_mode & VWRITE)
273 				mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
274 			if (ap->a_mode & VEXEC)
275 				mode |= NFSV3ACCESS_EXECUTE;
276 		}
277 		*tl = txdr_unsigned(mode);
278 		nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
279 		nfsm_postop_attr(vp, attrflag);
280 		if (!error) {
281 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
282 			rmode = fxdr_unsigned(u_int32_t, *tl);
283 			/*
284 			 * The NFS V3 spec does not clarify whether or not
285 			 * the returned access bits can be a superset of
286 			 * the ones requested, so...
287 			 */
288 			if ((rmode & mode) != mode)
289 				error = EACCES;
290 		}
291 		nfsm_reqdone;
292 		return (error);
293 	} else
294 		return (nfsspec_access(ap));
295 }
296 
297 /*
298  * nfs open vnode op
299  * Check to see if the type is ok
300  * and that deletion is not in progress.
301  * For paged in text files, you will need to flush the page cache
302  * if consistency is lost.
303  */
304 /* ARGSUSED */
305 int
306 nfs_open(v)
307 	void *v;
308 {
309 	struct vop_open_args /* {
310 		struct vnode *a_vp;
311 		int  a_mode;
312 		struct ucred *a_cred;
313 		struct proc *a_p;
314 	} */ *ap = v;
315 	struct vnode *vp = ap->a_vp;
316 	struct nfsnode *np = VTONFS(vp);
317 	struct vattr vattr;
318 	int error;
319 
320 	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
321 #ifdef DIAGNOSTIC
322 		printf("open eacces vtyp=%d\n",vp->v_type);
323 #endif
324 		return (EACCES);
325 	}
326 
327 	/*
328 	 * Initialize read and write creds here, for swapfiles
329 	 * and other paths that don't set the creds themselves.
330 	 */
331 
332 	if (ap->a_mode & FREAD) {
333 		if (np->n_rcred) {
334 			crfree(np->n_rcred);
335 		}
336 		np->n_rcred = ap->a_cred;
337 		crhold(np->n_rcred);
338 	}
339 	if (ap->a_mode & FWRITE) {
340 		if (np->n_wcred) {
341 			crfree(np->n_wcred);
342 		}
343 		np->n_wcred = ap->a_cred;
344 		crhold(np->n_wcred);
345 	}
346 
347 	if (np->n_flag & NMODIFIED) {
348 		if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
349 			 ap->a_p, 1)) == EINTR)
350 			return (error);
351 		uvm_vnp_uncache(vp);
352 		np->n_attrstamp = 0;
353 		if (vp->v_type == VDIR)
354 			np->n_direofoffset = 0;
355 		error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
356 		if (error)
357 			return (error);
358 		np->n_mtime = vattr.va_mtime.tv_sec;
359 	} else {
360 		error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
361 		if (error)
362 			return (error);
363 		if (np->n_mtime != vattr.va_mtime.tv_sec) {
364 			if (vp->v_type == VDIR)
365 				np->n_direofoffset = 0;
366 			if ((error = nfs_vinvalbuf(vp, V_SAVE,
367 				 ap->a_cred, ap->a_p, 1)) == EINTR)
368 				return (error);
369 			uvm_vnp_uncache(vp);
370 			np->n_mtime = vattr.va_mtime.tv_sec;
371 		}
372 	}
373 	np->n_attrstamp = 0; /* For Open/Close consistency */
374 	return (0);
375 }
376 
377 /*
378  * nfs close vnode op
379  * What an NFS client should do upon close after writing is a debatable issue.
380  * Most NFS clients push delayed writes to the server upon close, basically for
381  * two reasons:
382  * 1 - So that any write errors may be reported back to the client process
383  *     doing the close system call. By far the two most likely errors are
384  *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
385  * 2 - To put a worst case upper bound on cache inconsistency between
386  *     multiple clients for the file.
387  * There is also a consistency problem for Version 2 of the protocol w.r.t.
388  * not being able to tell if other clients are writing a file concurrently,
389  * since there is no way of knowing if the changed modify time in the reply
390  * is only due to the write for this client.
391  * (NFS Version 3 provides weak cache consistency data in the reply that
392  *  should be sufficient to detect and handle this case.)
393  *
394  * The current code does the following:
395  * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
396  * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
397  *                     or commit them (this satisfies 1 and 2 except for the
398  *                     case where the server crashes after this close but
399  *                     before the commit RPC, which is felt to be "good
400  *                     enough". Changing the last argument to nfs_flush() to
401  *                     a 1 would force a commit operation, if it is felt a
402  *                     commit is necessary now.
403  */
404 /* ARGSUSED */
405 int
406 nfs_close(v)
407 	void *v;
408 {
409 	struct vop_close_args /* {
410 		struct vnodeop_desc *a_desc;
411 		struct vnode *a_vp;
412 		int  a_fflag;
413 		struct ucred *a_cred;
414 		struct proc *a_p;
415 	} */ *ap = v;
416 	struct vnode *vp = ap->a_vp;
417 	struct nfsnode *np = VTONFS(vp);
418 	int error = 0;
419 
420 	if (vp->v_type == VREG) {
421 	    if (np->n_flag & NMODIFIED) {
422 		if (NFS_ISV3(vp)) {
423 		    error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
424 		    np->n_flag &= ~NMODIFIED;
425 		} else
426 		    error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
427 		np->n_attrstamp = 0;
428 	    }
429 	    if (np->n_flag & NWRITEERR) {
430 		np->n_flag &= ~NWRITEERR;
431 		error = np->n_error;
432 	    }
433 	}
434 	return (error);
435 }
436 
437 /*
438  * nfs getattr call from vfs.
439  */
440 int
441 nfs_getattr(v)
442 	void *v;
443 {
444 	struct vop_getattr_args /* {
445 		struct vnode *a_vp;
446 		struct vattr *a_vap;
447 		struct ucred *a_cred;
448 		struct proc *a_p;
449 	} */ *ap = v;
450 	struct vnode *vp = ap->a_vp;
451 	struct nfsnode *np = VTONFS(vp);
452 	caddr_t cp;
453 	u_int32_t *tl;
454 	int32_t t1, t2;
455 	caddr_t bpos, dpos;
456 	int error = 0;
457 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
458 	int v3 = NFS_ISV3(vp);
459 
460 	/*
461 	 * Update local times for special files.
462 	 */
463 	if (np->n_flag & (NACC | NUPD))
464 		np->n_flag |= NCHG;
465 	/*
466 	 * First look in the cache.
467 	 */
468 	if (nfs_getattrcache(vp, ap->a_vap) == 0)
469 		return (0);
470 	nfsstats.rpccnt[NFSPROC_GETATTR]++;
471 	nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
472 	nfsm_fhtom(vp, v3);
473 	nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
474 	if (!error)
475 		nfsm_loadattr(vp, ap->a_vap);
476 	nfsm_reqdone;
477 	return (error);
478 }
479 
480 /*
481  * nfs setattr call.
482  */
483 int
484 nfs_setattr(v)
485 	void *v;
486 {
487 	struct vop_setattr_args /* {
488 		struct vnodeop_desc *a_desc;
489 		struct vnode *a_vp;
490 		struct vattr *a_vap;
491 		struct ucred *a_cred;
492 		struct proc *a_p;
493 	} */ *ap = v;
494 	struct vnode *vp = ap->a_vp;
495 	struct nfsnode *np = VTONFS(vp);
496 	struct vattr *vap = ap->a_vap;
497 	int error = 0;
498 	u_quad_t tsize = 0;
499 
500 	/*
501 	 * Setting of flags is not supported.
502 	 */
503 	if (vap->va_flags != VNOVAL)
504 		return (EOPNOTSUPP);
505 
506 	/*
507 	 * Disallow write attempts if the filesystem is mounted read-only.
508 	 */
509   	if ((vap->va_uid != (uid_t)VNOVAL ||
510 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
511 	    vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
512 	    (vp->v_mount->mnt_flag & MNT_RDONLY))
513 		return (EROFS);
514 	if (vap->va_size != VNOVAL) {
515  		switch (vp->v_type) {
516  		case VDIR:
517  			return (EISDIR);
518  		case VCHR:
519  		case VBLK:
520  		case VSOCK:
521  		case VFIFO:
522 			if (vap->va_mtime.tv_sec == VNOVAL &&
523 			    vap->va_atime.tv_sec == VNOVAL &&
524 			    vap->va_mode == (mode_t)VNOVAL &&
525 			    vap->va_uid == (uid_t)VNOVAL &&
526 			    vap->va_gid == (gid_t)VNOVAL)
527 				return (0);
528  			vap->va_size = VNOVAL;
529  			break;
530  		default:
531 			/*
532 			 * Disallow write attempts if the filesystem is
533 			 * mounted read-only.
534 			 */
535 			if (vp->v_mount->mnt_flag & MNT_RDONLY)
536 				return (EROFS);
537  			if (vap->va_size == 0)
538  				error = nfs_vinvalbuf(vp, 0,
539  				     ap->a_cred, ap->a_p, 1);
540 			else
541 				error = nfs_vinvalbuf(vp, V_SAVE,
542  				     ap->a_cred, ap->a_p, 1);
543 			if (error)
544 				return (error);
545  			tsize = np->n_size;
546  			np->n_size = np->n_vattr.va_size = vap->va_size;
547 			uvm_vnp_setsize(vp, np->n_size);
548   		};
549   	} else if ((vap->va_mtime.tv_sec != VNOVAL ||
550 		vap->va_atime.tv_sec != VNOVAL) &&
551 		vp->v_type == VREG &&
552   		(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
553 		 ap->a_p, 1)) == EINTR)
554 		return (error);
555 	error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
556 	if (error && vap->va_size != VNOVAL) {
557 		np->n_size = np->n_vattr.va_size = tsize;
558 		uvm_vnp_setsize(vp, np->n_size);
559 	}
560 	return (error);
561 }
562 
563 /*
564  * Do an nfs setattr rpc.
565  */
566 int
567 nfs_setattrrpc(vp, vap, cred, procp)
568 	struct vnode *vp;
569 	struct vattr *vap;
570 	struct ucred *cred;
571 	struct proc *procp;
572 {
573 	struct nfsv2_sattr *sp;
574 	caddr_t cp;
575 	int32_t t1, t2;
576 	caddr_t bpos, dpos, cp2;
577 	u_int32_t *tl;
578 	int error = 0, wccflag = NFSV3_WCCRATTR;
579 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
580 	int v3 = NFS_ISV3(vp);
581 
582 	nfsstats.rpccnt[NFSPROC_SETATTR]++;
583 	nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
584 	nfsm_fhtom(vp, v3);
585 	if (v3) {
586 		nfsm_v3attrbuild(vap, TRUE);
587 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
588 		*tl = nfs_false;
589 	} else {
590 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
591 		if (vap->va_mode == (mode_t)VNOVAL)
592 			sp->sa_mode = nfs_xdrneg1;
593 		else
594 			sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
595 		if (vap->va_uid == (uid_t)VNOVAL)
596 			sp->sa_uid = nfs_xdrneg1;
597 		else
598 			sp->sa_uid = txdr_unsigned(vap->va_uid);
599 		if (vap->va_gid == (gid_t)VNOVAL)
600 			sp->sa_gid = nfs_xdrneg1;
601 		else
602 			sp->sa_gid = txdr_unsigned(vap->va_gid);
603 		sp->sa_size = txdr_unsigned(vap->va_size);
604 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
605 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
606 	}
607 	nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
608 	if (v3) {
609 		nfsm_wcc_data(vp, wccflag);
610 	} else
611 		nfsm_loadattr(vp, (struct vattr *)0);
612 	nfsm_reqdone;
613 	return (error);
614 }
615 
616 /*
617  * nfs lookup call, one step at a time...
618  * First look in cache
619  * If not found, unlock the directory nfsnode and do the rpc
620  */
621 int
622 nfs_lookup(v)
623 	void *v;
624 {
625 	struct vop_lookup_args /* {
626 		struct vnodeop_desc *a_desc;
627 		struct vnode *a_dvp;
628 		struct vnode **a_vpp;
629 		struct componentname *a_cnp;
630 	} */ *ap = v;
631 	struct componentname *cnp = ap->a_cnp;
632 	struct vnode *dvp = ap->a_dvp;
633 	struct vnode **vpp = ap->a_vpp;
634 	struct proc *p = cnp->cn_proc;
635 	int flags;
636 	struct vnode *newvp;
637 	u_int32_t *tl;
638 	caddr_t cp;
639 	int32_t t1, t2;
640 	struct nfsmount *nmp;
641 	caddr_t bpos, dpos, cp2;
642 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
643 	long len;
644 	nfsfh_t *fhp;
645 	struct nfsnode *np;
646 	int lockparent, wantparent, error = 0, attrflag, fhsize;
647 	int v3 = NFS_ISV3(dvp);
648 
649 	cnp->cn_flags &= ~PDIRUNLOCK;
650 	flags = cnp->cn_flags;
651 
652 	*vpp = NULLVP;
653 	if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
654 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
655 		return (EROFS);
656 	if (dvp->v_type != VDIR)
657 		return (ENOTDIR);
658 	lockparent = flags & LOCKPARENT;
659 	wantparent = flags & (LOCKPARENT|WANTPARENT);
660 	nmp = VFSTONFS(dvp->v_mount);
661 	np = VTONFS(dvp);
662 
663 	/*
664 	 * Before tediously performing a linear scan of the directory,
665 	 * check the name cache to see if the directory/name pair
666 	 * we are looking for is known already.
667 	 * If the directory/name pair is found in the name cache,
668 	 * we have to ensure the directory has not changed from
669 	 * the time the cache entry has been created. If it has,
670 	 * the cache entry has to be ignored.
671 	 */
672 	if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
673 		struct vattr vattr;
674 		int err2;
675 
676 		if (error && error != ENOENT) {
677 			*vpp = NULLVP;
678 			return (error);
679 		}
680 
681 		if (cnp->cn_flags & PDIRUNLOCK) {
682 			err2 = vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
683 			if (err2 != 0) {
684 				*vpp = NULLVP;
685 				return (err2);
686 			}
687 			cnp->cn_flags &= ~PDIRUNLOCK;
688 		}
689 
690 		err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
691 		if (err2 != 0) {
692 			if (error == 0) {
693 				if (*vpp != dvp)
694 					vput(*vpp);
695 				else
696 					vrele(*vpp);
697 			}
698 			*vpp = NULLVP;
699 			return (err2);
700 		}
701 
702 		if (error == ENOENT) {
703 			if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
704 			    cnp->cn_proc) && vattr.va_mtime.tv_sec ==
705 			    VTONFS(dvp)->n_ctime)
706 				return (ENOENT);
707 			cache_purge(dvp);
708 			np->n_ctime = 0;
709 			goto dorpc;
710 		}
711 
712 		newvp = *vpp;
713 		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
714 			&& vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime)
715 		{
716 			nfsstats.lookupcache_hits++;
717 			if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
718 				cnp->cn_flags |= SAVENAME;
719 			if ((!lockparent || !(flags & ISLASTCN)) &&
720 			     newvp != dvp)
721 				VOP_UNLOCK(dvp, 0, p);
722 			return (0);
723 		}
724 		cache_purge(newvp);
725 		if (newvp != dvp)
726 			vput(newvp);
727 		else
728 			vrele(newvp);
729 		*vpp = NULLVP;
730 	}
731 dorpc:
732 	error = 0;
733 	newvp = NULLVP;
734 	nfsstats.lookupcache_misses++;
735 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
736 	len = cnp->cn_namelen;
737 	nfsm_reqhead(dvp, NFSPROC_LOOKUP,
738 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
739 	nfsm_fhtom(dvp, v3);
740 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
741 	nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
742 	if (error) {
743 		nfsm_postop_attr(dvp, attrflag);
744 		m_freem(mrep);
745 		goto nfsmout;
746 	}
747 	nfsm_getfh(fhp, fhsize, v3);
748 
749 	/*
750 	 * Handle RENAME case...
751 	 */
752 	if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
753 		if (NFS_CMPFH(np, fhp, fhsize)) {
754 			m_freem(mrep);
755 			return (EISDIR);
756 		}
757 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
758 		if (error) {
759 			m_freem(mrep);
760 			return (error);
761 		}
762 		newvp = NFSTOV(np);
763 		if (v3) {
764 			nfsm_postop_attr(newvp, attrflag);
765 			nfsm_postop_attr(dvp, attrflag);
766 		} else
767 			nfsm_loadattr(newvp, (struct vattr *)0);
768 		*vpp = newvp;
769 		m_freem(mrep);
770 		cnp->cn_flags |= SAVENAME;
771 		if (!lockparent) {
772 			VOP_UNLOCK(dvp, 0, p);
773 			cnp->cn_flags |= PDIRUNLOCK;
774 		}
775 		return (0);
776 	}
777 
778 	/*
779 	 * The postop attr handling is duplicated for each if case,
780 	 * because it should be done while dvp is locked (unlocking
781 	 * dvp is different for each case).
782 	 */
783 
784 	if (NFS_CMPFH(np, fhp, fhsize)) {
785 		VREF(dvp);
786 		newvp = dvp;
787 		if (v3) {
788 			nfsm_postop_attr(newvp, attrflag);
789 			nfsm_postop_attr(dvp, attrflag);
790 		} else
791 			nfsm_loadattr(newvp, (struct vattr *)0);
792 	} else if (flags & ISDOTDOT) {
793 		VOP_UNLOCK(dvp, 0, p);
794 		cnp->cn_flags |= PDIRUNLOCK;
795 
796 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
797 		if (error) {
798 			if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
799 				cnp->cn_flags &= ~PDIRUNLOCK;
800 			m_freem(mrep);
801 			return (error);
802 		}
803 		newvp = NFSTOV(np);
804 
805 		if (v3) {
806 			nfsm_postop_attr(newvp, attrflag);
807 			nfsm_postop_attr(dvp, attrflag);
808 		} else
809 			nfsm_loadattr(newvp, (struct vattr *)0);
810 
811 		if (lockparent && (flags & ISLASTCN)) {
812 			if ((error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
813 				m_freem(mrep);
814 				vput(newvp);
815 				return error;
816 			}
817 			cnp->cn_flags &= ~PDIRUNLOCK;
818 		}
819 
820 	} else {
821 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
822 		if (error) {
823 			m_freem(mrep);
824 			return error;
825 		}
826 		newvp = NFSTOV(np);
827 		if (v3) {
828 			nfsm_postop_attr(newvp, attrflag);
829 			nfsm_postop_attr(dvp, attrflag);
830 		} else
831 			nfsm_loadattr(newvp, (struct vattr *)0);
832 		if (!lockparent || !(flags & ISLASTCN)) {
833 			VOP_UNLOCK(dvp, 0, p);
834 			cnp->cn_flags |= PDIRUNLOCK;
835 		}
836 	}
837 	if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
838 		cnp->cn_flags |= SAVENAME;
839 	if ((cnp->cn_flags & MAKEENTRY) &&
840 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
841 		np->n_ctime = np->n_vattr.va_ctime.tv_sec;
842 		cache_enter(dvp, newvp, cnp);
843 	}
844 	*vpp = newvp;
845 	nfsm_reqdone;
846 	if (error) {
847 		/*
848 		 * We get here only because of errors returned by
849 		 * the RPC. Otherwise we'll have returned above
850 		 * (the nfsm_* macros will jump to nfsm_reqdone
851 		 * on error).
852 		 */
853 		if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
854 		    cnp->cn_nameiop != CREATE) {
855 			if (VTONFS(dvp)->n_ctime == 0)
856 				VTONFS(dvp)->n_ctime =
857 				    VTONFS(dvp)->n_vattr.va_mtime.tv_sec;
858 			cache_enter(dvp, NULL, cnp);
859 		}
860 		if (newvp != NULLVP) {
861 			vrele(newvp);
862 			if (newvp != dvp)
863 				VOP_UNLOCK(newvp, 0, p);
864 		}
865 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
866 		    (flags & ISLASTCN) && error == ENOENT) {
867 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
868 				error = EROFS;
869 			else
870 				error = EJUSTRETURN;
871 		}
872 		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
873 			cnp->cn_flags |= SAVENAME;
874 		*vpp = NULL;
875 	}
876 	return (error);
877 }
878 
879 /*
880  * nfs read call.
881  * Just call nfs_bioread() to do the work.
882  */
883 int
884 nfs_read(v)
885 	void *v;
886 {
887 	struct vop_read_args /* {
888 		struct vnode *a_vp;
889 		struct uio *a_uio;
890 		int  a_ioflag;
891 		struct ucred *a_cred;
892 	} */ *ap = v;
893 	struct vnode *vp = ap->a_vp;
894 
895 	if (vp->v_type != VREG)
896 		return (EPERM);
897 	return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
898 }
899 
900 /*
901  * nfs readlink call
902  */
903 int
904 nfs_readlink(v)
905 	void *v;
906 {
907 	struct vop_readlink_args /* {
908 		struct vnode *a_vp;
909 		struct uio *a_uio;
910 		struct ucred *a_cred;
911 	} */ *ap = v;
912 	struct vnode *vp = ap->a_vp;
913 
914 	if (vp->v_type != VLNK)
915 		return (EPERM);
916 	return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
917 }
918 
919 /*
920  * Do a readlink rpc.
921  * Called by nfs_doio() from below the buffer cache.
922  */
923 int
924 nfs_readlinkrpc(vp, uiop, cred)
925 	struct vnode *vp;
926 	struct uio *uiop;
927 	struct ucred *cred;
928 {
929 	u_int32_t *tl;
930 	caddr_t cp;
931 	int32_t t1, t2;
932 	caddr_t bpos, dpos, cp2;
933 	int error = 0, len, attrflag;
934 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
935 	int v3 = NFS_ISV3(vp);
936 
937 	nfsstats.rpccnt[NFSPROC_READLINK]++;
938 	nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
939 	nfsm_fhtom(vp, v3);
940 	nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
941 	if (v3)
942 		nfsm_postop_attr(vp, attrflag);
943 	if (!error) {
944 		nfsm_strsiz(len, NFS_MAXPATHLEN);
945 		nfsm_mtouio(uiop, len);
946 	}
947 	nfsm_reqdone;
948 	return (error);
949 }
950 
951 /*
952  * nfs read rpc call
953  * Ditto above
954  */
955 int
956 nfs_readrpc(vp, uiop)
957 	struct vnode *vp;
958 	struct uio *uiop;
959 {
960 	u_int32_t *tl;
961 	caddr_t cp;
962 	int32_t t1, t2;
963 	caddr_t bpos, dpos, cp2;
964 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
965 	struct nfsmount *nmp;
966 	int error = 0, len, retlen, tsiz, eof, attrflag;
967 	int v3 = NFS_ISV3(vp);
968 
969 #ifndef nolint
970 	eof = 0;
971 #endif
972 	nmp = VFSTONFS(vp->v_mount);
973 	tsiz = uiop->uio_resid;
974 	if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
975 		return (EFBIG);
976 	while (tsiz > 0) {
977 		nfsstats.rpccnt[NFSPROC_READ]++;
978 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
979 		nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
980 		nfsm_fhtom(vp, v3);
981 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
982 		if (v3) {
983 			txdr_hyper(uiop->uio_offset, tl);
984 			*(tl + 2) = txdr_unsigned(len);
985 		} else {
986 			*tl++ = txdr_unsigned(uiop->uio_offset);
987 			*tl++ = txdr_unsigned(len);
988 			*tl = 0;
989 		}
990 		nfsm_request(vp, NFSPROC_READ, uiop->uio_procp,
991 		    VTONFS(vp)->n_rcred);
992 		if (v3) {
993 			nfsm_postop_attr(vp, attrflag);
994 			if (error) {
995 				m_freem(mrep);
996 				goto nfsmout;
997 			}
998 			nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
999 			eof = fxdr_unsigned(int, *(tl + 1));
1000 		} else
1001 			nfsm_loadattr(vp, (struct vattr *)0);
1002 		nfsm_strsiz(retlen, nmp->nm_rsize);
1003 		nfsm_mtouio(uiop, retlen);
1004 		m_freem(mrep);
1005 		tsiz -= retlen;
1006 		if (v3) {
1007 			if (eof || retlen == 0)
1008 				tsiz = 0;
1009 		} else if (retlen < len)
1010 			tsiz = 0;
1011 	}
1012 nfsmout:
1013 	return (error);
1014 }
1015 
1016 /*
1017  * nfs write call
1018  */
1019 int
1020 nfs_writerpc(vp, uiop, iomode, must_commit)
1021 	struct vnode *vp;
1022 	struct uio *uiop;
1023 	int *iomode, *must_commit;
1024 {
1025 	u_int32_t *tl;
1026 	caddr_t cp;
1027 	int32_t t1, t2, backup;
1028 	caddr_t bpos, dpos, cp2;
1029 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1030 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1031 	int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1032 	int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1033 
1034 #ifndef DIAGNOSTIC
1035 	if (uiop->uio_iovcnt != 1)
1036 		panic("nfs: writerpc iovcnt > 1");
1037 #endif
1038 	*must_commit = 0;
1039 	tsiz = uiop->uio_resid;
1040 	if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
1041 		return (EFBIG);
1042 	while (tsiz > 0) {
1043 		nfsstats.rpccnt[NFSPROC_WRITE]++;
1044 		len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1045 		nfsm_reqhead(vp, NFSPROC_WRITE,
1046 			NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1047 		nfsm_fhtom(vp, v3);
1048 		if (v3) {
1049 			nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1050 			txdr_hyper(uiop->uio_offset, tl);
1051 			tl += 2;
1052 			*tl++ = txdr_unsigned(len);
1053 			*tl++ = txdr_unsigned(*iomode);
1054 			*tl = txdr_unsigned(len);
1055 		} else {
1056 			u_int32_t x;
1057 
1058 			nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1059 			/* Set both "begin" and "current" to non-garbage. */
1060 			x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1061 			*tl++ = x;      /* "begin offset" */
1062 			*tl++ = x;      /* "current offset" */
1063 			x = txdr_unsigned(len);
1064 			*tl++ = x;      /* total to this offset */
1065 			*tl = x;        /* size of this write */
1066 
1067 		}
1068 		nfsm_uiotom(uiop, len);
1069 		nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp,
1070 		    VTONFS(vp)->n_wcred);
1071 		if (v3) {
1072 			wccflag = NFSV3_WCCCHK;
1073 			nfsm_wcc_data(vp, wccflag);
1074 			if (!error) {
1075 				nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1076 					+ NFSX_V3WRITEVERF);
1077 				rlen = fxdr_unsigned(int, *tl++);
1078 				if (rlen == 0) {
1079 					error = NFSERR_IO;
1080 					break;
1081 				} else if (rlen < len) {
1082 					backup = len - rlen;
1083 					uiop->uio_iov->iov_base -= backup;
1084 					uiop->uio_iov->iov_len += backup;
1085 					uiop->uio_offset -= backup;
1086 					uiop->uio_resid += backup;
1087 					len = rlen;
1088 				}
1089 				commit = fxdr_unsigned(int, *tl++);
1090 
1091 				/*
1092 				 * Return the lowest committment level
1093 				 * obtained by any of the RPCs.
1094 				 */
1095 				if (committed == NFSV3WRITE_FILESYNC)
1096 					committed = commit;
1097 				else if (committed == NFSV3WRITE_DATASYNC &&
1098 					commit == NFSV3WRITE_UNSTABLE)
1099 					committed = commit;
1100 				if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) {
1101 				    bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1102 					NFSX_V3WRITEVERF);
1103 				    nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1104 				} else if (bcmp((caddr_t)tl,
1105 				    (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1106 				    *must_commit = 1;
1107 				    bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1108 					NFSX_V3WRITEVERF);
1109 				}
1110 			}
1111 		} else
1112 		    nfsm_loadattr(vp, (struct vattr *)0);
1113 		if (wccflag)
1114 		    VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1115 		m_freem(mrep);
1116 		tsiz -= len;
1117 	}
1118 nfsmout:
1119 	*iomode = committed;
1120 	if (error)
1121 		uiop->uio_resid = tsiz;
1122 	return (error);
1123 }
1124 
1125 /*
1126  * nfs mknod rpc
1127  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1128  * mode set to specify the file type and the size field for rdev.
1129  */
1130 int
1131 nfs_mknodrpc(dvp, vpp, cnp, vap)
1132 	struct vnode *dvp;
1133 	struct vnode **vpp;
1134 	struct componentname *cnp;
1135 	struct vattr *vap;
1136 {
1137 	struct nfsv2_sattr *sp;
1138 	u_int32_t *tl;
1139 	caddr_t cp;
1140 	int32_t t1, t2;
1141 	struct vnode *newvp = (struct vnode *)0;
1142 	struct nfsnode *np;
1143 	char *cp2;
1144 	caddr_t bpos, dpos;
1145 	int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1146 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1147 	u_int32_t rdev;
1148 	int v3 = NFS_ISV3(dvp);
1149 
1150 	if (vap->va_type == VCHR || vap->va_type == VBLK)
1151 		rdev = txdr_unsigned(vap->va_rdev);
1152 	else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1153 		rdev = nfs_xdrneg1;
1154 	else {
1155 		VOP_ABORTOP(dvp, cnp);
1156 		vput(dvp);
1157 		return (EOPNOTSUPP);
1158 	}
1159 	nfsstats.rpccnt[NFSPROC_MKNOD]++;
1160 	nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1161 		+ nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1162 	nfsm_fhtom(dvp, v3);
1163 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1164 	if (v3) {
1165 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1166 		*tl++ = vtonfsv3_type(vap->va_type);
1167 		nfsm_v3attrbuild(vap, FALSE);
1168 		if (vap->va_type == VCHR || vap->va_type == VBLK) {
1169 			nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1170 			*tl++ = txdr_unsigned(major(vap->va_rdev));
1171 			*tl = txdr_unsigned(minor(vap->va_rdev));
1172 		}
1173 	} else {
1174 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1175 		sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1176 		sp->sa_uid = nfs_xdrneg1;
1177 		sp->sa_gid = nfs_xdrneg1;
1178 		sp->sa_size = rdev;
1179 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1180 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1181 	}
1182 	nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred);
1183 	if (!error) {
1184 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1185 		if (!gotvp) {
1186 			if (newvp) {
1187 				vrele(newvp);
1188 				newvp = (struct vnode *)0;
1189 			}
1190 			error = nfs_lookitup(dvp, cnp->cn_nameptr,
1191 			    cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1192 			if (!error)
1193 				newvp = NFSTOV(np);
1194 		}
1195 	}
1196 	if (v3)
1197 		nfsm_wcc_data(dvp, wccflag);
1198 	nfsm_reqdone;
1199 	if (error) {
1200 		if (newvp)
1201 			vrele(newvp);
1202 	} else {
1203 		if (cnp->cn_flags & MAKEENTRY)
1204 			cache_enter(dvp, newvp, cnp);
1205 		*vpp = newvp;
1206 	}
1207 	FREE(cnp->cn_pnbuf, M_NAMEI);
1208 	VTONFS(dvp)->n_flag |= NMODIFIED;
1209 	if (!wccflag)
1210 		VTONFS(dvp)->n_attrstamp = 0;
1211 	vrele(dvp);
1212 	return (error);
1213 }
1214 
1215 /*
1216  * nfs mknod vop
1217  * just call nfs_mknodrpc() to do the work.
1218  */
1219 /* ARGSUSED */
1220 int
1221 nfs_mknod(v)
1222 	void *v;
1223 {
1224 	struct vop_mknod_args /* {
1225 		struct vnode *a_dvp;
1226 		struct vnode **a_vpp;
1227 		struct componentname *a_cnp;
1228 		struct vattr *a_vap;
1229 	} */ *ap = v;
1230 	struct vnode *newvp;
1231 	int error;
1232 
1233 	error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1234 	if (!error)
1235 		vrele(newvp);
1236 	return (error);
1237 }
1238 
1239 static u_long create_verf;
1240 /*
1241  * nfs file create call
1242  */
1243 int
1244 nfs_create(v)
1245 	void *v;
1246 {
1247 	struct vop_create_args /* {
1248 		struct vnode *a_dvp;
1249 		struct vnode **a_vpp;
1250 		struct componentname *a_cnp;
1251 		struct vattr *a_vap;
1252 	} */ *ap = v;
1253 	struct vnode *dvp = ap->a_dvp;
1254 	struct vattr *vap = ap->a_vap;
1255 	struct componentname *cnp = ap->a_cnp;
1256 	struct nfsv2_sattr *sp;
1257 	u_int32_t *tl;
1258 	caddr_t cp;
1259 	int32_t t1, t2;
1260 	struct nfsnode *np = (struct nfsnode *)0;
1261 	struct vnode *newvp = (struct vnode *)0;
1262 	caddr_t bpos, dpos, cp2;
1263 	int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1264 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1265 	int v3 = NFS_ISV3(dvp);
1266 
1267 	/*
1268 	 * Oops, not for me..
1269 	 */
1270 	if (vap->va_type == VSOCK)
1271 		return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1272 
1273 #ifdef VA_EXCLUSIVE
1274 	if (vap->va_vaflags & VA_EXCLUSIVE)
1275 		fmode |= O_EXCL;
1276 #endif
1277 again:
1278 	nfsstats.rpccnt[NFSPROC_CREATE]++;
1279 	nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1280 		nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1281 	nfsm_fhtom(dvp, v3);
1282 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1283 	if (v3) {
1284 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1285 		if (fmode & O_EXCL) {
1286 			*tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1287 			nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
1288 			if (TAILQ_FIRST(&in_ifaddr))
1289 				*tl++ = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr.s_addr;
1290 			else
1291 				*tl++ = create_verf;
1292 			*tl = ++create_verf;
1293 		} else {
1294 			*tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1295 			nfsm_v3attrbuild(vap, FALSE);
1296 		}
1297 	} else {
1298 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1299 		sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1300 		sp->sa_uid = nfs_xdrneg1;
1301 		sp->sa_gid = nfs_xdrneg1;
1302 		sp->sa_size = 0;
1303 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1304 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1305 	}
1306 	nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
1307 	if (!error) {
1308 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1309 		if (!gotvp) {
1310 			if (newvp) {
1311 				vrele(newvp);
1312 				newvp = (struct vnode *)0;
1313 			}
1314 			error = nfs_lookitup(dvp, cnp->cn_nameptr,
1315 			    cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1316 			if (!error)
1317 				newvp = NFSTOV(np);
1318 		}
1319 	}
1320 	if (v3)
1321 		nfsm_wcc_data(dvp, wccflag);
1322 	nfsm_reqdone;
1323 	if (error) {
1324 		if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1325 			fmode &= ~O_EXCL;
1326 			goto again;
1327 		}
1328 		if (newvp)
1329 			vrele(newvp);
1330 	} else if (v3 && (fmode & O_EXCL))
1331 		error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1332 	if (!error) {
1333 		if (cnp->cn_flags & MAKEENTRY)
1334 			cache_enter(dvp, newvp, cnp);
1335 		*ap->a_vpp = newvp;
1336 	}
1337 	FREE(cnp->cn_pnbuf, M_NAMEI);
1338 	VTONFS(dvp)->n_flag |= NMODIFIED;
1339 	if (!wccflag)
1340 		VTONFS(dvp)->n_attrstamp = 0;
1341 	vrele(dvp);
1342 	return (error);
1343 }
1344 
1345 /*
1346  * nfs file remove call
1347  * To try and make nfs semantics closer to ufs semantics, a file that has
1348  * other processes using the vnode is renamed instead of removed and then
1349  * removed later on the last close.
1350  * - If v_usecount > 1
1351  *	  If a rename is not already in the works
1352  *	     call nfs_sillyrename() to set it up
1353  *     else
1354  *	  do the remove rpc
1355  */
1356 int
1357 nfs_remove(v)
1358 	void *v;
1359 {
1360 	struct vop_remove_args /* {
1361 		struct vnodeop_desc *a_desc;
1362 		struct vnode * a_dvp;
1363 		struct vnode * a_vp;
1364 		struct componentname * a_cnp;
1365 	} */ *ap = v;
1366 	struct vnode *vp = ap->a_vp;
1367 	struct vnode *dvp = ap->a_dvp;
1368 	struct componentname *cnp = ap->a_cnp;
1369 	struct nfsnode *np = VTONFS(vp);
1370 	int error = 0;
1371 	struct vattr vattr;
1372 
1373 #ifndef DIAGNOSTIC
1374 	if ((cnp->cn_flags & HASBUF) == 0)
1375 		panic("nfs_remove: no name");
1376 	if (vp->v_usecount < 1)
1377 		panic("nfs_remove: bad v_usecount");
1378 #endif
1379 	if (vp->v_type == VDIR)
1380 		error = EPERM;
1381 	else if (vp->v_usecount == 1 || (np->n_sillyrename &&
1382 	    VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1383 	    vattr.va_nlink > 1)) {
1384 		/*
1385 		 * Purge the name cache so that the chance of a lookup for
1386 		 * the name succeeding while the remove is in progress is
1387 		 * minimized. Without node locking it can still happen, such
1388 		 * that an I/O op returns ESTALE, but since you get this if
1389 		 * another host removes the file..
1390 		 */
1391 		cache_purge(vp);
1392 		/*
1393 		 * throw away biocache buffers, mainly to avoid
1394 		 * unnecessary delayed writes later.
1395 		 */
1396 		error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1397 		/* Do the rpc */
1398 		if (error != EINTR)
1399 			error = nfs_removerpc(dvp, cnp->cn_nameptr,
1400 				cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1401 		/*
1402 		 * Kludge City: If the first reply to the remove rpc is lost..
1403 		 *   the reply to the retransmitted request will be ENOENT
1404 		 *   since the file was in fact removed
1405 		 *   Therefore, we cheat and return success.
1406 		 */
1407 		if (error == ENOENT)
1408 			error = 0;
1409 	} else if (!np->n_sillyrename)
1410 		error = nfs_sillyrename(dvp, vp, cnp);
1411 	FREE(cnp->cn_pnbuf, M_NAMEI);
1412 	np->n_attrstamp = 0;
1413 	vrele(dvp);
1414 	vrele(vp);
1415 	return (error);
1416 }
1417 
1418 /*
1419  * nfs file remove rpc called from nfs_inactive
1420  */
1421 int
1422 nfs_removeit(sp)
1423 	struct sillyrename *sp;
1424 {
1425 
1426 	return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1427 		(struct proc *)0));
1428 }
1429 
1430 /*
1431  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1432  */
1433 int
1434 nfs_removerpc(dvp, name, namelen, cred, proc)
1435 	struct vnode *dvp;
1436 	char *name;
1437 	int namelen;
1438 	struct ucred *cred;
1439 	struct proc *proc;
1440 {
1441 	u_int32_t *tl;
1442 	caddr_t cp;
1443 	int32_t t1, t2;
1444 	caddr_t bpos, dpos, cp2;
1445 	int error = 0, wccflag = NFSV3_WCCRATTR;
1446 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1447 	int v3 = NFS_ISV3(dvp);
1448 
1449 	nfsstats.rpccnt[NFSPROC_REMOVE]++;
1450 	nfsm_reqhead(dvp, NFSPROC_REMOVE,
1451 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1452 	nfsm_fhtom(dvp, v3);
1453 	nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1454 	nfsm_request(dvp, NFSPROC_REMOVE, proc, cred);
1455 	if (v3)
1456 		nfsm_wcc_data(dvp, wccflag);
1457 	nfsm_reqdone;
1458 	VTONFS(dvp)->n_flag |= NMODIFIED;
1459 	if (!wccflag)
1460 		VTONFS(dvp)->n_attrstamp = 0;
1461 	return (error);
1462 }
1463 
1464 /*
1465  * nfs file rename call
1466  */
1467 int
1468 nfs_rename(v)
1469 	void *v;
1470 {
1471 	struct vop_rename_args  /* {
1472 		struct vnode *a_fdvp;
1473 		struct vnode *a_fvp;
1474 		struct componentname *a_fcnp;
1475 		struct vnode *a_tdvp;
1476 		struct vnode *a_tvp;
1477 		struct componentname *a_tcnp;
1478 	} */ *ap = v;
1479 	struct vnode *fvp = ap->a_fvp;
1480 	struct vnode *tvp = ap->a_tvp;
1481 	struct vnode *fdvp = ap->a_fdvp;
1482 	struct vnode *tdvp = ap->a_tdvp;
1483 	struct componentname *tcnp = ap->a_tcnp;
1484 	struct componentname *fcnp = ap->a_fcnp;
1485 	int error;
1486 
1487 #ifndef DIAGNOSTIC
1488 	if ((tcnp->cn_flags & HASBUF) == 0 ||
1489 	    (fcnp->cn_flags & HASBUF) == 0)
1490 		panic("nfs_rename: no name");
1491 #endif
1492 	/* Check for cross-device rename */
1493 	if ((fvp->v_mount != tdvp->v_mount) ||
1494 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
1495 		error = EXDEV;
1496 		goto out;
1497 	}
1498 
1499 	/*
1500 	 * If the tvp exists and is in use, sillyrename it before doing the
1501 	 * rename of the new file over it.
1502 	 */
1503 	if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1504 	    tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1505 		vrele(tvp);
1506 		tvp = NULL;
1507 	}
1508 
1509 	error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1510 		tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1511 		tcnp->cn_proc);
1512 
1513 	if (fvp->v_type == VDIR) {
1514 		if (tvp != NULL && tvp->v_type == VDIR)
1515 			cache_purge(tdvp);
1516 		cache_purge(fdvp);
1517 	}
1518 out:
1519 	if (tdvp == tvp)
1520 		vrele(tdvp);
1521 	else
1522 		vput(tdvp);
1523 	if (tvp)
1524 		vput(tvp);
1525 	vrele(fdvp);
1526 	vrele(fvp);
1527 	/*
1528 	 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1529 	 */
1530 	if (error == ENOENT)
1531 		error = 0;
1532 	return (error);
1533 }
1534 
1535 /*
1536  * nfs file rename rpc called from nfs_remove() above
1537  */
1538 int
1539 nfs_renameit(sdvp, scnp, sp)
1540 	struct vnode *sdvp;
1541 	struct componentname *scnp;
1542 	struct sillyrename *sp;
1543 {
1544 	return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1545 		sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
1546 }
1547 
1548 /*
1549  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1550  */
1551 int
1552 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
1553 	struct vnode *fdvp;
1554 	char *fnameptr;
1555 	int fnamelen;
1556 	struct vnode *tdvp;
1557 	char *tnameptr;
1558 	int tnamelen;
1559 	struct ucred *cred;
1560 	struct proc *proc;
1561 {
1562 	u_int32_t *tl;
1563 	caddr_t cp;
1564 	int32_t t1, t2;
1565 	caddr_t bpos, dpos, cp2;
1566 	int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1567 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1568 	int v3 = NFS_ISV3(fdvp);
1569 
1570 	nfsstats.rpccnt[NFSPROC_RENAME]++;
1571 	nfsm_reqhead(fdvp, NFSPROC_RENAME,
1572 		(NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1573 		nfsm_rndup(tnamelen));
1574 	nfsm_fhtom(fdvp, v3);
1575 	nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1576 	nfsm_fhtom(tdvp, v3);
1577 	nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1578 	nfsm_request(fdvp, NFSPROC_RENAME, proc, cred);
1579 	if (v3) {
1580 		nfsm_wcc_data(fdvp, fwccflag);
1581 		nfsm_wcc_data(tdvp, twccflag);
1582 	}
1583 	nfsm_reqdone;
1584 	VTONFS(fdvp)->n_flag |= NMODIFIED;
1585 	VTONFS(tdvp)->n_flag |= NMODIFIED;
1586 	if (!fwccflag)
1587 		VTONFS(fdvp)->n_attrstamp = 0;
1588 	if (!twccflag)
1589 		VTONFS(tdvp)->n_attrstamp = 0;
1590 	return (error);
1591 }
1592 
1593 /*
1594  * nfs hard link create call
1595  */
1596 int
1597 nfs_link(v)
1598 	void *v;
1599 {
1600 	struct vop_link_args /* {
1601 		struct vnode *a_dvp;
1602 		struct vnode *a_vp;
1603 		struct componentname *a_cnp;
1604 	} */ *ap = v;
1605 	struct vnode *vp = ap->a_vp;
1606 	struct vnode *dvp = ap->a_dvp;
1607 	struct componentname *cnp = ap->a_cnp;
1608 	u_int32_t *tl;
1609 	caddr_t cp;
1610 	int32_t t1, t2;
1611 	caddr_t bpos, dpos, cp2;
1612 	int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1613 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1614 	int v3 = NFS_ISV3(vp);
1615 
1616 
1617 	if (dvp->v_mount != vp->v_mount) {
1618 		FREE(cnp->cn_pnbuf, M_NAMEI);
1619 		if (vp == dvp)
1620 			vrele(dvp);
1621 		else
1622 			vput(dvp);
1623 		return (EXDEV);
1624 	}
1625 
1626 	/*
1627 	 * Push all writes to the server, so that the attribute cache
1628 	 * doesn't get "out of sync" with the server.
1629 	 * XXX There should be a better way!
1630 	 */
1631 	VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1632 
1633 	nfsstats.rpccnt[NFSPROC_LINK]++;
1634 	nfsm_reqhead(vp, NFSPROC_LINK,
1635 		NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1636 	nfsm_fhtom(vp, v3);
1637 	nfsm_fhtom(dvp, v3);
1638 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1639 	nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1640 	if (v3) {
1641 		nfsm_postop_attr(vp, attrflag);
1642 		nfsm_wcc_data(dvp, wccflag);
1643 	}
1644 	nfsm_reqdone;
1645 	FREE(cnp->cn_pnbuf, M_NAMEI);
1646 	VTONFS(dvp)->n_flag |= NMODIFIED;
1647 	if (!attrflag)
1648 		VTONFS(vp)->n_attrstamp = 0;
1649 	if (!wccflag)
1650 		VTONFS(dvp)->n_attrstamp = 0;
1651 	vput(dvp);
1652 	/*
1653 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1654 	 */
1655 	if (error == EEXIST)
1656 		error = 0;
1657 	return (error);
1658 }
1659 
1660 /*
1661  * nfs symbolic link create call
1662  */
1663 int
1664 nfs_symlink(v)
1665 	void *v;
1666 {
1667 	struct vop_symlink_args /* {
1668 		struct vnode *a_dvp;
1669 		struct vnode **a_vpp;
1670 		struct componentname *a_cnp;
1671 		struct vattr *a_vap;
1672 		char *a_target;
1673 	} */ *ap = v;
1674 	struct vnode *dvp = ap->a_dvp;
1675 	struct vattr *vap = ap->a_vap;
1676 	struct componentname *cnp = ap->a_cnp;
1677 	struct nfsv2_sattr *sp;
1678 	u_int32_t *tl;
1679 	caddr_t cp;
1680 	int32_t t1, t2;
1681 	caddr_t bpos, dpos, cp2;
1682 	int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1683 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1684 	struct vnode *newvp = (struct vnode *)0;
1685 	int v3 = NFS_ISV3(dvp);
1686 
1687 	nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1688 	slen = strlen(ap->a_target);
1689 	nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1690 	    nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1691 	nfsm_fhtom(dvp, v3);
1692 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1693 	if (v3)
1694 		nfsm_v3attrbuild(vap, FALSE);
1695 	nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1696 	if (!v3) {
1697 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1698 		sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1699 		sp->sa_uid = nfs_xdrneg1;
1700 		sp->sa_gid = nfs_xdrneg1;
1701 		sp->sa_size = nfs_xdrneg1;
1702 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1703 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1704 	}
1705 	nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1706 	if (v3) {
1707 		if (!error)
1708 			nfsm_mtofh(dvp, newvp, v3, gotvp);
1709 		nfsm_wcc_data(dvp, wccflag);
1710 	}
1711 	nfsm_reqdone;
1712 	if (newvp)
1713 		vrele(newvp);
1714 	FREE(cnp->cn_pnbuf, M_NAMEI);
1715 	VTONFS(dvp)->n_flag |= NMODIFIED;
1716 	if (!wccflag)
1717 		VTONFS(dvp)->n_attrstamp = 0;
1718 	vrele(dvp);
1719 	/*
1720 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1721 	 */
1722 	if (error == EEXIST)
1723 		error = 0;
1724 	return (error);
1725 }
1726 
1727 /*
1728  * nfs make dir call
1729  */
1730 int
1731 nfs_mkdir(v)
1732 	void *v;
1733 {
1734 	struct vop_mkdir_args /* {
1735 		struct vnode *a_dvp;
1736 		struct vnode **a_vpp;
1737 		struct componentname *a_cnp;
1738 		struct vattr *a_vap;
1739 	} */ *ap = v;
1740 	struct vnode *dvp = ap->a_dvp;
1741 	struct vattr *vap = ap->a_vap;
1742 	struct componentname *cnp = ap->a_cnp;
1743 	struct nfsv2_sattr *sp;
1744 	u_int32_t *tl;
1745 	caddr_t cp;
1746 	int32_t t1, t2;
1747 	int len;
1748 	struct nfsnode *np = (struct nfsnode *)0;
1749 	struct vnode *newvp = (struct vnode *)0;
1750 	caddr_t bpos, dpos, cp2;
1751 	int error = 0, wccflag = NFSV3_WCCRATTR;
1752 	int gotvp = 0;
1753 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1754 	int v3 = NFS_ISV3(dvp);
1755 
1756 	len = cnp->cn_namelen;
1757 	nfsstats.rpccnt[NFSPROC_MKDIR]++;
1758 	nfsm_reqhead(dvp, NFSPROC_MKDIR,
1759 	  NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
1760 	nfsm_fhtom(dvp, v3);
1761 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1762 	if (v3) {
1763 		nfsm_v3attrbuild(vap, FALSE);
1764 	} else {
1765 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1766 		sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1767 		sp->sa_uid = nfs_xdrneg1;
1768 		sp->sa_gid = nfs_xdrneg1;
1769 		sp->sa_size = nfs_xdrneg1;
1770 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1771 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1772 	}
1773 	nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1774 	if (!error)
1775 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1776 	if (v3)
1777 		nfsm_wcc_data(dvp, wccflag);
1778 	nfsm_reqdone;
1779 	VTONFS(dvp)->n_flag |= NMODIFIED;
1780 	if (!wccflag)
1781 		VTONFS(dvp)->n_attrstamp = 0;
1782 	/*
1783 	 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1784 	 * if we can succeed in looking up the directory.
1785 	 */
1786 	if (error == EEXIST || (!error && !gotvp)) {
1787 		if (newvp) {
1788 			vrele(newvp);
1789 			newvp = (struct vnode *)0;
1790 		}
1791 		error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1792 			cnp->cn_proc, &np);
1793 		if (!error) {
1794 			newvp = NFSTOV(np);
1795 			if (newvp->v_type != VDIR)
1796 				error = EEXIST;
1797 		}
1798 	}
1799 	if (error) {
1800 		if (newvp)
1801 			vrele(newvp);
1802 	} else
1803 		*ap->a_vpp = newvp;
1804 	FREE(cnp->cn_pnbuf, M_NAMEI);
1805 	vrele(dvp);
1806 	return (error);
1807 }
1808 
1809 /*
1810  * nfs remove directory call
1811  */
1812 int
1813 nfs_rmdir(v)
1814 	void *v;
1815 {
1816 	struct vop_rmdir_args /* {
1817 		struct vnode *a_dvp;
1818 		struct vnode *a_vp;
1819 		struct componentname *a_cnp;
1820 	} */ *ap = v;
1821 	struct vnode *vp = ap->a_vp;
1822 	struct vnode *dvp = ap->a_dvp;
1823 	struct componentname *cnp = ap->a_cnp;
1824 	u_int32_t *tl;
1825 	caddr_t cp;
1826 	int32_t t1, t2;
1827 	caddr_t bpos, dpos, cp2;
1828 	int error = 0, wccflag = NFSV3_WCCRATTR;
1829 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1830 	int v3 = NFS_ISV3(dvp);
1831 
1832 	if (dvp == vp) {
1833 		vrele(dvp);
1834 		vrele(dvp);
1835 		FREE(cnp->cn_pnbuf, M_NAMEI);
1836 		return (EINVAL);
1837 	}
1838 	nfsstats.rpccnt[NFSPROC_RMDIR]++;
1839 	nfsm_reqhead(dvp, NFSPROC_RMDIR,
1840 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1841 	nfsm_fhtom(dvp, v3);
1842 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1843 	nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1844 	if (v3)
1845 		nfsm_wcc_data(dvp, wccflag);
1846 	nfsm_reqdone;
1847 	FREE(cnp->cn_pnbuf, M_NAMEI);
1848 	VTONFS(dvp)->n_flag |= NMODIFIED;
1849 	if (!wccflag)
1850 		VTONFS(dvp)->n_attrstamp = 0;
1851 	cache_purge(dvp);
1852 	cache_purge(vp);
1853 	vrele(vp);
1854 	vrele(dvp);
1855 	/*
1856 	 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1857 	 */
1858 	if (error == ENOENT)
1859 		error = 0;
1860 	return (error);
1861 }
1862 
1863 
1864 /*
1865  * The readdir logic below has a big design bug. It stores the NFS cookie in
1866  * the returned uio->uio_offset but does not store the verifier (it cannot).
1867  * Instead, the code stores the verifier in the nfsnode and applies that
1868  * verifies to all cookies, no matter what verifier was originally with
1869  * the cookie.
1870  *
1871  * From a practical standpoint, this is not a problem since almost all
1872  * NFS servers do not change the validity of cookies across deletes
1873  * and inserts.
1874  */
1875 
1876 struct nfs_dirent {
1877 	u_int32_t cookie[2];
1878 	struct dirent dirent;
1879 };
1880 
1881 #define	NFS_DIRHDSIZ    (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1))
1882 #define NFS_DIRENT_OVERHEAD  offsetof(struct nfs_dirent, dirent)
1883 
1884 /*
1885  * nfs readdir call
1886  */
1887 int
1888 nfs_readdir(v)
1889 	void *v;
1890 {
1891 	struct vop_readdir_args /* {
1892 		struct vnode *a_vp;
1893 		struct uio *a_uio;
1894 		struct ucred *a_cred;
1895 		int *a_eofflag;
1896 		u_long **a_cookies;
1897 		int *a_ncookies;
1898 	} */ *ap = v;
1899 	struct vnode *vp = ap->a_vp;
1900 	struct nfsnode *np = VTONFS(vp);
1901 	struct uio *uio = ap->a_uio;
1902 	int tresid, error;
1903 	struct vattr vattr;
1904 	u_long *cookies = NULL;
1905 	int ncookies = 0, cnt;
1906 	u_int64_t  newoff = uio->uio_offset;
1907 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1908 	struct uio readdir_uio;
1909 	struct iovec readdir_iovec;
1910 	struct proc * p = uio->uio_procp;
1911 	int done = 0, eof = 0;
1912 	struct ucred *cred = ap->a_cred;
1913 	void *data;
1914 
1915 	if (vp->v_type != VDIR)
1916 		return (EPERM);
1917 	/*
1918 	 * First, check for hit on the EOF offset cache
1919 	 */
1920 	if (np->n_direofoffset != 0 &&
1921 	    uio->uio_offset == np->n_direofoffset) {
1922 		if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1923 		    np->n_mtime == vattr.va_mtime.tv_sec) {
1924 			nfsstats.direofcache_hits++;
1925 			*ap->a_eofflag = 1;
1926 			return (0);
1927 		}
1928 	}
1929 
1930 	if (uio->uio_resid < NFS_FABLKSIZE)
1931 		return (EINVAL);
1932 
1933 	tresid = uio->uio_resid;
1934 
1935 	if (uio->uio_rw != UIO_READ)
1936 		return (EINVAL);
1937 
1938 	if (ap->a_cookies) {
1939 		ncookies = uio->uio_resid / 20;
1940 
1941 		MALLOC(cookies, u_long *, sizeof(*cookies) * ncookies,
1942 		       M_TEMP, M_WAITOK);
1943 		*ap->a_ncookies = ncookies;
1944 		*ap->a_cookies = cookies;
1945 	}
1946 
1947 	if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
1948 		(void)nfs_fsinfo(nmp, vp, cred, p);
1949 
1950 	cnt = 5;
1951 
1952 	MALLOC(data, void *, NFS_DIRBLKSIZ, M_TEMP,
1953 	    M_WAITOK);
1954 
1955 	do {
1956 		struct nfs_dirent *ndp = data;
1957 
1958 		readdir_iovec.iov_len = NFS_DIRBLKSIZ;
1959 		readdir_iovec.iov_base = data;
1960 		readdir_uio.uio_offset = newoff;
1961 		readdir_uio.uio_iov = &readdir_iovec;
1962 		readdir_uio.uio_iovcnt = 1;
1963 		readdir_uio.uio_segflg = UIO_SYSSPACE;
1964 		readdir_uio.uio_rw = UIO_READ;
1965 		readdir_uio.uio_resid = NFS_DIRBLKSIZ;
1966 		readdir_uio.uio_procp = curproc;
1967 
1968 		if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
1969 			error = nfs_readdirplusrpc(vp, &readdir_uio, cred,
1970 			    &eof);
1971 			if (error == NFSERR_NOTSUPP)
1972 				nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
1973 		}
1974 		if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
1975 			error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof);
1976 
1977 		if (error == NFSERR_BAD_COOKIE)
1978 			error = EINVAL;
1979 
1980 		while (error == 0 &&
1981 		    (ap->a_cookies == NULL || ncookies != 0) &&
1982 		    ndp < (struct nfs_dirent *)readdir_iovec.iov_base) {
1983 			struct dirent *dp = &ndp->dirent;
1984 			int reclen = dp->d_reclen;
1985 
1986 			dp->d_reclen -= NFS_DIRENT_OVERHEAD;
1987 
1988 			if (uio->uio_resid < dp->d_reclen) {
1989 				done = 1;
1990 				break;
1991 			}
1992 
1993 			error = uiomove((caddr_t)dp, dp->d_reclen, uio);
1994 			if (error)
1995 				break;
1996 
1997 			newoff = fxdr_hyper(&ndp->cookie[0]);
1998 
1999 			if (ap->a_cookies != NULL) {
2000 				*cookies = newoff;
2001 				cookies++;
2002 				ncookies--;
2003 			}
2004 
2005 			ndp = (struct nfs_dirent *)((u_int8_t *)ndp + reclen);
2006 		}
2007 	} while (!error && !done && !eof && cnt--);
2008 
2009 	FREE(data, M_TEMP);
2010 	data = NULL;
2011 
2012 	if (ap->a_cookies) {
2013 		if (error) {
2014 			FREE(*ap->a_cookies, M_TEMP);
2015 			*ap->a_cookies = NULL;
2016 			*ap->a_ncookies = 0;
2017 		} else {
2018 			*ap->a_ncookies -= ncookies;
2019 		}
2020 	}
2021 
2022 	if (!error)
2023 		uio->uio_offset = newoff;
2024 
2025 	if (!error && (eof || uio->uio_resid == tresid)) {
2026 		nfsstats.direofcache_misses++;
2027 		*ap->a_eofflag = 1;
2028 		return (0);
2029 	}
2030 
2031 	*ap->a_eofflag = 0;
2032 	return (error);
2033 }
2034 
2035 
2036 /*
2037  * The function below stuff the cookies in after the name
2038  */
2039 
2040 /*
2041  * Readdir rpc call.
2042  */
2043 int
2044 nfs_readdirrpc(struct vnode *vp,
2045     struct uio *uiop,
2046     struct ucred *cred,
2047     int *end_of_directory)
2048 {
2049 	int len, left;
2050 	struct nfs_dirent *ndp = NULL;
2051 	struct dirent *dp = NULL;
2052 	u_int32_t *tl;
2053 	caddr_t cp;
2054 	int32_t t1, t2;
2055 	caddr_t bpos, dpos, cp2;
2056 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2057 	nfsuint64 cookie;
2058 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2059 	struct nfsnode *dnp = VTONFS(vp);
2060 	u_quad_t fileno;
2061 	int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2062 	int attrflag;
2063 	int v3 = NFS_ISV3(vp);
2064 
2065 #ifndef DIAGNOSTIC
2066 	if (uiop->uio_iovcnt != 1 ||
2067 		(uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2068 		panic("nfs readdirrpc bad uio");
2069 #endif
2070 
2071 	txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2072 
2073 	/*
2074 	 * Loop around doing readdir rpc's of size nm_readdirsize
2075 	 * truncated to a multiple of NFS_READDIRBLKSIZ.
2076 	 * The stopping criteria is EOF or buffer full.
2077 	 */
2078 	while (more_dirs && bigenough) {
2079 		nfsstats.rpccnt[NFSPROC_READDIR]++;
2080 		nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2081 			NFSX_READDIR(v3));
2082 		nfsm_fhtom(vp, v3);
2083 		if (v3) {
2084 			nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2085 			*tl++ = cookie.nfsuquad[0];
2086 			*tl++ = cookie.nfsuquad[1];
2087 			if (cookie.nfsuquad[0] == 0 &&
2088 			    cookie.nfsuquad[1] == 0) {
2089 				*tl++ = 0;
2090 				*tl++ = 0;
2091 			} else {
2092 				*tl++ = dnp->n_cookieverf.nfsuquad[0];
2093 				*tl++ = dnp->n_cookieverf.nfsuquad[1];
2094 			}
2095 		} else {
2096 			nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2097 			*tl++ = cookie.nfsuquad[1];
2098 		}
2099 		*tl = txdr_unsigned(nmp->nm_readdirsize);
2100 		nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
2101 		if (v3) {
2102 			nfsm_postop_attr(vp, attrflag);
2103 			if (!error) {
2104 				nfsm_dissect(tl, u_int32_t *,
2105 				    2 * NFSX_UNSIGNED);
2106 				dnp->n_cookieverf.nfsuquad[0] = *tl++;
2107 				dnp->n_cookieverf.nfsuquad[1] = *tl;
2108 			} else {
2109 				m_freem(mrep);
2110 				goto nfsmout;
2111 			}
2112 		}
2113 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2114 		more_dirs = fxdr_unsigned(int, *tl);
2115 
2116 		/* loop thru the dir entries, doctoring them to 4bsd form */
2117 		while (more_dirs && bigenough) {
2118 			if (v3) {
2119 				nfsm_dissect(tl, u_int32_t *,
2120 				    3 * NFSX_UNSIGNED);
2121 				fileno = fxdr_hyper(tl);
2122 				len = fxdr_unsigned(int, *(tl + 2));
2123 			} else {
2124 				nfsm_dissect(tl, u_int32_t *,
2125 				    2 * NFSX_UNSIGNED);
2126 				fileno = fxdr_unsigned(u_quad_t, *tl++);
2127 				len = fxdr_unsigned(int, *tl);
2128 			}
2129 			if (len <= 0 || len > NFS_MAXNAMLEN) {
2130 				error = EBADRPC;
2131 				m_freem(mrep);
2132 				goto nfsmout;
2133 			}
2134 			tlen = nfsm_rndup(len + 1);
2135 			left = NFS_READDIRBLKSIZ - blksiz;
2136 			if ((tlen + NFS_DIRHDSIZ) > left) {
2137 				dp->d_reclen += left;
2138 				(caddr_t)uiop->uio_iov->iov_base += left;
2139 				uiop->uio_iov->iov_len -= left;
2140 				uiop->uio_resid -= left;
2141 				blksiz = 0;
2142 			}
2143 			if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2144 				bigenough = 0;
2145 			if (bigenough) {
2146 				ndp = (struct nfs_dirent *)
2147 				    uiop->uio_iov->iov_base;
2148 				dp = &ndp->dirent;
2149 				dp->d_fileno = (int)fileno;
2150 				dp->d_namlen = len;
2151 				dp->d_reclen = tlen + NFS_DIRHDSIZ;
2152 				dp->d_type = DT_UNKNOWN;
2153 				blksiz += dp->d_reclen;
2154 				if (blksiz == NFS_READDIRBLKSIZ)
2155 					blksiz = 0;
2156 				uiop->uio_resid -= NFS_DIRHDSIZ;
2157 				uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2158 				uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2159 				nfsm_mtouio(uiop, len);
2160 				cp = uiop->uio_iov->iov_base;
2161 				tlen -= len;
2162 				*cp = '\0';	/* null terminate */
2163 				(caddr_t)uiop->uio_iov->iov_base += tlen;
2164 				uiop->uio_iov->iov_len -= tlen;
2165 				uiop->uio_resid -= tlen;
2166 			} else
2167 				nfsm_adv(nfsm_rndup(len));
2168 			if (v3) {
2169 				nfsm_dissect(tl, u_int32_t *,
2170 				    3 * NFSX_UNSIGNED);
2171 			} else {
2172 				nfsm_dissect(tl, u_int32_t *,
2173 				    2 * NFSX_UNSIGNED);
2174 			}
2175 			if (bigenough) {
2176 				if (v3) {
2177 					ndp->cookie[0] = cookie.nfsuquad[0] =
2178 					    *tl++;
2179 				} else
2180 					ndp->cookie[0] = 0;
2181 
2182 				ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2183 			} else if (v3)
2184 				tl += 2;
2185 			else
2186 				tl++;
2187 			more_dirs = fxdr_unsigned(int, *tl);
2188 		}
2189 		/*
2190 		 * If at end of rpc data, get the eof boolean
2191 		 */
2192 		if (!more_dirs) {
2193 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2194 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
2195 		}
2196 		m_freem(mrep);
2197 	}
2198 	/*
2199 	 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2200 	 * by increasing d_reclen for the last record.
2201 	 */
2202 	if (blksiz > 0) {
2203 		left = NFS_READDIRBLKSIZ - blksiz;
2204 		dp->d_reclen += left;
2205 		uiop->uio_iov->iov_base += left;
2206 		uiop->uio_iov->iov_len -= left;
2207 		uiop->uio_resid -= left;
2208 	}
2209 
2210 	/*
2211 	 * We are now either at the end of the directory or have filled the
2212 	 * block.
2213 	 */
2214 	if (bigenough) {
2215 		dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2216 		if (end_of_directory) *end_of_directory = 1;
2217 	} else {
2218 		if (uiop->uio_resid > 0)
2219 			printf("EEK! readdirrpc resid > 0\n");
2220 	}
2221 
2222 nfsmout:
2223 	return (error);
2224 }
2225 
2226 /*
2227  * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2228  */
2229 int
2230 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2231     int *end_of_directory)
2232 {
2233 	int len, left;
2234 	struct nfs_dirent *ndirp = NULL;
2235 	struct dirent *dp = NULL;
2236 	u_int32_t *tl;
2237 	caddr_t cp;
2238 	int32_t t1, t2;
2239 	struct vnode *newvp;
2240 	caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2241 	struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2242 	struct nameidata nami, *ndp = &nami;
2243 	struct componentname *cnp = &ndp->ni_cnd;
2244 	nfsuint64 cookie;
2245 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2246 	struct nfsnode *dnp = VTONFS(vp), *np;
2247 	nfsfh_t *fhp;
2248 	u_quad_t fileno;
2249 	int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2250 	int attrflag, fhsize;
2251 
2252 #ifndef DIAGNOSTIC
2253 	if (uiop->uio_iovcnt != 1 ||
2254 		(uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2255 		panic("nfs readdirplusrpc bad uio");
2256 #endif
2257 	ndp->ni_dvp = vp;
2258 	newvp = NULLVP;
2259 
2260 	txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2261 
2262         /*
2263 	 * Loop around doing readdir rpc's of size nm_readdirsize
2264 	 * truncated to a multiple of NFS_READDIRBLKSIZ.
2265 	 * The stopping criteria is EOF or buffer full.
2266 	 */
2267 	while (more_dirs && bigenough) {
2268 		nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2269 		nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2270 			NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2271 		nfsm_fhtom(vp, 1);
2272  		nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2273 		*tl++ = cookie.nfsuquad[0];
2274 		*tl++ = cookie.nfsuquad[1];
2275 		if (cookie.nfsuquad[0] == 0 &&
2276 		    cookie.nfsuquad[1] == 0) {
2277 			*tl++ = 0;
2278 			*tl++ = 0;
2279 		} else {
2280 			*tl++ = dnp->n_cookieverf.nfsuquad[0];
2281 			*tl++ = dnp->n_cookieverf.nfsuquad[1];
2282 		}
2283 		*tl++ = txdr_unsigned(nmp->nm_readdirsize);
2284 		*tl = txdr_unsigned(nmp->nm_rsize);
2285 		nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2286 		nfsm_postop_attr(vp, attrflag);
2287 		if (error) {
2288 			m_freem(mrep);
2289 			goto nfsmout;
2290 		}
2291 		nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2292 		dnp->n_cookieverf.nfsuquad[0] = *tl++;
2293 		dnp->n_cookieverf.nfsuquad[1] = *tl++;
2294 		more_dirs = fxdr_unsigned(int, *tl);
2295 
2296 		/* loop thru the dir entries, doctoring them to 4bsd form */
2297 		while (more_dirs && bigenough) {
2298 			nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2299 			fileno = fxdr_hyper(tl);
2300 			len = fxdr_unsigned(int, *(tl + 2));
2301 			if (len <= 0 || len > NFS_MAXNAMLEN) {
2302 				error = EBADRPC;
2303 				m_freem(mrep);
2304 				goto nfsmout;
2305 			}
2306 			tlen = nfsm_rndup(len + 1);
2307 			left = NFS_READDIRBLKSIZ - blksiz;
2308 			if ((tlen + NFS_DIRHDSIZ) > left) {
2309 				dp->d_reclen += left;
2310 				uiop->uio_iov->iov_base += left;
2311 				uiop->uio_iov->iov_len -= left;
2312 				uiop->uio_resid -= left;
2313 				blksiz = 0;
2314 			}
2315 			if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2316 				bigenough = 0;
2317 			if (bigenough) {
2318 				ndirp = (struct nfs_dirent *)
2319 				    uiop->uio_iov->iov_base;
2320 				dp = &ndirp->dirent;
2321 				dp->d_fileno = (int)fileno;
2322 				dp->d_namlen = len;
2323 				dp->d_reclen = tlen + NFS_DIRHDSIZ;
2324 				dp->d_type = DT_UNKNOWN;
2325 				blksiz += dp->d_reclen;
2326 				if (blksiz == NFS_READDIRBLKSIZ)
2327 					blksiz = 0;
2328 				uiop->uio_resid -= NFS_DIRHDSIZ;
2329 				uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2330 				uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2331 				cnp->cn_nameptr = uiop->uio_iov->iov_base;
2332 				cnp->cn_namelen = len;
2333 				nfsm_mtouio(uiop, len);
2334 				cp = uiop->uio_iov->iov_base;
2335 				tlen -= len;
2336 				*cp = '\0';
2337 				uiop->uio_iov->iov_base += tlen;
2338 				uiop->uio_iov->iov_len -= tlen;
2339 				uiop->uio_resid -= tlen;
2340 			} else
2341 				nfsm_adv(nfsm_rndup(len));
2342 			nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2343 			if (bigenough) {
2344 				ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++;
2345 				ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2346 			} else
2347 				tl += 2;
2348 
2349 			/*
2350 			 * Since the attributes are before the file handle
2351 			 * (sigh), we must skip over the attributes and then
2352 			 * come back and get them.
2353 			 */
2354 			attrflag = fxdr_unsigned(int, *tl);
2355 			if (attrflag) {
2356 			    dpossav1 = dpos;
2357 			    mdsav1 = md;
2358 			    nfsm_adv(NFSX_V3FATTR);
2359 			    nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2360 			    doit = fxdr_unsigned(int, *tl);
2361 			    if (doit) {
2362 				nfsm_getfh(fhp, fhsize, 1);
2363 				if (NFS_CMPFH(dnp, fhp, fhsize)) {
2364 				    VREF(vp);
2365 				    newvp = vp;
2366 				    np = dnp;
2367 				} else {
2368 				    error = nfs_nget(vp->v_mount, fhp,
2369 					fhsize, &np);
2370 				    if (error)
2371 					doit = 0;
2372 				    else
2373 					newvp = NFSTOV(np);
2374 				}
2375 			    }
2376 			    if (doit) {
2377 				dpossav2 = dpos;
2378 				dpos = dpossav1;
2379 				mdsav2 = md;
2380 				md = mdsav1;
2381 				nfsm_loadattr(newvp, (struct vattr *)0);
2382 				dpos = dpossav2;
2383 				md = mdsav2;
2384 				dp->d_type =
2385 				    IFTODT(VTTOIF(np->n_vattr.va_type));
2386 				ndp->ni_vp = newvp;
2387 				cnp->cn_hash = 0;
2388 				for (cp = cnp->cn_nameptr, i = 1; i <= len;
2389 				    i++, cp++)
2390 				    cnp->cn_hash += (unsigned char)*cp * i;
2391 				if (cnp->cn_namelen <= NCHNAMLEN)
2392 				    cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
2393 			    }
2394 			} else {
2395 			    /* Just skip over the file handle */
2396 			    nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2397 			    i = fxdr_unsigned(int, *tl);
2398 			    nfsm_adv(nfsm_rndup(i));
2399 			}
2400 			if (newvp != NULLVP) {
2401 			    vrele(newvp);
2402 			    newvp = NULLVP;
2403 			}
2404 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2405 			more_dirs = fxdr_unsigned(int, *tl);
2406 		}
2407 		/*
2408 		 * If at end of rpc data, get the eof boolean
2409 		 */
2410 		if (!more_dirs) {
2411 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2412 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
2413 		}
2414 		m_freem(mrep);
2415 	}
2416 	/*
2417 	 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2418 	 * by increasing d_reclen for the last record.
2419 	 */
2420 	if (blksiz > 0) {
2421 		left = NFS_READDIRBLKSIZ - blksiz;
2422 		dp->d_reclen += left;
2423 		uiop->uio_iov->iov_base += left;
2424 		uiop->uio_iov->iov_len -= left;
2425 		uiop->uio_resid -= left;
2426 	}
2427 
2428 	/*
2429 	 * We are now either at the end of the directory or have filled the
2430 	 * block.
2431 	 */
2432 	if (bigenough) {
2433 		dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2434 		if (end_of_directory) *end_of_directory = 1;
2435 	} else {
2436 		if (uiop->uio_resid > 0)
2437 			printf("EEK! readdirplusrpc resid > 0\n");
2438 	}
2439 
2440 nfsmout:
2441 	if (newvp != NULLVP)
2442 		vrele(newvp);
2443 	return (error);
2444 }
2445 
2446 /*
2447  * Silly rename. To make the NFS filesystem that is stateless look a little
2448  * more like the "ufs" a remove of an active vnode is translated to a rename
2449  * to a funny looking filename that is removed by nfs_inactive on the
2450  * nfsnode. There is the potential for another process on a different client
2451  * to create the same funny name between the nfs_lookitup() fails and the
2452  * nfs_rename() completes, but...
2453  */
2454 int
2455 nfs_sillyrename(dvp, vp, cnp)
2456 	struct vnode *dvp, *vp;
2457 	struct componentname *cnp;
2458 {
2459 	struct sillyrename *sp;
2460 	struct nfsnode *np;
2461 	int error;
2462 
2463 	cache_purge(dvp);
2464 	np = VTONFS(vp);
2465 	MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2466 		M_NFSREQ, M_WAITOK);
2467 	sp->s_cred = crdup(cnp->cn_cred);
2468 	sp->s_dvp = dvp;
2469 	VREF(dvp);
2470 
2471 	if (vp->v_type == VDIR) {
2472 #ifdef DIAGNOSTIC
2473 		printf("nfs: sillyrename dir\n");
2474 #endif
2475 		error = EINVAL;
2476 		goto bad;
2477 	}
2478 
2479 	/* Fudge together a funny name */
2480 	sp->s_namlen = snprintf(sp->s_name, sizeof sp->s_name,
2481 	    ".nfsA%05x4.4", cnp->cn_proc->p_pid);
2482 
2483 	/* Try lookitups until we get one that isn't there */
2484 	while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2485 		cnp->cn_proc, (struct nfsnode **)0) == 0) {
2486 		sp->s_name[4]++;
2487 		if (sp->s_name[4] > 'z') {
2488 			error = EINVAL;
2489 			goto bad;
2490 		}
2491 	}
2492 	error = nfs_renameit(dvp, cnp, sp);
2493 	if (error)
2494 		goto bad;
2495 	error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2496 		cnp->cn_proc, &np);
2497 	np->n_sillyrename = sp;
2498 	return (0);
2499 bad:
2500 	vrele(sp->s_dvp);
2501 	crfree(sp->s_cred);
2502 	FREE((caddr_t)sp, M_NFSREQ);
2503 	return (error);
2504 }
2505 
2506 /*
2507  * Look up a file name and optionally either update the file handle or
2508  * allocate an nfsnode, depending on the value of npp.
2509  * npp == NULL	--> just do the lookup
2510  * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2511  *			handled too
2512  * *npp != NULL --> update the file handle in the vnode
2513  */
2514 int
2515 nfs_lookitup(dvp, name, len, cred, procp, npp)
2516 	struct vnode *dvp;
2517 	char *name;
2518 	int len;
2519 	struct ucred *cred;
2520 	struct proc *procp;
2521 	struct nfsnode **npp;
2522 {
2523 	u_int32_t *tl;
2524 	caddr_t cp;
2525 	int32_t t1, t2;
2526 	struct vnode *newvp = (struct vnode *)0;
2527 	struct nfsnode *np, *dnp = VTONFS(dvp);
2528 	caddr_t bpos, dpos, cp2;
2529 	int error = 0, fhlen, attrflag;
2530 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2531 	nfsfh_t *nfhp;
2532 	int v3 = NFS_ISV3(dvp);
2533 
2534 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2535 	nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2536 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2537 	nfsm_fhtom(dvp, v3);
2538 	nfsm_strtom(name, len, NFS_MAXNAMLEN);
2539 	nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred);
2540 	if (npp && !error) {
2541 		nfsm_getfh(nfhp, fhlen, v3);
2542 		if (*npp) {
2543 		    np = *npp;
2544 		    if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2545 			free((caddr_t)np->n_fhp, M_NFSBIGFH);
2546 			np->n_fhp = &np->n_fh;
2547 		    } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2548 			np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2549 		    bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2550 		    np->n_fhsize = fhlen;
2551 		    newvp = NFSTOV(np);
2552 		} else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2553 		    VREF(dvp);
2554 		    newvp = dvp;
2555 		} else {
2556 		    error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2557 		    if (error) {
2558 			m_freem(mrep);
2559 			return (error);
2560 		    }
2561 		    newvp = NFSTOV(np);
2562 		}
2563 		if (v3) {
2564 			nfsm_postop_attr(newvp, attrflag);
2565 			if (!attrflag && *npp == NULL) {
2566 				m_freem(mrep);
2567 				vrele(newvp);
2568 				return (ENOENT);
2569 			}
2570 		} else
2571 			nfsm_loadattr(newvp, (struct vattr *)0);
2572 	}
2573 	nfsm_reqdone;
2574 	if (npp && *npp == NULL) {
2575 		if (error) {
2576 			if (newvp)
2577 				vrele(newvp);
2578 		} else
2579 			*npp = np;
2580 	}
2581 	return (error);
2582 }
2583 
2584 /*
2585  * Nfs Version 3 commit rpc
2586  */
2587 int
2588 nfs_commit(vp, offset, cnt, procp)
2589 	struct vnode *vp;
2590 	u_quad_t offset;
2591 	int cnt;
2592 	struct proc *procp;
2593 {
2594 	caddr_t cp;
2595 	u_int32_t *tl;
2596 	int32_t t1, t2;
2597 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2598 	caddr_t bpos, dpos, cp2;
2599 	int error = 0, wccflag = NFSV3_WCCRATTR;
2600 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2601 
2602 	if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0)
2603 		return (0);
2604 	nfsstats.rpccnt[NFSPROC_COMMIT]++;
2605 	nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
2606 	nfsm_fhtom(vp, 1);
2607 	nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2608 	txdr_hyper(offset, tl);
2609 	tl += 2;
2610 	*tl = txdr_unsigned(cnt);
2611 	nfsm_request(vp, NFSPROC_COMMIT, procp, VTONFS(vp)->n_wcred);
2612 	nfsm_wcc_data(vp, wccflag);
2613 	if (!error) {
2614 		nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
2615 		if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
2616 			NFSX_V3WRITEVERF)) {
2617 			bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
2618 				NFSX_V3WRITEVERF);
2619 			error = NFSERR_STALEWRITEVERF;
2620 		}
2621 	}
2622 	nfsm_reqdone;
2623 	return (error);
2624 }
2625 
2626 /*
2627  * Kludge City..
2628  * - make nfs_bmap() essentially a no-op that does no translation
2629  * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2630  *   (Maybe I could use the process's page mapping, but I was concerned that
2631  *    Kernel Write might not be enabled and also figured copyout() would do
2632  *    a lot more work than bcopy() and also it currently happens in the
2633  *    context of the swapper process (2).
2634  */
2635 int
2636 nfs_bmap(v)
2637 	void *v;
2638 {
2639 	struct vop_bmap_args /* {
2640 		struct vnode *a_vp;
2641 		daddr_t  a_bn;
2642 		struct vnode **a_vpp;
2643 		daddr_t *a_bnp;
2644 		int *a_runp;
2645 	} */ *ap = v;
2646 	struct vnode *vp = ap->a_vp;
2647 
2648 	if (ap->a_vpp != NULL)
2649 		*ap->a_vpp = vp;
2650 	if (ap->a_bnp != NULL)
2651 		*ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2652 	return (0);
2653 }
2654 
2655 /*
2656  * Strategy routine.
2657  * For async requests when nfsiod(s) are running, queue the request by
2658  * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2659  * request.
2660  */
2661 int
2662 nfs_strategy(v)
2663 	void *v;
2664 {
2665 	struct vop_strategy_args *ap = v;
2666 	struct buf *bp = ap->a_bp;
2667 	struct proc *p;
2668 	int error = 0;
2669 
2670 	if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
2671 		panic("nfs physio/async");
2672 	if (bp->b_flags & B_ASYNC)
2673 		p = NULL;
2674 	else
2675 		p = curproc;	/* XXX */
2676 	/*
2677 	 * If the op is asynchronous and an i/o daemon is waiting
2678 	 * queue the request, wake it up and wait for completion
2679 	 * otherwise just do it ourselves.
2680 	 */
2681 	if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp))
2682 		error = nfs_doio(bp, p);
2683 	return (error);
2684 }
2685 
2686 /*
2687  * fsync vnode op. Just call nfs_flush() with commit == 1.
2688  */
2689 /* ARGSUSED */
2690 int
2691 nfs_fsync(v)
2692 	void *v;
2693 {
2694 	struct vop_fsync_args /* {
2695 		struct vnodeop_desc *a_desc;
2696 		struct vnode * a_vp;
2697 		struct ucred * a_cred;
2698 		int  a_waitfor;
2699 		struct proc * a_p;
2700 	} */ *ap = v;
2701 
2702 	return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2703 }
2704 
2705 /*
2706  * Flush all the blocks associated with a vnode.
2707  * 	Walk through the buffer pool and push any dirty pages
2708  *	associated with the vnode.
2709  */
2710 int
2711 nfs_flush(vp, cred, waitfor, p, commit)
2712 	struct vnode *vp;
2713 	struct ucred *cred;
2714 	int waitfor;
2715 	struct proc *p;
2716 	int commit;
2717 {
2718 	struct nfsnode *np = VTONFS(vp);
2719 	struct buf *bp;
2720 	int i;
2721 	struct buf *nbp;
2722 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2723 	int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2724 	int passone = 1;
2725 	u_quad_t off = (u_quad_t)-1, endoff = 0, toff;
2726 #ifndef NFS_COMMITBVECSIZ
2727 #define NFS_COMMITBVECSIZ	20
2728 #endif
2729 	struct buf *bvec[NFS_COMMITBVECSIZ];
2730 
2731 	if (nmp->nm_flag & NFSMNT_INT)
2732 		slpflag = PCATCH;
2733 	if (!commit)
2734 		passone = 0;
2735 	/*
2736 	 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2737 	 * server, but nas not been committed to stable storage on the server
2738 	 * yet. On the first pass, the byte range is worked out and the commit
2739 	 * rpc is done. On the second pass, nfs_writebp() is called to do the
2740 	 * job.
2741 	 */
2742 again:
2743 	bvecpos = 0;
2744 	if (NFS_ISV3(vp) && commit) {
2745 		s = splbio();
2746 		for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2747 			nbp = LIST_NEXT(bp, b_vnbufs);
2748 			if (bvecpos >= NFS_COMMITBVECSIZ)
2749 				break;
2750 			if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2751 				!= (B_DELWRI | B_NEEDCOMMIT))
2752 				continue;
2753 			bremfree(bp);
2754 			bp->b_flags |= (B_BUSY | B_WRITEINPROG);
2755 			/*
2756 			 * A list of these buffers is kept so that the
2757 			 * second loop knows which buffers have actually
2758 			 * been committed. This is necessary, since there
2759 			 * may be a race between the commit rpc and new
2760 			 * uncommitted writes on the file.
2761 			 */
2762 			bvec[bvecpos++] = bp;
2763 			toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2764 				bp->b_dirtyoff;
2765 			if (toff < off)
2766 				off = toff;
2767 			toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2768 			if (toff > endoff)
2769 				endoff = toff;
2770 		}
2771 		splx(s);
2772 	}
2773 	if (bvecpos > 0) {
2774 		/*
2775 		 * Commit data on the server, as required.
2776 		 */
2777 		retv = nfs_commit(vp, off, (int)(endoff - off), p);
2778 		if (retv == NFSERR_STALEWRITEVERF)
2779 			nfs_clearcommit(vp->v_mount);
2780 		/*
2781 		 * Now, either mark the blocks I/O done or mark the
2782 		 * blocks dirty, depending on whether the commit
2783 		 * succeeded.
2784 		 */
2785 		for (i = 0; i < bvecpos; i++) {
2786 			bp = bvec[i];
2787 			bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2788 			if (retv)
2789 			    brelse(bp);
2790 			else {
2791 			    s = splbio();
2792 			    buf_undirty(bp);
2793 			    vp->v_numoutput++;
2794 			    bp->b_flags |= B_ASYNC;
2795 			    bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2796 			    bp->b_dirtyoff = bp->b_dirtyend = 0;
2797 			    biodone(bp);
2798 			    splx(s);
2799 			}
2800 		}
2801 	}
2802 
2803 	/*
2804 	 * Start/do any write(s) that are required.
2805 	 */
2806 loop:
2807 	s = splbio();
2808 	for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2809 		nbp = LIST_NEXT(bp, b_vnbufs);
2810 		if (bp->b_flags & B_BUSY) {
2811 			if (waitfor != MNT_WAIT || passone)
2812 				continue;
2813 			bp->b_flags |= B_WANTED;
2814 			error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
2815 				"nfsfsync", slptimeo);
2816 			splx(s);
2817 			if (error) {
2818 			    if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2819 				return (EINTR);
2820 			    if (slpflag == PCATCH) {
2821 				slpflag = 0;
2822 				slptimeo = 2 * hz;
2823 			    }
2824 			}
2825 			goto loop;
2826 		}
2827 		if ((bp->b_flags & B_DELWRI) == 0)
2828 			panic("nfs_fsync: not dirty");
2829 		if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2830 			continue;
2831 		bremfree(bp);
2832 		if (passone || !commit)
2833 		    bp->b_flags |= (B_BUSY|B_ASYNC);
2834 		else
2835 		    bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2836 		splx(s);
2837 		VOP_BWRITE(bp);
2838 		goto loop;
2839 	}
2840 	splx(s);
2841 	if (passone) {
2842 		passone = 0;
2843 		goto again;
2844 	}
2845 	if (waitfor == MNT_WAIT) {
2846  loop2:
2847 	        s = splbio();
2848 		error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo);
2849 		splx(s);
2850 		if (error) {
2851 			if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2852 				return (EINTR);
2853 			if (slpflag == PCATCH) {
2854 				slpflag = 0;
2855 				slptimeo = 2 * hz;
2856 			}
2857 			goto loop2;
2858 		}
2859 
2860 		if (LIST_FIRST(&vp->v_dirtyblkhd) && commit) {
2861 #if 0
2862 			vprint("nfs_fsync: dirty", vp);
2863 #endif
2864 			goto loop;
2865 		}
2866 	}
2867 	if (np->n_flag & NWRITEERR) {
2868 		error = np->n_error;
2869 		np->n_flag &= ~NWRITEERR;
2870 	}
2871 	return (error);
2872 }
2873 
2874 /*
2875  * Return POSIX pathconf information applicable to nfs.
2876  *
2877  * The NFS V2 protocol doesn't support this, so just return EINVAL
2878  * for V2.
2879  */
2880 /* ARGSUSED */
2881 int
2882 nfs_pathconf(v)
2883 	void *v;
2884 {
2885 #if 0
2886 	struct vop_pathconf_args /* {
2887 		struct vnode *a_vp;
2888 		int a_name;
2889 		register_t *a_retval;
2890 	} */ *ap = v;
2891 #endif
2892 
2893 	return (EINVAL);
2894 }
2895 
2896 /*
2897  * NFS advisory byte-level locks.
2898  */
2899 int
2900 nfs_advlock(v)
2901 	void *v;
2902 {
2903 	struct vop_advlock_args /* {
2904 		struct vnode *a_vp;
2905 		caddr_t  a_id;
2906 		int  a_op;
2907 		struct flock *a_fl;
2908 		int  a_flags;
2909 	} */ *ap = v;
2910 	struct nfsnode *np = VTONFS(ap->a_vp);
2911 
2912 	return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op,
2913 	    ap->a_fl, ap->a_flags));
2914 }
2915 
2916 /*
2917  * Print out the contents of an nfsnode.
2918  */
2919 int
2920 nfs_print(v)
2921 	void *v;
2922 {
2923 	struct vop_print_args /* {
2924 		struct vnode *a_vp;
2925 	} */ *ap = v;
2926 	struct vnode *vp = ap->a_vp;
2927 	struct nfsnode *np = VTONFS(vp);
2928 
2929 	printf("tag VT_NFS, fileid %ld fsid 0x%lx",
2930 		np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2931 #ifdef FIFO
2932 	if (vp->v_type == VFIFO)
2933 		fifo_printinfo(vp);
2934 #endif
2935 	printf("\n");
2936 	return (0);
2937 }
2938 
2939 /*
2940  * Just call nfs_writebp() with the force argument set to 1.
2941  */
2942 int
2943 nfs_bwrite(v)
2944 	void *v;
2945 {
2946 	struct vop_bwrite_args /* {
2947 		struct buf *a_bp;
2948 	} */ *ap = v;
2949 
2950 	return (nfs_writebp(ap->a_bp, 1));
2951 }
2952 
2953 /*
2954  * This is a clone of vop_generic_bwrite(), except that B_WRITEINPROG isn't set unless
2955  * the force flag is one and it also handles the B_NEEDCOMMIT flag.
2956  */
2957 int
2958 nfs_writebp(bp, force)
2959 	struct buf *bp;
2960 	int force;
2961 {
2962 	int oldflags = bp->b_flags, retv = 1;
2963 	struct proc *p = curproc;	/* XXX */
2964 	off_t off;
2965 	int   s;
2966 
2967 	if(!(bp->b_flags & B_BUSY))
2968 		panic("bwrite: buffer is not busy???");
2969 
2970 #ifdef fvdl_debug
2971 	printf("nfs_writebp(%x): vp %x voff %d vend %d doff %d dend %d\n",
2972 	    bp, bp->b_vp, bp->b_validoff, bp->b_validend, bp->b_dirtyoff,
2973 	    bp->b_dirtyend);
2974 #endif
2975 	bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2976 
2977 	s = splbio();
2978 	buf_undirty(bp);
2979 
2980 	if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p)
2981 		++p->p_stats->p_ru.ru_oublock;
2982 
2983 	bp->b_vp->v_numoutput++;
2984 	splx(s);
2985 
2986 	/*
2987 	 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
2988 	 * an actual write will have to be scheduled via. VOP_STRATEGY().
2989 	 * If B_WRITEINPROG is already set, then push it with a write anyhow.
2990 	 */
2991 	if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
2992 		off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
2993 		bp->b_flags |= B_WRITEINPROG;
2994 		retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
2995 			bp->b_proc);
2996 		bp->b_flags &= ~B_WRITEINPROG;
2997 		if (!retv) {
2998 			bp->b_dirtyoff = bp->b_dirtyend = 0;
2999 			bp->b_flags &= ~B_NEEDCOMMIT;
3000 			s = splbio();
3001 			biodone(bp);
3002 			splx(s);
3003 		} else if (retv == NFSERR_STALEWRITEVERF)
3004 			nfs_clearcommit(bp->b_vp->v_mount);
3005 	}
3006 	if (retv) {
3007 		if (force)
3008 			bp->b_flags |= B_WRITEINPROG;
3009 		VOP_STRATEGY(bp);
3010 	}
3011 
3012 	if( (oldflags & B_ASYNC) == 0) {
3013 		int rtval = biowait(bp);
3014 		if (!(oldflags & B_DELWRI) && p) {
3015 			++p->p_stats->p_ru.ru_oublock;
3016 		}
3017 		brelse(bp);
3018 		return (rtval);
3019 	}
3020 
3021 	return (0);
3022 }
3023 
3024 /*
3025  * nfs special file access vnode op.
3026  * Essentially just get vattr and then imitate iaccess() since the device is
3027  * local to the client.
3028  */
3029 int
3030 nfsspec_access(v)
3031 	void *v;
3032 {
3033 	struct vop_access_args /* {
3034 		struct vnode *a_vp;
3035 		int  a_mode;
3036 		struct ucred *a_cred;
3037 		struct proc *a_p;
3038 	} */ *ap = v;
3039 	struct vattr va;
3040 	struct vnode *vp = ap->a_vp;
3041 	int error;
3042 
3043         /*
3044 	 * Disallow write attempts on filesystems mounted read-only;
3045 	 * unless the file is a socket, fifo, or a block or character
3046 	 * device resident on the filesystem.
3047 	 */
3048 	if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3049 		switch (vp->v_type) {
3050 		case VREG:
3051 		case VDIR:
3052 		case VLNK:
3053 			return (EROFS);
3054 		default:
3055 			break;
3056 		}
3057 	}
3058 
3059 	error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p);
3060 	if (error)
3061 		return (error);
3062 
3063 	return (vaccess(va.va_mode, va.va_uid, va.va_gid, ap->a_mode,
3064 	    ap->a_cred));
3065 }
3066 
3067 /*
3068  * Read wrapper for special devices.
3069  */
3070 int
3071 nfsspec_read(v)
3072 	void *v;
3073 {
3074 	struct vop_read_args /* {
3075 		struct vnode *a_vp;
3076 		struct uio *a_uio;
3077 		int  a_ioflag;
3078 		struct ucred *a_cred;
3079 	} */ *ap = v;
3080 	struct nfsnode *np = VTONFS(ap->a_vp);
3081 
3082 	/*
3083 	 * Set access flag.
3084 	 */
3085 	np->n_flag |= NACC;
3086 	np->n_atim.tv_sec = time.tv_sec;
3087 	np->n_atim.tv_nsec = time.tv_usec * 1000;
3088 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3089 }
3090 
3091 /*
3092  * Write wrapper for special devices.
3093  */
3094 int
3095 nfsspec_write(v)
3096 	void *v;
3097 {
3098 	struct vop_write_args /* {
3099 		struct vnode *a_vp;
3100 		struct uio *a_uio;
3101 		int  a_ioflag;
3102 		struct ucred *a_cred;
3103 	} */ *ap = v;
3104 	struct nfsnode *np = VTONFS(ap->a_vp);
3105 
3106 	/*
3107 	 * Set update flag.
3108 	 */
3109 	np->n_flag |= NUPD;
3110 	np->n_mtim.tv_sec = time.tv_sec;
3111 	np->n_mtim.tv_nsec = time.tv_usec * 1000;
3112 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3113 }
3114 
3115 /*
3116  * Close wrapper for special devices.
3117  *
3118  * Update the times on the nfsnode then do device close.
3119  */
3120 int
3121 nfsspec_close(v)
3122 	void *v;
3123 {
3124 	struct vop_close_args /* {
3125 		struct vnode *a_vp;
3126 		int  a_fflag;
3127 		struct ucred *a_cred;
3128 		struct proc *a_p;
3129 	} */ *ap = v;
3130 	struct vnode *vp = ap->a_vp;
3131 	struct nfsnode *np = VTONFS(vp);
3132 	struct vattr vattr;
3133 
3134 	if (np->n_flag & (NACC | NUPD)) {
3135 		np->n_flag |= NCHG;
3136 		if (vp->v_usecount == 1 &&
3137 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3138 			VATTR_NULL(&vattr);
3139 			if (np->n_flag & NACC)
3140 				vattr.va_atime = np->n_atim;
3141 			if (np->n_flag & NUPD)
3142 				vattr.va_mtime = np->n_mtim;
3143 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3144 		}
3145 	}
3146 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3147 }
3148 
3149 #ifdef FIFO
3150 /*
3151  * Read wrapper for fifos.
3152  */
3153 int
3154 nfsfifo_read(v)
3155 	void *v;
3156 {
3157 	struct vop_read_args /* {
3158 		struct vnode *a_vp;
3159 		struct uio *a_uio;
3160 		int  a_ioflag;
3161 		struct ucred *a_cred;
3162 	} */ *ap = v;
3163 	extern int (**fifo_vnodeop_p)(void *);
3164 	struct nfsnode *np = VTONFS(ap->a_vp);
3165 
3166 	/*
3167 	 * Set access flag.
3168 	 */
3169 	np->n_flag |= NACC;
3170 	np->n_atim.tv_sec = time.tv_sec;
3171 	np->n_atim.tv_nsec = time.tv_usec * 1000;
3172 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3173 }
3174 
3175 /*
3176  * Write wrapper for fifos.
3177  */
3178 int
3179 nfsfifo_write(v)
3180 	void *v;
3181 {
3182 	struct vop_write_args /* {
3183 		struct vnode *a_vp;
3184 		struct uio *a_uio;
3185 		int  a_ioflag;
3186 		struct ucred *a_cred;
3187 	} */ *ap = v;
3188 	extern int (**fifo_vnodeop_p)(void *);
3189 	struct nfsnode *np = VTONFS(ap->a_vp);
3190 
3191 	/*
3192 	 * Set update flag.
3193 	 */
3194 	np->n_flag |= NUPD;
3195 	np->n_mtim.tv_sec = time.tv_sec;
3196 	np->n_mtim.tv_nsec = time.tv_usec * 1000;
3197 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3198 }
3199 
3200 /*
3201  * Close wrapper for fifos.
3202  *
3203  * Update the times on the nfsnode then do fifo close.
3204  */
3205 int
3206 nfsfifo_close(v)
3207 	void *v;
3208 {
3209 	struct vop_close_args /* {
3210 		struct vnode *a_vp;
3211 		int  a_fflag;
3212 		struct ucred *a_cred;
3213 		struct proc *a_p;
3214 	} */ *ap = v;
3215 	struct vnode *vp = ap->a_vp;
3216 	struct nfsnode *np = VTONFS(vp);
3217 	struct vattr vattr;
3218 	extern int (**fifo_vnodeop_p)(void *);
3219 
3220 	if (np->n_flag & (NACC | NUPD)) {
3221 		if (np->n_flag & NACC) {
3222 			np->n_atim.tv_sec = time.tv_sec;
3223 			np->n_atim.tv_nsec = time.tv_usec * 1000;
3224 		}
3225 		if (np->n_flag & NUPD) {
3226 			np->n_mtim.tv_sec = time.tv_sec;
3227 			np->n_mtim.tv_nsec = time.tv_usec * 1000;
3228 		}
3229 		np->n_flag |= NCHG;
3230 		if (vp->v_usecount == 1 &&
3231 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3232 			VATTR_NULL(&vattr);
3233 			if (np->n_flag & NACC)
3234 				vattr.va_atime = np->n_atim;
3235 			if (np->n_flag & NUPD)
3236 				vattr.va_mtime = np->n_mtim;
3237 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3238 		}
3239 	}
3240 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3241 }
3242 #endif /* ! FIFO */
3243