xref: /csrg-svn/sys/nfs/nfs_vnops.c (revision 54668)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)nfs_vnops.c	7.85 (Berkeley) 07/03/92
11  */
12 
13 /*
14  * vnode op calls for sun nfs version 2
15  */
16 
17 #include <sys/param.h>
18 #include <sys/proc.h>
19 #include <sys/kernel.h>
20 #include <sys/systm.h>
21 #include <sys/mount.h>
22 #include <sys/buf.h>
23 #include <sys/malloc.h>
24 #include <sys/mbuf.h>
25 #include <sys/conf.h>
26 #include <sys/namei.h>
27 #include <sys/vnode.h>
28 #include <sys/specdev.h>
29 #include <sys/fifo.h>
30 #include <sys/map.h>
31 
32 #include <vm/vm.h>
33 
34 #include <nfs/rpcv2.h>
35 #include <nfs/nfsv2.h>
36 #include <nfs/nfs.h>
37 #include <nfs/nfsnode.h>
38 #include <nfs/nfsmount.h>
39 #include <nfs/xdr_subs.h>
40 #include <nfs/nfsm_subs.h>
41 #include <nfs/nqnfs.h>
42 
43 /* Defs */
44 #define	TRUE	1
45 #define	FALSE	0
46 
47 /*
48  * Global vfs data structures for nfs
49  */
50 int (**nfsv2_vnodeop_p)();
51 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
52 	{ &vop_default_desc, vn_default_error },
53 	{ &vop_lookup_desc, nfs_lookup },	/* lookup */
54 	{ &vop_create_desc, nfs_create },	/* create */
55 	{ &vop_mknod_desc, nfs_mknod },		/* mknod */
56 	{ &vop_open_desc, nfs_open },		/* open */
57 	{ &vop_close_desc, nfs_close },		/* close */
58 	{ &vop_access_desc, nfs_access },	/* access */
59 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
60 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
61 	{ &vop_read_desc, nfs_read },		/* read */
62 	{ &vop_write_desc, nfs_write },		/* write */
63 	{ &vop_ioctl_desc, nfs_ioctl },		/* ioctl */
64 	{ &vop_select_desc, nfs_select },	/* select */
65 	{ &vop_mmap_desc, nfs_mmap },		/* mmap */
66 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
67 	{ &vop_seek_desc, nfs_seek },		/* seek */
68 	{ &vop_remove_desc, nfs_remove },	/* remove */
69 	{ &vop_link_desc, nfs_link },		/* link */
70 	{ &vop_rename_desc, nfs_rename },	/* rename */
71 	{ &vop_mkdir_desc, nfs_mkdir },		/* mkdir */
72 	{ &vop_rmdir_desc, nfs_rmdir },		/* rmdir */
73 	{ &vop_symlink_desc, nfs_symlink },	/* symlink */
74 	{ &vop_readdir_desc, nfs_readdir },	/* readdir */
75 	{ &vop_readlink_desc, nfs_readlink },	/* readlink */
76 	{ &vop_abortop_desc, nfs_abortop },	/* abortop */
77 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
78 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
79 	{ &vop_lock_desc, nfs_lock },		/* lock */
80 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
81 	{ &vop_bmap_desc, nfs_bmap },		/* bmap */
82 	{ &vop_strategy_desc, nfs_strategy },	/* strategy */
83 	{ &vop_print_desc, nfs_print },		/* print */
84 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
85 	{ &vop_advlock_desc, nfs_advlock },	/* advlock */
86 	{ &vop_blkatoff_desc, nfs_blkatoff },	/* blkatoff */
87 	{ &vop_valloc_desc, nfs_valloc },	/* valloc */
88 	{ &vop_vfree_desc, nfs_vfree },		/* vfree */
89 	{ &vop_truncate_desc, nfs_truncate },	/* truncate */
90 	{ &vop_update_desc, nfs_update },	/* update */
91 	{ &vop_bwrite_desc, vn_bwrite },
92 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
93 };
94 struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
95 	{ &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
96 
97 /*
98  * Special device vnode ops
99  */
100 int (**spec_nfsv2nodeop_p)();
101 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
102 	{ &vop_default_desc, vn_default_error },
103 	{ &vop_lookup_desc, spec_lookup },	/* lookup */
104 	{ &vop_create_desc, spec_create },	/* create */
105 	{ &vop_mknod_desc, spec_mknod },	/* mknod */
106 	{ &vop_open_desc, spec_open },		/* open */
107 	{ &vop_close_desc, nfsspec_close },	/* close */
108 	{ &vop_access_desc, nfs_access },	/* access */
109 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
110 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
111 	{ &vop_read_desc, nfsspec_read },	/* read */
112 	{ &vop_write_desc, nfsspec_write },	/* write */
113 	{ &vop_ioctl_desc, spec_ioctl },	/* ioctl */
114 	{ &vop_select_desc, spec_select },	/* select */
115 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
116 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
117 	{ &vop_seek_desc, spec_seek },		/* seek */
118 	{ &vop_remove_desc, spec_remove },	/* remove */
119 	{ &vop_link_desc, spec_link },		/* link */
120 	{ &vop_rename_desc, spec_rename },	/* rename */
121 	{ &vop_mkdir_desc, spec_mkdir },	/* mkdir */
122 	{ &vop_rmdir_desc, spec_rmdir },	/* rmdir */
123 	{ &vop_symlink_desc, spec_symlink },	/* symlink */
124 	{ &vop_readdir_desc, spec_readdir },	/* readdir */
125 	{ &vop_readlink_desc, spec_readlink },	/* readlink */
126 	{ &vop_abortop_desc, spec_abortop },	/* abortop */
127 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
128 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
129 	{ &vop_lock_desc, nfs_lock },		/* lock */
130 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
131 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
132 	{ &vop_strategy_desc, spec_strategy },	/* strategy */
133 	{ &vop_print_desc, nfs_print },		/* print */
134 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
135 	{ &vop_advlock_desc, spec_advlock },	/* advlock */
136 	{ &vop_blkatoff_desc, spec_blkatoff },	/* blkatoff */
137 	{ &vop_valloc_desc, spec_valloc },	/* valloc */
138 	{ &vop_vfree_desc, spec_vfree },	/* vfree */
139 	{ &vop_truncate_desc, spec_truncate },	/* truncate */
140 	{ &vop_update_desc, nfs_update },	/* update */
141 	{ &vop_bwrite_desc, vn_bwrite },
142 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
143 };
144 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
145 	{ &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
146 
147 #ifdef FIFO
148 int (**fifo_nfsv2nodeop_p)();
149 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
150 	{ &vop_default_desc, vn_default_error },
151 	{ &vop_lookup_desc, fifo_lookup },	/* lookup */
152 	{ &vop_create_desc, fifo_create },	/* create */
153 	{ &vop_mknod_desc, fifo_mknod },	/* mknod */
154 	{ &vop_open_desc, fifo_open },		/* open */
155 	{ &vop_close_desc, nfsfifo_close },	/* close */
156 	{ &vop_access_desc, nfs_access },	/* access */
157 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
158 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
159 	{ &vop_read_desc, nfsfifo_read },	/* read */
160 	{ &vop_write_desc, nfsfifo_write },	/* write */
161 	{ &vop_ioctl_desc, fifo_ioctl },	/* ioctl */
162 	{ &vop_select_desc, fifo_select },	/* select */
163 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
164 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
165 	{ &vop_seek_desc, fifo_seek },		/* seek */
166 	{ &vop_remove_desc, fifo_remove },	/* remove */
167 	{ &vop_link_desc, fifo_link },		/* link */
168 	{ &vop_rename_desc, fifo_rename },	/* rename */
169 	{ &vop_mkdir_desc, fifo_mkdir },	/* mkdir */
170 	{ &vop_rmdir_desc, fifo_rmdir },	/* rmdir */
171 	{ &vop_symlink_desc, fifo_symlink },	/* symlink */
172 	{ &vop_readdir_desc, fifo_readdir },	/* readdir */
173 	{ &vop_readlink_desc, fifo_readlink },	/* readlink */
174 	{ &vop_abortop_desc, fifo_abortop },	/* abortop */
175 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
176 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
177 	{ &vop_lock_desc, nfs_lock },		/* lock */
178 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
179 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
180 	{ &vop_strategy_desc, fifo_badop },	/* strategy */
181 	{ &vop_print_desc, nfs_print },		/* print */
182 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
183 	{ &vop_advlock_desc, fifo_advlock },	/* advlock */
184 	{ &vop_blkatoff_desc, fifo_blkatoff },	/* blkatoff */
185 	{ &vop_valloc_desc, fifo_valloc },	/* valloc */
186 	{ &vop_vfree_desc, fifo_vfree },	/* vfree */
187 	{ &vop_truncate_desc, fifo_truncate },	/* truncate */
188 	{ &vop_update_desc, nfs_update },	/* update */
189 	{ &vop_bwrite_desc, vn_bwrite },
190 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
191 };
192 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
193 	{ &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
194 #endif /* FIFO */
195 
196 /*
197  * Global variables
198  */
199 extern u_long nfs_procids[NFS_NPROCS];
200 extern u_long nfs_prog, nfs_vers;
201 extern char nfsiobuf[MAXPHYS+NBPG];
202 struct buf nfs_bqueue;		/* Queue head for nfsiod's */
203 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
204 int nfs_numasync = 0;
205 #define	DIRHDSIZ	(sizeof (struct readdir) - (MAXNAMLEN + 1))
206 
207 /*
208  * nfs null call from vfs.
209  */
210 int
211 nfs_null(vp, cred, procp)
212 	struct vnode *vp;
213 	struct ucred *cred;
214 	struct proc *procp;
215 {
216 	caddr_t bpos, dpos;
217 	int error = 0;
218 	struct mbuf *mreq, *mrep, *md, *mb;
219 
220 	nfsm_reqhead(vp, NFSPROC_NULL, 0);
221 	nfsm_request(vp, NFSPROC_NULL, procp, cred);
222 	nfsm_reqdone;
223 	return (error);
224 }
225 
226 /*
227  * nfs access vnode op.
228  * Essentially just get vattr and then imitate iaccess()
229  */
230 int
231 nfs_access(ap)
232 	struct vop_access_args /* {
233 		struct vnode *a_vp;
234 		int  a_mode;
235 		struct ucred *a_cred;
236 		struct proc *a_p;
237 	} */ *ap;
238 {
239 	register struct vattr *vap;
240 	register gid_t *gp;
241 	register struct ucred *cred = ap->a_cred;
242 	mode_t mode = ap->a_mode;
243 	struct vattr vattr;
244 	register int i;
245 	int error;
246 
247 	/*
248 	 * If you're the super-user,
249 	 * you always get access.
250 	 */
251 	if (cred->cr_uid == 0)
252 		return (0);
253 	vap = &vattr;
254 	if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p))
255 		return (error);
256 	/*
257 	 * Access check is based on only one of owner, group, public.
258 	 * If not owner, then check group. If not a member of the
259 	 * group, then check public access.
260 	 */
261 	if (cred->cr_uid != vap->va_uid) {
262 		mode >>= 3;
263 		gp = cred->cr_groups;
264 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
265 			if (vap->va_gid == *gp)
266 				goto found;
267 		mode >>= 3;
268 found:
269 		;
270 	}
271 	if ((vap->va_mode & mode) != 0)
272 		return (0);
273 	return (EACCES);
274 }
275 
276 /*
277  * nfs open vnode op
278  * Just check to see if the type is ok
279  * and that deletion is not in progress.
280  */
281 /* ARGSUSED */
282 int
283 nfs_open(ap)
284 	struct vop_open_args /* {
285 		struct vnode *a_vp;
286 		int  a_mode;
287 		struct ucred *a_cred;
288 		struct proc *a_p;
289 	} */ *ap;
290 {
291 	register struct vnode *vp = ap->a_vp;
292 
293 	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
294 		return (EACCES);
295 	if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0)
296 		VTONFS(vp)->n_attrstamp = 0; /* For Open/Close consistency */
297 	return (0);
298 }
299 
300 /*
301  * nfs close vnode op
302  * For reg files, invalidate any buffer cache entries.
303  */
304 /* ARGSUSED */
305 int
306 nfs_close(ap)
307 	struct vop_close_args /* {
308 		struct vnodeop_desc *a_desc;
309 		struct vnode *a_vp;
310 		int  a_fflag;
311 		struct ucred *a_cred;
312 		struct proc *a_p;
313 	} */ *ap;
314 {
315 	register struct vnode *vp = ap->a_vp;
316 	register struct nfsnode *np = VTONFS(vp);
317 	int error = 0;
318 
319 	if (vp->v_type == VREG) {
320 	    if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
321 		(np->n_flag & NMODIFIED)) {
322 		error = vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
323 		np->n_flag &= ~NMODIFIED;
324 		np->n_attrstamp = 0;
325 	    }
326 	    if (np->n_flag & NWRITEERR) {
327 		np->n_flag &= ~NWRITEERR;
328 		error = np->n_error;
329 	    }
330 	}
331 	return (error);
332 }
333 
334 /*
335  * nfs getattr call from vfs.
336  */
337 int
338 nfs_getattr(ap)
339 	struct vop_getattr_args /* {
340 		struct vnode *a_vp;
341 		struct vattr *a_vap;
342 		struct ucred *a_cred;
343 		struct proc *a_p;
344 	} */ *ap;
345 {
346 	register struct vnode *vp = ap->a_vp;
347 	register struct nfsnode *np = VTONFS(vp);
348 	register caddr_t cp;
349 	caddr_t bpos, dpos;
350 	int error = 0;
351 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
352 
353 	/*
354 	 * Update local times for special files.
355 	 */
356 	if (np->n_flag & (NACC | NUPD)) {
357 		if (np->n_flag & NACC)
358 			np->n_atim = time;
359 		if (np->n_flag & NUPD)
360 			np->n_mtim = time;
361 		np->n_flag |= NCHG;
362 	}
363 	/*
364 	 * First look in the cache.
365 	 */
366 	if (nfs_getattrcache(vp, ap->a_vap) == 0)
367 		return (0);
368 	nfsstats.rpccnt[NFSPROC_GETATTR]++;
369 	nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH);
370 	nfsm_fhtom(vp);
371 	nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
372 	nfsm_loadattr(vp, ap->a_vap);
373 	nfsm_reqdone;
374 	return (error);
375 }
376 
377 /*
378  * nfs setattr call.
379  */
380 int
381 nfs_setattr(ap)
382 	struct vop_setattr_args /* {
383 		struct vnodeop_desc *a_desc;
384 		struct vnode *a_vp;
385 		struct vattr *a_vap;
386 		struct ucred *a_cred;
387 		struct proc *a_p;
388 	} */ *ap;
389 {
390 	register struct nfsv2_sattr *sp;
391 	register caddr_t cp;
392 	register long t1;
393 	caddr_t bpos, dpos, cp2;
394 	u_long *tl;
395 	int error = 0;
396 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
397 	register struct vnode *vp = ap->a_vp;
398 	register struct nfsnode *np = VTONFS(vp);
399 	register struct vattr *vap = ap->a_vap;
400 	u_quad_t frev;
401 
402 	nfsstats.rpccnt[NFSPROC_SETATTR]++;
403 	nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR);
404 	nfsm_fhtom(vp);
405 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
406 	if (vap->va_mode == 0xffff)
407 		sp->sa_mode = VNOVAL;
408 	else
409 		sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
410 	if (vap->va_uid == 0xffff)
411 		sp->sa_uid = VNOVAL;
412 	else
413 		sp->sa_uid = txdr_unsigned(vap->va_uid);
414 	if (vap->va_gid == 0xffff)
415 		sp->sa_gid = VNOVAL;
416 	else
417 		sp->sa_gid = txdr_unsigned(vap->va_gid);
418 	sp->sa_size = txdr_unsigned(vap->va_size);
419 	sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.ts_sec);
420 	sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
421 	txdr_time(&vap->va_mtime, &sp->sa_mtime);
422 	if (vap->va_size != VNOVAL || vap->va_mtime.ts_sec != VNOVAL ||
423 	    vap->va_atime.ts_sec != VNOVAL) {
424 		if (np->n_flag & NMODIFIED) {
425 			if (vap->va_size == 0)
426 				error =
427 				    vinvalbuf(vp, FALSE, ap->a_cred, ap->a_p);
428 			else
429 				error =
430 				    vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
431 			np->n_flag &= ~NMODIFIED;
432 		}
433 	}
434 	nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred);
435 	nfsm_loadattr(vp, (struct vattr *)0);
436 	if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) &&
437 	    NQNFS_CKCACHABLE(vp, NQL_WRITE)) {
438 		nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
439 		fxdr_hyper(tl, &frev);
440 		if (frev > np->n_brev)
441 			np->n_brev = frev;
442 	}
443 	nfsm_reqdone;
444 	return (error);
445 }
446 
447 /*
448  * nfs lookup call, one step at a time...
449  * First look in cache
450  * If not found, unlock the directory nfsnode and do the rpc
451  */
452 int
453 nfs_lookup(ap)
454 	struct vop_lookup_args /* {
455 		struct vnodeop_desc *a_desc;
456 		struct vnode *a_dvp;
457 		struct vnode **a_vpp;
458 		struct componentname *a_cnp;
459 	} */ *ap;
460 {
461 	register struct componentname *cnp = ap->a_cnp;
462 	register struct vnode *dvp = ap->a_dvp;
463 	register struct vnode **vpp = ap->a_vpp;
464 	register struct vnode *vdp;
465 	register u_long *tl;
466 	register caddr_t cp;
467 	register long t1, t2;
468 	struct nfsmount *nmp;
469 	struct nfsnode *tp;
470 	caddr_t bpos, dpos, cp2;
471 	time_t reqtime;
472 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
473 	struct vnode *newvp;
474 	long len;
475 	nfsv2fh_t *fhp;
476 	struct nfsnode *np;
477 	int lockparent, wantparent, error = 0;
478 	int nqlflag, cachable;
479 	u_quad_t frev;
480 
481 	*vpp = NULL;
482 	if (dvp->v_type != VDIR)
483 		return (ENOTDIR);
484 	lockparent = cnp->cn_flags & LOCKPARENT;
485 	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
486 	nmp = VFSTONFS(dvp->v_mount);
487 	np = VTONFS(dvp);
488 	if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
489 		struct vattr vattr;
490 		int vpid;
491 
492 		vdp = *vpp;
493 		vpid = vdp->v_id;
494 		/*
495 		 * See the comment starting `Step through' in ufs/ufs_lookup.c
496 		 * for an explanation of the locking protocol
497 		 */
498 		if (dvp == vdp) {
499 			VREF(vdp);
500 			error = 0;
501 		} else
502 			error = vget(vdp);
503 		if (!error) {
504 			if (vpid == vdp->v_id) {
505 			   if (nmp->nm_flag & NFSMNT_NQNFS) {
506 			        if (NQNFS_CKCACHABLE(dvp, NQL_READ)) {
507 					if (np->n_lrev != np->n_brev ||
508 					    (np->n_flag & NMODIFIED)) {
509 						np->n_direofoffset = 0;
510 						cache_purge(dvp);
511 						error = vinvalbuf(dvp, FALSE,
512 						    cnp->cn_cred, cnp->cn_proc);
513 						np->n_flag &= ~NMODIFIED;
514 						np->n_brev = np->n_lrev;
515 					} else {
516 						nfsstats.lookupcache_hits++;
517 						if (cnp->cn_nameiop != LOOKUP &&
518 						    (cnp->cn_flags&ISLASTCN))
519 						    cnp->cn_flags |= SAVENAME;
520 						return (0);
521 					}
522 				}
523 			   } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) &&
524 			       vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) {
525 				nfsstats.lookupcache_hits++;
526 				if (cnp->cn_nameiop != LOOKUP &&
527 				    (cnp->cn_flags&ISLASTCN))
528 					cnp->cn_flags |= SAVENAME;
529 				return (0);
530 			   }
531 			   cache_purge(vdp);
532 			}
533 			vrele(vdp);
534 		}
535 		*vpp = NULLVP;
536 	}
537 	error = 0;
538 	nfsstats.lookupcache_misses++;
539 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
540 	len = cnp->cn_namelen;
541 	nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
542 
543 	/*
544 	 * For nqnfs optionally piggyback a getlease request for the name
545 	 * being looked up.
546 	 */
547 	if (nmp->nm_flag & NFSMNT_NQNFS) {
548 		if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) &&
549 		    ((cnp->cn_flags&MAKEENTRY) &&
550 		    (cnp->cn_nameiop != DELETE || !(cnp->cn_flags&ISLASTCN)))) {
551 			nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
552 			*tl++ = txdr_unsigned(NQL_READ);
553 			*tl = txdr_unsigned(nmp->nm_leaseterm);
554 		} else {
555 			nfsm_build(tl, u_long *, NFSX_UNSIGNED);
556 			*tl = 0;
557 		}
558 	}
559 	nfsm_fhtom(dvp);
560 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
561 	reqtime = time.tv_sec;
562 	nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
563 nfsmout:
564 	if (error) {
565 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
566 		    (cnp->cn_flags & ISLASTCN) && error == ENOENT)
567 			error = EJUSTRETURN;
568 		if (cnp->cn_nameiop != LOOKUP && (cnp->cn_flags&ISLASTCN))
569 			cnp->cn_flags |= SAVENAME;
570 		return (error);
571 	}
572 	if (nmp->nm_flag & NFSMNT_NQNFS) {
573 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
574 		if (*tl) {
575 			nqlflag = fxdr_unsigned(int, *tl);
576 			nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
577 			cachable = fxdr_unsigned(int, *tl++);
578 			reqtime += fxdr_unsigned(int, *tl++);
579 			fxdr_hyper(tl, &frev);
580 		} else
581 			nqlflag = 0;
582 	}
583 	nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH);
584 
585 	/*
586 	 * Handle RENAME case...
587 	 */
588 	if (cnp->cn_nameiop == RENAME && wantparent && (cnp->cn_flags&ISLASTCN)) {
589 		if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
590 			m_freem(mrep);
591 			return (EISDIR);
592 		}
593 		if (error = nfs_nget(dvp->v_mount, fhp, &np)) {
594 			m_freem(mrep);
595 			return (error);
596 		}
597 		newvp = NFSTOV(np);
598 		if (error =
599 		    nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
600 			vrele(newvp);
601 			m_freem(mrep);
602 			return (error);
603 		}
604 		*vpp = newvp;
605 		m_freem(mrep);
606 		cnp->cn_flags |= SAVENAME;
607 		return (0);
608 	}
609 
610 	if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
611 		VREF(dvp);
612 		newvp = dvp;
613 	} else {
614 		if (error = nfs_nget(dvp->v_mount, fhp, &np)) {
615 			m_freem(mrep);
616 			return (error);
617 		}
618 		newvp = NFSTOV(np);
619 	}
620 	if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
621 		vrele(newvp);
622 		m_freem(mrep);
623 		return (error);
624 	}
625 	m_freem(mrep);
626 	*vpp = newvp;
627 	if (cnp->cn_nameiop != LOOKUP && (cnp->cn_flags&ISLASTCN))
628 		cnp->cn_flags |= SAVENAME;
629 	if ((cnp->cn_flags&MAKEENTRY) &&
630 	    (cnp->cn_nameiop != DELETE || !(cnp->cn_flags&ISLASTCN))) {
631 		if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
632 			np->n_ctime = np->n_vattr.va_ctime.ts_sec;
633 		else if (nqlflag && reqtime > time.tv_sec) {
634 			if (np->n_tnext) {
635 				if (np->n_tnext == (struct nfsnode *)nmp)
636 					nmp->nm_tprev = np->n_tprev;
637 				else
638 					np->n_tnext->n_tprev = np->n_tprev;
639 				if (np->n_tprev == (struct nfsnode *)nmp)
640 					nmp->nm_tnext = np->n_tnext;
641 				else
642 					np->n_tprev->n_tnext = np->n_tnext;
643 				if (nqlflag == NQL_WRITE)
644 					np->n_flag |= NQNFSWRITE;
645 			} else if (nqlflag == NQL_READ)
646 				np->n_flag &= ~NQNFSWRITE;
647 			else
648 				np->n_flag |= NQNFSWRITE;
649 			if (cachable)
650 				np->n_flag &= ~NQNFSNONCACHE;
651 			else
652 				np->n_flag |= NQNFSNONCACHE;
653 			np->n_expiry = reqtime;
654 			np->n_lrev = frev;
655 			tp = nmp->nm_tprev;
656 			while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
657 				tp = tp->n_tprev;
658 			if (tp == (struct nfsnode *)nmp) {
659 				np->n_tnext = nmp->nm_tnext;
660 				nmp->nm_tnext = np;
661 			} else {
662 				np->n_tnext = tp->n_tnext;
663 				tp->n_tnext = np;
664 			}
665 			np->n_tprev = tp;
666 			if (np->n_tnext == (struct nfsnode *)nmp)
667 				nmp->nm_tprev = np;
668 			else
669 				np->n_tnext->n_tprev = np;
670 		}
671 		cache_enter(dvp, *vpp, cnp);
672 	}
673 	return (0);
674 }
675 
676 /*
677  * nfs read call.
678  * Just call nfs_bioread() to do the work.
679  */
680 int
681 nfs_read(ap)
682 	struct vop_read_args /* {
683 		struct vnode *a_vp;
684 		struct uio *a_uio;
685 		int  a_ioflag;
686 		struct ucred *a_cred;
687 	} */ *ap;
688 {
689 	register struct vnode *vp = ap->a_vp;
690 
691 	if (vp->v_type != VREG)
692 		return (EPERM);
693 	return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
694 }
695 
696 /*
697  * nfs readlink call
698  */
699 int
700 nfs_readlink(ap)
701 	struct vop_readlink_args /* {
702 		struct vnode *a_vp;
703 		struct uio *a_uio;
704 		struct ucred *a_cred;
705 	} */ *ap;
706 {
707 	register struct vnode *vp = ap->a_vp;
708 
709 	if (vp->v_type != VLNK)
710 		return (EPERM);
711 	return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
712 }
713 
714 /*
715  * Do a readlink rpc.
716  * Called by nfs_doio() from below the buffer cache.
717  */
718 int
719 nfs_readlinkrpc(vp, uiop, cred)
720 	register struct vnode *vp;
721 	struct uio *uiop;
722 	struct ucred *cred;
723 {
724 	register u_long *tl;
725 	register caddr_t cp;
726 	register long t1;
727 	caddr_t bpos, dpos, cp2;
728 	int error = 0;
729 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
730 	long len;
731 
732 	nfsstats.rpccnt[NFSPROC_READLINK]++;
733 	nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH);
734 	nfsm_fhtom(vp);
735 	nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
736 	nfsm_strsiz(len, NFS_MAXPATHLEN);
737 	nfsm_mtouio(uiop, len);
738 	nfsm_reqdone;
739 	return (error);
740 }
741 
742 /*
743  * nfs read rpc call
744  * Ditto above
745  */
746 int
747 nfs_readrpc(vp, uiop, cred)
748 	register struct vnode *vp;
749 	struct uio *uiop;
750 	struct ucred *cred;
751 {
752 	register u_long *tl;
753 	register caddr_t cp;
754 	register long t1;
755 	caddr_t bpos, dpos, cp2;
756 	int error = 0;
757 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
758 	struct nfsmount *nmp;
759 	long len, retlen, tsiz;
760 
761 	nmp = VFSTONFS(vp->v_mount);
762 	tsiz = uiop->uio_resid;
763 	while (tsiz > 0) {
764 		nfsstats.rpccnt[NFSPROC_READ]++;
765 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
766 		nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3);
767 		nfsm_fhtom(vp);
768 		nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
769 		*tl++ = txdr_unsigned(uiop->uio_offset);
770 		*tl++ = txdr_unsigned(len);
771 		*tl = 0;
772 		nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);
773 		nfsm_loadattr(vp, (struct vattr *)0);
774 		nfsm_strsiz(retlen, nmp->nm_rsize);
775 		nfsm_mtouio(uiop, retlen);
776 		m_freem(mrep);
777 		if (retlen < len)
778 			tsiz = 0;
779 		else
780 			tsiz -= len;
781 	}
782 nfsmout:
783 	return (error);
784 }
785 
786 /*
787  * nfs write call
788  */
789 int
790 nfs_writerpc(vp, uiop, cred)
791 	register struct vnode *vp;
792 	struct uio *uiop;
793 	struct ucred *cred;
794 {
795 	register u_long *tl;
796 	register caddr_t cp;
797 	register long t1;
798 	caddr_t bpos, dpos, cp2;
799 	int error = 0;
800 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
801 	struct nfsmount *nmp;
802 	struct nfsnode *np = VTONFS(vp);
803 	u_quad_t frev;
804 	long len, tsiz;
805 
806 	nmp = VFSTONFS(vp->v_mount);
807 	tsiz = uiop->uio_resid;
808 	while (tsiz > 0) {
809 		nfsstats.rpccnt[NFSPROC_WRITE]++;
810 		len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
811 		nfsm_reqhead(vp, NFSPROC_WRITE,
812 			NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len));
813 		nfsm_fhtom(vp);
814 		nfsm_build(tl, u_long *, NFSX_UNSIGNED*4);
815 		*(tl+1) = txdr_unsigned(uiop->uio_offset);
816 		*(tl+3) = txdr_unsigned(len);
817 		nfsm_uiotom(uiop, len);
818 		nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);
819 		nfsm_loadattr(vp, (struct vattr *)0);
820 		if (nmp->nm_flag & NFSMNT_MYWRITE)
821 			VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec;
822 		else if ((nmp->nm_flag & NFSMNT_NQNFS) &&
823 			 NQNFS_CKCACHABLE(vp, NQL_WRITE)) {
824 			nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
825 			fxdr_hyper(tl, &frev);
826 			if (frev > np->n_brev)
827 				np->n_brev = frev;
828 		}
829 		m_freem(mrep);
830 		tsiz -= len;
831 	}
832 nfsmout:
833 	if (error)
834 		uiop->uio_resid = tsiz;
835 	return (error);
836 }
837 
838 /*
839  * nfs mknod call
840  * This is a kludge. Use a create rpc but with the IFMT bits of the mode
841  * set to specify the file type and the size field for rdev.
842  */
843 /* ARGSUSED */
844 int
845 nfs_mknod(ap)
846 	struct vop_mknod_args /* {
847 		struct vnode *a_dvp;
848 		struct vnode **a_vpp;
849 		struct componentname *a_cnp;
850 		struct vattr *a_vap;
851 	} */ *ap;
852 {
853 	register struct vnode *dvp = ap->a_dvp;
854 	register struct vattr *vap = ap->a_vap;
855 	register struct componentname *cnp = ap->a_cnp;
856 	register struct nfsv2_sattr *sp;
857 	register u_long *tl;
858 	register caddr_t cp;
859 	register long t2;
860 	caddr_t bpos, dpos;
861 	int error = 0;
862 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
863 	u_long rdev;
864 
865 	if (vap->va_type == VCHR || vap->va_type == VBLK)
866 		rdev = txdr_unsigned(vap->va_rdev);
867 #ifdef FIFO
868 	else if (vap->va_type == VFIFO)
869 		rdev = 0xffffffff;
870 #endif /* FIFO */
871 	else {
872 		VOP_ABORTOP(dvp, cnp);
873 		vput(dvp);
874 		return (EOPNOTSUPP);
875 	}
876 	nfsstats.rpccnt[NFSPROC_CREATE]++;
877 	nfsm_reqhead(dvp, NFSPROC_CREATE,
878 	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR);
879 	nfsm_fhtom(dvp);
880 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
881 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
882 	sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
883 	sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
884 	sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
885 	sp->sa_size = rdev;
886 	/* or should these be VNOVAL ?? */
887 	txdr_time(&vap->va_atime, &sp->sa_atime);
888 	txdr_time(&vap->va_mtime, &sp->sa_mtime);
889 	nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
890 	nfsm_reqdone;
891 	FREE(cnp->cn_pnbuf, M_NAMEI);
892 	VTONFS(dvp)->n_flag |= NMODIFIED;
893 	vrele(dvp);
894 	return (error);
895 }
896 
897 /*
898  * nfs file create call
899  */
900 int
901 nfs_create(ap)
902 	struct vop_create_args /* {
903 		struct vnode *a_dvp;
904 		struct vnode **a_vpp;
905 		struct componentname *a_cnp;
906 		struct vattr *a_vap;
907 	} */ *ap;
908 {
909 	register struct vnode *dvp = ap->a_dvp;
910 	register struct vattr *vap = ap->a_vap;
911 	register struct componentname *cnp = ap->a_cnp;
912 	register struct nfsv2_sattr *sp;
913 	register u_long *tl;
914 	register caddr_t cp;
915 	register long t1, t2;
916 	caddr_t bpos, dpos, cp2;
917 	int error = 0;
918 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
919 
920 	nfsstats.rpccnt[NFSPROC_CREATE]++;
921 	nfsm_reqhead(dvp, NFSPROC_CREATE,
922 	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR);
923 	nfsm_fhtom(dvp);
924 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
925 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
926 	sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
927 	sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
928 	sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
929 	sp->sa_size = txdr_unsigned(0);
930 	/* or should these be VNOVAL ?? */
931 	txdr_time(&vap->va_atime, &sp->sa_atime);
932 	txdr_time(&vap->va_mtime, &sp->sa_mtime);
933 	nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
934 	nfsm_mtofh(dvp, *ap->a_vpp);
935 	nfsm_reqdone;
936 	FREE(cnp->cn_pnbuf, M_NAMEI);
937 	VTONFS(dvp)->n_flag |= NMODIFIED;
938 	vrele(dvp);
939 	return (error);
940 }
941 
942 /*
943  * nfs file remove call
944  * To try and make nfs semantics closer to ufs semantics, a file that has
945  * other processes using the vnode is renamed instead of removed and then
946  * removed later on the last close.
947  * - If v_usecount > 1
948  *	  If a rename is not already in the works
949  *	     call nfs_sillyrename() to set it up
950  *     else
951  *	  do the remove rpc
952  */
953 int
954 nfs_remove(ap)
955 	struct vop_remove_args /* {
956 		struct vnodeop_desc *a_desc;
957 		struct vnode * a_dvp;
958 		struct vnode * a_vp;
959 		struct componentname * a_cnp;
960 	} */ *ap;
961 {
962 	register struct vnode *vp = ap->a_vp;
963 	register struct vnode *dvp = ap->a_dvp;
964 	register struct componentname *cnp = ap->a_cnp;
965 	register struct nfsnode *np = VTONFS(vp);
966 	register u_long *tl;
967 	register caddr_t cp;
968 	register long t2;
969 	caddr_t bpos, dpos;
970 	int error = 0;
971 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
972 
973 	if (vp->v_usecount > 1) {
974 		if (!np->n_sillyrename)
975 			error = nfs_sillyrename(dvp, vp, cnp);
976 	} else {
977 		/*
978 		 * Purge the name cache so that the chance of a lookup for
979 		 * the name succeeding while the remove is in progress is
980 		 * minimized. Without node locking it can still happen, such
981 		 * that an I/O op returns ESTALE, but since you get this if
982 		 * another host removes the file..
983 		 */
984 		cache_purge(vp);
985 		/*
986 		 * Throw away biocache buffers. Mainly to avoid
987 		 * unnecessary delayed writes.
988 		 */
989 		error = vinvalbuf(vp, FALSE, cnp->cn_cred, cnp->cn_proc);
990 		/* Do the rpc */
991 		nfsstats.rpccnt[NFSPROC_REMOVE]++;
992 		nfsm_reqhead(dvp, NFSPROC_REMOVE,
993 			NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen));
994 		nfsm_fhtom(dvp);
995 		nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
996 		nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred);
997 		nfsm_reqdone;
998 		FREE(cnp->cn_pnbuf, M_NAMEI);
999 		VTONFS(dvp)->n_flag |= NMODIFIED;
1000 		/*
1001 		 * Kludge City: If the first reply to the remove rpc is lost..
1002 		 *   the reply to the retransmitted request will be ENOENT
1003 		 *   since the file was in fact removed
1004 		 *   Therefore, we cheat and return success.
1005 		 */
1006 		if (error == ENOENT)
1007 			error = 0;
1008 	}
1009 	np->n_attrstamp = 0;
1010 	vrele(dvp);
1011 	vrele(vp);
1012 	return (error);
1013 }
1014 
1015 /*
1016  * nfs file remove rpc called from nfs_inactive
1017  */
1018 int
1019 nfs_removeit(sp)
1020 	register struct sillyrename *sp;
1021 {
1022 	register u_long *tl;
1023 	register caddr_t cp;
1024 	register long t2;
1025 	caddr_t bpos, dpos;
1026 	int error = 0;
1027 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1028 
1029 	nfsstats.rpccnt[NFSPROC_REMOVE]++;
1030 	nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE,
1031 		NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen));
1032 	nfsm_fhtom(sp->s_dvp);
1033 	nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
1034 	nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred);
1035 	nfsm_reqdone;
1036 	VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
1037 	return (error);
1038 }
1039 
1040 /*
1041  * nfs file rename call
1042  */
1043 int
1044 nfs_rename(ap)
1045 	struct vop_rename_args  /* {
1046 		struct vnode *a_fdvp;
1047 		struct vnode *a_fvp;
1048 		struct componentname *a_fcnp;
1049 		struct vnode *a_tdvp;
1050 		struct vnode *a_tvp;
1051 		struct componentname *a_tcnp;
1052 	} */ *ap;
1053 {
1054 	register struct vnode *fvp = ap->a_fvp;
1055 	register struct vnode *tvp = ap->a_tvp;
1056 	register struct vnode *fdvp = ap->a_fdvp;
1057 	register struct vnode *tdvp = ap->a_tdvp;
1058 	register struct componentname *tcnp = ap->a_tcnp;
1059 	register struct componentname *fcnp = ap->a_fcnp;
1060 	register u_long *tl;
1061 	register caddr_t cp;
1062 	register long t2;
1063 	caddr_t bpos, dpos;
1064 	int error = 0;
1065 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1066 
1067 	/* Check for cross-device rename */
1068 	if ((fvp->v_mount != tdvp->v_mount) ||
1069 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
1070 		error = EXDEV;
1071 		goto out;
1072 	}
1073 
1074 
1075 	nfsstats.rpccnt[NFSPROC_RENAME]++;
1076 	nfsm_reqhead(fdvp, NFSPROC_RENAME,
1077 		(NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+
1078 		nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/
1079 	nfsm_fhtom(fdvp);
1080 	nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN);
1081 	nfsm_fhtom(tdvp);
1082 	nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN);
1083 	nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred);
1084 	nfsm_reqdone;
1085 	VTONFS(fdvp)->n_flag |= NMODIFIED;
1086 	VTONFS(tdvp)->n_flag |= NMODIFIED;
1087 	if (fvp->v_type == VDIR) {
1088 		if (tvp != NULL && tvp->v_type == VDIR)
1089 			cache_purge(tdvp);
1090 		cache_purge(fdvp);
1091 	}
1092 out:
1093 	if (tdvp == tvp)
1094 		vrele(tdvp);
1095 	else
1096 		vput(tdvp);
1097 	if (tvp)
1098 		vput(tvp);
1099 	vrele(fdvp);
1100 	vrele(fvp);
1101 	/*
1102 	 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1103 	 */
1104 	if (error == ENOENT)
1105 		error = 0;
1106 	return (error);
1107 }
1108 
1109 /*
1110  * nfs file rename rpc called from nfs_remove() above
1111  */
1112 int
1113 nfs_renameit(sdvp, scnp, sp)
1114 	struct vnode *sdvp;
1115 	struct componentname *scnp;
1116 	register struct sillyrename *sp;
1117 {
1118 	register u_long *tl;
1119 	register caddr_t cp;
1120 	register long t2;
1121 	caddr_t bpos, dpos;
1122 	int error = 0;
1123 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1124 
1125 	nfsstats.rpccnt[NFSPROC_RENAME]++;
1126 	nfsm_reqhead(sdvp, NFSPROC_RENAME,
1127 		(NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+
1128 		nfsm_rndup(sp->s_namlen));
1129 	nfsm_fhtom(sdvp);
1130 	nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN);
1131 	nfsm_fhtom(sdvp);
1132 	nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
1133 	nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred);
1134 	nfsm_reqdone;
1135 	FREE(scnp->cn_pnbuf, M_NAMEI);
1136 	VTONFS(sdvp)->n_flag |= NMODIFIED;
1137 	return (error);
1138 }
1139 
1140 /*
1141  * nfs hard link create call
1142  */
1143 int
1144 nfs_link(ap)
1145 	struct vop_link_args /* {
1146 		struct vnode *a_vp;
1147 		struct vnode *a_tdvp;
1148 		struct componentname *a_cnp;
1149 	} */ *ap;
1150 {
1151 	register struct vnode *vp = ap->a_vp;
1152 	register struct vnode *tdvp = ap->a_tdvp;
1153 	register struct componentname *cnp = ap->a_cnp;
1154 	register u_long *tl;
1155 	register caddr_t cp;
1156 	register long t2;
1157 	caddr_t bpos, dpos;
1158 	int error = 0;
1159 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1160 
1161 	if (vp->v_mount != tdvp->v_mount) {
1162 		/*VOP_ABORTOP(vp, cnp);*/
1163 		if (tdvp == vp)
1164 			vrele(vp);
1165 		else
1166 			vput(vp);
1167 		return (EXDEV);
1168 	}
1169 
1170 	nfsstats.rpccnt[NFSPROC_LINK]++;
1171 	nfsm_reqhead(tdvp, NFSPROC_LINK,
1172 		NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen));
1173 	nfsm_fhtom(tdvp);
1174 	nfsm_fhtom(vp);
1175 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1176 	nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1177 	nfsm_reqdone;
1178 	FREE(cnp->cn_pnbuf, M_NAMEI);
1179 	VTONFS(tdvp)->n_attrstamp = 0;
1180 	VTONFS(vp)->n_flag |= NMODIFIED;
1181 	vrele(vp);
1182 	/*
1183 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1184 	 */
1185 	if (error == EEXIST)
1186 		error = 0;
1187 	return (error);
1188 }
1189 
1190 /*
1191  * nfs symbolic link create call
1192  */
1193 /* start here */
1194 int
1195 nfs_symlink(ap)
1196 	struct vop_symlink_args /* {
1197 		struct vnode *a_dvp;
1198 		struct vnode **a_vpp;
1199 		struct componentname *a_cnp;
1200 		struct vattr *a_vap;
1201 		char *a_target;
1202 	} */ *ap;
1203 {
1204 	register struct vnode *dvp = ap->a_dvp;
1205 	register struct vattr *vap = ap->a_vap;
1206 	register struct componentname *cnp = ap->a_cnp;
1207 	register struct nfsv2_sattr *sp;
1208 	register u_long *tl;
1209 	register caddr_t cp;
1210 	register long t2;
1211 	caddr_t bpos, dpos;
1212 	int slen, error = 0;
1213 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1214 
1215 	nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1216 	slen = strlen(ap->a_target);
1217 	nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+
1218 	    nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR);
1219 	nfsm_fhtom(dvp);
1220 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1221 	nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1222 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1223 	sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
1224 	sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1225 	sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
1226 	sp->sa_size = txdr_unsigned(VNOVAL);
1227 	txdr_time(&vap->va_atime, &sp->sa_atime);	/* or VNOVAL ?? */
1228 	txdr_time(&vap->va_mtime, &sp->sa_mtime);	/* or VNOVAL ?? */
1229 	nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1230 	nfsm_reqdone;
1231 	FREE(cnp->cn_pnbuf, M_NAMEI);
1232 	VTONFS(dvp)->n_flag |= NMODIFIED;
1233 	vrele(dvp);
1234 	/*
1235 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1236 	 */
1237 	if (error == EEXIST)
1238 		error = 0;
1239 	return (error);
1240 }
1241 
1242 /*
1243  * nfs make dir call
1244  */
1245 int
1246 nfs_mkdir(ap)
1247 	struct vop_mkdir_args /* {
1248 		struct vnode *a_dvp;
1249 		struct vnode **a_vpp;
1250 		struct componentname *a_cnp;
1251 		struct vattr *a_vap;
1252 	} */ *ap;
1253 {
1254 	register struct vnode *dvp = ap->a_dvp;
1255 	register struct vattr *vap = ap->a_vap;
1256 	register struct componentname *cnp = ap->a_cnp;
1257 	register struct vnode **vpp = ap->a_vpp;
1258 	register struct nfsv2_sattr *sp;
1259 	register u_long *tl;
1260 	register caddr_t cp;
1261 	register long t1, t2;
1262 	register int len;
1263 	caddr_t bpos, dpos, cp2;
1264 	int error = 0, firsttry = 1;
1265 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1266 
1267 	len = cnp->cn_namelen;
1268 	nfsstats.rpccnt[NFSPROC_MKDIR]++;
1269 	nfsm_reqhead(dvp, NFSPROC_MKDIR,
1270 	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
1271 	nfsm_fhtom(dvp);
1272 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1273 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1274 	sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
1275 	sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1276 	sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
1277 	sp->sa_size = txdr_unsigned(VNOVAL);
1278 	txdr_time(&vap->va_atime, &sp->sa_atime);	/* or VNOVAL ?? */
1279 	txdr_time(&vap->va_mtime, &sp->sa_mtime);	/* or VNOVAL ?? */
1280 	nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1281 	nfsm_mtofh(dvp, *vpp);
1282 	nfsm_reqdone;
1283 	VTONFS(dvp)->n_flag |= NMODIFIED;
1284 	/*
1285 	 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1286 	 * if we can succeed in looking up the directory.
1287 	 * "firsttry" is necessary since the macros may "goto nfsmout" which
1288 	 * is above the if on errors. (Ugh)
1289 	 */
1290 	if (error == EEXIST && firsttry) {
1291 		firsttry = 0;
1292 		error = 0;
1293 		nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1294 		*vpp = NULL;
1295 		nfsm_reqhead(dvp, NFSPROC_LOOKUP,
1296 		    NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1297 		nfsm_fhtom(dvp);
1298 		nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1299 		nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
1300 		nfsm_mtofh(dvp, *vpp);
1301 		if ((*vpp)->v_type != VDIR) {
1302 			vput(*vpp);
1303 			error = EEXIST;
1304 		}
1305 		m_freem(mrep);
1306 	}
1307 	FREE(cnp->cn_pnbuf, M_NAMEI);
1308 	vrele(dvp);
1309 	return (error);
1310 }
1311 
1312 /*
1313  * nfs remove directory call
1314  */
1315 int
1316 nfs_rmdir(ap)
1317 	struct vop_rmdir_args /* {
1318 		struct vnode *a_dvp;
1319 		struct vnode *a_vp;
1320 		struct componentname *a_cnp;
1321 	} */ *ap;
1322 {
1323 	register struct vnode *vp = ap->a_vp;
1324 	register struct vnode *dvp = ap->a_dvp;
1325 	register struct componentname *cnp = ap->a_cnp;
1326 	register u_long *tl;
1327 	register caddr_t cp;
1328 	register long t2;
1329 	caddr_t bpos, dpos;
1330 	int error = 0;
1331 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1332 
1333 	if (dvp == vp) {
1334 		vrele(dvp);
1335 		vrele(dvp);
1336 		FREE(cnp->cn_pnbuf, M_NAMEI);
1337 		return (EINVAL);
1338 	}
1339 	nfsstats.rpccnt[NFSPROC_RMDIR]++;
1340 	nfsm_reqhead(dvp, NFSPROC_RMDIR,
1341 		NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen));
1342 	nfsm_fhtom(dvp);
1343 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1344 	nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1345 	nfsm_reqdone;
1346 	FREE(cnp->cn_pnbuf, M_NAMEI);
1347 	VTONFS(dvp)->n_flag |= NMODIFIED;
1348 	cache_purge(dvp);
1349 	cache_purge(vp);
1350 	vrele(vp);
1351 	vrele(dvp);
1352 	/*
1353 	 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1354 	 */
1355 	if (error == ENOENT)
1356 		error = 0;
1357 	return (error);
1358 }
1359 
1360 /*
1361  * nfs readdir call
1362  * Although cookie is defined as opaque, I translate it to/from net byte
1363  * order so that it looks more sensible. This appears consistent with the
1364  * Ultrix implementation of NFS.
1365  */
1366 int
1367 nfs_readdir(ap)
1368 	struct vop_readdir_args /* {
1369 		struct vnode *a_vp;
1370 		struct uio *a_uio;
1371 		struct ucred *a_cred;
1372 	} */ *ap;
1373 {
1374 	register struct vnode *vp = ap->a_vp;
1375 	register struct nfsnode *np = VTONFS(vp);
1376 	register struct uio *uio = ap->a_uio;
1377 	int tresid, error;
1378 	struct vattr vattr;
1379 
1380 	if (vp->v_type != VDIR)
1381 		return (EPERM);
1382 	/*
1383 	 * First, check for hit on the EOF offset cache
1384 	 */
1385 	if (uio->uio_offset != 0 && uio->uio_offset == np->n_direofoffset &&
1386 	    (np->n_flag & NMODIFIED) == 0) {
1387 		if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
1388 			if (NQNFS_CKCACHABLE(vp, NQL_READ)) {
1389 				nfsstats.direofcache_hits++;
1390 				return (0);
1391 			}
1392 		} else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1393 			np->n_mtime == vattr.va_mtime.ts_sec) {
1394 			nfsstats.direofcache_hits++;
1395 			return (0);
1396 		}
1397 	}
1398 
1399 	/*
1400 	 * Call nfs_bioread() to do the real work.
1401 	 */
1402 	tresid = uio->uio_resid;
1403 	error = nfs_bioread(vp, uio, 0, ap->a_cred);
1404 
1405 	if (!error && uio->uio_resid == tresid)
1406 		nfsstats.direofcache_misses++;
1407 	return (error);
1408 }
1409 
1410 /*
1411  * Readdir rpc call.
1412  * Called from below the buffer cache by nfs_doio().
1413  */
1414 int
1415 nfs_readdirrpc(vp, uiop, cred)
1416 	register struct vnode *vp;
1417 	struct uio *uiop;
1418 	struct ucred *cred;
1419 {
1420 	register long len;
1421 	register struct readdir *dp;
1422 	register u_long *tl;
1423 	register caddr_t cp;
1424 	register long t1;
1425 	long tlen, lastlen;
1426 	caddr_t bpos, dpos, cp2;
1427 	int error = 0;
1428 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1429 	struct mbuf *md2;
1430 	caddr_t dpos2;
1431 	int siz;
1432 	int more_dirs = 1;
1433 	off_t off, savoff;
1434 	struct readdir *savdp;
1435 	struct nfsmount *nmp;
1436 	struct nfsnode *np = VTONFS(vp);
1437 	long tresid;
1438 
1439 	nmp = VFSTONFS(vp->v_mount);
1440 	tresid = uiop->uio_resid;
1441 	/*
1442 	 * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
1443 	 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.
1444 	 * The stopping criteria is EOF or buffer full.
1445 	 */
1446 	while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
1447 		nfsstats.rpccnt[NFSPROC_READDIR]++;
1448 		nfsm_reqhead(vp, NFSPROC_READDIR,
1449 			NFSX_FH+2*NFSX_UNSIGNED);
1450 		nfsm_fhtom(vp);
1451 		nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1452 		*tl++ = txdr_unsigned(uiop->uio_offset);
1453 		*tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
1454 			nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
1455 		nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
1456 		siz = 0;
1457 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1458 		more_dirs = fxdr_unsigned(int, *tl);
1459 
1460 		/* Save the position so that we can do nfsm_mtouio() later */
1461 		dpos2 = dpos;
1462 		md2 = md;
1463 
1464 		/* loop thru the dir entries, doctoring them to 4bsd form */
1465 		off = uiop->uio_offset;
1466 #ifdef lint
1467 		dp = (struct readdir *)0;
1468 #endif /* lint */
1469 		while (more_dirs && siz < uiop->uio_resid) {
1470 			savoff = off;		/* Hold onto offset and dp */
1471 			savdp = dp;
1472 			nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED);
1473 			dp = (struct readdir *)tl;
1474 			dp->d_ino = fxdr_unsigned(u_long, *tl++);
1475 			len = fxdr_unsigned(int, *tl);
1476 			if (len <= 0 || len > NFS_MAXNAMLEN) {
1477 				error = EBADRPC;
1478 				m_freem(mrep);
1479 				goto nfsmout;
1480 			}
1481 			dp->d_namlen = (u_short)len;
1482 			nfsm_adv(len);		/* Point past name */
1483 			tlen = nfsm_rndup(len);
1484 			/*
1485 			 * This should not be necessary, but some servers have
1486 			 * broken XDR such that these bytes are not null filled.
1487 			 */
1488 			if (tlen != len) {
1489 				*dpos = '\0';	/* Null-terminate */
1490 				nfsm_adv(tlen - len);
1491 				len = tlen;
1492 			}
1493 			nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED);
1494 			off = fxdr_unsigned(off_t, *tl);
1495 			*tl++ = 0;	/* Ensures null termination of name */
1496 			more_dirs = fxdr_unsigned(int, *tl);
1497 			dp->d_reclen = len+4*NFSX_UNSIGNED;
1498 			siz += dp->d_reclen;
1499 		}
1500 		/*
1501 		 * If at end of rpc data, get the eof boolean
1502 		 */
1503 		if (!more_dirs) {
1504 			nfsm_dissecton(tl, u_long *, NFSX_UNSIGNED);
1505 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
1506 
1507 			/*
1508 			 * If at EOF, cache directory offset
1509 			 */
1510 			if (!more_dirs)
1511 				np->n_direofoffset = off;
1512 		}
1513 		/*
1514 		 * If there is too much to fit in the data buffer, use savoff and
1515 		 * savdp to trim off the last record.
1516 		 * --> we are not at eof
1517 		 */
1518 		if (siz > uiop->uio_resid) {
1519 			off = savoff;
1520 			siz -= dp->d_reclen;
1521 			dp = savdp;
1522 			more_dirs = 0;	/* Paranoia */
1523 		}
1524 		if (siz > 0) {
1525 			lastlen = dp->d_reclen;
1526 			md = md2;
1527 			dpos = dpos2;
1528 			nfsm_mtouio(uiop, siz);
1529 			uiop->uio_offset = off;
1530 		} else
1531 			more_dirs = 0;	/* Ugh, never happens, but in case.. */
1532 		m_freem(mrep);
1533 	}
1534 	/*
1535 	 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
1536 	 * by increasing d_reclen for the last record.
1537 	 */
1538 	if (uiop->uio_resid < tresid) {
1539 		len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);
1540 		if (len > 0) {
1541 			dp = (struct readdir *)
1542 				(uiop->uio_iov->iov_base - lastlen);
1543 			dp->d_reclen += len;
1544 			uiop->uio_iov->iov_base += len;
1545 			uiop->uio_iov->iov_len -= len;
1546 			uiop->uio_resid -= len;
1547 		}
1548 	}
1549 nfsmout:
1550 	return (error);
1551 }
1552 
1553 /*
1554  * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc() when
1555  * the "rdirlook" mount option is specified.
1556  */
1557 int
1558 nfs_readdirlookrpc(vp, uiop, cred)
1559 	struct vnode *vp;
1560 	register struct uio *uiop;
1561 	struct ucred *cred;
1562 {
1563 	register int len;
1564 	register struct readdir *dp;
1565 	register u_long *tl;
1566 	register caddr_t cp;
1567 	register long t1;
1568 	caddr_t bpos, dpos, cp2;
1569 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1570 	struct nameidata nami, *ndp = &nami;
1571 	struct componentname *cnp = &ndp->ni_cnd;
1572 	off_t off, endoff;
1573 	time_t reqtime, ltime;
1574 	struct nfsmount *nmp;
1575 	struct nfsnode *np, *tp;
1576 	struct vnode *newvp;
1577 	nfsv2fh_t *fhp;
1578 	u_long fileno;
1579 	u_quad_t frev;
1580 	int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i;
1581 	int cachable;
1582 
1583 	if (uiop->uio_iovcnt != 1)
1584 		panic("nfs rdirlook");
1585 	nmp = VFSTONFS(vp->v_mount);
1586 	tresid = uiop->uio_resid;
1587 	ndp->ni_dvp = vp;
1588 	newvp = NULLVP;
1589 	/*
1590 	 * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
1591 	 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.
1592 	 * The stopping criteria is EOF or buffer full.
1593 	 */
1594 	while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
1595 		nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++;
1596 		nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK,
1597 			NFSX_FH+3*NFSX_UNSIGNED);
1598 		nfsm_fhtom(vp);
1599 		nfsm_build(tl, u_long *, 3*NFSX_UNSIGNED);
1600 		*tl++ = txdr_unsigned(uiop->uio_offset);
1601 		*tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
1602 			nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
1603 		*tl = txdr_unsigned(nmp->nm_leaseterm);
1604 		reqtime = time.tv_sec;
1605 		nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred);
1606 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1607 		more_dirs = fxdr_unsigned(int, *tl);
1608 
1609 		/* loop thru the dir entries, doctoring them to 4bsd form */
1610 		off = uiop->uio_offset;
1611 		bigenough = 1;
1612 		while (more_dirs && bigenough) {
1613 			doit = 1;
1614 			nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
1615 			cachable = fxdr_unsigned(int, *tl++);
1616 			ltime = reqtime + fxdr_unsigned(int, *tl++);
1617 			fxdr_hyper(tl, &frev);
1618 			nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH);
1619 			if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
1620 				VREF(vp);
1621 				newvp = vp;
1622 				np = VTONFS(vp);
1623 			} else {
1624 				if (error = nfs_nget(vp->v_mount, fhp, &np))
1625 					doit = 0;
1626 				newvp = NFSTOV(np);
1627 			}
1628 			if (error = nfs_loadattrcache(&newvp, &md, &dpos,
1629 				(struct vattr *)0))
1630 				doit = 0;
1631 			nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
1632 			fileno = fxdr_unsigned(u_long, *tl++);
1633 			len = fxdr_unsigned(int, *tl);
1634 			if (len <= 0 || len > NFS_MAXNAMLEN) {
1635 				error = EBADRPC;
1636 				m_freem(mrep);
1637 				goto nfsmout;
1638 			}
1639 			tlen = (len + 4) & ~0x3;
1640 			if ((tlen + DIRHDSIZ) > uiop->uio_resid)
1641 				bigenough = 0;
1642 			if (bigenough && doit) {
1643 				dp = (struct readdir *)uiop->uio_iov->iov_base;
1644 				dp->d_ino = fileno;
1645 				dp->d_namlen = len;
1646 				dp->d_reclen = tlen + DIRHDSIZ;
1647 				uiop->uio_resid -= DIRHDSIZ;
1648 				uiop->uio_iov->iov_base += DIRHDSIZ;
1649 				uiop->uio_iov->iov_len -= DIRHDSIZ;
1650 				cnp->cn_nameptr = uiop->uio_iov->iov_base;
1651 				cnp->cn_namelen = len;
1652 				ndp->ni_vp = newvp;
1653 				nfsm_mtouio(uiop, len);
1654 				cp = uiop->uio_iov->iov_base;
1655 				tlen -= len;
1656 				for (i = 0; i < tlen; i++)
1657 					*cp++ = '\0';
1658 				uiop->uio_iov->iov_base += tlen;
1659 				uiop->uio_iov->iov_len -= tlen;
1660 				uiop->uio_resid -= tlen;
1661 				cnp->cn_hash = 0;
1662 				for (cp = cnp->cn_nameptr, i = 1; i <= len; i++, cp++)
1663 					cnp->cn_hash += (unsigned char)*cp * i;
1664 				if (ltime > time.tv_sec) {
1665 					if (np->n_tnext) {
1666 						if (np->n_tnext == (struct nfsnode *)nmp)
1667 							nmp->nm_tprev = np->n_tprev;
1668 						else
1669 							np->n_tnext->n_tprev = np->n_tprev;
1670 						if (np->n_tprev == (struct nfsnode *)nmp)
1671 							nmp->nm_tnext = np->n_tnext;
1672 						else
1673 							np->n_tprev->n_tnext = np->n_tnext;
1674 					} else
1675 						np->n_flag &= ~NQNFSWRITE;
1676 					if (cachable)
1677 						np->n_flag &= ~NQNFSNONCACHE;
1678 					else
1679 						np->n_flag |= NQNFSNONCACHE;
1680 					np->n_expiry = ltime;
1681 					np->n_lrev = frev;
1682 					tp = nmp->nm_tprev;
1683 					while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
1684 						tp = tp->n_tprev;
1685 					if (tp == (struct nfsnode *)nmp) {
1686 						np->n_tnext = nmp->nm_tnext;
1687 						nmp->nm_tnext = np;
1688 					} else {
1689 						np->n_tnext = tp->n_tnext;
1690 						tp->n_tnext = np;
1691 					}
1692 					np->n_tprev = tp;
1693 					if (np->n_tnext == (struct nfsnode *)nmp)
1694 						nmp->nm_tprev = np;
1695 					else
1696 						np->n_tnext->n_tprev = np;
1697 					cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
1698 				}
1699 			} else {
1700 				nfsm_adv(nfsm_rndup(len));
1701 			}
1702 			if (newvp != NULLVP) {
1703 				vrele(newvp);
1704 				newvp = NULLVP;
1705 			}
1706 			nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
1707 			if (bigenough)
1708 				endoff = off = fxdr_unsigned(off_t, *tl++);
1709 			else
1710 				endoff = fxdr_unsigned(off_t, *tl++);
1711 			more_dirs = fxdr_unsigned(int, *tl);
1712 		}
1713 		/*
1714 		 * If at end of rpc data, get the eof boolean
1715 		 */
1716 		if (!more_dirs) {
1717 			nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1718 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
1719 
1720 			/*
1721 			 * If at EOF, cache directory offset
1722 			 */
1723 			if (!more_dirs)
1724 				VTONFS(vp)->n_direofoffset = endoff;
1725 		}
1726 		if (uiop->uio_resid < tresid)
1727 			uiop->uio_offset = off;
1728 		else
1729 			more_dirs = 0;
1730 		m_freem(mrep);
1731 	}
1732 	/*
1733 	 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
1734 	 * by increasing d_reclen for the last record.
1735 	 */
1736 	if (uiop->uio_resid < tresid) {
1737 		len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);
1738 		if (len > 0) {
1739 			dp->d_reclen += len;
1740 			uiop->uio_iov->iov_base += len;
1741 			uiop->uio_iov->iov_len -= len;
1742 			uiop->uio_resid -= len;
1743 		}
1744 	}
1745 nfsmout:
1746 	if (newvp != NULLVP)
1747 		vrele(newvp);
1748 	return (error);
1749 }
1750 static char hextoasc[] = "0123456789abcdef";
1751 
1752 /*
1753  * Silly rename. To make the NFS filesystem that is stateless look a little
1754  * more like the "ufs" a remove of an active vnode is translated to a rename
1755  * to a funny looking filename that is removed by nfs_inactive on the
1756  * nfsnode. There is the potential for another process on a different client
1757  * to create the same funny name between the nfs_lookitup() fails and the
1758  * nfs_rename() completes, but...
1759  */
1760 int
1761 nfs_sillyrename(dvp, vp, cnp)
1762 	struct vnode *dvp, *vp;
1763 	struct componentname *cnp;
1764 {
1765 	register struct nfsnode *np;
1766 	register struct sillyrename *sp;
1767 	int error;
1768 	short pid;
1769 
1770 	cache_purge(dvp);
1771 	np = VTONFS(vp);
1772 #ifdef SILLYSEPARATE
1773 	MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
1774 		M_NFSREQ, M_WAITOK);
1775 #else
1776 	sp = &np->n_silly;
1777 #endif
1778 	sp->s_cred = crdup(cnp->cn_cred);
1779 	sp->s_dvp = dvp;
1780 	VREF(dvp);
1781 
1782 	/* Fudge together a funny name */
1783 	pid = cnp->cn_proc->p_pid;
1784 	bcopy(".nfsAxxxx4.4", sp->s_name, 13);
1785 	sp->s_namlen = 12;
1786 	sp->s_name[8] = hextoasc[pid & 0xf];
1787 	sp->s_name[7] = hextoasc[(pid >> 4) & 0xf];
1788 	sp->s_name[6] = hextoasc[(pid >> 8) & 0xf];
1789 	sp->s_name[5] = hextoasc[(pid >> 12) & 0xf];
1790 
1791 	/* Try lookitups until we get one that isn't there */
1792 	while (nfs_lookitup(sp, (nfsv2fh_t *)0, cnp->cn_proc) == 0) {
1793 		sp->s_name[4]++;
1794 		if (sp->s_name[4] > 'z') {
1795 			error = EINVAL;
1796 			goto bad;
1797 		}
1798 	}
1799 	if (error = nfs_renameit(dvp, cnp, sp))
1800 		goto bad;
1801 	nfs_lookitup(sp, &np->n_fh, cnp->cn_proc);
1802 	np->n_sillyrename = sp;
1803 	return (0);
1804 bad:
1805 	vrele(sp->s_dvp);
1806 	crfree(sp->s_cred);
1807 #ifdef SILLYSEPARATE
1808 	free((caddr_t)sp, M_NFSREQ);
1809 #endif
1810 	return (error);
1811 }
1812 
1813 /*
1814  * Look up a file name for silly rename stuff.
1815  * Just like nfs_lookup() except that it doesn't load returned values
1816  * into the nfsnode table.
1817  * If fhp != NULL it copies the returned file handle out
1818  */
1819 int
1820 nfs_lookitup(sp, fhp, procp)
1821 	register struct sillyrename *sp;
1822 	nfsv2fh_t *fhp;
1823 	struct proc *procp;
1824 {
1825 	register struct vnode *vp = sp->s_dvp;
1826 	register u_long *tl;
1827 	register caddr_t cp;
1828 	register long t1, t2;
1829 	caddr_t bpos, dpos, cp2;
1830 	u_long xid;
1831 	int error = 0;
1832 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1833 	long len;
1834 
1835 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1836 	len = sp->s_namlen;
1837 	nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1838 	nfsm_fhtom(vp);
1839 	nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
1840 	nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred);
1841 	if (fhp != NULL) {
1842 		nfsm_dissect(cp, caddr_t, NFSX_FH);
1843 		bcopy(cp, (caddr_t)fhp, NFSX_FH);
1844 	}
1845 	nfsm_reqdone;
1846 	return (error);
1847 }
1848 
1849 /*
1850  * Kludge City..
1851  * - make nfs_bmap() essentially a no-op that does no translation
1852  * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc
1853  *   after mapping the physical addresses into Kernel Virtual space in the
1854  *   nfsiobuf area.
1855  *   (Maybe I could use the process's page mapping, but I was concerned that
1856  *    Kernel Write might not be enabled and also figured copyout() would do
1857  *    a lot more work than bcopy() and also it currently happens in the
1858  *    context of the swapper process (2).
1859  */
1860 int
1861 nfs_bmap(ap)
1862 	struct vop_bmap_args /* {
1863 		struct vnode *a_vp;
1864 		daddr_t  a_bn;
1865 		struct vnode **a_vpp;
1866 		daddr_t *a_bnp;
1867 	} */ *ap;
1868 {
1869 	register struct vnode *vp = ap->a_vp;
1870 
1871 	if (ap->a_vpp != NULL)
1872 		*ap->a_vpp = vp;
1873 	if (ap->a_bnp != NULL)
1874 		*ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
1875 	return (0);
1876 }
1877 
1878 /*
1879  * Strategy routine for phys. i/o
1880  * If the biod's are running, queue a request
1881  * otherwise just call nfs_doio() to get it done
1882  */
1883 int
1884 nfs_strategy(ap)
1885 	struct vop_strategy_args /* {
1886 		struct buf *a_bp;
1887 	} */ *ap;
1888 {
1889 	register struct buf *bp = ap->a_bp;
1890 	register struct buf *dp;
1891 	register int i;
1892 	int error = 0;
1893 	int fnd = 0;
1894 
1895 	/*
1896 	 * Set b_proc. It seems a bit silly to do it here, but since bread()
1897 	 * doesn't set it, I will.
1898 	 * Set b_proc == NULL for asynchronous ops, since these may still
1899 	 * be hanging about after the process terminates.
1900 	 */
1901 	if ((bp->b_flags & B_PHYS) == 0) {
1902 		if (bp->b_flags & B_ASYNC)
1903 			bp->b_proc = (struct proc *)0;
1904 		else
1905 			bp->b_proc = curproc;
1906 	}
1907 	/*
1908 	 * If the op is asynchronous and an i/o daemon is waiting
1909 	 * queue the request, wake it up and wait for completion
1910 	 * otherwise just do it ourselves.
1911 	 */
1912 	if ((bp->b_flags & B_ASYNC) == 0 || nfs_numasync == 0)
1913 		return (nfs_doio(bp));
1914 	for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
1915 		if (nfs_iodwant[i]) {
1916 			dp = &nfs_bqueue;
1917 			if (dp->b_actf == NULL) {
1918 				dp->b_actl = bp;
1919 				bp->b_actf = dp;
1920 			} else {
1921 				dp->b_actf->b_actl = bp;
1922 				bp->b_actf = dp->b_actf;
1923 			}
1924 			dp->b_actf = bp;
1925 			bp->b_actl = dp;
1926 			fnd++;
1927 			wakeup((caddr_t)&nfs_iodwant[i]);
1928 			break;
1929 		}
1930 	}
1931 	if (!fnd)
1932 		error = nfs_doio(bp);
1933 	return (error);
1934 }
1935 
1936 /*
1937  * Fun and games with i/o
1938  * Essentially play ubasetup() and disk interrupt service routine by
1939  * mapping the data buffer into kernel virtual space and doing the
1940  * nfs read or write rpc's from it.
1941  * If the nfsiod's are not running, this is just called from nfs_strategy(),
1942  * otherwise it is called by the nfsiods to do what would normally be
1943  * partially disk interrupt driven.
1944  */
1945 int
1946 nfs_doio(bp)
1947 	register struct buf *bp;
1948 {
1949 	register struct uio *uiop;
1950 	register struct vnode *vp;
1951 	struct nfsnode *np;
1952 	struct ucred *cr;
1953 	int error;
1954 	struct uio uio;
1955 	struct iovec io;
1956 
1957 	vp = bp->b_vp;
1958 	np = VTONFS(vp);
1959 	uiop = &uio;
1960 	uiop->uio_iov = &io;
1961 	uiop->uio_iovcnt = 1;
1962 	uiop->uio_segflg = UIO_SYSSPACE;
1963 	uiop->uio_procp = bp->b_proc;
1964 
1965 	/*
1966 	 * For phys i/o, map the b_addr into kernel virtual space using
1967 	 * the Nfsiomap pte's
1968 	 * Also, add a temporary b_rcred for reading using the process's uid
1969 	 * and a guess at a group
1970 	 */
1971 	if (bp->b_flags & B_PHYS) {
1972 		if (bp->b_flags & B_DIRTY)
1973 			uiop->uio_procp = pageproc;
1974 		cr = crcopy(uiop->uio_procp->p_ucred);
1975 		/* mapping was already done by vmapbuf */
1976 		io.iov_base = bp->b_un.b_addr;
1977 
1978 		/*
1979 		 * And do the i/o rpc
1980 		 */
1981 		io.iov_len = uiop->uio_resid = bp->b_bcount;
1982 		uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1983 		if (bp->b_flags & B_READ) {
1984 			uiop->uio_rw = UIO_READ;
1985 			nfsstats.read_physios++;
1986 			bp->b_error = error = nfs_readrpc(vp, uiop, cr);
1987 			(void) vnode_pager_uncache(vp);
1988 		} else {
1989 			uiop->uio_rw = UIO_WRITE;
1990 			nfsstats.write_physios++;
1991 			bp->b_error = error = nfs_writerpc(vp, uiop, cr);
1992 		}
1993 
1994 		/*
1995 		 * Finally, release pte's used by physical i/o
1996 		 */
1997 		crfree(cr);
1998 	} else {
1999 		if (bp->b_flags & B_READ) {
2000 			io.iov_len = uiop->uio_resid = bp->b_bcount;
2001 			io.iov_base = bp->b_un.b_addr;
2002 			uiop->uio_rw = UIO_READ;
2003 			switch (vp->v_type) {
2004 			case VREG:
2005 				uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
2006 				nfsstats.read_bios++;
2007 				error = nfs_readrpc(vp, uiop, bp->b_rcred);
2008 				break;
2009 			case VLNK:
2010 				uiop->uio_offset = 0;
2011 				nfsstats.readlink_bios++;
2012 				error = nfs_readlinkrpc(vp, uiop, bp->b_rcred);
2013 				break;
2014 			case VDIR:
2015 				uiop->uio_offset = bp->b_lblkno;
2016 				nfsstats.readdir_bios++;
2017 				if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_RDIRALOOK)
2018 				    error = nfs_readdirlookrpc(vp, uiop, bp->b_rcred);
2019 				else
2020 				    error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
2021 				/*
2022 				 * Save offset cookie in b_blkno.
2023 				 */
2024 				bp->b_blkno = uiop->uio_offset;
2025 				break;
2026 			};
2027 			bp->b_error = error;
2028 		} else {
2029 			io.iov_len = uiop->uio_resid = bp->b_dirtyend
2030 				- bp->b_dirtyoff;
2031 			uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
2032 				+ bp->b_dirtyoff;
2033 			io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
2034 			uiop->uio_rw = UIO_WRITE;
2035 			nfsstats.write_bios++;
2036 			bp->b_error = error = nfs_writerpc(vp, uiop,
2037 				bp->b_wcred);
2038 			if (error) {
2039 				np->n_error = error;
2040 				np->n_flag |= NWRITEERR;
2041 			}
2042 			bp->b_dirtyoff = bp->b_dirtyend = 0;
2043 		}
2044 	}
2045 	if (error)
2046 		bp->b_flags |= B_ERROR;
2047 	bp->b_resid = uiop->uio_resid;
2048 	biodone(bp);
2049 	return (error);
2050 }
2051 
2052 /*
2053  * Mmap a file
2054  *
2055  * NB Currently unsupported.
2056  */
2057 /* ARGSUSED */
2058 int
2059 nfs_mmap(ap)
2060 	struct vop_mmap_args /* {
2061 		struct vnode *a_vp;
2062 		int  a_fflags;
2063 		struct ucred *a_cred;
2064 		struct proc *a_p;
2065 	} */ *ap;
2066 {
2067 
2068 	return (EINVAL);
2069 }
2070 
2071 /*
2072  * Flush all the blocks associated with a vnode.
2073  * 	Walk through the buffer pool and push any dirty pages
2074  *	associated with the vnode.
2075  */
2076 /* ARGSUSED */
2077 int
2078 nfs_fsync(ap)
2079 	struct vop_fsync_args /* {
2080 		struct vnodeop_desc *a_desc;
2081 		struct vnode * a_vp;
2082 		struct ucred * a_cred;
2083 		int  a_waitfor;
2084 		struct proc * a_p;
2085 	} */ *ap;
2086 {
2087 	register struct vnode *vp = ap->a_vp;
2088 	register struct nfsnode *np = VTONFS(vp);
2089 	register struct buf *bp;
2090 	struct buf *nbp;
2091 	int s, error = 0;
2092 
2093 loop:
2094 	s = splbio();
2095 	for (bp = vp->v_dirtyblkhd; bp; bp = nbp) {
2096 		nbp = bp->b_blockf;
2097 		if ((bp->b_flags & B_BUSY))
2098 			continue;
2099 		if ((bp->b_flags & B_DELWRI) == 0)
2100 			panic("nfs_fsync: not dirty");
2101 		bremfree(bp);
2102 		bp->b_flags |= B_BUSY;
2103 		splx(s);
2104 		error = bawrite(bp);
2105 		goto loop;
2106 	}
2107 	if (ap->a_waitfor == MNT_WAIT) {
2108 		while (vp->v_numoutput) {
2109 			vp->v_flag |= VBWAIT;
2110 			sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
2111 		}
2112 #ifdef DIAGNOSTIC
2113 		if (vp->v_dirtyblkhd) {
2114 			vprint("nfs_fsync: dirty", vp);
2115 			goto loop;
2116 		}
2117 #endif
2118 	}
2119 	splx(s);
2120 	np->n_flag &= ~NMODIFIED;
2121 	if (np->n_flag & NWRITEERR) {
2122 		error = np->n_error;
2123 		np->n_flag &= ~NWRITEERR;
2124 	}
2125 	return (error);
2126 }
2127 
2128 /*
2129  * NFS advisory byte-level locks.
2130  * Currently unsupported.
2131  */
2132 int
2133 nfs_advlock(ap)
2134 	struct vop_advlock_args /* {
2135 		struct vnode *a_vp;
2136 		caddr_t  a_id;
2137 		int  a_op;
2138 		struct flock *a_fl;
2139 		int  a_flags;
2140 	} */ *ap;
2141 {
2142 
2143 	return (EOPNOTSUPP);
2144 }
2145 
2146 /*
2147  * Print out the contents of an nfsnode.
2148  */
2149 int
2150 nfs_print(ap)
2151 	struct vop_print_args /* {
2152 		struct vnode *a_vp;
2153 	} */ *ap;
2154 {
2155 	register struct vnode *vp = ap->a_vp;
2156 	register struct nfsnode *np = VTONFS(vp);
2157 
2158 	printf("tag VT_NFS, fileid %d fsid 0x%x",
2159 		np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2160 #ifdef FIFO
2161 	if (vp->v_type == VFIFO)
2162 		fifo_printinfo(vp);
2163 #endif /* FIFO */
2164 	printf("\n");
2165 }
2166 
2167 /*
2168  * NFS directory offset lookup.
2169  * Currently unsupported.
2170  */
2171 int
2172 nfs_blkatoff(ap)
2173 	struct vop_blkatoff_args /* {
2174 		struct vnode *a_vp;
2175 		off_t a_offset;
2176 		char **a_res;
2177 		struct buf **a_bpp;
2178 	} */ *ap;
2179 {
2180 
2181 	return (EOPNOTSUPP);
2182 }
2183 
2184 /*
2185  * NFS flat namespace allocation.
2186  * Currently unsupported.
2187  */
2188 int
2189 nfs_valloc(ap)
2190 	struct vop_valloc_args /* {
2191 		struct vnode *a_pvp;
2192 		int a_mode;
2193 		struct ucred *a_cred;
2194 		struct vnode **a_vpp;
2195 	} */ *ap;
2196 {
2197 
2198 	return (EOPNOTSUPP);
2199 }
2200 
2201 /*
2202  * NFS flat namespace free.
2203  * Currently unsupported.
2204  */
2205 int
2206 nfs_vfree(ap)
2207 	struct vop_vfree_args /* {
2208 		struct vnode *a_pvp;
2209 		ino_t a_ino;
2210 		int a_mode;
2211 	} */ *ap;
2212 {
2213 
2214 	return (EOPNOTSUPP);
2215 }
2216 
2217 /*
2218  * NFS file truncation.
2219  */
2220 int
2221 nfs_truncate(ap)
2222 	struct vop_truncate_args /* {
2223 		struct vnode *a_vp;
2224 		off_t a_length;
2225 		int a_flags;
2226 		struct ucred *a_cred;
2227 		struct proc *a_p;
2228 	} */ *ap;
2229 {
2230 
2231 	/* Use nfs_setattr */
2232 	printf("nfs_truncate: need to implement!!");
2233 	return (EOPNOTSUPP);
2234 }
2235 
2236 /*
2237  * NFS update.
2238  */
2239 int
2240 nfs_update(ap)
2241 	struct vop_update_args /* {
2242 		struct vnode *a_vp;
2243 		struct timeval *a_ta;
2244 		struct timeval *a_tm;
2245 		int a_waitfor;
2246 	} */ *ap;
2247 {
2248 
2249 	/* Use nfs_setattr */
2250 	printf("nfs_update: need to implement!!");
2251 	return (EOPNOTSUPP);
2252 }
2253 
2254 /*
2255  * Read wrapper for special devices.
2256  */
2257 int
2258 nfsspec_read(ap)
2259 	struct vop_read_args /* {
2260 		struct vnode *a_vp;
2261 		struct uio *a_uio;
2262 		int  a_ioflag;
2263 		struct ucred *a_cred;
2264 	} */ *ap;
2265 {
2266 	extern int (**spec_vnodeop_p)();
2267 	register struct nfsnode *np = VTONFS(ap->a_vp);
2268 
2269 	/*
2270 	 * Set access flag.
2271 	 */
2272 	np->n_flag |= NACC;
2273 	np->n_atim = time;
2274 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
2275 }
2276 
2277 /*
2278  * Write wrapper for special devices.
2279  */
2280 int
2281 nfsspec_write(ap)
2282 	struct vop_write_args /* {
2283 		struct vnode *a_vp;
2284 		struct uio *a_uio;
2285 		int  a_ioflag;
2286 		struct ucred *a_cred;
2287 	} */ *ap;
2288 {
2289 	extern int (**spec_vnodeop_p)();
2290 	register struct nfsnode *np = VTONFS(ap->a_vp);
2291 
2292 	/*
2293 	 * Set update flag.
2294 	 */
2295 	np->n_flag |= NUPD;
2296 	np->n_mtim = time;
2297 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
2298 }
2299 
2300 /*
2301  * Close wrapper for special devices.
2302  *
2303  * Update the times on the nfsnode then do device close.
2304  */
2305 int
2306 nfsspec_close(ap)
2307 	struct vop_close_args /* {
2308 		struct vnode *a_vp;
2309 		int  a_fflag;
2310 		struct ucred *a_cred;
2311 		struct proc *a_p;
2312 	} */ *ap;
2313 {
2314 	register struct vnode *vp = ap->a_vp;
2315 	register struct nfsnode *np = VTONFS(vp);
2316 	struct vattr vattr;
2317 	extern int (**spec_vnodeop_p)();
2318 
2319 	if (np->n_flag & (NACC | NUPD)) {
2320 		if (np->n_flag & NACC)
2321 			np->n_atim = time;
2322 		if (np->n_flag & NUPD)
2323 			np->n_mtim = time;
2324 		np->n_flag |= NCHG;
2325 		if (vp->v_usecount == 1 &&
2326 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
2327 			VATTR_NULL(&vattr);
2328 			if (np->n_flag & NACC) {
2329 				vattr.va_atime.ts_sec = np->n_atim.tv_sec;
2330 				vattr.va_atime.ts_nsec =
2331 				    np->n_atim.tv_usec * 1000;
2332 			}
2333 			if (np->n_flag & NUPD) {
2334 				vattr.va_mtime.ts_sec = np->n_mtim.tv_sec;
2335 				vattr.va_mtime.ts_nsec =
2336 				    np->n_mtim.tv_usec * 1000;
2337 			}
2338 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
2339 		}
2340 	}
2341 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
2342 }
2343 
2344 #ifdef FIFO
2345 /*
2346  * Read wrapper for fifos.
2347  */
2348 int
2349 nfsfifo_read(ap)
2350 	struct vop_read_args /* {
2351 		struct vnode *a_vp;
2352 		struct uio *a_uio;
2353 		int  a_ioflag;
2354 		struct ucred *a_cred;
2355 	} */ *ap;
2356 {
2357 	extern int (**fifo_vnodeop_p)();
2358 	register struct nfsnode *np = VTONFS(ap->a_vp);
2359 
2360 	/*
2361 	 * Set access flag.
2362 	 */
2363 	np->n_flag |= NACC;
2364 	np->n_atim = time;
2365 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
2366 }
2367 
2368 /*
2369  * Write wrapper for fifos.
2370  */
2371 int
2372 nfsfifo_write(ap)
2373 	struct vop_write_args /* {
2374 		struct vnode *a_vp;
2375 		struct uio *a_uio;
2376 		int  a_ioflag;
2377 		struct ucred *a_cred;
2378 	} */ *ap;
2379 {
2380 	extern int (**fifo_vnodeop_p)();
2381 	register struct nfsnode *np = VTONFS(ap->a_vp);
2382 
2383 	/*
2384 	 * Set update flag.
2385 	 */
2386 	np->n_flag |= NUPD;
2387 	np->n_mtim = time;
2388 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
2389 }
2390 
2391 /*
2392  * Close wrapper for fifos.
2393  *
2394  * Update the times on the nfsnode then do fifo close.
2395  */
2396 int
2397 nfsfifo_close(ap)
2398 	struct vop_close_args /* {
2399 		struct vnode *a_vp;
2400 		int  a_fflag;
2401 		struct ucred *a_cred;
2402 		struct proc *a_p;
2403 	} */ *ap;
2404 {
2405 	register struct vnode *vp = ap->a_vp;
2406 	register struct nfsnode *np = VTONFS(vp);
2407 	struct vattr vattr;
2408 	extern int (**fifo_vnodeop_p)();
2409 
2410 	if (np->n_flag & (NACC | NUPD)) {
2411 		if (np->n_flag & NACC)
2412 			np->n_atim = time;
2413 		if (np->n_flag & NUPD)
2414 			np->n_mtim = time;
2415 		np->n_flag |= NCHG;
2416 		if (vp->v_usecount == 1 &&
2417 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
2418 			VATTR_NULL(&vattr);
2419 			if (np->n_flag & NACC) {
2420 				vattr.va_atime.ts_sec = np->n_atim.tv_sec;
2421 				vattr.va_atime.ts_nsec =
2422 				    np->n_atim.tv_usec * 1000;
2423 			}
2424 			if (np->n_flag & NUPD) {
2425 				vattr.va_mtime.ts_sec = np->n_mtim.tv_sec;
2426 				vattr.va_mtime.ts_nsec =
2427 				    np->n_mtim.tv_usec * 1000;
2428 			}
2429 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
2430 		}
2431 	}
2432 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
2433 }
2434 #endif /* FIFO */
2435