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