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