xref: /csrg-svn/sys/nfs/nfs_vnops.c (revision 39914)
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  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  *	@(#)nfs_vnops.c	7.24 (Berkeley) 01/15/90
21  */
22 
23 /*
24  * vnode op calls for sun nfs version 2
25  */
26 
27 #include "machine/pte.h"
28 #include "machine/mtpr.h"
29 #include "strings.h"
30 #include "param.h"
31 #include "user.h"
32 #include "proc.h"
33 #include "mount.h"
34 #include "buf.h"
35 #include "vm.h"
36 #include "../ufs/dir.h"
37 #include "malloc.h"
38 #include "mbuf.h"
39 #include "uio.h"
40 #include "ucred.h"
41 #include "namei.h"
42 #include "errno.h"
43 #include "file.h"
44 #include "conf.h"
45 #include "vnode.h"
46 #include "../ufs/inode.h"
47 #include "map.h"
48 #include "nfsv2.h"
49 #include "nfs.h"
50 #include "nfsnode.h"
51 #include "nfsmount.h"
52 #include "xdr_subs.h"
53 #include "nfsm_subs.h"
54 #include "nfsiom.h"
55 
56 /* Defs */
57 #define	TRUE	1
58 #define	FALSE	0
59 
60 /* Global vars */
61 int	nfs_lookup(),
62 	nfs_create(),
63 	nfs_mknod(),
64 	nfs_open(),
65 	nfs_close(),
66 	nfs_access(),
67 	nfs_getattr(),
68 	nfs_setattr(),
69 	nfs_read(),
70 	nfs_write(),
71 	vfs_noop(),
72 	vfs_nullop(),
73 	nfs_remove(),
74 	nfs_link(),
75 	nfs_rename(),
76 	nfs_mkdir(),
77 	nfs_rmdir(),
78 	nfs_symlink(),
79 	nfs_readdir(),
80 	nfs_readlink(),
81 	nfs_abortop(),
82 	nfs_lock(),
83 	nfs_unlock(),
84 	nfs_bmap(),
85 	nfs_strategy(),
86 	nfs_fsync(),
87 	nfs_inactive(),
88 	nfs_reclaim(),
89 	nfs_print(),
90 	nfs_islocked();
91 
92 struct vnodeops nfsv2_vnodeops = {
93 	nfs_lookup,		/* lookup */
94 	nfs_create,		/* create */
95 	nfs_mknod,		/* mknod */
96 	nfs_open,		/* open */
97 	nfs_close,		/* close */
98 	nfs_access,		/* access */
99 	nfs_getattr,		/* getattr */
100 	nfs_setattr,		/* setattr */
101 	nfs_read,		/* read */
102 	nfs_write,		/* write */
103 	vfs_noop,		/* ioctl */
104 	vfs_noop,		/* select */
105 	vfs_noop,		/* mmap */
106 	nfs_fsync,		/* fsync */
107 	vfs_nullop,		/* seek */
108 	nfs_remove,		/* remove */
109 	nfs_link,		/* link */
110 	nfs_rename,		/* rename */
111 	nfs_mkdir,		/* mkdir */
112 	nfs_rmdir,		/* rmdir */
113 	nfs_symlink,		/* symlink */
114 	nfs_readdir,		/* readdir */
115 	nfs_readlink,		/* readlink */
116 	nfs_abortop,		/* abortop */
117 	nfs_inactive,		/* inactive */
118 	nfs_reclaim,		/* reclaim */
119 	nfs_lock,		/* lock */
120 	nfs_unlock,		/* unlock */
121 	nfs_bmap,		/* bmap */
122 	nfs_strategy,		/* strategy */
123 	nfs_print,		/* print */
124 	nfs_islocked,		/* islocked */
125 };
126 
127 /* Special device vnode ops */
128 int	spec_lookup(),
129 	spec_open(),
130 	spec_read(),
131 	spec_write(),
132 	spec_strategy(),
133 	spec_bmap(),
134 	spec_ioctl(),
135 	spec_select(),
136 	spec_close(),
137 	spec_badop(),
138 	spec_nullop();
139 
140 struct vnodeops spec_nfsv2nodeops = {
141 	spec_lookup,		/* lookup */
142 	spec_badop,		/* create */
143 	spec_badop,		/* mknod */
144 	spec_open,		/* open */
145 	spec_close,		/* close */
146 	nfs_access,		/* access */
147 	nfs_getattr,		/* getattr */
148 	nfs_setattr,		/* setattr */
149 	spec_read,		/* read */
150 	spec_write,		/* write */
151 	spec_ioctl,		/* ioctl */
152 	spec_select,		/* select */
153 	spec_badop,		/* mmap */
154 	spec_nullop,		/* fsync */
155 	spec_badop,		/* seek */
156 	spec_badop,		/* remove */
157 	spec_badop,		/* link */
158 	spec_badop,		/* rename */
159 	spec_badop,		/* mkdir */
160 	spec_badop,		/* rmdir */
161 	spec_badop,		/* symlink */
162 	spec_badop,		/* readdir */
163 	spec_badop,		/* readlink */
164 	spec_badop,		/* abortop */
165 	nfs_inactive,		/* inactive */
166 	nfs_reclaim,		/* reclaim */
167 	nfs_lock,		/* lock */
168 	nfs_unlock,		/* unlock */
169 	spec_bmap,		/* bmap */
170 	spec_strategy,		/* strategy */
171 	nfs_print,		/* print */
172 	nfs_islocked,		/* islocked */
173 };
174 
175 extern u_long nfs_procids[NFS_NPROCS];
176 extern u_long nfs_prog, nfs_vers;
177 extern char nfsiobuf[MAXPHYS+NBPG];
178 struct map nfsmap[NFS_MSIZ];
179 enum vtype v_type[NFLNK+1];
180 struct buf nfs_bqueue;		/* Queue head for nfsiod's */
181 int nfs_asyncdaemons = 0;
182 struct proc *nfs_iodwant[MAX_ASYNCDAEMON];
183 static int nfsmap_want = 0;
184 
185 /*
186  * nfs null call from vfs.
187  */
188 nfs_null(vp, cred)
189 	struct vnode *vp;
190 	struct ucred *cred;
191 {
192 	caddr_t bpos, dpos;
193 	u_long xid;
194 	int error = 0;
195 	struct mbuf *mreq, *mrep, *md, *mb;
196 
197 	nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
198 	nfsm_request(vp);
199 	nfsm_reqdone;
200 	return (error);
201 }
202 
203 /*
204  * nfs access vnode op.
205  * Essentially just get vattr and then imitate iaccess()
206  */
207 nfs_access(vp, mode, cred)
208 	struct vnode *vp;
209 	int mode;
210 	register struct ucred *cred;
211 {
212 	register struct vattr *vap;
213 	register gid_t *gp;
214 	struct vattr vattr;
215 	register int i;
216 	int error;
217 
218 	/*
219 	 * If you're the super-user,
220 	 * you always get access.
221 	 */
222 	if (cred->cr_uid == 0)
223 		return (0);
224 	vap = &vattr;
225 	if (error = nfs_getattr(vp, vap, cred))
226 		return (error);
227 	/*
228 	 * Access check is based on only one of owner, group, public.
229 	 * If not owner, then check group. If not a member of the
230 	 * group, then check public access.
231 	 */
232 	if (cred->cr_uid != vap->va_uid) {
233 		mode >>= 3;
234 		gp = cred->cr_groups;
235 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
236 			if (vap->va_gid == *gp)
237 				goto found;
238 		mode >>= 3;
239 found:
240 		;
241 	}
242 	if ((vap->va_mode & mode) != 0)
243 		return (0);
244 	return (EACCES);
245 }
246 
247 /*
248  * nfs open vnode op
249  * Just check to see if the type is ok
250  */
251 /* ARGSUSED */
252 nfs_open(vp, mode, cred)
253 	struct vnode *vp;
254 	int mode;
255 	struct ucred *cred;
256 {
257 	register enum vtype vtyp;
258 
259 	vtyp = vp->v_type;
260 	if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK)
261 		return (0);
262 	else
263 		return (EACCES);
264 }
265 
266 /*
267  * nfs close vnode op
268  * For reg files, invalidate any buffer cache entries.
269  */
270 /* ARGSUSED */
271 nfs_close(vp, fflags, cred)
272 	register struct vnode *vp;
273 	int fflags;
274 	struct ucred *cred;
275 {
276 	register struct nfsnode *np = VTONFS(vp);
277 	int error = 0;
278 
279 	if (vp->v_type == VREG && ((np->n_flag & NMODIFIED) ||
280 	   ((np->n_flag & NBUFFERED) && np->n_sillyrename))) {
281 		nfs_lock(vp);
282 		np->n_flag &= ~(NMODIFIED|NBUFFERED);
283 		vinvalbuf(vp, TRUE);
284 		if (np->n_flag & NWRITEERR) {
285 			np->n_flag &= ~NWRITEERR;
286 			error = np->n_error;
287 		}
288 		nfs_unlock(vp);
289 	}
290 	return (error);
291 }
292 
293 /*
294  * nfs getattr call from vfs.
295  */
296 nfs_getattr(vp, vap, cred)
297 	register struct vnode *vp;
298 	struct vattr *vap;
299 	struct ucred *cred;
300 {
301 	register caddr_t cp;
302 	register long t1;
303 	caddr_t bpos, dpos;
304 	u_long xid;
305 	int error = 0;
306 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
307 
308 	/* First look in the cache.. */
309 	if (nfs_getattrcache(vp, vap) == 0)
310 		return (0);
311 	nfsstats.rpccnt[NFSPROC_GETATTR]++;
312 	nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
313 	nfsm_fhtom(vp);
314 	nfsm_request(vp);
315 	nfsm_loadattr(vp, vap);
316 	nfsm_reqdone;
317 	return (error);
318 }
319 
320 /*
321  * nfs setattr call.
322  */
323 nfs_setattr(vp, vap, cred)
324 	register struct vnode *vp;
325 	register struct vattr *vap;
326 	struct ucred *cred;
327 {
328 	register struct nfsv2_sattr *sp;
329 	register caddr_t cp;
330 	register long t1;
331 	caddr_t bpos, dpos;
332 	u_long xid;
333 	int error = 0;
334 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
335 	struct nfsnode *np;
336 
337 	nfsstats.rpccnt[NFSPROC_SETATTR]++;
338 	nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR);
339 	nfsm_fhtom(vp);
340 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
341 	if (vap->va_mode == 0xffff)
342 		sp->sa_mode = VNOVAL;
343 	else
344 		sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
345 	if (vap->va_uid == 0xffff)
346 		sp->sa_uid = VNOVAL;
347 	else
348 		sp->sa_uid = txdr_unsigned(vap->va_uid);
349 	if (vap->va_gid == 0xffff)
350 		sp->sa_gid = VNOVAL;
351 	else
352 		sp->sa_gid = txdr_unsigned(vap->va_gid);
353 	sp->sa_size = txdr_unsigned(vap->va_size);
354 	if (vap->va_size != VNOVAL) {
355 		np = VTONFS(vp);
356 		if (np->n_flag & NMODIFIED) {
357 			np->n_flag &= ~NMODIFIED;
358 			vinvalbuf(vp, TRUE);
359 		}
360 	}
361 	sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
362 	sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
363 	txdr_time(&vap->va_mtime, &sp->sa_mtime);
364 	nfsm_request(vp);
365 	nfsm_loadattr(vp, (struct vattr *)0);
366 	/* should we fill in any vap fields ?? */
367 	nfsm_reqdone;
368 	return (error);
369 }
370 
371 /*
372  * nfs lookup call, one step at a time...
373  * First look in cache
374  * If not found, unlock the directory nfsnode and do the rpc
375  */
376 nfs_lookup(vp, ndp)
377 	register struct vnode *vp;
378 	register struct nameidata *ndp;
379 {
380 	register struct vnode *vdp;
381 	register u_long *p;
382 	register caddr_t cp;
383 	register long t1, t2;
384 	caddr_t bpos, dpos, cp2;
385 	u_long xid;
386 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
387 	struct vnode *newvp;
388 	long len;
389 	nfsv2fh_t *fhp;
390 	struct nfsnode *np;
391 	int lockparent, wantparent, flag, error = 0;
392 
393 	ndp->ni_dvp = vp;
394 	ndp->ni_vp = NULL;
395 	if (vp->v_type != VDIR)
396 		return (ENOTDIR);
397 	lockparent = ndp->ni_nameiop & LOCKPARENT;
398 	flag = ndp->ni_nameiop & OPFLAG;
399 	wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
400 	if ((error = cache_lookup(ndp)) && error != ENOENT) {
401 		struct vattr vattr;
402 		int vpid;
403 
404 		if (vp == ndp->ni_rdir && ndp->ni_isdotdot)
405 			panic("nfs_lookup: .. through root");
406 		vdp = ndp->ni_vp;
407 		vpid = vdp->v_id;
408 		/*
409 		 * See the comment starting `Step through' in ufs/ufs_lookup.c
410 		 * for an explanation of the locking protocol
411 		 */
412 		if (vp == vdp) {
413 			VREF(vdp);
414 			error = 0;
415 		} else if (ndp->ni_isdotdot) {
416 			nfs_unlock(vp);
417 			error = vget(vdp);
418 		} else {
419 			error = vget(vdp);
420 			nfs_unlock(vp);
421 		}
422 		if (!error) {
423 			if (vpid == vdp->v_id &&
424 			   !nfs_getattr(vdp, &vattr, ndp->ni_cred)) {
425 				nfsstats.lookupcache_hits++;
426 				return (0);
427 			} else {
428 				nfs_nput(vdp);
429 			}
430 		}
431 		ndp->ni_vp = (struct vnode *)0;
432 	} else
433 		nfs_unlock(vp);
434 	error = 0;
435 	nfsstats.lookupcache_misses++;
436 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
437 	len = ndp->ni_namelen;
438 	nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
439 	nfsm_fhtom(vp);
440 	nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
441 	nfsm_request(vp);
442 nfsmout:
443 	if (error) {
444 		if (lockparent || (flag != CREATE && flag != RENAME) ||
445 		    *ndp->ni_next != 0)
446 			nfs_lock(vp);
447 		return (ENOENT);
448 	}
449 	nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
450 
451 	/*
452 	 * Handle DELETE and RENAME cases...
453 	 */
454 	if (flag == DELETE && *ndp->ni_next == 0) {
455 		if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
456 			VREF(vp);
457 			newvp = vp;
458 			np = VTONFS(vp);
459 		} else {
460 			if (error = nfs_nget(vp->v_mount, fhp, &np)) {
461 				nfs_lock(vp);
462 				m_freem(mrep);
463 				return (error);
464 			}
465 			newvp = NFSTOV(np);
466 		}
467 		if (error =
468 		    nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
469 			nfs_lock(vp);
470 			if (newvp != vp)
471 				nfs_nput(newvp);
472 			else
473 				vrele(vp);
474 			m_freem(mrep);
475 			return (error);
476 		}
477 		ndp->ni_vp = newvp;
478 		if (lockparent || vp == newvp)
479 			nfs_lock(vp);
480 		m_freem(mrep);
481 		return (0);
482 	}
483 
484 	if (flag == RENAME && wantparent && *ndp->ni_next == 0) {
485 		if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
486 			nfs_lock(vp);
487 			m_freem(mrep);
488 			return (EISDIR);
489 		}
490 		if (error = nfs_nget(vp->v_mount, fhp, &np)) {
491 			nfs_lock(vp);
492 			m_freem(mrep);
493 			return (error);
494 		}
495 		newvp = NFSTOV(np);
496 		if (error =
497 		    nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
498 			nfs_lock(vp);
499 			nfs_nput(newvp);
500 			m_freem(mrep);
501 			return (error);
502 		}
503 		ndp->ni_vp = newvp;
504 		if (lockparent)
505 			nfs_lock(vp);
506 		return (0);
507 	}
508 
509 	if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
510 		VREF(vp);
511 		newvp = vp;
512 		np = VTONFS(vp);
513 	} else if (ndp->ni_isdotdot) {
514 		if (error = nfs_nget(vp->v_mount, fhp, &np)) {
515 			nfs_lock(vp);
516 			m_freem(mrep);
517 			return (error);
518 		}
519 		newvp = NFSTOV(np);
520 	} else {
521 		if (error = nfs_nget(vp->v_mount, fhp, &np)) {
522 			nfs_lock(vp);
523 			m_freem(mrep);
524 			return (error);
525 		}
526 		newvp = NFSTOV(np);
527 	}
528 	if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
529 		nfs_lock(vp);
530 		if (newvp != vp)
531 			nfs_nput(newvp);
532 		else
533 			vrele(vp);
534 		m_freem(mrep);
535 		return (error);
536 	}
537 	m_freem(mrep);
538 
539 	if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
540 		nfs_lock(vp);
541 	ndp->ni_vp = newvp;
542 	if (error == 0 && ndp->ni_makeentry)
543 		cache_enter(ndp);
544 	return (error);
545 }
546 
547 /*
548  * nfs readlink call
549  */
550 nfs_readlink(vp, uiop, cred)
551 	register struct vnode *vp;
552 	struct uio *uiop;
553 	struct ucred *cred;
554 {
555 	register u_long *p;
556 	register caddr_t cp;
557 	register long t1;
558 	caddr_t bpos, dpos, cp2;
559 	u_long xid;
560 	int error = 0;
561 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
562 	long len;
563 
564 	nfsstats.rpccnt[NFSPROC_READLINK]++;
565 	nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
566 	nfsm_fhtom(vp);
567 	nfsm_request(vp);
568 	nfsm_strsiz(len, NFS_MAXPATHLEN);
569 	nfsm_mtouio(uiop, len);
570 	nfsm_reqdone;
571 	return (error);
572 }
573 
574 /*
575  * nfs read call
576  */
577 nfs_readrpc(vp, uiop, cred)
578 	register struct vnode *vp;
579 	struct uio *uiop;
580 	struct ucred *cred;
581 {
582 	register u_long *p;
583 	register caddr_t cp;
584 	register long t1;
585 	caddr_t bpos, dpos, cp2;
586 	u_long xid;
587 	int error = 0;
588 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
589 	struct nfsmount *nmp;
590 	long len, retlen, tsiz;
591 
592 	nmp = vfs_to_nfs(vp->v_mount);
593 	tsiz = uiop->uio_resid;
594 	while (tsiz > 0) {
595 		nfsstats.rpccnt[NFSPROC_READ]++;
596 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
597 		nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
598 		nfsm_fhtom(vp);
599 		nfsm_build(p, u_long *, NFSX_UNSIGNED*3);
600 		*p++ = txdr_unsigned(uiop->uio_offset);
601 		*p++ = txdr_unsigned(len);
602 		*p = 0;
603 		nfsm_request(vp);
604 		nfsm_loadattr(vp, (struct vattr *)0);
605 		nfsm_strsiz(retlen, nmp->nm_rsize);
606 		nfsm_mtouio(uiop, retlen);
607 		m_freem(mrep);
608 		if (retlen < len)
609 			tsiz = 0;
610 		else
611 			tsiz -= len;
612 	}
613 nfsmout:
614 	return (error);
615 }
616 
617 /*
618  * nfs write call
619  */
620 nfs_writerpc(vp, uiop, cred)
621 	register struct vnode *vp;
622 	struct uio *uiop;
623 	struct ucred *cred;
624 {
625 	register u_long *p;
626 	register caddr_t cp;
627 	register long t1;
628 	caddr_t bpos, dpos;
629 	u_long xid;
630 	int error = 0;
631 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
632 	struct nfsmount *nmp;
633 	long len, tsiz;
634 
635 	nmp = vfs_to_nfs(vp->v_mount);
636 	tsiz = uiop->uio_resid;
637 	while (tsiz > 0) {
638 		nfsstats.rpccnt[NFSPROC_WRITE]++;
639 		len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
640 		nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
641 			NFSX_FH+NFSX_UNSIGNED*4);
642 		nfsm_fhtom(vp);
643 		nfsm_build(p, u_long *, NFSX_UNSIGNED*4);
644 		*(p+1) = txdr_unsigned(uiop->uio_offset);
645 		*(p+3) = txdr_unsigned(len);
646 		nfsm_uiotom(uiop, len);
647 		nfsm_request(vp);
648 		nfsm_loadattr(vp, (struct vattr *)0);
649 		m_freem(mrep);
650 		tsiz -= len;
651 	}
652 nfsmout:
653 	return (error);
654 }
655 
656 /*
657  * nfs mknod call
658  * This call is currently not supported.
659  */
660 /* ARGSUSED */
661 nfs_mknod(ndp, vap, cred)
662 	struct nameidata *ndp;
663 	struct ucred *cred;
664 	struct vattr *vap;
665 {
666 
667 	nfs_abortop(ndp);
668 	return (EOPNOTSUPP);
669 }
670 
671 /*
672  * nfs file create call
673  */
674 nfs_create(ndp, vap)
675 	register struct nameidata *ndp;
676 	register struct vattr *vap;
677 {
678 	register struct nfsv2_sattr *sp;
679 	register u_long *p;
680 	register caddr_t cp;
681 	register long t1, t2;
682 	caddr_t bpos, dpos, cp2;
683 	u_long xid;
684 	int error = 0;
685 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
686 
687 	nfsstats.rpccnt[NFSPROC_CREATE]++;
688 	nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
689 	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
690 	nfsm_fhtom(ndp->ni_dvp);
691 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
692 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
693 	sp->sa_mode = vtonfs_mode(VREG, vap->va_mode);
694 	sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
695 	sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
696 	sp->sa_size = txdr_unsigned(0);
697 	/* or should these be VNOVAL ?? */
698 	txdr_time(&vap->va_atime, &sp->sa_atime);
699 	txdr_time(&vap->va_mtime, &sp->sa_mtime);
700 	nfsm_request(ndp->ni_dvp);
701 	nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
702 	nfsm_reqdone;
703 	nfs_nput(ndp->ni_dvp);
704 	return (error);
705 }
706 
707 /*
708  * nfs file remove call
709  * To try and make nfs semantics closer to vfs semantics, a file that has
710  * other references to the vnode is renamed instead of removed and then
711  * removed later on the last close.
712  * Unfortunately you must flush the buffer cache and cmap to get rid of
713  * all extraneous vnode references before you check the reference cnt.
714  * 1 - If the file could have blocks in the buffer cache
715  *	  flush them out and invalidate them
716  *	  mpurge the vnode to flush out cmap references
717  *	  (This is necessary to update the vnode ref cnt as well as sensible
718  *	   for actual removes, to free up the buffers)
719  * 2 - If v_usecount > 1
720  *	  If a rename is not already in the works
721  *	     call nfs_sillyrename() to set it up
722  *     else
723  *	  do the remove rpc
724  */
725 nfs_remove(ndp)
726 	register struct nameidata *ndp;
727 {
728 	register struct vnode *vp = ndp->ni_vp;
729 	register struct nfsnode *np = VTONFS(ndp->ni_vp);
730 	register u_long *p;
731 	register caddr_t cp;
732 	register long t1, t2;
733 	caddr_t bpos, dpos;
734 	u_long xid;
735 	int error = 0;
736 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
737 
738 	if (vp->v_type == VREG) {
739 		if (np->n_flag & (NMODIFIED|NBUFFERED)) {
740 			np->n_flag &= ~(NMODIFIED|NBUFFERED);
741 			vinvalbuf(vp, TRUE);
742 		}
743 		if (np->n_flag & NPAGEDON) {
744 			np->n_flag &= ~NPAGEDON;
745 			mpurge(vp);	/* In case cmap entries still ref it */
746 		}
747 	}
748 	if (vp->v_usecount > 1) {
749 		if (!np->n_sillyrename)
750 			error = nfs_sillyrename(ndp, REMOVE);
751 	} else {
752 		nfsstats.rpccnt[NFSPROC_REMOVE]++;
753 		nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
754 			NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
755 		nfsm_fhtom(ndp->ni_dvp);
756 		nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
757 		nfsm_request(ndp->ni_dvp);
758 		nfsm_reqdone;
759 		/*
760 		 * Kludge City: If the first reply to the remove rpc is lost..
761 		 *   the reply to the retransmitted request will be ENOENT
762 		 *   since the file was in fact removed
763 		 *   Therefore, we cheat and return success.
764 		 */
765 		if (error == ENOENT)
766 			error = 0;
767 	}
768 	if (ndp->ni_dvp == ndp->ni_vp)
769 		vrele(ndp->ni_vp);
770 	else
771 		nfs_nput(ndp->ni_vp);
772 	nfs_nput(ndp->ni_dvp);
773 	return (error);
774 }
775 
776 /*
777  * nfs file remove rpc called from nfs_inactive
778  */
779 nfs_removeit(ndp)
780 	register struct nameidata *ndp;
781 {
782 	register u_long *p;
783 	register caddr_t cp;
784 	register long t1, t2;
785 	caddr_t bpos, dpos;
786 	u_long xid;
787 	int error = 0;
788 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
789 
790 	nfsstats.rpccnt[NFSPROC_REMOVE]++;
791 	nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
792 		NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
793 	nfsm_fhtom(ndp->ni_dvp);
794 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
795 	nfsm_request(ndp->ni_dvp);
796 	nfsm_reqdone;
797 	return (error);
798 }
799 
800 /*
801  * nfs file rename call
802  */
803 nfs_rename(sndp, tndp)
804 	register struct nameidata *sndp, *tndp;
805 {
806 	register u_long *p;
807 	register caddr_t cp;
808 	register long t1, t2;
809 	caddr_t bpos, dpos;
810 	u_long xid;
811 	int error = 0;
812 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
813 
814 	nfsstats.rpccnt[NFSPROC_RENAME]++;
815 	nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
816 		(NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
817 		nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
818 	nfsm_fhtom(sndp->ni_dvp);
819 	nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
820 	nfsm_fhtom(tndp->ni_dvp);
821 	nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
822 	nfsm_request(sndp->ni_dvp);
823 	nfsm_reqdone;
824 	if (sndp->ni_vp->v_type == VDIR) {
825 		if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
826 			cache_purge(tndp->ni_dvp);
827 		cache_purge(sndp->ni_dvp);
828 	}
829 	nfs_abortop(sndp);
830 	nfs_abortop(tndp);
831 	return (error);
832 }
833 
834 /*
835  * nfs file rename rpc called from above
836  */
837 nfs_renameit(sndp, tndp)
838 	register struct nameidata *sndp, *tndp;
839 {
840 	register u_long *p;
841 	register caddr_t cp;
842 	register long t1, t2;
843 	caddr_t bpos, dpos;
844 	u_long xid;
845 	int error = 0;
846 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
847 
848 	nfsstats.rpccnt[NFSPROC_RENAME]++;
849 	nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
850 		(NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
851 		nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
852 	nfsm_fhtom(sndp->ni_dvp);
853 	nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
854 	nfsm_fhtom(tndp->ni_dvp);
855 	nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
856 	nfsm_request(sndp->ni_dvp);
857 	nfsm_reqdone;
858 	return (error);
859 }
860 
861 /*
862  * nfs hard link create call
863  */
864 nfs_link(vp, ndp)
865 	register struct vnode *vp;
866 	register struct nameidata *ndp;
867 {
868 	register u_long *p;
869 	register caddr_t cp;
870 	register long t1, t2;
871 	caddr_t bpos, dpos;
872 	u_long xid;
873 	int error = 0;
874 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
875 
876 	if (ndp->ni_dvp != vp)
877 		nfs_lock(vp);
878 	nfsstats.rpccnt[NFSPROC_LINK]++;
879 	nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
880 		NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
881 	nfsm_fhtom(vp);
882 	nfsm_fhtom(ndp->ni_dvp);
883 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
884 	nfsm_request(vp);
885 	nfsm_reqdone;
886 	if (ndp->ni_dvp != vp)
887 		nfs_unlock(vp);
888 	nfs_nput(ndp->ni_dvp);
889 	return (error);
890 }
891 
892 /*
893  * nfs symbolic link create call
894  */
895 nfs_symlink(ndp, vap, nm)
896 	struct nameidata *ndp;
897 	struct vattr *vap;
898 	char *nm;		/* is this the path ?? */
899 {
900 	register struct nfsv2_sattr *sp;
901 	register u_long *p;
902 	register caddr_t cp;
903 	register long t1, t2;
904 	caddr_t bpos, dpos;
905 	u_long xid;
906 	int error = 0;
907 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
908 
909 	nfsstats.rpccnt[NFSPROC_SYMLINK]++;
910 	nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
911 	NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_UNSIGNED);
912 	nfsm_fhtom(ndp->ni_dvp);
913 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
914 	nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
915 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
916 	sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
917 	sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
918 	sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
919 	sp->sa_size = txdr_unsigned(VNOVAL);
920 	txdr_time(&vap->va_atime, &sp->sa_atime);		/* or VNOVAL ?? */
921 	txdr_time(&vap->va_mtime, &sp->sa_mtime);	/* or VNOVAL ?? */
922 	nfsm_request(ndp->ni_dvp);
923 	nfsm_reqdone;
924 	nfs_nput(ndp->ni_dvp);
925 	return (error);
926 }
927 
928 /*
929  * nfs make dir call
930  */
931 nfs_mkdir(ndp, vap)
932 	register struct nameidata *ndp;
933 	struct vattr *vap;
934 {
935 	register struct nfsv2_sattr *sp;
936 	register u_long *p;
937 	register caddr_t cp;
938 	register long t1, t2;
939 	caddr_t bpos, dpos, cp2;
940 	u_long xid;
941 	int error = 0;
942 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
943 
944 	nfsstats.rpccnt[NFSPROC_MKDIR]++;
945 	nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
946 	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
947 	nfsm_fhtom(ndp->ni_dvp);
948 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
949 	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
950 	sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
951 	sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
952 	sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
953 	sp->sa_size = txdr_unsigned(VNOVAL);
954 	txdr_time(&vap->va_atime, &sp->sa_atime);		/* or VNOVAL ?? */
955 	txdr_time(&vap->va_mtime, &sp->sa_mtime);	/* or VNOVAL ?? */
956 	nfsm_request(ndp->ni_dvp);
957 	nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
958 	nfsm_reqdone;
959 	nfs_nput(ndp->ni_dvp);
960 	return (error);
961 }
962 
963 /*
964  * nfs remove directory call
965  */
966 nfs_rmdir(ndp)
967 	register struct nameidata *ndp;
968 {
969 	register u_long *p;
970 	register caddr_t cp;
971 	register long t1, t2;
972 	caddr_t bpos, dpos;
973 	u_long xid;
974 	int error = 0;
975 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
976 
977 	if (ndp->ni_dvp == ndp->ni_vp) {
978 		vrele(ndp->ni_dvp);
979 		nfs_nput(ndp->ni_dvp);
980 		return (EINVAL);
981 	}
982 	nfsstats.rpccnt[NFSPROC_RMDIR]++;
983 	nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
984 		NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
985 	nfsm_fhtom(ndp->ni_dvp);
986 	nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
987 	nfsm_request(ndp->ni_dvp);
988 	nfsm_reqdone;
989 	cache_purge(ndp->ni_dvp);
990 	cache_purge(ndp->ni_vp);
991 	nfs_nput(ndp->ni_vp);
992 	nfs_nput(ndp->ni_dvp);
993 	return (error);
994 }
995 
996 /*
997  * nfs readdir call
998  * Although cookie is defined as opaque, I translate it to/from net byte
999  * order so that it looks more sensible. This appears consistent with the
1000  * Ultrix implementation of NFS.
1001  */
1002 nfs_readdir(vp, uiop, cred)
1003 	register struct vnode *vp;
1004 	struct uio *uiop;
1005 	struct ucred *cred;
1006 {
1007 	register long len;
1008 	register struct direct *dp;
1009 	register u_long *p;
1010 	register caddr_t cp;
1011 	register long t1;
1012 	caddr_t bpos, dpos, cp2;
1013 	u_long xid;
1014 	int error = 0;
1015 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1016 	struct mbuf *md2;
1017 	caddr_t dpos2;
1018 	int siz;
1019 	int more_dirs;
1020 	off_t off, savoff;
1021 	struct direct *savdp;
1022 
1023 	nfsstats.rpccnt[NFSPROC_READDIR]++;
1024 	nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
1025 	nfsm_fhtom(vp);
1026 	nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
1027 	*p++ = txdr_unsigned(uiop->uio_offset);
1028 	*p = txdr_unsigned(uiop->uio_resid);
1029 	nfsm_request(vp);
1030 	siz = 0;
1031 	nfsm_disect(p, u_long *, NFSX_UNSIGNED);
1032 	more_dirs = fxdr_unsigned(int, *p);
1033 
1034 	/* Save the position so that we can do nfsm_mtouio() later */
1035 	dpos2 = dpos;
1036 	md2 = md;
1037 
1038 	/* loop thru the dir entries, doctoring them to 4bsd form */
1039 	savoff = off = 0;
1040 	savdp = dp = NULL;
1041 	while (more_dirs && siz < uiop->uio_resid) {
1042 		savoff = off;		/* Hold onto offset and dp */
1043 		savdp = dp;
1044 		nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
1045 		dp = (struct direct *)p;
1046 		dp->d_ino = fxdr_unsigned(u_long, *p++);
1047 		len = fxdr_unsigned(int, *p);
1048 		if (len <= 0 || len > NFS_MAXNAMLEN) {
1049 			error = EBADRPC;
1050 			m_freem(mrep);
1051 			goto nfsmout;
1052 		}
1053 		dp->d_namlen = (u_short)len;
1054 		len = nfsm_rndup(len);
1055 		nfsm_adv(len);
1056 		nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
1057 		off = fxdr_unsigned(off_t, *p);
1058 		*p++ = 0;		/* Ensures null termination of name */
1059 		more_dirs = fxdr_unsigned(int, *p);
1060 		dp->d_reclen = len+4*NFSX_UNSIGNED;
1061 		siz += dp->d_reclen;
1062 	}
1063 	/*
1064 	 * If at end of rpc data, get the eof boolean
1065 	 */
1066 	if (!more_dirs)
1067 		nfsm_disecton(p, u_long *, NFSX_UNSIGNED);
1068 	/*
1069 	 * If there is too much to fit in the data buffer, use savoff and
1070 	 * savdp to trim off the last record.
1071 	 * --> we are not at eof
1072 	 */
1073 	if (siz > uiop->uio_resid) {
1074 		off = savoff;
1075 		siz -= dp->d_reclen;
1076 		dp = savdp;
1077 	}
1078 	if (siz > 0) {
1079 		md = md2;
1080 		dpos = dpos2;
1081 		nfsm_mtouio(uiop, siz);
1082 		uiop->uio_offset = off;
1083 	}
1084 	nfsm_reqdone;
1085 	return (error);
1086 }
1087 
1088 /*
1089  * nfs statfs call
1090  * (Actually a vfsop, not a vnode op)
1091  */
1092 nfs_statfs(mp, sbp)
1093 	struct mount *mp;
1094 	register struct statfs *sbp;
1095 {
1096 	register struct vnode *vp;
1097 	register struct nfsv2_statfs *sfp;
1098 	register caddr_t cp;
1099 	register long t1;
1100 	caddr_t bpos, dpos, cp2;
1101 	u_long xid;
1102 	int error = 0;
1103 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1104 	struct nfsmount *nmp;
1105 	struct ucred *cred;
1106 	struct nfsnode *np;
1107 
1108 	nmp = vfs_to_nfs(mp);
1109 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
1110 		return (error);
1111 	vp = NFSTOV(np);
1112 	nfsstats.rpccnt[NFSPROC_STATFS]++;
1113 	cred = crget();
1114 	cred->cr_ngroups = 1;
1115 	nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
1116 	nfsm_fhtom(vp);
1117 	nfsm_request(vp);
1118 	nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
1119 	sbp->f_type = MOUNT_NFS;
1120 	sbp->f_flags = nmp->nm_flag;
1121 	sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize);
1122 	sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize);
1123 	sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
1124 	sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
1125 	sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
1126 	sbp->f_files = 0;
1127 	sbp->f_ffree = 0;
1128 	sbp->f_fsid.val[0] = mp->m_fsid.val[0];
1129 	sbp->f_fsid.val[1] = mp->m_fsid.val[1];
1130 	bcopy(nmp->nm_path, sbp->f_mntonname, MNAMELEN);
1131 	bcopy(nmp->nm_host, sbp->f_mntfromname, MNAMELEN);
1132 	nfsm_reqdone;
1133 	nfs_nput(vp);
1134 	crfree(cred);
1135 	return (error);
1136 }
1137 
1138 static char hextoasc[] = "0123456789abcdef";
1139 
1140 /*
1141  * Silly rename. To make the NFS filesystem that is stateless look a little
1142  * more like the "ufs" a remove of an active vnode is translated to a rename
1143  * to a funny looking filename that is removed by nfs_inactive on the
1144  * nfsnode. There is the potential for another process on a different client
1145  * to create the same funny name between the nfs_lookitup() fails and the
1146  * nfs_rename() completes, but...
1147  */
1148 nfs_sillyrename(ndp, flag)
1149 	register struct nameidata *ndp;
1150 	int flag;
1151 {
1152 	register struct nfsnode *np;
1153 	register struct sillyrename *sp;
1154 	register struct nameidata *tndp;
1155 	int error;
1156 	short pid;
1157 
1158 	np = VTONFS(ndp->ni_dvp);
1159 	cache_purge(ndp->ni_dvp);
1160 	MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
1161 		M_TEMP, M_WAITOK);
1162 	sp->s_flag = flag;
1163 	bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
1164 	np = VTONFS(ndp->ni_vp);
1165 	tndp = &sp->s_namei;
1166 	tndp->ni_cred = crdup(ndp->ni_cred);
1167 
1168 	/* Fudge together a funny name */
1169 	pid = u.u_procp->p_pid;
1170 	bcopy(".nfsAxxxx4.4", tndp->ni_dent.d_name, 13);
1171 	tndp->ni_dent.d_namlen = 12;
1172 	tndp->ni_dent.d_name[8] = hextoasc[pid & 0xf];
1173 	tndp->ni_dent.d_name[7] = hextoasc[(pid >> 4) & 0xf];
1174 	tndp->ni_dent.d_name[6] = hextoasc[(pid >> 8) & 0xf];
1175 	tndp->ni_dent.d_name[5] = hextoasc[(pid >> 12) & 0xf];
1176 
1177 	/* Try lookitups until we get one that isn't there */
1178 	while (nfs_lookitup(ndp->ni_dvp, tndp, (nfsv2fh_t *)0) == 0) {
1179 		tndp->ni_dent.d_name[4]++;
1180 		if (tndp->ni_dent.d_name[4] > 'z') {
1181 			error = EINVAL;
1182 			goto bad;
1183 		}
1184 	}
1185 	if (error = nfs_renameit(ndp, tndp))
1186 		goto bad;
1187 	nfs_lookitup(ndp->ni_dvp, tndp, &np->n_fh);
1188 	np->n_sillyrename = sp;
1189 	return (0);
1190 bad:
1191 	crfree(tndp->ni_cred);
1192 	free((caddr_t)sp, M_TEMP);
1193 	return (error);
1194 }
1195 
1196 /*
1197  * Look up a file name for silly rename stuff.
1198  * Just like nfs_lookup() except that it doesn't load returned values
1199  * into the nfsnode table.
1200  * If fhp != NULL it copies the returned file handle out
1201  */
1202 nfs_lookitup(vp, ndp, fhp)
1203 	register struct vnode *vp;
1204 	register struct nameidata *ndp;
1205 	nfsv2fh_t *fhp;
1206 {
1207 	register u_long *p;
1208 	register caddr_t cp;
1209 	register long t1, t2;
1210 	caddr_t bpos, dpos, cp2;
1211 	u_long xid;
1212 	int error = 0;
1213 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1214 	long len;
1215 
1216 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1217 	ndp->ni_dvp = vp;
1218 	ndp->ni_vp = NULL;
1219 	len = ndp->ni_dent.d_namlen;
1220 	nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1221 	nfsm_fhtom(vp);
1222 	nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
1223 	nfsm_request(vp);
1224 	if (fhp != NULL) {
1225 		nfsm_disect(cp, caddr_t, NFSX_FH);
1226 		bcopy(cp, (caddr_t)fhp, NFSX_FH);
1227 	}
1228 	nfsm_reqdone;
1229 	return (error);
1230 }
1231 
1232 /*
1233  * Kludge City..
1234  * - make nfs_bmap() essentially a no-op that does no translation
1235  * - do nfs_strategy() by faking physical I/O with nfs_readit/nfs_writeit
1236  *   after mapping the physical addresses into Kernel Virtual space in the
1237  *   nfsiobuf area.
1238  *   (Maybe I could use the process's page mapping, but I was concerned that
1239  *    Kernel Write might not be enabled and also figured copyout() would do
1240  *    a lot more work than bcopy() and also it currently happens in the
1241  *    context of the swapper process (2).
1242  */
1243 nfs_bmap(vp, bn, vpp, bnp)
1244 	struct vnode *vp;
1245 	daddr_t bn;
1246 	struct vnode **vpp;
1247 	daddr_t *bnp;
1248 {
1249 	if (vpp != NULL)
1250 		*vpp = vp;
1251 	if (bnp != NULL)
1252 		*bnp = bn * btodb(vp->v_mount->m_bsize);
1253 	return (0);
1254 }
1255 
1256 /*
1257  * Strategy routine for phys. i/o
1258  * If the biod's are running, queue a request
1259  * otherwise just call nfs_doio() to get it done
1260  */
1261 nfs_strategy(bp)
1262 	register struct buf *bp;
1263 {
1264 	register struct buf *dp;
1265 	register int i;
1266 	struct proc *rp;
1267 	int error = 0;
1268 	int fnd = 0;
1269 
1270 	/*
1271 	 * If an i/o daemon is waiting
1272 	 * queue the request, wake it up and wait for completion
1273 	 * otherwise just do it ourselves
1274 	 */
1275 	for (i = 0; i < nfs_asyncdaemons; i++) {
1276 		if (rp = nfs_iodwant[i]) {
1277 			/*
1278 			 * Ensure that the async_daemon is still waiting here
1279 			 */
1280 			if (rp->p_stat != SSLEEP ||
1281 			    rp->p_wchan != ((caddr_t)&nfs_iodwant[i])) {
1282 				nfs_iodwant[i] = (struct proc *)0;
1283 				continue;
1284 			}
1285 			dp = &nfs_bqueue;
1286 			if (dp->b_actf == NULL) {
1287 				dp->b_actl = bp;
1288 				bp->b_actf = dp;
1289 			} else {
1290 				dp->b_actf->b_actl = bp;
1291 				bp->b_actf = dp->b_actf;
1292 			}
1293 			dp->b_actf = bp;
1294 			bp->b_actl = dp;
1295 			fnd++;
1296 			nfs_iodwant[i] = (struct proc *)0;
1297 			wakeup((caddr_t)&nfs_iodwant[i]);
1298 			break;
1299 		}
1300 	}
1301 	if (!fnd)
1302 		error = nfs_doio(bp);
1303 	return (error);
1304 }
1305 
1306 /*
1307  * Fun and games with i/o
1308  * Essentially play ubasetup() and disk interrupt service routine by
1309  * mapping the data buffer into kernel virtual space and doing the
1310  * nfs read or write rpc's from it.
1311  * If the biod's are not running, this is just called from nfs_strategy(),
1312  * otherwise it is called by the biod's to do what would normally be
1313  * partially disk interrupt driven.
1314  */
1315 nfs_doio(bp)
1316 	register struct buf *bp;
1317 {
1318 	register struct pte *pte, *ppte;
1319 	register caddr_t vaddr;
1320 	register struct uio *uiop;
1321 	register struct vnode *vp;
1322 	struct nfsnode *np;
1323 	struct ucred *cr;
1324 	int npf, npf2;
1325 	int reg;
1326 	caddr_t vbase;
1327 	unsigned v;
1328 	struct proc *rp;
1329 	int o, error;
1330 	struct uio uio;
1331 	struct iovec io;
1332 
1333 	vp = bp->b_vp;
1334 	uiop = &uio;
1335 	uiop->uio_iov = &io;
1336 	uiop->uio_iovcnt = 1;
1337 	uiop->uio_segflg = UIO_SYSSPACE;
1338 
1339 	/*
1340 	 * For phys i/o, map the b_addr into kernel virtual space using
1341 	 * the Nfsiomap pte's
1342 	 * Also, add a temporary b_rcred for reading using the process's uid
1343 	 * and a guess at a group
1344 	 */
1345 	if (bp->b_flags & B_PHYS) {
1346 		VTONFS(vp)->n_flag |= NPAGEDON;
1347 		bp->b_rcred = cr = crget();
1348 		rp = (bp->b_flags & B_DIRTY) ? &proc[2] : bp->b_proc;
1349 		cr->cr_uid = rp->p_uid;
1350 		cr->cr_gid = 0;		/* Anything ?? */
1351 		cr->cr_ngroups = 1;
1352 		o = (int)bp->b_un.b_addr & PGOFSET;
1353 		npf2 = npf = btoc(bp->b_bcount + o);
1354 
1355 		/*
1356 		 * Get some mapping page table entries
1357 		 */
1358 		while ((reg = rmalloc(nfsmap, (long)npf)) == 0) {
1359 			nfsmap_want++;
1360 			sleep((caddr_t)&nfsmap_want, PZERO-1);
1361 		}
1362 		reg--;
1363 		if (bp->b_flags & B_PAGET)
1364 			pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
1365 		else {
1366 			v = btop(bp->b_un.b_addr);
1367 			if (bp->b_flags & B_UAREA)
1368 				pte = &rp->p_addr[v];
1369 			else
1370 				pte = vtopte(rp, v);
1371 		}
1372 
1373 		/*
1374 		 * Play vmaccess() but with the Nfsiomap page table
1375 		 */
1376 		ppte = &Nfsiomap[reg];
1377 		vbase = vaddr = &nfsiobuf[reg*NBPG];
1378 		while (npf != 0) {
1379 			mapin(ppte, (u_int)vaddr, pte->pg_pfnum, (int)(PG_V|PG_KW));
1380 #if defined(tahoe)
1381 			mtpr(P1DC, vaddr);
1382 #endif
1383 			ppte++;
1384 			pte++;
1385 			vaddr += NBPG;
1386 			--npf;
1387 		}
1388 
1389 		/*
1390 		 * And do the i/o rpc
1391 		 */
1392 		io.iov_base = vbase+o;
1393 		io.iov_len = uiop->uio_resid = bp->b_bcount;
1394 		uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1395 		if (bp->b_flags & B_READ) {
1396 			uiop->uio_rw = UIO_READ;
1397 			nfsstats.read_physios++;
1398 			bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred);
1399 		} else {
1400 			uiop->uio_rw = UIO_WRITE;
1401 			nfsstats.write_physios++;
1402 			bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred);
1403 		}
1404 
1405 		/*
1406 		 * Finally, release pte's used by physical i/o
1407 		 */
1408 		crfree(cr);
1409 		rmfree(nfsmap, (long)npf2, (long)++reg);
1410 		if (nfsmap_want) {
1411 			nfsmap_want = 0;
1412 			wakeup((caddr_t)&nfsmap_want);
1413 		}
1414 	} else {
1415 		if (bp->b_flags & B_READ) {
1416 			io.iov_len = uiop->uio_resid = bp->b_bcount;
1417 			uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1418 			io.iov_base = bp->b_un.b_addr;
1419 			uiop->uio_rw = UIO_READ;
1420 			nfsstats.read_bios++;
1421 			bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred);
1422 		} else {
1423 			io.iov_len = uiop->uio_resid = bp->b_dirtyend
1424 				- bp->b_dirtyoff;
1425 			uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
1426 				+ bp->b_dirtyoff;
1427 			io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
1428 			uiop->uio_rw = UIO_WRITE;
1429 			nfsstats.write_bios++;
1430 			bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred);
1431 			if (error) {
1432 				np = VTONFS(vp);
1433 				np->n_error = error;
1434 				np->n_flag |= NWRITEERR;
1435 			}
1436 			bp->b_dirtyoff = bp->b_dirtyend = 0;
1437 		}
1438 	}
1439 	if (error)
1440 		bp->b_flags |= B_ERROR;
1441 	bp->b_resid = uiop->uio_resid;
1442 	biodone(bp);
1443 	return (error);
1444 }
1445 
1446 /*
1447  * Flush all the blocks associated with a vnode.
1448  * 	Walk through the buffer pool and push any dirty pages
1449  *	associated with the vnode.
1450  */
1451 /* ARGSUSED */
1452 nfs_fsync(vp, fflags, cred, waitfor)
1453 	register struct vnode *vp;
1454 	int fflags;
1455 	struct ucred *cred;
1456 	int waitfor;
1457 {
1458 	register struct nfsnode *np = VTONFS(vp);
1459 	int error = 0;
1460 
1461 	if (np->n_flag & NMODIFIED) {
1462 		np->n_flag &= ~NMODIFIED;
1463 		vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
1464 	}
1465 	if (!error && (np->n_flag & NWRITEERR))
1466 		error = np->n_error;
1467 	return (error);
1468 }
1469 
1470 /*
1471  * Print out the contents of an nfsnode.
1472  */
1473 nfs_print(vp)
1474 	struct vnode *vp;
1475 {
1476 	register struct nfsnode *np = VTONFS(vp);
1477 
1478 	printf("tag VT_NFS, fileid %d fsid 0x%x%s\n",
1479 		np->n_vattr.va_fileid, np->n_vattr.va_fsid,
1480 		(np->n_flag & NLOCKED) ? " (LOCKED)" : "");
1481 	if (np->n_lockholder == 0)
1482 		return;
1483 	printf("\towner pid %d", np->n_lockholder);
1484 	if (np->n_lockwaiter)
1485 		printf(" waiting pid %d", np->n_lockwaiter);
1486 	printf("\n");
1487 }
1488