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