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