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