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