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