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