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