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