1 /**	$MirOS: src/sys/nfs/nfs_vnops.c,v 1.5 2005/12/19 22:22:14 tg Exp $ */
2 /*	$OpenBSD: nfs_vnops.c,v 1.64 2005/04/21 23:29:04 deraadt Exp $	*/
3 /*	$NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $	*/
4 
5 /*
6  * Copyright (c) 1989, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Rick Macklem at The University of Guelph.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)nfs_vnops.c	8.16 (Berkeley) 5/27/95
37  */
38 
39 
40 /*
41  * vnode op calls for Sun NFS version 2 and 3
42  */
43 
44 #include <sys/param.h>
45 #include <sys/proc.h>
46 #include <sys/kernel.h>
47 #include <sys/systm.h>
48 #include <sys/resourcevar.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/mount.h>
52 #include <sys/buf.h>
53 #include <sys/malloc.h>
54 #include <sys/pool.h>
55 #include <sys/mbuf.h>
56 #include <sys/conf.h>
57 #include <sys/namei.h>
58 #include <sys/vnode.h>
59 #include <sys/dirent.h>
60 #include <sys/fcntl.h>
61 #include <sys/lockf.h>
62 
63 #include <uvm/uvm_extern.h>
64 
65 #include <miscfs/specfs/specdev.h>
66 #include <miscfs/fifofs/fifo.h>
67 
68 #include <nfs/rpcv2.h>
69 #include <nfs/nfsproto.h>
70 #include <nfs/nfs.h>
71 #include <nfs/nfsnode.h>
72 #include <nfs/nfsmount.h>
73 #include <nfs/xdr_subs.h>
74 #include <nfs/nfsm_subs.h>
75 #include <nfs/nfs_var.h>
76 
77 #include <net/if.h>
78 #include <netinet/in.h>
79 #include <netinet/in_var.h>
80 
81 /* Defs */
82 #define	TRUE	1
83 #define	FALSE	0
84 
85 /*
86  * Global vfs data structures for nfs
87  */
88 int (**nfsv2_vnodeop_p)(void *);
89 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
90 	{ &vop_default_desc, vn_default_error },
91 	{ &vop_lookup_desc, nfs_lookup },	/* lookup */
92 	{ &vop_create_desc, nfs_create },	/* create */
93 	{ &vop_mknod_desc, nfs_mknod },		/* mknod */
94 	{ &vop_open_desc, nfs_open },		/* open */
95 	{ &vop_close_desc, nfs_close },		/* close */
96 	{ &vop_access_desc, nfs_access },	/* access */
97 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
98 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
99 	{ &vop_read_desc, nfs_read },		/* read */
100 	{ &vop_write_desc, nfs_write },		/* write */
101 	{ &vop_lease_desc, nfs_lease_check },	/* lease */
102 	{ &vop_ioctl_desc, nfs_ioctl },		/* ioctl */
103 	{ &vop_poll_desc, nfs_poll },		/* poll */
104 	{ &vop_kqfilter_desc, nfs_kqfilter },	/* kqfilter */
105 	{ &vop_revoke_desc, nfs_revoke },	/* revoke */
106 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
107 	{ &vop_remove_desc, nfs_remove },	/* remove */
108 	{ &vop_link_desc, nfs_link },		/* link */
109 	{ &vop_rename_desc, nfs_rename },	/* rename */
110 	{ &vop_mkdir_desc, nfs_mkdir },		/* mkdir */
111 	{ &vop_rmdir_desc, nfs_rmdir },		/* rmdir */
112 	{ &vop_symlink_desc, nfs_symlink },	/* symlink */
113 	{ &vop_readdir_desc, nfs_readdir },	/* readdir */
114 	{ &vop_readlink_desc, nfs_readlink },	/* readlink */
115 	{ &vop_abortop_desc, vop_generic_abortop },	/* abortop */
116 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
117 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
118 	{ &vop_lock_desc, nfs_lock },		/* lock */
119 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
120 	{ &vop_bmap_desc, nfs_bmap },		/* bmap */
121 	{ &vop_strategy_desc, nfs_strategy },	/* strategy */
122 	{ &vop_print_desc, nfs_print },		/* print */
123 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
124 	{ &vop_pathconf_desc, nfs_pathconf },	/* pathconf */
125 	{ &vop_advlock_desc, nfs_advlock },	/* advlock */
126 	{ &vop_reallocblks_desc, nfs_reallocblks },	/* reallocblks */
127 	{ &vop_bwrite_desc, nfs_bwrite },
128 	{ NULL, NULL }
129 };
130 struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
131 	{ &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
132 
133 /*
134  * Special device vnode ops
135  */
136 int (**spec_nfsv2nodeop_p)(void *);
137 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
138 	{ &vop_default_desc, spec_vnoperate },
139 	{ &vop_close_desc, nfsspec_close },	/* close */
140 	{ &vop_access_desc, nfsspec_access },	/* access */
141 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
142 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
143 	{ &vop_read_desc, nfsspec_read },	/* read */
144 	{ &vop_write_desc, nfsspec_write },	/* write */
145 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
146 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
147 	{ &vop_reclaim_desc, nfs_reclaim },	/* reclaim */
148 	{ &vop_lock_desc, nfs_lock },		/* lock */
149 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
150 	{ &vop_print_desc, nfs_print },		/* print */
151 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
152 	{ NULL, NULL }
153 };
154 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
155 	{ &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
156 
157 #ifdef FIFO
158 int (**fifo_nfsv2nodeop_p)(void *);
159 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
160 	{ &vop_default_desc, fifo_vnoperate },
161 	{ &vop_close_desc, nfsfifo_close },	/* close */
162 	{ &vop_access_desc, nfsspec_access },	/* access */
163 	{ &vop_getattr_desc, nfs_getattr },	/* getattr */
164 	{ &vop_setattr_desc, nfs_setattr },	/* setattr */
165 	{ &vop_read_desc, nfsfifo_read },	/* read */
166 	{ &vop_write_desc, nfsfifo_write },	/* write */
167 	{ &vop_fsync_desc, nfs_fsync },		/* fsync */
168 	{ &vop_inactive_desc, nfs_inactive },	/* inactive */
169 	{ &vop_reclaim_desc, nfsfifo_reclaim },	/* reclaim */
170 	{ &vop_lock_desc, nfs_lock },		/* lock */
171 	{ &vop_unlock_desc, nfs_unlock },	/* unlock */
172 	{ &vop_print_desc, nfs_print },		/* print */
173 	{ &vop_islocked_desc, nfs_islocked },	/* islocked */
174 	{ &vop_bwrite_desc, vop_generic_bwrite },
175 	{ NULL, NULL }
176 };
177 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
178 	{ &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
179 #endif /* FIFO */
180 
181 /*
182  * Global variables
183  */
184 extern u_int32_t nfs_true, nfs_false;
185 extern u_int32_t nfs_xdrneg1;
186 extern struct nfsstats nfsstats;
187 extern nfstype nfsv3_type[9];
188 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
189 int nfs_numasync = 0;
190 
191 /*
192  * nfs null call from vfs.
193  */
194 int
nfs_null(vp,cred,procp)195 nfs_null(vp, cred, procp)
196 	struct vnode *vp;
197 	struct ucred *cred;
198 	struct proc *procp;
199 {
200 	caddr_t bpos, dpos;
201 	int error = 0;
202 	struct mbuf *mreq, *mrep, *md, *mb;
203 
204 	nfsm_reqhead(vp, NFSPROC_NULL, 0);
205 	nfsm_request(vp, NFSPROC_NULL, procp, cred);
206 	nfsm_reqdone;
207 	return (error);
208 }
209 
210 /*
211  * nfs access vnode op.
212  * For nfs version 2, just return ok. File accesses may fail later.
213  * For nfs version 3, use the access rpc to check accessibility. If file modes
214  * are changed on the server, accesses might still fail later.
215  */
216 int
nfs_access(v)217 nfs_access(v)
218 	void *v;
219 {
220 	struct vop_access_args /* {
221 		struct vnode *a_vp;
222 		int  a_mode;
223 		struct ucred *a_cred;
224 		struct proc *a_p;
225 	} */ *ap = v;
226 	struct vnode *vp = ap->a_vp;
227 	u_int32_t *tl;
228 	caddr_t cp;
229 	int32_t t1, t2;
230 	caddr_t bpos, dpos, cp2;
231 	int error = 0, attrflag;
232 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
233 	u_int32_t mode, rmode;
234 	int v3 = NFS_ISV3(vp);
235 
236 	/*
237 	 * Disallow write attempts on filesystems mounted read-only;
238 	 * unless the file is a socket, fifo, or a block or character
239 	 * device resident on the filesystem.
240 	 */
241 	if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
242 		switch (vp->v_type) {
243 		case VREG:
244 		case VDIR:
245 		case VLNK:
246 			return (EROFS);
247 		default:
248 			break;
249 		}
250 	}
251 	/*
252 	 * For nfs v3, do an access rpc, otherwise you are stuck emulating
253 	 * ufs_access() locally using the vattr. This may not be correct,
254 	 * since the server may apply other access criteria such as
255 	 * client uid-->server uid mapping that we do not know about, but
256 	 * this is better than just returning anything that is lying about
257 	 * in the cache.
258 	 */
259 	if (v3) {
260 		nfsstats.rpccnt[NFSPROC_ACCESS]++;
261 		nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
262 		nfsm_fhtom(vp, v3);
263 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
264 		if (ap->a_mode & VREAD)
265 			mode = NFSV3ACCESS_READ;
266 		else
267 			mode = 0;
268 		if (vp->v_type == VDIR) {
269 			if (ap->a_mode & VWRITE)
270 				mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
271 					 NFSV3ACCESS_DELETE);
272 			if (ap->a_mode & VEXEC)
273 				mode |= NFSV3ACCESS_LOOKUP;
274 		} else {
275 			if (ap->a_mode & VWRITE)
276 				mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
277 			if (ap->a_mode & VEXEC)
278 				mode |= NFSV3ACCESS_EXECUTE;
279 		}
280 		*tl = txdr_unsigned(mode);
281 		nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
282 		nfsm_postop_attr(vp, attrflag);
283 		if (!error) {
284 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
285 			rmode = fxdr_unsigned(u_int32_t, *tl);
286 			/*
287 			 * The NFS V3 spec does not clarify whether or not
288 			 * the returned access bits can be a superset of
289 			 * the ones requested, so...
290 			 */
291 			if ((rmode & mode) != mode)
292 				error = EACCES;
293 		}
294 		nfsm_reqdone;
295 		return (error);
296 	} else
297 		return (nfsspec_access(ap));
298 }
299 
300 /*
301  * nfs open vnode op
302  * Check to see if the type is ok
303  * and that deletion is not in progress.
304  * For paged in text files, you will need to flush the page cache
305  * if consistency is lost.
306  */
307 /* ARGSUSED */
308 int
nfs_open(v)309 nfs_open(v)
310 	void *v;
311 {
312 	struct vop_open_args /* {
313 		struct vnode *a_vp;
314 		int  a_mode;
315 		struct ucred *a_cred;
316 		struct proc *a_p;
317 	} */ *ap = v;
318 	struct vnode *vp = ap->a_vp;
319 	struct nfsnode *np = VTONFS(vp);
320 	struct vattr vattr;
321 	int error;
322 
323 	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
324 #ifdef DIAGNOSTIC
325 		printf("open eacces vtyp=%d\n",vp->v_type);
326 #endif
327 		return (EACCES);
328 	}
329 
330 	/*
331 	 * Initialize read and write creds here, for swapfiles
332 	 * and other paths that don't set the creds themselves.
333 	 */
334 
335 	if (ap->a_mode & FREAD) {
336 		if (np->n_rcred) {
337 			crfree(np->n_rcred);
338 		}
339 		np->n_rcred = ap->a_cred;
340 		crhold(np->n_rcred);
341 	}
342 	if (ap->a_mode & FWRITE) {
343 		if (np->n_wcred) {
344 			crfree(np->n_wcred);
345 		}
346 		np->n_wcred = ap->a_cred;
347 		crhold(np->n_wcred);
348 	}
349 
350 	if (np->n_flag & NMODIFIED) {
351 		if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
352 			 ap->a_p, 1)) == EINTR)
353 			return (error);
354 		uvm_vnp_uncache(vp);
355 		np->n_attrstamp = 0;
356 		if (vp->v_type == VDIR)
357 			np->n_direofoffset = 0;
358 		error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
359 		if (error)
360 			return (error);
361 		np->n_mtime = vattr.va_mtime.tv_sec;
362 	} else {
363 		error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
364 		if (error)
365 			return (error);
366 		if (np->n_mtime != vattr.va_mtime.tv_sec) {
367 			if (vp->v_type == VDIR)
368 				np->n_direofoffset = 0;
369 			if ((error = nfs_vinvalbuf(vp, V_SAVE,
370 				 ap->a_cred, ap->a_p, 1)) == EINTR)
371 				return (error);
372 			uvm_vnp_uncache(vp);
373 			np->n_mtime = vattr.va_mtime.tv_sec;
374 		}
375 	}
376 	np->n_attrstamp = 0; /* For Open/Close consistency */
377 	return (0);
378 }
379 
380 /*
381  * nfs close vnode op
382  * What an NFS client should do upon close after writing is a debatable issue.
383  * Most NFS clients push delayed writes to the server upon close, basically for
384  * two reasons:
385  * 1 - So that any write errors may be reported back to the client process
386  *     doing the close system call. By far the two most likely errors are
387  *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
388  * 2 - To put a worst case upper bound on cache inconsistency between
389  *     multiple clients for the file.
390  * There is also a consistency problem for Version 2 of the protocol w.r.t.
391  * not being able to tell if other clients are writing a file concurrently,
392  * since there is no way of knowing if the changed modify time in the reply
393  * is only due to the write for this client.
394  * (NFS Version 3 provides weak cache consistency data in the reply that
395  *  should be sufficient to detect and handle this case.)
396  *
397  * The current code does the following:
398  * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
399  * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
400  *                     or commit them (this satisfies 1 and 2 except for the
401  *                     case where the server crashes after this close but
402  *                     before the commit RPC, which is felt to be "good
403  *                     enough". Changing the last argument to nfs_flush() to
404  *                     a 1 would force a commit operation, if it is felt a
405  *                     commit is necessary now.
406  */
407 /* ARGSUSED */
408 int
nfs_close(v)409 nfs_close(v)
410 	void *v;
411 {
412 	struct vop_close_args /* {
413 		struct vnodeop_desc *a_desc;
414 		struct vnode *a_vp;
415 		int  a_fflag;
416 		struct ucred *a_cred;
417 		struct proc *a_p;
418 	} */ *ap = v;
419 	struct vnode *vp = ap->a_vp;
420 	struct nfsnode *np = VTONFS(vp);
421 	int error = 0;
422 
423 	if (vp->v_type == VREG) {
424 	    if (np->n_flag & NMODIFIED) {
425 		if (NFS_ISV3(vp)) {
426 		    error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
427 		    np->n_flag &= ~NMODIFIED;
428 		} else
429 		    error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
430 		np->n_attrstamp = 0;
431 	    }
432 	    if (np->n_flag & NWRITEERR) {
433 		np->n_flag &= ~NWRITEERR;
434 		error = np->n_error;
435 	    }
436 	}
437 	return (error);
438 }
439 
440 /*
441  * nfs getattr call from vfs.
442  */
443 int
nfs_getattr(v)444 nfs_getattr(v)
445 	void *v;
446 {
447 	struct vop_getattr_args /* {
448 		struct vnode *a_vp;
449 		struct vattr *a_vap;
450 		struct ucred *a_cred;
451 		struct proc *a_p;
452 	} */ *ap = v;
453 	struct vnode *vp = ap->a_vp;
454 	struct nfsnode *np = VTONFS(vp);
455 	caddr_t cp;
456 	u_int32_t *tl;
457 	int32_t t1, t2;
458 	caddr_t bpos, dpos;
459 	int error = 0;
460 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
461 	int v3 = NFS_ISV3(vp);
462 
463 	/*
464 	 * Update local times for special files.
465 	 */
466 	if (np->n_flag & (NACC | NUPD))
467 		np->n_flag |= NCHG;
468 	/*
469 	 * First look in the cache.
470 	 */
471 	if (nfs_getattrcache(vp, ap->a_vap) == 0)
472 		return (0);
473 	nfsstats.rpccnt[NFSPROC_GETATTR]++;
474 	nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
475 	nfsm_fhtom(vp, v3);
476 	nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
477 	if (!error)
478 		nfsm_loadattr(vp, ap->a_vap);
479 	nfsm_reqdone;
480 	return (error);
481 }
482 
483 /*
484  * nfs setattr call.
485  */
486 int
nfs_setattr(v)487 nfs_setattr(v)
488 	void *v;
489 {
490 	struct vop_setattr_args /* {
491 		struct vnodeop_desc *a_desc;
492 		struct vnode *a_vp;
493 		struct vattr *a_vap;
494 		struct ucred *a_cred;
495 		struct proc *a_p;
496 	} */ *ap = v;
497 	struct vnode *vp = ap->a_vp;
498 	struct nfsnode *np = VTONFS(vp);
499 	struct vattr *vap = ap->a_vap;
500 	int error = 0;
501 	u_quad_t tsize = 0;
502 
503 	/*
504 	 * Setting of flags is not supported.
505 	 */
506 	if (vap->va_flags != VNOVAL)
507 		return (EOPNOTSUPP);
508 
509 	/*
510 	 * Disallow write attempts if the filesystem is mounted read-only.
511 	 */
512   	if ((vap->va_uid != (uid_t)VNOVAL ||
513 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
514 	    vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
515 	    (vp->v_mount->mnt_flag & MNT_RDONLY))
516 		return (EROFS);
517 	if (vap->va_size != VNOVAL) {
518  		switch (vp->v_type) {
519  		case VDIR:
520  			return (EISDIR);
521  		case VCHR:
522  		case VBLK:
523  		case VSOCK:
524  		case VFIFO:
525 			if (vap->va_mtime.tv_sec == VNOVAL &&
526 			    vap->va_atime.tv_sec == VNOVAL &&
527 			    vap->va_mode == (mode_t)VNOVAL &&
528 			    vap->va_uid == (uid_t)VNOVAL &&
529 			    vap->va_gid == (gid_t)VNOVAL)
530 				return (0);
531  			vap->va_size = VNOVAL;
532  			break;
533  		default:
534 			/*
535 			 * Disallow write attempts if the filesystem is
536 			 * mounted read-only.
537 			 */
538 			if (vp->v_mount->mnt_flag & MNT_RDONLY)
539 				return (EROFS);
540  			if (vap->va_size == 0)
541  				error = nfs_vinvalbuf(vp, 0,
542  				     ap->a_cred, ap->a_p, 1);
543 			else
544 				error = nfs_vinvalbuf(vp, V_SAVE,
545  				     ap->a_cred, ap->a_p, 1);
546 			if (error)
547 				return (error);
548  			tsize = np->n_size;
549  			np->n_size = np->n_vattr.va_size = vap->va_size;
550 			uvm_vnp_setsize(vp, np->n_size);
551   		};
552   	} else if ((vap->va_mtime.tv_sec != VNOVAL ||
553 		vap->va_atime.tv_sec != VNOVAL) &&
554 		vp->v_type == VREG &&
555   		(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
556 		 ap->a_p, 1)) == EINTR)
557 		return (error);
558 	error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
559 	if (error && vap->va_size != VNOVAL) {
560 		np->n_size = np->n_vattr.va_size = tsize;
561 		uvm_vnp_setsize(vp, np->n_size);
562 	}
563 
564 	VN_KNOTE(vp, NOTE_ATTRIB); /* XXX setattrrpc? */
565 
566 	return (error);
567 }
568 
569 /*
570  * Do an nfs setattr rpc.
571  */
572 int
nfs_setattrrpc(vp,vap,cred,procp)573 nfs_setattrrpc(vp, vap, cred, procp)
574 	struct vnode *vp;
575 	struct vattr *vap;
576 	struct ucred *cred;
577 	struct proc *procp;
578 {
579 	struct nfsv2_sattr *sp;
580 	caddr_t cp;
581 	int32_t t1, t2;
582 	caddr_t bpos, dpos, cp2;
583 	u_int32_t *tl;
584 	int error = 0, wccflag = NFSV3_WCCRATTR;
585 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
586 	int v3 = NFS_ISV3(vp);
587 
588 	nfsstats.rpccnt[NFSPROC_SETATTR]++;
589 	nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
590 	nfsm_fhtom(vp, v3);
591 	if (v3) {
592 		nfsm_v3attrbuild(vap, TRUE);
593 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
594 		*tl = nfs_false;
595 	} else {
596 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
597 		if (vap->va_mode == (mode_t)VNOVAL)
598 			sp->sa_mode = nfs_xdrneg1;
599 		else
600 			sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
601 		if (vap->va_uid == (uid_t)VNOVAL)
602 			sp->sa_uid = nfs_xdrneg1;
603 		else
604 			sp->sa_uid = txdr_unsigned(vap->va_uid);
605 		if (vap->va_gid == (gid_t)VNOVAL)
606 			sp->sa_gid = nfs_xdrneg1;
607 		else
608 			sp->sa_gid = txdr_unsigned(vap->va_gid);
609 		sp->sa_size = txdr_unsigned(vap->va_size);
610 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
611 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
612 	}
613 	nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
614 	if (v3) {
615 		nfsm_wcc_data(vp, wccflag);
616 	} else
617 		nfsm_loadattr(vp, (struct vattr *)0);
618 	nfsm_reqdone;
619 	return (error);
620 }
621 
622 /*
623  * nfs lookup call, one step at a time...
624  * First look in cache
625  * If not found, unlock the directory nfsnode and do the rpc
626  */
627 int
nfs_lookup(v)628 nfs_lookup(v)
629 	void *v;
630 {
631 	struct vop_lookup_args /* {
632 		struct vnodeop_desc *a_desc;
633 		struct vnode *a_dvp;
634 		struct vnode **a_vpp;
635 		struct componentname *a_cnp;
636 	} */ *ap = v;
637 	struct componentname *cnp = ap->a_cnp;
638 	struct vnode *dvp = ap->a_dvp;
639 	struct vnode **vpp = ap->a_vpp;
640 	struct proc *p = cnp->cn_proc;
641 	int flags;
642 	struct vnode *newvp;
643 	u_int32_t *tl;
644 	caddr_t cp;
645 	int32_t t1, t2;
646 	struct nfsmount *nmp;
647 	caddr_t bpos, dpos, cp2;
648 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
649 	long len;
650 	nfsfh_t *fhp;
651 	struct nfsnode *np;
652 	int lockparent, wantparent, error = 0, attrflag, fhsize;
653 	int v3 = NFS_ISV3(dvp);
654 
655 	cnp->cn_flags &= ~PDIRUNLOCK;
656 	flags = cnp->cn_flags;
657 
658 	*vpp = NULLVP;
659 	if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
660 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
661 		return (EROFS);
662 	if (dvp->v_type != VDIR)
663 		return (ENOTDIR);
664 	lockparent = flags & LOCKPARENT;
665 	wantparent = flags & (LOCKPARENT|WANTPARENT);
666 	nmp = VFSTONFS(dvp->v_mount);
667 	np = VTONFS(dvp);
668 
669 	/*
670 	 * Before tediously performing a linear scan of the directory,
671 	 * check the name cache to see if the directory/name pair
672 	 * we are looking for is known already.
673 	 * If the directory/name pair is found in the name cache,
674 	 * we have to ensure the directory has not changed from
675 	 * the time the cache entry has been created. If it has,
676 	 * the cache entry has to be ignored.
677 	 */
678 	if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
679 		struct vattr vattr;
680 		int err2;
681 
682 		if (error && error != ENOENT) {
683 			*vpp = NULLVP;
684 			return (error);
685 		}
686 
687 		if (cnp->cn_flags & PDIRUNLOCK) {
688 			err2 = vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
689 			if (err2 != 0) {
690 				*vpp = NULLVP;
691 				return (err2);
692 			}
693 			cnp->cn_flags &= ~PDIRUNLOCK;
694 		}
695 
696 		err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
697 		if (err2 != 0) {
698 			if (error == 0) {
699 				if (*vpp != dvp)
700 					vput(*vpp);
701 				else
702 					vrele(*vpp);
703 			}
704 			*vpp = NULLVP;
705 			return (err2);
706 		}
707 
708 		if (error == ENOENT) {
709 			if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
710 			    cnp->cn_proc) && vattr.va_mtime.tv_sec ==
711 			    VTONFS(dvp)->n_ctime)
712 				return (ENOENT);
713 			cache_purge(dvp);
714 			np->n_ctime = 0;
715 			goto dorpc;
716 		}
717 
718 		newvp = *vpp;
719 		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
720 			&& vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime)
721 		{
722 			nfsstats.lookupcache_hits++;
723 			if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
724 				cnp->cn_flags |= SAVENAME;
725 			if ((!lockparent || !(flags & ISLASTCN)) &&
726 			     newvp != dvp)
727 				VOP_UNLOCK(dvp, 0, p);
728 			return (0);
729 		}
730 		cache_purge(newvp);
731 		if (newvp != dvp)
732 			vput(newvp);
733 		else
734 			vrele(newvp);
735 		*vpp = NULLVP;
736 	}
737 dorpc:
738 	error = 0;
739 	newvp = NULLVP;
740 	nfsstats.lookupcache_misses++;
741 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
742 	len = cnp->cn_namelen;
743 	nfsm_reqhead(dvp, NFSPROC_LOOKUP,
744 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
745 	nfsm_fhtom(dvp, v3);
746 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
747 	nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
748 	if (error) {
749 		nfsm_postop_attr(dvp, attrflag);
750 		m_freem(mrep);
751 		goto nfsmout;
752 	}
753 	nfsm_getfh(fhp, fhsize, v3);
754 
755 	/*
756 	 * Handle RENAME case...
757 	 */
758 	if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
759 		if (NFS_CMPFH(np, fhp, fhsize)) {
760 			m_freem(mrep);
761 			return (EISDIR);
762 		}
763 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
764 		if (error) {
765 			m_freem(mrep);
766 			return (error);
767 		}
768 		newvp = NFSTOV(np);
769 		if (v3) {
770 			nfsm_postop_attr(newvp, attrflag);
771 			nfsm_postop_attr(dvp, attrflag);
772 		} else
773 			nfsm_loadattr(newvp, (struct vattr *)0);
774 		*vpp = newvp;
775 		m_freem(mrep);
776 		cnp->cn_flags |= SAVENAME;
777 		if (!lockparent) {
778 			VOP_UNLOCK(dvp, 0, p);
779 			cnp->cn_flags |= PDIRUNLOCK;
780 		}
781 		return (0);
782 	}
783 
784 	/*
785 	 * The postop attr handling is duplicated for each if case,
786 	 * because it should be done while dvp is locked (unlocking
787 	 * dvp is different for each case).
788 	 */
789 
790 	if (NFS_CMPFH(np, fhp, fhsize)) {
791 		VREF(dvp);
792 		newvp = dvp;
793 		if (v3) {
794 			nfsm_postop_attr(newvp, attrflag);
795 			nfsm_postop_attr(dvp, attrflag);
796 		} else
797 			nfsm_loadattr(newvp, (struct vattr *)0);
798 	} else if (flags & ISDOTDOT) {
799 		VOP_UNLOCK(dvp, 0, p);
800 		cnp->cn_flags |= PDIRUNLOCK;
801 
802 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
803 		if (error) {
804 			if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
805 				cnp->cn_flags &= ~PDIRUNLOCK;
806 			m_freem(mrep);
807 			return (error);
808 		}
809 		newvp = NFSTOV(np);
810 
811 		if (v3) {
812 			nfsm_postop_attr(newvp, attrflag);
813 			nfsm_postop_attr(dvp, attrflag);
814 		} else
815 			nfsm_loadattr(newvp, (struct vattr *)0);
816 
817 		if (lockparent && (flags & ISLASTCN)) {
818 			if ((error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
819 				m_freem(mrep);
820 				vput(newvp);
821 				return error;
822 			}
823 			cnp->cn_flags &= ~PDIRUNLOCK;
824 		}
825 
826 	} else {
827 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
828 		if (error) {
829 			m_freem(mrep);
830 			return error;
831 		}
832 		newvp = NFSTOV(np);
833 		if (v3) {
834 			nfsm_postop_attr(newvp, attrflag);
835 			nfsm_postop_attr(dvp, attrflag);
836 		} else
837 			nfsm_loadattr(newvp, (struct vattr *)0);
838 		if (!lockparent || !(flags & ISLASTCN)) {
839 			VOP_UNLOCK(dvp, 0, p);
840 			cnp->cn_flags |= PDIRUNLOCK;
841 		}
842 	}
843 	if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
844 		cnp->cn_flags |= SAVENAME;
845 	if ((cnp->cn_flags & MAKEENTRY) &&
846 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
847 		np->n_ctime = np->n_vattr.va_ctime.tv_sec;
848 		cache_enter(dvp, newvp, cnp);
849 	}
850 	*vpp = newvp;
851 	nfsm_reqdone;
852 	if (error) {
853 		/*
854 		 * We get here only because of errors returned by
855 		 * the RPC. Otherwise we'll have returned above
856 		 * (the nfsm_* macros will jump to nfsm_reqdone
857 		 * on error).
858 		 */
859 		if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
860 		    cnp->cn_nameiop != CREATE) {
861 			if (VTONFS(dvp)->n_ctime == 0)
862 				VTONFS(dvp)->n_ctime =
863 				    VTONFS(dvp)->n_vattr.va_mtime.tv_sec;
864 			cache_enter(dvp, NULL, cnp);
865 		}
866 		if (newvp != NULLVP) {
867 			vrele(newvp);
868 			if (newvp != dvp)
869 				VOP_UNLOCK(newvp, 0, p);
870 		}
871 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
872 		    (flags & ISLASTCN) && error == ENOENT) {
873 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
874 				error = EROFS;
875 			else
876 				error = EJUSTRETURN;
877 		}
878 		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
879 			cnp->cn_flags |= SAVENAME;
880 		*vpp = NULL;
881 	}
882 	return (error);
883 }
884 
885 /*
886  * nfs read call.
887  * Just call nfs_bioread() to do the work.
888  */
889 int
nfs_read(v)890 nfs_read(v)
891 	void *v;
892 {
893 	struct vop_read_args /* {
894 		struct vnode *a_vp;
895 		struct uio *a_uio;
896 		int  a_ioflag;
897 		struct ucred *a_cred;
898 	} */ *ap = v;
899 	struct vnode *vp = ap->a_vp;
900 
901 	if (vp->v_type != VREG)
902 		return (EPERM);
903 	return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
904 }
905 
906 /*
907  * nfs readlink call
908  */
909 int
nfs_readlink(v)910 nfs_readlink(v)
911 	void *v;
912 {
913 	struct vop_readlink_args /* {
914 		struct vnode *a_vp;
915 		struct uio *a_uio;
916 		struct ucred *a_cred;
917 	} */ *ap = v;
918 	struct vnode *vp = ap->a_vp;
919 
920 	if (vp->v_type != VLNK)
921 		return (EPERM);
922 	return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
923 }
924 
925 /*
926  * Do a readlink rpc.
927  * Called by nfs_doio() from below the buffer cache.
928  */
929 int
nfs_readlinkrpc(vp,uiop,cred)930 nfs_readlinkrpc(vp, uiop, cred)
931 	struct vnode *vp;
932 	struct uio *uiop;
933 	struct ucred *cred;
934 {
935 	u_int32_t *tl;
936 	caddr_t cp;
937 	int32_t t1, t2;
938 	caddr_t bpos, dpos, cp2;
939 	int error = 0, len, attrflag;
940 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
941 	int v3 = NFS_ISV3(vp);
942 
943 	nfsstats.rpccnt[NFSPROC_READLINK]++;
944 	nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
945 	nfsm_fhtom(vp, v3);
946 	nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
947 	if (v3)
948 		nfsm_postop_attr(vp, attrflag);
949 	if (!error) {
950 		nfsm_strsiz(len, NFS_MAXPATHLEN);
951 		nfsm_mtouio(uiop, len);
952 	}
953 	nfsm_reqdone;
954 	return (error);
955 }
956 
957 /*
958  * nfs read rpc call
959  * Ditto above
960  */
961 int
nfs_readrpc(vp,uiop)962 nfs_readrpc(vp, uiop)
963 	struct vnode *vp;
964 	struct uio *uiop;
965 {
966 	u_int32_t *tl;
967 	caddr_t cp;
968 	int32_t t1, t2;
969 	caddr_t bpos, dpos, cp2;
970 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
971 	struct nfsmount *nmp;
972 	int error = 0, len, retlen, tsiz, eof, attrflag;
973 	int v3 = NFS_ISV3(vp);
974 
975 #ifndef nolint
976 	eof = 0;
977 #endif
978 	nmp = VFSTONFS(vp->v_mount);
979 	tsiz = uiop->uio_resid;
980 	if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
981 		return (EFBIG);
982 	while (tsiz > 0) {
983 		nfsstats.rpccnt[NFSPROC_READ]++;
984 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
985 		nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
986 		nfsm_fhtom(vp, v3);
987 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
988 		if (v3) {
989 			txdr_hyper(uiop->uio_offset, tl);
990 			*(tl + 2) = txdr_unsigned(len);
991 		} else {
992 			*tl++ = txdr_unsigned(uiop->uio_offset);
993 			*tl++ = txdr_unsigned(len);
994 			*tl = 0;
995 		}
996 		nfsm_request(vp, NFSPROC_READ, uiop->uio_procp,
997 		    VTONFS(vp)->n_rcred);
998 		if (v3) {
999 			nfsm_postop_attr(vp, attrflag);
1000 			if (error) {
1001 				m_freem(mrep);
1002 				goto nfsmout;
1003 			}
1004 			nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1005 			eof = fxdr_unsigned(int, *(tl + 1));
1006 		} else
1007 			nfsm_loadattr(vp, (struct vattr *)0);
1008 		nfsm_strsiz(retlen, nmp->nm_rsize);
1009 		nfsm_mtouio(uiop, retlen);
1010 		m_freem(mrep);
1011 		tsiz -= retlen;
1012 		if (v3) {
1013 			if (eof || retlen == 0)
1014 				tsiz = 0;
1015 		} else if (retlen < len)
1016 			tsiz = 0;
1017 	}
1018 nfsmout:
1019 	return (error);
1020 }
1021 
1022 /*
1023  * nfs write call
1024  */
1025 int
nfs_writerpc(vp,uiop,iomode,must_commit)1026 nfs_writerpc(vp, uiop, iomode, must_commit)
1027 	struct vnode *vp;
1028 	struct uio *uiop;
1029 	int *iomode, *must_commit;
1030 {
1031 	u_int32_t *tl;
1032 	caddr_t cp;
1033 	int32_t t1, t2, backup;
1034 	caddr_t bpos, dpos, cp2;
1035 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1036 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1037 	int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1038 	int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1039 
1040 #ifndef DIAGNOSTIC
1041 	if (uiop->uio_iovcnt != 1)
1042 		panic("nfs: writerpc iovcnt > 1");
1043 #endif
1044 	*must_commit = 0;
1045 	tsiz = uiop->uio_resid;
1046 	if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
1047 		return (EFBIG);
1048 	while (tsiz > 0) {
1049 		nfsstats.rpccnt[NFSPROC_WRITE]++;
1050 		len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1051 		nfsm_reqhead(vp, NFSPROC_WRITE,
1052 			NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1053 		nfsm_fhtom(vp, v3);
1054 		if (v3) {
1055 			nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1056 			txdr_hyper(uiop->uio_offset, tl);
1057 			tl += 2;
1058 			*tl++ = txdr_unsigned(len);
1059 			*tl++ = txdr_unsigned(*iomode);
1060 			*tl = txdr_unsigned(len);
1061 		} else {
1062 			u_int32_t x;
1063 
1064 			nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1065 			/* Set both "begin" and "current" to non-garbage. */
1066 			x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1067 			*tl++ = x;      /* "begin offset" */
1068 			*tl++ = x;      /* "current offset" */
1069 			x = txdr_unsigned(len);
1070 			*tl++ = x;      /* total to this offset */
1071 			*tl = x;        /* size of this write */
1072 
1073 		}
1074 		nfsm_uiotom(uiop, len);
1075 		nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp,
1076 		    VTONFS(vp)->n_wcred);
1077 		if (v3) {
1078 			wccflag = NFSV3_WCCCHK;
1079 			nfsm_wcc_data(vp, wccflag);
1080 			if (!error) {
1081 				nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1082 					+ NFSX_V3WRITEVERF);
1083 				rlen = fxdr_unsigned(int, *tl++);
1084 				if (rlen == 0) {
1085 					error = NFSERR_IO;
1086 					break;
1087 				} else if (rlen < len) {
1088 					backup = len - rlen;
1089 					uiop->uio_iov->iov_base -= backup;
1090 					uiop->uio_iov->iov_len += backup;
1091 					uiop->uio_offset -= backup;
1092 					uiop->uio_resid += backup;
1093 					len = rlen;
1094 				}
1095 				commit = fxdr_unsigned(int, *tl++);
1096 
1097 				/*
1098 				 * Return the lowest committment level
1099 				 * obtained by any of the RPCs.
1100 				 */
1101 				if (committed == NFSV3WRITE_FILESYNC)
1102 					committed = commit;
1103 				else if (committed == NFSV3WRITE_DATASYNC &&
1104 					commit == NFSV3WRITE_UNSTABLE)
1105 					committed = commit;
1106 				if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) {
1107 				    bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1108 					NFSX_V3WRITEVERF);
1109 				    nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1110 				} else if (bcmp((caddr_t)tl,
1111 				    (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1112 				    *must_commit = 1;
1113 				    bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1114 					NFSX_V3WRITEVERF);
1115 				}
1116 			}
1117 		} else
1118 		    nfsm_loadattr(vp, (struct vattr *)0);
1119 		if (wccflag)
1120 		    VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1121 		m_freem(mrep);
1122 		tsiz -= len;
1123 	}
1124 nfsmout:
1125 	*iomode = committed;
1126 	if (error)
1127 		uiop->uio_resid = tsiz;
1128 	return (error);
1129 }
1130 
1131 /*
1132  * nfs mknod rpc
1133  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1134  * mode set to specify the file type and the size field for rdev.
1135  */
1136 int
nfs_mknodrpc(dvp,vpp,cnp,vap)1137 nfs_mknodrpc(dvp, vpp, cnp, vap)
1138 	struct vnode *dvp;
1139 	struct vnode **vpp;
1140 	struct componentname *cnp;
1141 	struct vattr *vap;
1142 {
1143 	struct nfsv2_sattr *sp;
1144 	u_int32_t *tl;
1145 	caddr_t cp;
1146 	int32_t t1, t2;
1147 	struct vnode *newvp = (struct vnode *)0;
1148 	struct nfsnode *np;
1149 	char *cp2;
1150 	caddr_t bpos, dpos;
1151 	int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1152 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1153 	u_int32_t rdev;
1154 	int v3 = NFS_ISV3(dvp);
1155 
1156 	if (vap->va_type == VCHR || vap->va_type == VBLK)
1157 		rdev = txdr_unsigned(vap->va_rdev);
1158 	else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1159 		rdev = nfs_xdrneg1;
1160 	else {
1161 		VOP_ABORTOP(dvp, cnp);
1162 		vput(dvp);
1163 		return (EOPNOTSUPP);
1164 	}
1165 	nfsstats.rpccnt[NFSPROC_MKNOD]++;
1166 	nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1167 		+ nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1168 	nfsm_fhtom(dvp, v3);
1169 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1170 	if (v3) {
1171 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1172 		*tl++ = vtonfsv3_type(vap->va_type);
1173 		nfsm_v3attrbuild(vap, FALSE);
1174 		if (vap->va_type == VCHR || vap->va_type == VBLK) {
1175 			nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1176 			*tl++ = txdr_unsigned(major(vap->va_rdev));
1177 			*tl = txdr_unsigned(minor(vap->va_rdev));
1178 		}
1179 	} else {
1180 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1181 		sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1182 		sp->sa_uid = nfs_xdrneg1;
1183 		sp->sa_gid = nfs_xdrneg1;
1184 		sp->sa_size = rdev;
1185 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1186 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1187 	}
1188 	nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred);
1189 	if (!error) {
1190 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1191 		if (!gotvp) {
1192 			if (newvp) {
1193 				vrele(newvp);
1194 				newvp = (struct vnode *)0;
1195 			}
1196 			error = nfs_lookitup(dvp, cnp->cn_nameptr,
1197 			    cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1198 			if (!error)
1199 				newvp = NFSTOV(np);
1200 		}
1201 	}
1202 	if (v3)
1203 		nfsm_wcc_data(dvp, wccflag);
1204 	nfsm_reqdone;
1205 	if (error) {
1206 		if (newvp)
1207 			vrele(newvp);
1208 	} else {
1209 		if (cnp->cn_flags & MAKEENTRY)
1210 			cache_enter(dvp, newvp, cnp);
1211 		*vpp = newvp;
1212 	}
1213 	pool_put(&namei_pool, cnp->cn_pnbuf);
1214 	VTONFS(dvp)->n_flag |= NMODIFIED;
1215 	if (!wccflag)
1216 		VTONFS(dvp)->n_attrstamp = 0;
1217 	vrele(dvp);
1218 	return (error);
1219 }
1220 
1221 /*
1222  * nfs mknod vop
1223  * just call nfs_mknodrpc() to do the work.
1224  */
1225 /* ARGSUSED */
1226 int
nfs_mknod(v)1227 nfs_mknod(v)
1228 	void *v;
1229 {
1230 	struct vop_mknod_args /* {
1231 		struct vnode *a_dvp;
1232 		struct vnode **a_vpp;
1233 		struct componentname *a_cnp;
1234 		struct vattr *a_vap;
1235 	} */ *ap = v;
1236 	struct vnode *newvp;
1237 	int error;
1238 
1239 	error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1240 	if (!error)
1241 		vrele(newvp);
1242 
1243 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1244 
1245 	return (error);
1246 }
1247 
1248 static u_long create_verf;
1249 /*
1250  * nfs file create call
1251  */
1252 int
nfs_create(v)1253 nfs_create(v)
1254 	void *v;
1255 {
1256 	struct vop_create_args /* {
1257 		struct vnode *a_dvp;
1258 		struct vnode **a_vpp;
1259 		struct componentname *a_cnp;
1260 		struct vattr *a_vap;
1261 	} */ *ap = v;
1262 	struct vnode *dvp = ap->a_dvp;
1263 	struct vattr *vap = ap->a_vap;
1264 	struct componentname *cnp = ap->a_cnp;
1265 	struct nfsv2_sattr *sp;
1266 	u_int32_t *tl;
1267 	caddr_t cp;
1268 	int32_t t1, t2;
1269 	struct nfsnode *np = (struct nfsnode *)0;
1270 	struct vnode *newvp = (struct vnode *)0;
1271 	caddr_t bpos, dpos, cp2;
1272 	int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1273 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1274 	int v3 = NFS_ISV3(dvp);
1275 
1276 	/*
1277 	 * Oops, not for me..
1278 	 */
1279 	if (vap->va_type == VSOCK)
1280 		return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1281 
1282 #ifdef VA_EXCLUSIVE
1283 	if (vap->va_vaflags & VA_EXCLUSIVE)
1284 		fmode |= O_EXCL;
1285 #endif
1286 again:
1287 	nfsstats.rpccnt[NFSPROC_CREATE]++;
1288 	nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1289 		nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1290 	nfsm_fhtom(dvp, v3);
1291 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1292 	if (v3) {
1293 		nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1294 		if (fmode & O_EXCL) {
1295 			*tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1296 			nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
1297 			if (TAILQ_FIRST(&in_ifaddr))
1298 				*tl++ = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr.s_addr;
1299 			else
1300 				*tl++ = create_verf;
1301 			*tl = ++create_verf;
1302 		} else {
1303 			*tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1304 			nfsm_v3attrbuild(vap, FALSE);
1305 		}
1306 	} else {
1307 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1308 		sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1309 		sp->sa_uid = nfs_xdrneg1;
1310 		sp->sa_gid = nfs_xdrneg1;
1311 		sp->sa_size = 0;
1312 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1313 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1314 	}
1315 	nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
1316 	if (!error) {
1317 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1318 		if (!gotvp) {
1319 			if (newvp) {
1320 				vrele(newvp);
1321 				newvp = (struct vnode *)0;
1322 			}
1323 			error = nfs_lookitup(dvp, cnp->cn_nameptr,
1324 			    cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1325 			if (!error)
1326 				newvp = NFSTOV(np);
1327 		}
1328 	}
1329 	if (v3)
1330 		nfsm_wcc_data(dvp, wccflag);
1331 	nfsm_reqdone;
1332 	if (error) {
1333 		if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1334 			fmode &= ~O_EXCL;
1335 			goto again;
1336 		}
1337 		if (newvp)
1338 			vrele(newvp);
1339 	} else if (v3 && (fmode & O_EXCL))
1340 		error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1341 	if (!error) {
1342 		if (cnp->cn_flags & MAKEENTRY)
1343 			cache_enter(dvp, newvp, cnp);
1344 		*ap->a_vpp = newvp;
1345 	}
1346 	pool_put(&namei_pool, cnp->cn_pnbuf);
1347 	VTONFS(dvp)->n_flag |= NMODIFIED;
1348 	if (!wccflag)
1349 		VTONFS(dvp)->n_attrstamp = 0;
1350 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1351 	vrele(dvp);
1352 	return (error);
1353 }
1354 
1355 /*
1356  * nfs file remove call
1357  * To try and make nfs semantics closer to ufs semantics, a file that has
1358  * other processes using the vnode is renamed instead of removed and then
1359  * removed later on the last close.
1360  * - If v_usecount > 1
1361  *	  If a rename is not already in the works
1362  *	     call nfs_sillyrename() to set it up
1363  *     else
1364  *	  do the remove rpc
1365  */
1366 int
nfs_remove(v)1367 nfs_remove(v)
1368 	void *v;
1369 {
1370 	struct vop_remove_args /* {
1371 		struct vnodeop_desc *a_desc;
1372 		struct vnode * a_dvp;
1373 		struct vnode * a_vp;
1374 		struct componentname * a_cnp;
1375 	} */ *ap = v;
1376 	struct vnode *vp = ap->a_vp;
1377 	struct vnode *dvp = ap->a_dvp;
1378 	struct componentname *cnp = ap->a_cnp;
1379 	struct nfsnode *np = VTONFS(vp);
1380 	int error = 0;
1381 	struct vattr vattr;
1382 
1383 #ifndef DIAGNOSTIC
1384 	if ((cnp->cn_flags & HASBUF) == 0)
1385 		panic("nfs_remove: no name");
1386 	if (vp->v_usecount < 1)
1387 		panic("nfs_remove: bad v_usecount");
1388 #endif
1389 	if (vp->v_type == VDIR)
1390 		error = EPERM;
1391 	else if (vp->v_usecount == 1 || (np->n_sillyrename &&
1392 	    VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1393 	    vattr.va_nlink > 1)) {
1394 		/*
1395 		 * Purge the name cache so that the chance of a lookup for
1396 		 * the name succeeding while the remove is in progress is
1397 		 * minimized. Without node locking it can still happen, such
1398 		 * that an I/O op returns ESTALE, but since you get this if
1399 		 * another host removes the file..
1400 		 */
1401 		cache_purge(vp);
1402 		/*
1403 		 * throw away biocache buffers, mainly to avoid
1404 		 * unnecessary delayed writes later.
1405 		 */
1406 		error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1407 		/* Do the rpc */
1408 		if (error != EINTR)
1409 			error = nfs_removerpc(dvp, cnp->cn_nameptr,
1410 				cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1411 		/*
1412 		 * Kludge City: If the first reply to the remove rpc is lost..
1413 		 *   the reply to the retransmitted request will be ENOENT
1414 		 *   since the file was in fact removed
1415 		 *   Therefore, we cheat and return success.
1416 		 */
1417 		if (error == ENOENT)
1418 			error = 0;
1419 	} else if (!np->n_sillyrename)
1420 		error = nfs_sillyrename(dvp, vp, cnp);
1421 	pool_put(&namei_pool, cnp->cn_pnbuf);
1422 	np->n_attrstamp = 0;
1423 	vrele(dvp);
1424 	vrele(vp);
1425 
1426 	VN_KNOTE(vp, NOTE_DELETE);
1427 	VN_KNOTE(dvp, NOTE_WRITE);
1428 
1429 	return (error);
1430 }
1431 
1432 /*
1433  * nfs file remove rpc called from nfs_inactive
1434  */
1435 int
nfs_removeit(sp)1436 nfs_removeit(sp)
1437 	struct sillyrename *sp;
1438 {
1439 
1440 	return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1441 		(struct proc *)0));
1442 }
1443 
1444 /*
1445  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1446  */
1447 int
nfs_removerpc(dvp,name,namelen,cred,proc)1448 nfs_removerpc(dvp, name, namelen, cred, proc)
1449 	struct vnode *dvp;
1450 	char *name;
1451 	int namelen;
1452 	struct ucred *cred;
1453 	struct proc *proc;
1454 {
1455 	u_int32_t *tl;
1456 	caddr_t cp;
1457 	int32_t t1, t2;
1458 	caddr_t bpos, dpos, cp2;
1459 	int error = 0, wccflag = NFSV3_WCCRATTR;
1460 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1461 	int v3 = NFS_ISV3(dvp);
1462 
1463 	nfsstats.rpccnt[NFSPROC_REMOVE]++;
1464 	nfsm_reqhead(dvp, NFSPROC_REMOVE,
1465 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1466 	nfsm_fhtom(dvp, v3);
1467 	nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1468 	nfsm_request(dvp, NFSPROC_REMOVE, proc, cred);
1469 	if (v3)
1470 		nfsm_wcc_data(dvp, wccflag);
1471 	nfsm_reqdone;
1472 	VTONFS(dvp)->n_flag |= NMODIFIED;
1473 	if (!wccflag)
1474 		VTONFS(dvp)->n_attrstamp = 0;
1475 	return (error);
1476 }
1477 
1478 /*
1479  * nfs file rename call
1480  */
1481 int
nfs_rename(v)1482 nfs_rename(v)
1483 	void *v;
1484 {
1485 	struct vop_rename_args  /* {
1486 		struct vnode *a_fdvp;
1487 		struct vnode *a_fvp;
1488 		struct componentname *a_fcnp;
1489 		struct vnode *a_tdvp;
1490 		struct vnode *a_tvp;
1491 		struct componentname *a_tcnp;
1492 	} */ *ap = v;
1493 	struct vnode *fvp = ap->a_fvp;
1494 	struct vnode *tvp = ap->a_tvp;
1495 	struct vnode *fdvp = ap->a_fdvp;
1496 	struct vnode *tdvp = ap->a_tdvp;
1497 	struct componentname *tcnp = ap->a_tcnp;
1498 	struct componentname *fcnp = ap->a_fcnp;
1499 	int error;
1500 
1501 #ifndef DIAGNOSTIC
1502 	if ((tcnp->cn_flags & HASBUF) == 0 ||
1503 	    (fcnp->cn_flags & HASBUF) == 0)
1504 		panic("nfs_rename: no name");
1505 #endif
1506 	/* Check for cross-device rename */
1507 	if ((fvp->v_mount != tdvp->v_mount) ||
1508 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
1509 		error = EXDEV;
1510 		goto out;
1511 	}
1512 
1513 	/*
1514 	 * If the tvp exists and is in use, sillyrename it before doing the
1515 	 * rename of the new file over it.
1516 	 */
1517 	if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1518 	    tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1519 		VN_KNOTE(tvp, NOTE_DELETE);
1520 		vrele(tvp);
1521 		tvp = NULL;
1522 	}
1523 
1524 	error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1525 		tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1526 		tcnp->cn_proc);
1527 
1528 	VN_KNOTE(fdvp, NOTE_WRITE);
1529 	VN_KNOTE(tdvp, NOTE_WRITE);
1530 
1531 	if (fvp->v_type == VDIR) {
1532 		if (tvp != NULL && tvp->v_type == VDIR)
1533 			cache_purge(tdvp);
1534 		cache_purge(fdvp);
1535 	}
1536 out:
1537 	if (tdvp == tvp)
1538 		vrele(tdvp);
1539 	else
1540 		vput(tdvp);
1541 	if (tvp)
1542 		vput(tvp);
1543 	vrele(fdvp);
1544 	vrele(fvp);
1545 	/*
1546 	 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1547 	 */
1548 	if (error == ENOENT)
1549 		error = 0;
1550 	return (error);
1551 }
1552 
1553 /*
1554  * nfs file rename rpc called from nfs_remove() above
1555  */
1556 int
nfs_renameit(sdvp,scnp,sp)1557 nfs_renameit(sdvp, scnp, sp)
1558 	struct vnode *sdvp;
1559 	struct componentname *scnp;
1560 	struct sillyrename *sp;
1561 {
1562 	return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1563 		sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
1564 }
1565 
1566 /*
1567  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1568  */
1569 int
nfs_renamerpc(fdvp,fnameptr,fnamelen,tdvp,tnameptr,tnamelen,cred,proc)1570 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
1571 	struct vnode *fdvp;
1572 	char *fnameptr;
1573 	int fnamelen;
1574 	struct vnode *tdvp;
1575 	char *tnameptr;
1576 	int tnamelen;
1577 	struct ucred *cred;
1578 	struct proc *proc;
1579 {
1580 	u_int32_t *tl;
1581 	caddr_t cp;
1582 	int32_t t1, t2;
1583 	caddr_t bpos, dpos, cp2;
1584 	int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1585 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1586 	int v3 = NFS_ISV3(fdvp);
1587 
1588 	nfsstats.rpccnt[NFSPROC_RENAME]++;
1589 	nfsm_reqhead(fdvp, NFSPROC_RENAME,
1590 		(NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1591 		nfsm_rndup(tnamelen));
1592 	nfsm_fhtom(fdvp, v3);
1593 	nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1594 	nfsm_fhtom(tdvp, v3);
1595 	nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1596 	nfsm_request(fdvp, NFSPROC_RENAME, proc, cred);
1597 	if (v3) {
1598 		nfsm_wcc_data(fdvp, fwccflag);
1599 		nfsm_wcc_data(tdvp, twccflag);
1600 	}
1601 	nfsm_reqdone;
1602 	VTONFS(fdvp)->n_flag |= NMODIFIED;
1603 	VTONFS(tdvp)->n_flag |= NMODIFIED;
1604 	if (!fwccflag)
1605 		VTONFS(fdvp)->n_attrstamp = 0;
1606 	if (!twccflag)
1607 		VTONFS(tdvp)->n_attrstamp = 0;
1608 	return (error);
1609 }
1610 
1611 /*
1612  * nfs hard link create call
1613  */
1614 int
nfs_link(v)1615 nfs_link(v)
1616 	void *v;
1617 {
1618 	struct vop_link_args /* {
1619 		struct vnode *a_dvp;
1620 		struct vnode *a_vp;
1621 		struct componentname *a_cnp;
1622 	} */ *ap = v;
1623 	struct vnode *vp = ap->a_vp;
1624 	struct vnode *dvp = ap->a_dvp;
1625 	struct componentname *cnp = ap->a_cnp;
1626 	u_int32_t *tl;
1627 	caddr_t cp;
1628 	int32_t t1, t2;
1629 	caddr_t bpos, dpos, cp2;
1630 	int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1631 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1632 	int v3;
1633 
1634 	if (dvp->v_mount != vp->v_mount) {
1635 		pool_put(&namei_pool, cnp->cn_pnbuf);
1636 		if (vp == dvp)
1637 			vrele(dvp);
1638 		else
1639 			vput(dvp);
1640 		return (EXDEV);
1641 	}
1642 
1643 	/*
1644 	 * Push all writes to the server, so that the attribute cache
1645 	 * doesn't get "out of sync" with the server.
1646 	 * XXX There should be a better way!
1647 	 */
1648 	VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1649 
1650 	v3 = NFS_ISV3(vp);
1651 	nfsstats.rpccnt[NFSPROC_LINK]++;
1652 	nfsm_reqhead(vp, NFSPROC_LINK,
1653 		NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1654 	nfsm_fhtom(vp, v3);
1655 	nfsm_fhtom(dvp, v3);
1656 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1657 	nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1658 	if (v3) {
1659 		nfsm_postop_attr(vp, attrflag);
1660 		nfsm_wcc_data(dvp, wccflag);
1661 	}
1662 	nfsm_reqdone;
1663 	pool_put(&namei_pool, cnp->cn_pnbuf);
1664 	VTONFS(dvp)->n_flag |= NMODIFIED;
1665 	if (!attrflag)
1666 		VTONFS(vp)->n_attrstamp = 0;
1667 	if (!wccflag)
1668 		VTONFS(dvp)->n_attrstamp = 0;
1669 
1670 	VN_KNOTE(vp, NOTE_LINK);
1671 	VN_KNOTE(dvp, NOTE_WRITE);
1672 	vput(dvp);
1673 	/*
1674 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1675 	 */
1676 	if (error == EEXIST)
1677 		error = 0;
1678 	return (error);
1679 }
1680 
1681 /*
1682  * nfs symbolic link create call
1683  */
1684 int
nfs_symlink(v)1685 nfs_symlink(v)
1686 	void *v;
1687 {
1688 	struct vop_symlink_args /* {
1689 		struct vnode *a_dvp;
1690 		struct vnode **a_vpp;
1691 		struct componentname *a_cnp;
1692 		struct vattr *a_vap;
1693 		char *a_target;
1694 	} */ *ap = v;
1695 	struct vnode *dvp = ap->a_dvp;
1696 	struct vattr *vap = ap->a_vap;
1697 	struct componentname *cnp = ap->a_cnp;
1698 	struct nfsv2_sattr *sp;
1699 	u_int32_t *tl;
1700 	caddr_t cp;
1701 	int32_t t1, t2;
1702 	caddr_t bpos, dpos, cp2;
1703 	int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1704 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1705 	struct vnode *newvp = (struct vnode *)0;
1706 	int v3 = NFS_ISV3(dvp);
1707 
1708 	nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1709 	slen = strlen(ap->a_target);
1710 	nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1711 	    nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1712 	nfsm_fhtom(dvp, v3);
1713 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1714 	if (v3)
1715 		nfsm_v3attrbuild(vap, FALSE);
1716 	nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1717 	if (!v3) {
1718 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1719 		sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1720 		sp->sa_uid = nfs_xdrneg1;
1721 		sp->sa_gid = nfs_xdrneg1;
1722 		sp->sa_size = nfs_xdrneg1;
1723 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1724 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1725 	}
1726 	nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1727 	if (v3) {
1728 		if (!error)
1729 			nfsm_mtofh(dvp, newvp, v3, gotvp);
1730 		nfsm_wcc_data(dvp, wccflag);
1731 	}
1732 	nfsm_reqdone;
1733 	if (newvp)
1734 		vrele(newvp);
1735 	pool_put(&namei_pool, cnp->cn_pnbuf);
1736 	VTONFS(dvp)->n_flag |= NMODIFIED;
1737 	if (!wccflag)
1738 		VTONFS(dvp)->n_attrstamp = 0;
1739 	VN_KNOTE(dvp, NOTE_WRITE);
1740 	vrele(dvp);
1741 	/*
1742 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1743 	 */
1744 	if (error == EEXIST)
1745 		error = 0;
1746 	return (error);
1747 }
1748 
1749 /*
1750  * nfs make dir call
1751  */
1752 int
nfs_mkdir(v)1753 nfs_mkdir(v)
1754 	void *v;
1755 {
1756 	struct vop_mkdir_args /* {
1757 		struct vnode *a_dvp;
1758 		struct vnode **a_vpp;
1759 		struct componentname *a_cnp;
1760 		struct vattr *a_vap;
1761 	} */ *ap = v;
1762 	struct vnode *dvp = ap->a_dvp;
1763 	struct vattr *vap = ap->a_vap;
1764 	struct componentname *cnp = ap->a_cnp;
1765 	struct nfsv2_sattr *sp;
1766 	u_int32_t *tl;
1767 	caddr_t cp;
1768 	int32_t t1, t2;
1769 	int len;
1770 	struct nfsnode *np = (struct nfsnode *)0;
1771 	struct vnode *newvp = (struct vnode *)0;
1772 	caddr_t bpos, dpos, cp2;
1773 	int error = 0, wccflag = NFSV3_WCCRATTR;
1774 	int gotvp = 0;
1775 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1776 	int v3 = NFS_ISV3(dvp);
1777 
1778 	len = cnp->cn_namelen;
1779 	nfsstats.rpccnt[NFSPROC_MKDIR]++;
1780 	nfsm_reqhead(dvp, NFSPROC_MKDIR,
1781 	  NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
1782 	nfsm_fhtom(dvp, v3);
1783 	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1784 	if (v3) {
1785 		nfsm_v3attrbuild(vap, FALSE);
1786 	} else {
1787 		nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1788 		sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1789 		sp->sa_uid = nfs_xdrneg1;
1790 		sp->sa_gid = nfs_xdrneg1;
1791 		sp->sa_size = nfs_xdrneg1;
1792 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1793 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1794 	}
1795 	nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1796 	if (!error)
1797 		nfsm_mtofh(dvp, newvp, v3, gotvp);
1798 	if (v3)
1799 		nfsm_wcc_data(dvp, wccflag);
1800 	nfsm_reqdone;
1801 	VTONFS(dvp)->n_flag |= NMODIFIED;
1802 	if (!wccflag)
1803 		VTONFS(dvp)->n_attrstamp = 0;
1804 	/*
1805 	 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1806 	 * if we can succeed in looking up the directory.
1807 	 */
1808 	if (error == EEXIST || (!error && !gotvp)) {
1809 		if (newvp) {
1810 			vrele(newvp);
1811 			newvp = (struct vnode *)0;
1812 		}
1813 		error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1814 			cnp->cn_proc, &np);
1815 		if (!error) {
1816 			newvp = NFSTOV(np);
1817 			if (newvp->v_type != VDIR)
1818 				error = EEXIST;
1819 		}
1820 	}
1821 	if (error) {
1822 		if (newvp)
1823 			vrele(newvp);
1824 	} else {
1825 		VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
1826 		*ap->a_vpp = newvp;
1827 	}
1828 	pool_put(&namei_pool, cnp->cn_pnbuf);
1829 	vrele(dvp);
1830 	return (error);
1831 }
1832 
1833 /*
1834  * nfs remove directory call
1835  */
1836 int
nfs_rmdir(v)1837 nfs_rmdir(v)
1838 	void *v;
1839 {
1840 	struct vop_rmdir_args /* {
1841 		struct vnode *a_dvp;
1842 		struct vnode *a_vp;
1843 		struct componentname *a_cnp;
1844 	} */ *ap = v;
1845 	struct vnode *vp = ap->a_vp;
1846 	struct vnode *dvp = ap->a_dvp;
1847 	struct componentname *cnp = ap->a_cnp;
1848 	u_int32_t *tl;
1849 	caddr_t cp;
1850 	int32_t t1, t2;
1851 	caddr_t bpos, dpos, cp2;
1852 	int error = 0, wccflag = NFSV3_WCCRATTR;
1853 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1854 	int v3 = NFS_ISV3(dvp);
1855 
1856 	if (dvp == vp) {
1857 		vrele(dvp);
1858 		vrele(dvp);
1859 		pool_put(&namei_pool, cnp->cn_pnbuf);
1860 		return (EINVAL);
1861 	}
1862 	nfsstats.rpccnt[NFSPROC_RMDIR]++;
1863 	nfsm_reqhead(dvp, NFSPROC_RMDIR,
1864 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1865 	nfsm_fhtom(dvp, v3);
1866 	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1867 	nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1868 	if (v3)
1869 		nfsm_wcc_data(dvp, wccflag);
1870 	nfsm_reqdone;
1871 	pool_put(&namei_pool, cnp->cn_pnbuf);
1872 	VTONFS(dvp)->n_flag |= NMODIFIED;
1873 	if (!wccflag)
1874 		VTONFS(dvp)->n_attrstamp = 0;
1875 
1876 	VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
1877 	VN_KNOTE(vp, NOTE_DELETE);
1878 
1879 	cache_purge(dvp);
1880 	cache_purge(vp);
1881 	vrele(vp);
1882 	vrele(dvp);
1883 	/*
1884 	 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1885 	 */
1886 	if (error == ENOENT)
1887 		error = 0;
1888 	return (error);
1889 }
1890 
1891 
1892 /*
1893  * The readdir logic below has a big design bug. It stores the NFS cookie in
1894  * the returned uio->uio_offset but does not store the verifier (it cannot).
1895  * Instead, the code stores the verifier in the nfsnode and applies that
1896  * verifies to all cookies, no matter what verifier was originally with
1897  * the cookie.
1898  *
1899  * From a practical standpoint, this is not a problem since almost all
1900  * NFS servers do not change the validity of cookies across deletes
1901  * and inserts.
1902  */
1903 
1904 struct nfs_dirent {
1905 	u_int32_t cookie[2];
1906 	struct dirent dirent;
1907 };
1908 
1909 #define	NFS_DIRHDSIZ    (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1))
1910 #define NFS_DIRENT_OVERHEAD  offsetof(struct nfs_dirent, dirent)
1911 
1912 /*
1913  * nfs readdir call
1914  */
1915 int
nfs_readdir(v)1916 nfs_readdir(v)
1917 	void *v;
1918 {
1919 	struct vop_readdir_args /* {
1920 		struct vnode *a_vp;
1921 		struct uio *a_uio;
1922 		struct ucred *a_cred;
1923 		int *a_eofflag;
1924 		u_long **a_cookies;
1925 		int *a_ncookies;
1926 	} */ *ap = v;
1927 	struct vnode *vp = ap->a_vp;
1928 	struct nfsnode *np = VTONFS(vp);
1929 	struct uio *uio = ap->a_uio;
1930 	int tresid, error;
1931 	struct vattr vattr;
1932 	u_long *cookies = NULL;
1933 	int ncookies = 0, cnt;
1934 	u_int64_t  newoff = uio->uio_offset;
1935 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1936 	struct uio readdir_uio;
1937 	struct iovec readdir_iovec;
1938 	struct proc * p = uio->uio_procp;
1939 	int done = 0, eof = 0;
1940 	struct ucred *cred = ap->a_cred;
1941 	void *data;
1942 
1943 	if (vp->v_type != VDIR)
1944 		return (EPERM);
1945 	/*
1946 	 * First, check for hit on the EOF offset cache
1947 	 */
1948 	if (np->n_direofoffset != 0 &&
1949 	    uio->uio_offset == np->n_direofoffset) {
1950 		if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1951 		    np->n_mtime == vattr.va_mtime.tv_sec) {
1952 			nfsstats.direofcache_hits++;
1953 			*ap->a_eofflag = 1;
1954 			return (0);
1955 		}
1956 	}
1957 
1958 	if (uio->uio_resid < NFS_FABLKSIZE)
1959 		return (EINVAL);
1960 
1961 	tresid = uio->uio_resid;
1962 
1963 	if (uio->uio_rw != UIO_READ)
1964 		return (EINVAL);
1965 
1966 	if (ap->a_cookies) {
1967 		ncookies = uio->uio_resid / 20;
1968 
1969 		MALLOC(cookies, u_long *, sizeof(*cookies) * ncookies,
1970 		       M_TEMP, M_WAITOK);
1971 		*ap->a_ncookies = ncookies;
1972 		*ap->a_cookies = cookies;
1973 	}
1974 
1975 	if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
1976 		(void)nfs_fsinfo(nmp, vp, cred, p);
1977 
1978 	cnt = 5;
1979 
1980 	MALLOC(data, void *, NFS_DIRBLKSIZ, M_TEMP,
1981 	    M_WAITOK);
1982 
1983 	do {
1984 		struct nfs_dirent *ndp = data;
1985 
1986 		readdir_iovec.iov_len = NFS_DIRBLKSIZ;
1987 		readdir_iovec.iov_base = data;
1988 		readdir_uio.uio_offset = newoff;
1989 		readdir_uio.uio_iov = &readdir_iovec;
1990 		readdir_uio.uio_iovcnt = 1;
1991 		readdir_uio.uio_segflg = UIO_SYSSPACE;
1992 		readdir_uio.uio_rw = UIO_READ;
1993 		readdir_uio.uio_resid = NFS_DIRBLKSIZ;
1994 		readdir_uio.uio_procp = curproc;
1995 
1996 		if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
1997 			error = nfs_readdirplusrpc(vp, &readdir_uio, cred,
1998 			    &eof);
1999 			if (error == NFSERR_NOTSUPP)
2000 				nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
2001 		}
2002 		if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
2003 			error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof);
2004 
2005 		if (error == NFSERR_BAD_COOKIE)
2006 			error = EINVAL;
2007 
2008 		while (error == 0 &&
2009 		    (ap->a_cookies == NULL || ncookies != 0) &&
2010 		    ndp < (struct nfs_dirent *)readdir_iovec.iov_base) {
2011 			struct dirent *dp = &ndp->dirent;
2012 			int reclen = dp->d_reclen;
2013 
2014 			dp->d_reclen -= NFS_DIRENT_OVERHEAD;
2015 
2016 			if (uio->uio_resid < dp->d_reclen) {
2017 				done = 1;
2018 				break;
2019 			}
2020 
2021 			error = uiomove((caddr_t)dp, dp->d_reclen, uio);
2022 			if (error)
2023 				break;
2024 
2025 			newoff = fxdr_hyper(&ndp->cookie[0]);
2026 
2027 			if (ap->a_cookies != NULL) {
2028 				*cookies = newoff;
2029 				cookies++;
2030 				ncookies--;
2031 			}
2032 
2033 			ndp = (struct nfs_dirent *)((u_int8_t *)ndp + reclen);
2034 		}
2035 	} while (!error && !done && !eof && cnt--);
2036 
2037 	FREE(data, M_TEMP);
2038 	data = NULL;
2039 
2040 	if (ap->a_cookies) {
2041 		if (error) {
2042 			FREE(*ap->a_cookies, M_TEMP);
2043 			*ap->a_cookies = NULL;
2044 			*ap->a_ncookies = 0;
2045 		} else {
2046 			*ap->a_ncookies -= ncookies;
2047 		}
2048 	}
2049 
2050 	if (!error)
2051 		uio->uio_offset = newoff;
2052 
2053 	if (!error && (eof || uio->uio_resid == tresid)) {
2054 		nfsstats.direofcache_misses++;
2055 		*ap->a_eofflag = 1;
2056 		return (0);
2057 	}
2058 
2059 	*ap->a_eofflag = 0;
2060 	return (error);
2061 }
2062 
2063 
2064 /*
2065  * The function below stuff the cookies in after the name
2066  */
2067 
2068 /*
2069  * Readdir rpc call.
2070  */
2071 int
nfs_readdirrpc(struct vnode * vp,struct uio * uiop,struct ucred * cred,int * end_of_directory)2072 nfs_readdirrpc(struct vnode *vp,
2073     struct uio *uiop,
2074     struct ucred *cred,
2075     int *end_of_directory)
2076 {
2077 	int len, left;
2078 	struct nfs_dirent *ndp = NULL;
2079 	struct dirent *dp = NULL;
2080 	u_int32_t *tl;
2081 	caddr_t cp;
2082 	int32_t t1, t2;
2083 	caddr_t bpos, dpos, cp2;
2084 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2085 	nfsuint64 cookie;
2086 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2087 	struct nfsnode *dnp = VTONFS(vp);
2088 	u_quad_t fileno;
2089 	int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2090 	int attrflag;
2091 	int v3 = NFS_ISV3(vp);
2092 
2093 #ifndef DIAGNOSTIC
2094 	if (uiop->uio_iovcnt != 1 ||
2095 		(uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2096 		panic("nfs readdirrpc bad uio");
2097 #endif
2098 
2099 	txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2100 
2101 	/*
2102 	 * Loop around doing readdir rpc's of size nm_readdirsize
2103 	 * truncated to a multiple of NFS_READDIRBLKSIZ.
2104 	 * The stopping criteria is EOF or buffer full.
2105 	 */
2106 	while (more_dirs && bigenough) {
2107 		nfsstats.rpccnt[NFSPROC_READDIR]++;
2108 		nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2109 			NFSX_READDIR(v3));
2110 		nfsm_fhtom(vp, v3);
2111 		if (v3) {
2112 			nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2113 			*tl++ = cookie.nfsuquad[0];
2114 			*tl++ = cookie.nfsuquad[1];
2115 			if (cookie.nfsuquad[0] == 0 &&
2116 			    cookie.nfsuquad[1] == 0) {
2117 				*tl++ = 0;
2118 				*tl++ = 0;
2119 			} else {
2120 				*tl++ = dnp->n_cookieverf.nfsuquad[0];
2121 				*tl++ = dnp->n_cookieverf.nfsuquad[1];
2122 			}
2123 		} else {
2124 			nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2125 			*tl++ = cookie.nfsuquad[1];
2126 		}
2127 		*tl = txdr_unsigned(nmp->nm_readdirsize);
2128 		nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
2129 		if (v3) {
2130 			nfsm_postop_attr(vp, attrflag);
2131 			if (!error) {
2132 				nfsm_dissect(tl, u_int32_t *,
2133 				    2 * NFSX_UNSIGNED);
2134 				dnp->n_cookieverf.nfsuquad[0] = *tl++;
2135 				dnp->n_cookieverf.nfsuquad[1] = *tl;
2136 			} else {
2137 				m_freem(mrep);
2138 				goto nfsmout;
2139 			}
2140 		}
2141 		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2142 		more_dirs = fxdr_unsigned(int, *tl);
2143 
2144 		/* loop thru the dir entries, doctoring them to 4bsd form */
2145 		while (more_dirs && bigenough) {
2146 			if (v3) {
2147 				nfsm_dissect(tl, u_int32_t *,
2148 				    3 * NFSX_UNSIGNED);
2149 				fileno = fxdr_hyper(tl);
2150 				len = fxdr_unsigned(int, *(tl + 2));
2151 			} else {
2152 				nfsm_dissect(tl, u_int32_t *,
2153 				    2 * NFSX_UNSIGNED);
2154 				fileno = fxdr_unsigned(u_quad_t, *tl++);
2155 				len = fxdr_unsigned(int, *tl);
2156 			}
2157 			if (len <= 0 || len > NFS_MAXNAMLEN) {
2158 				error = EBADRPC;
2159 				m_freem(mrep);
2160 				goto nfsmout;
2161 			}
2162 			tlen = nfsm_rndup(len + 1);
2163 			left = NFS_READDIRBLKSIZ - blksiz;
2164 			if ((tlen + NFS_DIRHDSIZ) > left) {
2165 				caddr_t tmp = left +
2166 				    (caddr_t)uiop->uio_iov->iov_base;
2167 
2168 				dp->d_reclen += left;
2169 				uiop->uio_iov->iov_base = tmp;
2170 				uiop->uio_iov->iov_len -= left;
2171 				uiop->uio_resid -= left;
2172 				blksiz = 0;
2173 			}
2174 			if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2175 				bigenough = 0;
2176 			if (bigenough) {
2177 				caddr_t tmp;
2178 
2179 				ndp = (struct nfs_dirent *)
2180 				    uiop->uio_iov->iov_base;
2181 				dp = &ndp->dirent;
2182 				dp->d_fileno = (int)fileno;
2183 				dp->d_namlen = len;
2184 				dp->d_reclen = tlen + NFS_DIRHDSIZ;
2185 				dp->d_type = DT_UNKNOWN;
2186 				blksiz += dp->d_reclen;
2187 				if (blksiz == NFS_READDIRBLKSIZ)
2188 					blksiz = 0;
2189 				uiop->uio_resid -= NFS_DIRHDSIZ;
2190 				uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2191 				uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2192 				nfsm_mtouio(uiop, len);
2193 				cp = uiop->uio_iov->iov_base;
2194 				tlen -= len;
2195 				*cp = '\0';	/* null terminate */
2196 				tmp = (caddr_t)uiop->uio_iov->iov_base + tlen;
2197 				uiop->uio_iov->iov_base = tmp;
2198 				uiop->uio_iov->iov_len -= tlen;
2199 				uiop->uio_resid -= tlen;
2200 			} else
2201 				nfsm_adv(nfsm_rndup(len));
2202 			if (v3) {
2203 				nfsm_dissect(tl, u_int32_t *,
2204 				    3 * NFSX_UNSIGNED);
2205 			} else {
2206 				nfsm_dissect(tl, u_int32_t *,
2207 				    2 * NFSX_UNSIGNED);
2208 			}
2209 			if (bigenough) {
2210 				if (v3) {
2211 					ndp->cookie[0] = cookie.nfsuquad[0] =
2212 					    *tl++;
2213 				} else
2214 					ndp->cookie[0] = 0;
2215 
2216 				ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2217 			} else if (v3)
2218 				tl += 2;
2219 			else
2220 				tl++;
2221 			more_dirs = fxdr_unsigned(int, *tl);
2222 		}
2223 		/*
2224 		 * If at end of rpc data, get the eof boolean
2225 		 */
2226 		if (!more_dirs) {
2227 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2228 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
2229 		}
2230 		m_freem(mrep);
2231 	}
2232 	/*
2233 	 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2234 	 * by increasing d_reclen for the last record.
2235 	 */
2236 	if (blksiz > 0) {
2237 		left = NFS_READDIRBLKSIZ - blksiz;
2238 		dp->d_reclen += left;
2239 		uiop->uio_iov->iov_base += left;
2240 		uiop->uio_iov->iov_len -= left;
2241 		uiop->uio_resid -= left;
2242 	}
2243 
2244 	/*
2245 	 * We are now either at the end of the directory or have filled the
2246 	 * block.
2247 	 */
2248 	if (bigenough) {
2249 		dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2250 		if (end_of_directory) *end_of_directory = 1;
2251 	} else {
2252 		if (uiop->uio_resid > 0)
2253 			printf("EEK! readdirrpc resid > 0\n");
2254 	}
2255 
2256 nfsmout:
2257 	return (error);
2258 }
2259 
2260 /*
2261  * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2262  */
2263 int
nfs_readdirplusrpc(struct vnode * vp,struct uio * uiop,struct ucred * cred,int * end_of_directory)2264 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2265     int *end_of_directory)
2266 {
2267 	int len, left;
2268 	struct nfs_dirent *ndirp = NULL;
2269 	struct dirent *dp = NULL;
2270 	u_int32_t *tl;
2271 	caddr_t cp;
2272 	int32_t t1, t2;
2273 	struct vnode *newvp;
2274 	caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2275 	struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2276 	struct nameidata nami, *ndp = &nami;
2277 	struct componentname *cnp = &ndp->ni_cnd;
2278 	nfsuint64 cookie;
2279 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2280 	struct nfsnode *dnp = VTONFS(vp), *np;
2281 	nfsfh_t *fhp;
2282 	u_quad_t fileno;
2283 	int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2284 	int attrflag, fhsize;
2285 
2286 #ifndef DIAGNOSTIC
2287 	if (uiop->uio_iovcnt != 1 ||
2288 		(uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2289 		panic("nfs readdirplusrpc bad uio");
2290 #endif
2291 	ndp->ni_dvp = vp;
2292 	newvp = NULLVP;
2293 
2294 	txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2295 
2296         /*
2297 	 * Loop around doing readdir rpc's of size nm_readdirsize
2298 	 * truncated to a multiple of NFS_READDIRBLKSIZ.
2299 	 * The stopping criteria is EOF or buffer full.
2300 	 */
2301 	while (more_dirs && bigenough) {
2302 		nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2303 		nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2304 			NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2305 		nfsm_fhtom(vp, 1);
2306  		nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2307 		*tl++ = cookie.nfsuquad[0];
2308 		*tl++ = cookie.nfsuquad[1];
2309 		if (cookie.nfsuquad[0] == 0 &&
2310 		    cookie.nfsuquad[1] == 0) {
2311 			*tl++ = 0;
2312 			*tl++ = 0;
2313 		} else {
2314 			*tl++ = dnp->n_cookieverf.nfsuquad[0];
2315 			*tl++ = dnp->n_cookieverf.nfsuquad[1];
2316 		}
2317 		*tl++ = txdr_unsigned(nmp->nm_readdirsize);
2318 		*tl = txdr_unsigned(nmp->nm_rsize);
2319 		nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2320 		nfsm_postop_attr(vp, attrflag);
2321 		if (error) {
2322 			m_freem(mrep);
2323 			goto nfsmout;
2324 		}
2325 		nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2326 		dnp->n_cookieverf.nfsuquad[0] = *tl++;
2327 		dnp->n_cookieverf.nfsuquad[1] = *tl++;
2328 		more_dirs = fxdr_unsigned(int, *tl);
2329 
2330 		/* loop thru the dir entries, doctoring them to 4bsd form */
2331 		while (more_dirs && bigenough) {
2332 			nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2333 			fileno = fxdr_hyper(tl);
2334 			len = fxdr_unsigned(int, *(tl + 2));
2335 			if (len <= 0 || len > NFS_MAXNAMLEN) {
2336 				error = EBADRPC;
2337 				m_freem(mrep);
2338 				goto nfsmout;
2339 			}
2340 			tlen = nfsm_rndup(len + 1);
2341 			left = NFS_READDIRBLKSIZ - blksiz;
2342 			if ((tlen + NFS_DIRHDSIZ) > left) {
2343 				dp->d_reclen += left;
2344 				uiop->uio_iov->iov_base += left;
2345 				uiop->uio_iov->iov_len -= left;
2346 				uiop->uio_resid -= left;
2347 				blksiz = 0;
2348 			}
2349 			if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2350 				bigenough = 0;
2351 			if (bigenough) {
2352 				ndirp = (struct nfs_dirent *)
2353 				    uiop->uio_iov->iov_base;
2354 				dp = &ndirp->dirent;
2355 				dp->d_fileno = (int)fileno;
2356 				dp->d_namlen = len;
2357 				dp->d_reclen = tlen + NFS_DIRHDSIZ;
2358 				dp->d_type = DT_UNKNOWN;
2359 				blksiz += dp->d_reclen;
2360 				if (blksiz == NFS_READDIRBLKSIZ)
2361 					blksiz = 0;
2362 				uiop->uio_resid -= NFS_DIRHDSIZ;
2363 				uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2364 				uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2365 				cnp->cn_nameptr = uiop->uio_iov->iov_base;
2366 				cnp->cn_namelen = len;
2367 				nfsm_mtouio(uiop, len);
2368 				cp = uiop->uio_iov->iov_base;
2369 				tlen -= len;
2370 				*cp = '\0';
2371 				uiop->uio_iov->iov_base += tlen;
2372 				uiop->uio_iov->iov_len -= tlen;
2373 				uiop->uio_resid -= tlen;
2374 			} else
2375 				nfsm_adv(nfsm_rndup(len));
2376 			nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2377 			if (bigenough) {
2378 				ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++;
2379 				ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2380 			} else
2381 				tl += 2;
2382 
2383 			/*
2384 			 * Since the attributes are before the file handle
2385 			 * (sigh), we must skip over the attributes and then
2386 			 * come back and get them.
2387 			 */
2388 			attrflag = fxdr_unsigned(int, *tl);
2389 			if (attrflag) {
2390 			    dpossav1 = dpos;
2391 			    mdsav1 = md;
2392 			    nfsm_adv(NFSX_V3FATTR);
2393 			    nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2394 			    doit = fxdr_unsigned(int, *tl);
2395 			    if (doit) {
2396 				nfsm_getfh(fhp, fhsize, 1);
2397 				if (NFS_CMPFH(dnp, fhp, fhsize)) {
2398 				    VREF(vp);
2399 				    newvp = vp;
2400 				    np = dnp;
2401 				} else {
2402 				    error = nfs_nget(vp->v_mount, fhp,
2403 					fhsize, &np);
2404 				    if (error)
2405 					doit = 0;
2406 				    else
2407 					newvp = NFSTOV(np);
2408 				}
2409 			    }
2410 			    if (doit) {
2411 				dpossav2 = dpos;
2412 				dpos = dpossav1;
2413 				mdsav2 = md;
2414 				md = mdsav1;
2415 				nfsm_loadattr(newvp, (struct vattr *)0);
2416 				dpos = dpossav2;
2417 				md = mdsav2;
2418 				dp->d_type =
2419 				    IFTODT(VTTOIF(np->n_vattr.va_type));
2420 				ndp->ni_vp = newvp;
2421 				cnp->cn_hash = 0;
2422 				for (cp = cnp->cn_nameptr, i = 1; i <= len;
2423 				    i++, cp++)
2424 				    cnp->cn_hash += (unsigned char)*cp * i;
2425 				if (cnp->cn_namelen <= NCHNAMLEN)
2426 				    cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
2427 			    }
2428 			} else {
2429 			    /* Just skip over the file handle */
2430 			    nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2431 			    i = fxdr_unsigned(int, *tl);
2432 			    nfsm_adv(nfsm_rndup(i));
2433 			}
2434 			if (newvp != NULLVP) {
2435 			    vrele(newvp);
2436 			    newvp = NULLVP;
2437 			}
2438 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2439 			more_dirs = fxdr_unsigned(int, *tl);
2440 		}
2441 		/*
2442 		 * If at end of rpc data, get the eof boolean
2443 		 */
2444 		if (!more_dirs) {
2445 			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2446 			more_dirs = (fxdr_unsigned(int, *tl) == 0);
2447 		}
2448 		m_freem(mrep);
2449 	}
2450 	/*
2451 	 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2452 	 * by increasing d_reclen for the last record.
2453 	 */
2454 	if (blksiz > 0) {
2455 		left = NFS_READDIRBLKSIZ - blksiz;
2456 		dp->d_reclen += left;
2457 		uiop->uio_iov->iov_base += left;
2458 		uiop->uio_iov->iov_len -= left;
2459 		uiop->uio_resid -= left;
2460 	}
2461 
2462 	/*
2463 	 * We are now either at the end of the directory or have filled the
2464 	 * block.
2465 	 */
2466 	if (bigenough) {
2467 		dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2468 		if (end_of_directory) *end_of_directory = 1;
2469 	} else {
2470 		if (uiop->uio_resid > 0)
2471 			printf("EEK! readdirplusrpc resid > 0\n");
2472 	}
2473 
2474 nfsmout:
2475 	if (newvp != NULLVP)
2476 		vrele(newvp);
2477 	return (error);
2478 }
2479 
2480 /*
2481  * Silly rename. To make the NFS filesystem that is stateless look a little
2482  * more like the "ufs" a remove of an active vnode is translated to a rename
2483  * to a funny looking filename that is removed by nfs_inactive on the
2484  * nfsnode. There is the potential for another process on a different client
2485  * to create the same funny name between the nfs_lookitup() fails and the
2486  * nfs_rename() completes, but...
2487  */
2488 int
nfs_sillyrename(dvp,vp,cnp)2489 nfs_sillyrename(dvp, vp, cnp)
2490 	struct vnode *dvp, *vp;
2491 	struct componentname *cnp;
2492 {
2493 	struct sillyrename *sp;
2494 	struct nfsnode *np;
2495 	int error;
2496 
2497 	cache_purge(dvp);
2498 	np = VTONFS(vp);
2499 	MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2500 		M_NFSREQ, M_WAITOK);
2501 	sp->s_cred = crdup(cnp->cn_cred);
2502 	sp->s_dvp = dvp;
2503 	VREF(dvp);
2504 
2505 	if (vp->v_type == VDIR) {
2506 #ifdef DIAGNOSTIC
2507 		printf("nfs: sillyrename dir\n");
2508 #endif
2509 		error = EINVAL;
2510 		goto bad;
2511 	}
2512 
2513 	/* Fudge together a funny name */
2514 	sp->s_namlen = snprintf(sp->s_name, sizeof sp->s_name,
2515 	    ".nfsA%05x4.4", cnp->cn_proc->p_pid);
2516 	if (sp->s_namlen > sizeof sp->s_name)
2517 		sp->s_namlen = strlen(sp->s_name);
2518 
2519 	/* Try lookitups until we get one that isn't there */
2520 	while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2521 		cnp->cn_proc, (struct nfsnode **)0) == 0) {
2522 		sp->s_name[4]++;
2523 		if (sp->s_name[4] > 'z') {
2524 			error = EINVAL;
2525 			goto bad;
2526 		}
2527 	}
2528 	error = nfs_renameit(dvp, cnp, sp);
2529 	if (error)
2530 		goto bad;
2531 	error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2532 		cnp->cn_proc, &np);
2533 	np->n_sillyrename = sp;
2534 	return (0);
2535 bad:
2536 	vrele(sp->s_dvp);
2537 	crfree(sp->s_cred);
2538 	FREE((caddr_t)sp, M_NFSREQ);
2539 	return (error);
2540 }
2541 
2542 /*
2543  * Look up a file name and optionally either update the file handle or
2544  * allocate an nfsnode, depending on the value of npp.
2545  * npp == NULL	--> just do the lookup
2546  * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2547  *			handled too
2548  * *npp != NULL --> update the file handle in the vnode
2549  */
2550 int
nfs_lookitup(dvp,name,len,cred,procp,npp)2551 nfs_lookitup(dvp, name, len, cred, procp, npp)
2552 	struct vnode *dvp;
2553 	char *name;
2554 	int len;
2555 	struct ucred *cred;
2556 	struct proc *procp;
2557 	struct nfsnode **npp;
2558 {
2559 	u_int32_t *tl;
2560 	caddr_t cp;
2561 	int32_t t1, t2;
2562 	struct vnode *newvp = (struct vnode *)0;
2563 	struct nfsnode *np, *dnp = VTONFS(dvp);
2564 	caddr_t bpos, dpos, cp2;
2565 	int error = 0, fhlen, attrflag;
2566 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2567 	nfsfh_t *nfhp;
2568 	int v3 = NFS_ISV3(dvp);
2569 
2570 	nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2571 	nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2572 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2573 	nfsm_fhtom(dvp, v3);
2574 	nfsm_strtom(name, len, NFS_MAXNAMLEN);
2575 	nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred);
2576 	if (npp && !error) {
2577 		nfsm_getfh(nfhp, fhlen, v3);
2578 		if (*npp) {
2579 		    np = *npp;
2580 		    if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2581 			free((caddr_t)np->n_fhp, M_NFSBIGFH);
2582 			np->n_fhp = &np->n_fh;
2583 		    } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2584 			np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2585 		    bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2586 		    np->n_fhsize = fhlen;
2587 		    newvp = NFSTOV(np);
2588 		} else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2589 		    VREF(dvp);
2590 		    newvp = dvp;
2591 		} else {
2592 		    error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2593 		    if (error) {
2594 			m_freem(mrep);
2595 			return (error);
2596 		    }
2597 		    newvp = NFSTOV(np);
2598 		}
2599 		if (v3) {
2600 			nfsm_postop_attr(newvp, attrflag);
2601 			if (!attrflag && *npp == NULL) {
2602 				m_freem(mrep);
2603 				vrele(newvp);
2604 				return (ENOENT);
2605 			}
2606 		} else
2607 			nfsm_loadattr(newvp, (struct vattr *)0);
2608 	}
2609 	nfsm_reqdone;
2610 	if (npp && *npp == NULL) {
2611 		if (error) {
2612 			if (newvp)
2613 				vrele(newvp);
2614 		} else
2615 			*npp = np;
2616 	}
2617 	return (error);
2618 }
2619 
2620 /*
2621  * Nfs Version 3 commit rpc
2622  */
2623 int
nfs_commit(vp,offset,cnt,procp)2624 nfs_commit(vp, offset, cnt, procp)
2625 	struct vnode *vp;
2626 	u_quad_t offset;
2627 	int cnt;
2628 	struct proc *procp;
2629 {
2630 	caddr_t cp;
2631 	u_int32_t *tl;
2632 	int32_t t1, t2;
2633 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2634 	caddr_t bpos, dpos, cp2;
2635 	int error = 0, wccflag = NFSV3_WCCRATTR;
2636 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2637 
2638 	if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0)
2639 		return (0);
2640 	nfsstats.rpccnt[NFSPROC_COMMIT]++;
2641 	nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
2642 	nfsm_fhtom(vp, 1);
2643 	nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2644 	txdr_hyper(offset, tl);
2645 	tl += 2;
2646 	*tl = txdr_unsigned(cnt);
2647 	nfsm_request(vp, NFSPROC_COMMIT, procp, VTONFS(vp)->n_wcred);
2648 	nfsm_wcc_data(vp, wccflag);
2649 	if (!error) {
2650 		nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
2651 		if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
2652 			NFSX_V3WRITEVERF)) {
2653 			bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
2654 				NFSX_V3WRITEVERF);
2655 			error = NFSERR_STALEWRITEVERF;
2656 		}
2657 	}
2658 	nfsm_reqdone;
2659 	return (error);
2660 }
2661 
2662 /*
2663  * Kludge City..
2664  * - make nfs_bmap() essentially a no-op that does no translation
2665  * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2666  *   (Maybe I could use the process's page mapping, but I was concerned that
2667  *    Kernel Write might not be enabled and also figured copyout() would do
2668  *    a lot more work than bcopy() and also it currently happens in the
2669  *    context of the swapper process (2).
2670  */
2671 int
nfs_bmap(v)2672 nfs_bmap(v)
2673 	void *v;
2674 {
2675 	struct vop_bmap_args /* {
2676 		struct vnode *a_vp;
2677 		daddr_t  a_bn;
2678 		struct vnode **a_vpp;
2679 		daddr_t *a_bnp;
2680 		int *a_runp;
2681 	} */ *ap = v;
2682 	struct vnode *vp = ap->a_vp;
2683 
2684 	if (ap->a_vpp != NULL)
2685 		*ap->a_vpp = vp;
2686 	if (ap->a_bnp != NULL)
2687 		*ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2688 	return (0);
2689 }
2690 
2691 /*
2692  * Strategy routine.
2693  * For async requests when nfsiod(s) are running, queue the request by
2694  * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2695  * request.
2696  */
2697 int
nfs_strategy(v)2698 nfs_strategy(v)
2699 	void *v;
2700 {
2701 	struct vop_strategy_args *ap = v;
2702 	struct buf *bp = ap->a_bp;
2703 	struct proc *p;
2704 	int error = 0;
2705 
2706 	if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
2707 		panic("nfs physio/async");
2708 	if (bp->b_flags & B_ASYNC)
2709 		p = NULL;
2710 	else
2711 		p = curproc;	/* XXX */
2712 	/*
2713 	 * If the op is asynchronous and an i/o daemon is waiting
2714 	 * queue the request, wake it up and wait for completion
2715 	 * otherwise just do it ourselves.
2716 	 */
2717 	if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp))
2718 		error = nfs_doio(bp, p);
2719 	return (error);
2720 }
2721 
2722 /*
2723  * fsync vnode op. Just call nfs_flush() with commit == 1.
2724  */
2725 /* ARGSUSED */
2726 int
nfs_fsync(v)2727 nfs_fsync(v)
2728 	void *v;
2729 {
2730 	struct vop_fsync_args /* {
2731 		struct vnodeop_desc *a_desc;
2732 		struct vnode * a_vp;
2733 		struct ucred * a_cred;
2734 		int  a_waitfor;
2735 		struct proc * a_p;
2736 	} */ *ap = v;
2737 
2738 	return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2739 }
2740 
2741 /*
2742  * Flush all the blocks associated with a vnode.
2743  * 	Walk through the buffer pool and push any dirty pages
2744  *	associated with the vnode.
2745  */
2746 int
nfs_flush(vp,cred,waitfor,p,commit)2747 nfs_flush(vp, cred, waitfor, p, commit)
2748 	struct vnode *vp;
2749 	struct ucred *cred;
2750 	int waitfor;
2751 	struct proc *p;
2752 	int commit;
2753 {
2754 	struct nfsnode *np = VTONFS(vp);
2755 	struct buf *bp;
2756 	int i;
2757 	struct buf *nbp;
2758 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2759 	int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2760 	int passone = 1;
2761 	u_quad_t off = (u_quad_t)-1, endoff = 0, toff;
2762 #ifndef NFS_COMMITBVECSIZ
2763 #define NFS_COMMITBVECSIZ	20
2764 #endif
2765 	struct buf *bvec[NFS_COMMITBVECSIZ];
2766 
2767 	if (nmp->nm_flag & NFSMNT_INT)
2768 		slpflag = PCATCH;
2769 	if (!commit)
2770 		passone = 0;
2771 	/*
2772 	 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2773 	 * server, but nas not been committed to stable storage on the server
2774 	 * yet. On the first pass, the byte range is worked out and the commit
2775 	 * rpc is done. On the second pass, nfs_writebp() is called to do the
2776 	 * job.
2777 	 */
2778 again:
2779 	bvecpos = 0;
2780 	if (NFS_ISV3(vp) && commit) {
2781 		s = splbio();
2782 		for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2783 			nbp = LIST_NEXT(bp, b_vnbufs);
2784 			if (bvecpos >= NFS_COMMITBVECSIZ)
2785 				break;
2786 			if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2787 				!= (B_DELWRI | B_NEEDCOMMIT))
2788 				continue;
2789 			bremfree(bp);
2790 			bp->b_flags |= (B_BUSY | B_WRITEINPROG);
2791 			/*
2792 			 * A list of these buffers is kept so that the
2793 			 * second loop knows which buffers have actually
2794 			 * been committed. This is necessary, since there
2795 			 * may be a race between the commit rpc and new
2796 			 * uncommitted writes on the file.
2797 			 */
2798 			bvec[bvecpos++] = bp;
2799 			toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2800 				bp->b_dirtyoff;
2801 			if (toff < off)
2802 				off = toff;
2803 			toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2804 			if (toff > endoff)
2805 				endoff = toff;
2806 		}
2807 		splx(s);
2808 	}
2809 	if (bvecpos > 0) {
2810 		/*
2811 		 * Commit data on the server, as required.
2812 		 */
2813 		retv = nfs_commit(vp, off, (int)(endoff - off), p);
2814 		if (retv == NFSERR_STALEWRITEVERF)
2815 			nfs_clearcommit(vp->v_mount);
2816 		/*
2817 		 * Now, either mark the blocks I/O done or mark the
2818 		 * blocks dirty, depending on whether the commit
2819 		 * succeeded.
2820 		 */
2821 		for (i = 0; i < bvecpos; i++) {
2822 			bp = bvec[i];
2823 			bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2824 			if (retv)
2825 			    brelse(bp);
2826 			else {
2827 			    s = splbio();
2828 			    buf_undirty(bp);
2829 			    vp->v_numoutput++;
2830 			    bp->b_flags |= B_ASYNC;
2831 			    bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2832 			    bp->b_dirtyoff = bp->b_dirtyend = 0;
2833 			    biodone(bp);
2834 			    splx(s);
2835 			}
2836 		}
2837 	}
2838 
2839 	/*
2840 	 * Start/do any write(s) that are required.
2841 	 */
2842 loop:
2843 	s = splbio();
2844 	for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2845 		nbp = LIST_NEXT(bp, b_vnbufs);
2846 		if (bp->b_flags & B_BUSY) {
2847 			if (waitfor != MNT_WAIT || passone)
2848 				continue;
2849 			bp->b_flags |= B_WANTED;
2850 			error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
2851 				"nfsfsync", slptimeo);
2852 			splx(s);
2853 			if (error) {
2854 			    if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2855 				return (EINTR);
2856 			    if (slpflag == PCATCH) {
2857 				slpflag = 0;
2858 				slptimeo = 2 * hz;
2859 			    }
2860 			}
2861 			goto loop;
2862 		}
2863 		if ((bp->b_flags & B_DELWRI) == 0)
2864 			panic("nfs_fsync: not dirty");
2865 		if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2866 			continue;
2867 		bremfree(bp);
2868 		if (passone || !commit)
2869 		    bp->b_flags |= (B_BUSY|B_ASYNC);
2870 		else
2871 		    bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2872 		splx(s);
2873 		VOP_BWRITE(bp);
2874 		goto loop;
2875 	}
2876 	splx(s);
2877 	if (passone) {
2878 		passone = 0;
2879 		goto again;
2880 	}
2881 	if (waitfor == MNT_WAIT) {
2882  loop2:
2883 	        s = splbio();
2884 		error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo);
2885 		splx(s);
2886 		if (error) {
2887 			if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2888 				return (EINTR);
2889 			if (slpflag == PCATCH) {
2890 				slpflag = 0;
2891 				slptimeo = 2 * hz;
2892 			}
2893 			goto loop2;
2894 		}
2895 
2896 		if (LIST_FIRST(&vp->v_dirtyblkhd) && commit) {
2897 #if 0
2898 			vprint("nfs_fsync: dirty", vp);
2899 #endif
2900 			goto loop;
2901 		}
2902 	}
2903 	if (np->n_flag & NWRITEERR) {
2904 		error = np->n_error;
2905 		np->n_flag &= ~NWRITEERR;
2906 	}
2907 	return (error);
2908 }
2909 
2910 /*
2911  * Return POSIX pathconf information applicable to nfs.
2912  *
2913  * The NFS V2 protocol doesn't support this, so just return EINVAL
2914  * for V2.
2915  */
2916 /* ARGSUSED */
2917 int
nfs_pathconf(v)2918 nfs_pathconf(v)
2919 	void *v;
2920 {
2921 #if 0
2922 	struct vop_pathconf_args /* {
2923 		struct vnode *a_vp;
2924 		int a_name;
2925 		register_t *a_retval;
2926 	} */ *ap = v;
2927 #endif
2928 
2929 	return (EINVAL);
2930 }
2931 
2932 /*
2933  * NFS advisory byte-level locks.
2934  */
2935 int
nfs_advlock(v)2936 nfs_advlock(v)
2937 	void *v;
2938 {
2939 	struct vop_advlock_args /* {
2940 		struct vnode *a_vp;
2941 		caddr_t  a_id;
2942 		int  a_op;
2943 		struct flock *a_fl;
2944 		int  a_flags;
2945 	} */ *ap = v;
2946 	struct nfsnode *np = VTONFS(ap->a_vp);
2947 
2948 	return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op,
2949 	    ap->a_fl, ap->a_flags));
2950 }
2951 
2952 /*
2953  * Print out the contents of an nfsnode.
2954  */
2955 int
nfs_print(v)2956 nfs_print(v)
2957 	void *v;
2958 {
2959 	struct vop_print_args /* {
2960 		struct vnode *a_vp;
2961 	} */ *ap = v;
2962 	struct vnode *vp = ap->a_vp;
2963 	struct nfsnode *np = VTONFS(vp);
2964 
2965 	printf("tag VT_NFS, fileid %ld fsid 0x%lx",
2966 		np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2967 #ifdef FIFO
2968 	if (vp->v_type == VFIFO)
2969 		fifo_printinfo(vp);
2970 #endif
2971 	printf("\n");
2972 	return (0);
2973 }
2974 
2975 /*
2976  * Just call nfs_writebp() with the force argument set to 1.
2977  */
2978 int
nfs_bwrite(v)2979 nfs_bwrite(v)
2980 	void *v;
2981 {
2982 	struct vop_bwrite_args /* {
2983 		struct buf *a_bp;
2984 	} */ *ap = v;
2985 
2986 	return (nfs_writebp(ap->a_bp, 1));
2987 }
2988 
2989 /*
2990  * This is a clone of vop_generic_bwrite(), except that B_WRITEINPROG isn't set unless
2991  * the force flag is one and it also handles the B_NEEDCOMMIT flag.
2992  */
2993 int
nfs_writebp(bp,force)2994 nfs_writebp(bp, force)
2995 	struct buf *bp;
2996 	int force;
2997 {
2998 	int oldflags = bp->b_flags, retv = 1;
2999 	struct proc *p = curproc;	/* XXX */
3000 	off_t off;
3001 	size_t cnt;
3002 	int   s;
3003 	struct vnode *vp;
3004 	struct nfsnode *np;
3005 
3006 	if(!(bp->b_flags & B_BUSY))
3007 		panic("bwrite: buffer is not busy???");
3008 
3009 	vp = bp->b_vp;
3010 	np = VTONFS(vp);
3011 
3012 #ifdef fvdl_debug
3013 	printf("nfs_writebp(%x): vp %x voff %d vend %d doff %d dend %d\n",
3014 	    bp, bp->b_vp, bp->b_validoff, bp->b_validend, bp->b_dirtyoff,
3015 	    bp->b_dirtyend);
3016 #endif
3017 	bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
3018 
3019 	s = splbio();
3020 	buf_undirty(bp);
3021 
3022 	if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p)
3023 		++p->p_stats->p_ru.ru_oublock;
3024 
3025 	bp->b_vp->v_numoutput++;
3026 	splx(s);
3027 
3028 	/*
3029 	 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3030 	 * an actual write will have to be scheduled via. VOP_STRATEGY().
3031 	 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3032 	 */
3033 	if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
3034 		off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
3035 		cnt = bp->b_dirtyend - bp->b_dirtyoff;
3036 
3037 		rw_enter_write(&np->n_commitlock);
3038 		if (!(bp->b_flags & B_NEEDCOMMIT)) {
3039 			rw_exit_write(&np->n_commitlock);
3040 			return (0);
3041 		}
3042 
3043 		/*
3044 		 * If it's already been commited by somebody else,
3045 		 * bail.
3046 		 */
3047 		if (!nfs_in_committed_range(vp, bp)) {
3048 			int pushedrange = 0;
3049 			/*
3050 			 * Since we're going to do this, push as much
3051 			 * as we can.
3052 			 */
3053 
3054 			if (nfs_in_tobecommitted_range(vp, bp)) {
3055 				pushedrange = 1;
3056 				off = np->n_pushlo;
3057 				cnt = np->n_pushhi - np->n_pushlo;
3058 			}
3059 
3060 			bp->b_flags |= B_WRITEINPROG;
3061 			retv = nfs_commit(bp->b_vp, off, cnt, bp->b_proc);
3062 			bp->b_flags &= ~B_WRITEINPROG;
3063 
3064 			if (retv == 0) {
3065 				if (pushedrange)
3066 					nfs_merge_commit_ranges(vp);
3067 				else
3068 					nfs_add_committed_range(vp, bp);
3069 			}
3070 		} else
3071 			retv = 0; /* It has already been commited. */
3072 
3073 		rw_exit_write(&np->n_commitlock);
3074 		if (!retv) {
3075 			bp->b_dirtyoff = bp->b_dirtyend = 0;
3076 			bp->b_flags &= ~B_NEEDCOMMIT;
3077 			s = splbio();
3078 			biodone(bp);
3079 			splx(s);
3080 		} else if (retv == NFSERR_STALEWRITEVERF)
3081 			nfs_clearcommit(bp->b_vp->v_mount);
3082 	}
3083 	if (retv) {
3084 		if (force)
3085 			bp->b_flags |= B_WRITEINPROG;
3086 		VOP_STRATEGY(bp);
3087 	}
3088 
3089 	if( (oldflags & B_ASYNC) == 0) {
3090 		int rtval = biowait(bp);
3091 		if (!(oldflags & B_DELWRI) && p) {
3092 			++p->p_stats->p_ru.ru_oublock;
3093 		}
3094 		brelse(bp);
3095 		return (rtval);
3096 	}
3097 
3098 	return (0);
3099 }
3100 
3101 /*
3102  * nfs special file access vnode op.
3103  * Essentially just get vattr and then imitate iaccess() since the device is
3104  * local to the client.
3105  */
3106 int
nfsspec_access(v)3107 nfsspec_access(v)
3108 	void *v;
3109 {
3110 	struct vop_access_args /* {
3111 		struct vnode *a_vp;
3112 		int  a_mode;
3113 		struct ucred *a_cred;
3114 		struct proc *a_p;
3115 	} */ *ap = v;
3116 	struct vattr va;
3117 	struct vnode *vp = ap->a_vp;
3118 	int error;
3119 
3120         /*
3121 	 * Disallow write attempts on filesystems mounted read-only;
3122 	 * unless the file is a socket, fifo, or a block or character
3123 	 * device resident on the filesystem.
3124 	 */
3125 	if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3126 		switch (vp->v_type) {
3127 		case VREG:
3128 		case VDIR:
3129 		case VLNK:
3130 			return (EROFS);
3131 		default:
3132 			break;
3133 		}
3134 	}
3135 
3136 	error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p);
3137 	if (error)
3138 		return (error);
3139 
3140 	return (vaccess(va.va_mode, va.va_uid, va.va_gid, ap->a_mode,
3141 	    ap->a_cred));
3142 }
3143 
3144 /* ARGSUSED */
3145 int
nfs_poll(v)3146 nfs_poll(v)
3147         void *v;
3148 {
3149 	struct vop_poll_args /* {
3150 		struct vnode *a_vp;
3151 		int  a_events;
3152 		struct proc *a_p;
3153 	} */ *ap = v;
3154 
3155 	/*
3156 	 * We should really check to see if I/O is possible.
3157 	 */
3158 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
3159 }
3160 
3161 /*
3162  * Read wrapper for special devices.
3163  */
3164 int
nfsspec_read(v)3165 nfsspec_read(v)
3166 	void *v;
3167 {
3168 	struct vop_read_args /* {
3169 		struct vnode *a_vp;
3170 		struct uio *a_uio;
3171 		int  a_ioflag;
3172 		struct ucred *a_cred;
3173 	} */ *ap = v;
3174 	struct nfsnode *np = VTONFS(ap->a_vp);
3175 
3176 	/*
3177 	 * Set access flag.
3178 	 */
3179 	np->n_flag |= NACC;
3180 	np->n_atim.tv_sec = time.tv_sec;
3181 	np->n_atim.tv_nsec = time.tv_usec * 1000;
3182 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3183 }
3184 
3185 /*
3186  * Write wrapper for special devices.
3187  */
3188 int
nfsspec_write(v)3189 nfsspec_write(v)
3190 	void *v;
3191 {
3192 	struct vop_write_args /* {
3193 		struct vnode *a_vp;
3194 		struct uio *a_uio;
3195 		int  a_ioflag;
3196 		struct ucred *a_cred;
3197 	} */ *ap = v;
3198 	struct nfsnode *np = VTONFS(ap->a_vp);
3199 
3200 	/*
3201 	 * Set update flag.
3202 	 */
3203 	np->n_flag |= NUPD;
3204 	np->n_mtim.tv_sec = time.tv_sec;
3205 	np->n_mtim.tv_nsec = time.tv_usec * 1000;
3206 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3207 }
3208 
3209 /*
3210  * Close wrapper for special devices.
3211  *
3212  * Update the times on the nfsnode then do device close.
3213  */
3214 int
nfsspec_close(v)3215 nfsspec_close(v)
3216 	void *v;
3217 {
3218 	struct vop_close_args /* {
3219 		struct vnode *a_vp;
3220 		int  a_fflag;
3221 		struct ucred *a_cred;
3222 		struct proc *a_p;
3223 	} */ *ap = v;
3224 	struct vnode *vp = ap->a_vp;
3225 	struct nfsnode *np = VTONFS(vp);
3226 	struct vattr vattr;
3227 
3228 	if (np->n_flag & (NACC | NUPD)) {
3229 		np->n_flag |= NCHG;
3230 		if (vp->v_usecount == 1 &&
3231 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3232 			VATTR_NULL(&vattr);
3233 			if (np->n_flag & NACC)
3234 				vattr.va_atime = np->n_atim;
3235 			if (np->n_flag & NUPD)
3236 				vattr.va_mtime = np->n_mtim;
3237 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3238 		}
3239 	}
3240 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3241 }
3242 
3243 #ifdef FIFO
3244 /*
3245  * Read wrapper for fifos.
3246  */
3247 int
nfsfifo_read(v)3248 nfsfifo_read(v)
3249 	void *v;
3250 {
3251 	struct vop_read_args /* {
3252 		struct vnode *a_vp;
3253 		struct uio *a_uio;
3254 		int  a_ioflag;
3255 		struct ucred *a_cred;
3256 	} */ *ap = v;
3257 	extern int (**fifo_vnodeop_p)(void *);
3258 	struct nfsnode *np = VTONFS(ap->a_vp);
3259 
3260 	/*
3261 	 * Set access flag.
3262 	 */
3263 	np->n_flag |= NACC;
3264 	np->n_atim.tv_sec = time.tv_sec;
3265 	np->n_atim.tv_nsec = time.tv_usec * 1000;
3266 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3267 }
3268 
3269 /*
3270  * Write wrapper for fifos.
3271  */
3272 int
nfsfifo_write(v)3273 nfsfifo_write(v)
3274 	void *v;
3275 {
3276 	struct vop_write_args /* {
3277 		struct vnode *a_vp;
3278 		struct uio *a_uio;
3279 		int  a_ioflag;
3280 		struct ucred *a_cred;
3281 	} */ *ap = v;
3282 	extern int (**fifo_vnodeop_p)(void *);
3283 	struct nfsnode *np = VTONFS(ap->a_vp);
3284 
3285 	/*
3286 	 * Set update flag.
3287 	 */
3288 	np->n_flag |= NUPD;
3289 	np->n_mtim.tv_sec = time.tv_sec;
3290 	np->n_mtim.tv_nsec = time.tv_usec * 1000;
3291 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3292 }
3293 
3294 /*
3295  * Close wrapper for fifos.
3296  *
3297  * Update the times on the nfsnode then do fifo close.
3298  */
3299 int
nfsfifo_close(v)3300 nfsfifo_close(v)
3301 	void *v;
3302 {
3303 	struct vop_close_args /* {
3304 		struct vnode *a_vp;
3305 		int  a_fflag;
3306 		struct ucred *a_cred;
3307 		struct proc *a_p;
3308 	} */ *ap = v;
3309 	struct vnode *vp = ap->a_vp;
3310 	struct nfsnode *np = VTONFS(vp);
3311 	struct vattr vattr;
3312 	extern int (**fifo_vnodeop_p)(void *);
3313 
3314 	if (np->n_flag & (NACC | NUPD)) {
3315 		if (np->n_flag & NACC) {
3316 			np->n_atim.tv_sec = time.tv_sec;
3317 			np->n_atim.tv_nsec = time.tv_usec * 1000;
3318 		}
3319 		if (np->n_flag & NUPD) {
3320 			np->n_mtim.tv_sec = time.tv_sec;
3321 			np->n_mtim.tv_nsec = time.tv_usec * 1000;
3322 		}
3323 		np->n_flag |= NCHG;
3324 		if (vp->v_usecount == 1 &&
3325 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3326 			VATTR_NULL(&vattr);
3327 			if (np->n_flag & NACC)
3328 				vattr.va_atime = np->n_atim;
3329 			if (np->n_flag & NUPD)
3330 				vattr.va_mtime = np->n_mtim;
3331 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3332 		}
3333 	}
3334 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3335 }
3336 
3337 int
nfsfifo_reclaim(void * v)3338 nfsfifo_reclaim(void *v)
3339 {
3340 	fifo_reclaim(v);
3341 	return (nfs_reclaim(v));
3342 }
3343 #endif /* ! FIFO */
3344