1/*-
2 *             Coda: an Experimental Distributed File System
3 *                              Release 3.1
4 *
5 *           Copyright (c) 1987-1998 Carnegie Mellon University
6 *                          All Rights Reserved
7 *
8 * Permission  to  use, copy, modify and distribute this software and its
9 * documentation is hereby granted,  provided  that  both  the  copyright
10 * notice  and  this  permission  notice  appear  in  all  copies  of the
11 * software, derivative works or  modified  versions,  and  any  portions
12 * thereof, and that both notices appear in supporting documentation, and
13 * that credit is given to Carnegie Mellon University  in  all  documents
14 * and publicity pertaining to direct or indirect use of this code or its
15 * derivatives.
16 *
17 * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
18 * SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
19 * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
20 * DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
21 * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
22 * ANY DERIVATIVE WORK.
23 *
24 * Carnegie  Mellon  encourages  users  of  this  software  to return any
25 * improvements or extensions that  they  make,  and  to  grant  Carnegie
26 * Mellon the rights to redistribute these changes without encumbrance.
27 *
28 *  	@(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
29 */
30/*
31 * Mach Operating System
32 * Copyright (c) 1990 Carnegie-Mellon University
33 * Copyright (c) 1989 Carnegie-Mellon University
34 * All rights reserved.  The CMU software License Agreement specifies
35 * the terms and conditions for use and redistribution.
36 */
37
38/*
39 * This code was written for the Coda filesystem at Carnegie Mellon
40 * University.  Contributers include David Steere, James Kistler, and
41 * M. Satyanarayanan.
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD$");
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/acct.h>
50#include <sys/errno.h>
51#include <sys/fcntl.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
55#include <sys/file.h>		/* Must come after sys/malloc.h */
56#include <sys/mount.h>
57#include <sys/mutex.h>
58#include <sys/namei.h>
59#include <sys/proc.h>
60#include <sys/uio.h>
61#include <sys/unistd.h>
62
63#include <vm/vm.h>
64#include <vm/vm_object.h>
65#include <vm/vm_extern.h>
66
67#include <fs/coda/coda.h>
68#include <fs/coda/cnode.h>
69#include <fs/coda/coda_vnops.h>
70#include <fs/coda/coda_venus.h>
71#include <fs/coda/coda_opstats.h>
72#include <fs/coda/coda_subr.h>
73#include <fs/coda/coda_pioctl.h>
74
75/*
76 * These flags select various performance enhancements.
77 */
78static int coda_attr_cache = 1;		/* Set to cache attributes. */
79static int coda_symlink_cache = 1;	/* Set to cache symbolic links. */
80static int coda_access_cache = 1;	/* Set to cache some access checks. */
81
82/*
83 * Structure to keep track of vfs calls.
84 */
85static struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE];
86
87#define	MARK_ENTRY(op)		(coda_vnodeopstats[op].entries++)
88#define	MARK_INT_SAT(op)	(coda_vnodeopstats[op].sat_intrn++)
89#define	MARK_INT_FAIL(op)	(coda_vnodeopstats[op].unsat_intrn++)
90#define	MARK_INT_GEN(op)	(coda_vnodeopstats[op].gen_intrn++)
91
92/*
93 * What we are delaying for in printf.
94 */
95int coda_printf_delay = 0;	/* In microseconds */
96int coda_vnop_print_entry = 0;
97static int coda_lockdebug = 0;
98
99/*
100 * Some FreeBSD details:
101 *
102 * codadev_modevent is called at boot time or module load time.
103 */
104#define	ENTRY do {							\
105	if (coda_vnop_print_entry)					\
106		myprintf(("Entered %s\n", __func__));			\
107} while (0)
108
109/*
110 * Definition of the vnode operation vector.
111 */
112struct vop_vector coda_vnodeops = {
113	.vop_default = &default_vnodeops,
114	.vop_cachedlookup = coda_lookup,	/* uncached lookup */
115	.vop_lookup = vfs_cache_lookup,		/* namecache lookup */
116	.vop_create = coda_create,		/* create */
117	.vop_open = coda_open,			/* open */
118	.vop_close = coda_close,		/* close */
119	.vop_access = coda_access,		/* access */
120	.vop_getattr = coda_getattr,		/* getattr */
121	.vop_setattr = coda_setattr,		/* setattr */
122	.vop_read = coda_read,			/* read */
123	.vop_write = coda_write,		/* write */
124	.vop_ioctl = coda_ioctl,		/* ioctl */
125	.vop_fsync = coda_fsync,		/* fsync */
126	.vop_remove = coda_remove,		/* remove */
127	.vop_link = coda_link,			/* link */
128	.vop_rename = coda_rename,		/* rename */
129	.vop_mkdir = coda_mkdir,		/* mkdir */
130	.vop_rmdir = coda_rmdir,		/* rmdir */
131	.vop_symlink = coda_symlink,		/* symlink */
132	.vop_readdir = coda_readdir,		/* readdir */
133	.vop_readlink = coda_readlink,		/* readlink */
134	.vop_inactive = coda_inactive,		/* inactive */
135	.vop_reclaim = coda_reclaim,		/* reclaim */
136	.vop_lock1 = coda_lock,			/* lock */
137	.vop_unlock = coda_unlock,		/* unlock */
138	.vop_bmap = VOP_EOPNOTSUPP,		/* bmap */
139	.vop_print = VOP_NULL,			/* print */
140	.vop_islocked = coda_islocked,		/* islocked */
141	.vop_pathconf = coda_pathconf,		/* pathconf */
142	.vop_poll = vop_stdpoll,
143	.vop_getpages = vop_stdgetpages,	/* pager intf.*/
144	.vop_putpages = vop_stdputpages,	/* pager intf.*/
145	.vop_getwritemount = vop_stdgetwritemount,
146#if 0
147	/* missing */
148	.vop_cachedlookup = ufs_lookup,
149	.vop_whiteout =	ufs_whiteout,
150#endif
151
152};
153
154static void	coda_print_vattr(struct vattr *attr);
155
156int
157coda_vnodeopstats_init(void)
158{
159	int i;
160
161	for(i=0; i<CODA_VNODEOPS_SIZE; i++) {
162		coda_vnodeopstats[i].opcode = i;
163		coda_vnodeopstats[i].entries = 0;
164		coda_vnodeopstats[i].sat_intrn = 0;
165		coda_vnodeopstats[i].unsat_intrn = 0;
166		coda_vnodeopstats[i].gen_intrn = 0;
167	}
168	return (0);
169}
170
171/*
172 * coda_open calls Venus which returns an open file descriptor the cache file
173 * holding the data.  We get the vnode while we are still in the context of
174 * the venus process in coda_psdev.c.  This vnode is then passed back to the
175 * caller and opened.
176 */
177int
178coda_open(struct vop_open_args *ap)
179{
180
181	/*
182	 * FreeBSD can pass the O_EXCL flag in mode, even though the check
183	 * has already happened.  Venus defensively assumes that if open is
184	 * passed the EXCL, it must be a bug.  We strip the flag here.
185	 */
186	/* true args */
187	struct vnode **vpp = &(ap->a_vp);
188	struct cnode *cp = VTOC(*vpp);
189	int flag = ap->a_mode & (~O_EXCL);
190	struct ucred *cred = ap->a_cred;
191	struct thread *td = ap->a_td;
192	/* locals */
193	int error;
194	struct vnode *vp;
195
196	MARK_ENTRY(CODA_OPEN_STATS);
197
198	/*
199	 * Check for open of control file.
200	 */
201	if (IS_CTL_VP(*vpp)) {
202		/* XXX */
203		/* if (WRITEABLE(flag)) */
204		if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) {
205			MARK_INT_FAIL(CODA_OPEN_STATS);
206			return (EACCES);
207		}
208		MARK_INT_SAT(CODA_OPEN_STATS);
209		return (0);
210	}
211	error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred,
212	    td->td_proc, &vp);
213	if (error)
214		return (error);
215	CODADEBUG(CODA_OPEN, myprintf(("open: vp %p result %d\n", vp,
216	    error)););
217
218	/*
219	 * Save the vnode pointer for the cache file.
220	 */
221	if (cp->c_ovp == NULL) {
222		cp->c_ovp = vp;
223	} else {
224		if (cp->c_ovp != vp)
225			panic("coda_open: cp->c_ovp != ITOV(ip)");
226	}
227	cp->c_ocount++;
228
229	/*
230	 * Flush the attribute cached if writing the file.
231	 */
232	if (flag & FWRITE) {
233		cp->c_owrite++;
234		cp->c_flags &= ~C_VATTR;
235	}
236
237	/*
238	 * Open the cache file.
239	 */
240	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
241	error = VOP_OPEN(vp, flag, cred, td, NULL);
242	if (error) {
243		VOP_UNLOCK(vp, 0);
244    		printf("coda_open: VOP_OPEN on container failed %d\n", error);
245		return (error);
246	}
247	(*vpp)->v_object = vp->v_object;
248	VOP_UNLOCK(vp, 0);
249	return (0);
250}
251
252/*
253 * Close the cache file used for I/O and notify Venus.
254 */
255int
256coda_close(struct vop_close_args *ap)
257{
258	/* true args */
259	struct vnode *vp = ap->a_vp;
260	struct cnode *cp = VTOC(vp);
261	int flag = ap->a_fflag;
262	struct ucred *cred = ap->a_cred;
263	struct thread *td = ap->a_td;
264	/* locals */
265	int error;
266
267	MARK_ENTRY(CODA_CLOSE_STATS);
268
269	/*
270	 * Check for close of control file.
271	 */
272	if (IS_CTL_VP(vp)) {
273		MARK_INT_SAT(CODA_CLOSE_STATS);
274		return (0);
275	}
276	if (cp->c_ovp) {
277		vn_lock(cp->c_ovp, LK_EXCLUSIVE | LK_RETRY);
278		/* Do errors matter here? */
279		VOP_CLOSE(cp->c_ovp, flag, cred, td);
280		vput(cp->c_ovp);
281	}
282#ifdef CODA_VERBOSE
283	else
284		printf("coda_close: NO container vp %p/cp %p\n", vp, cp);
285#endif
286	if (--cp->c_ocount == 0)
287		cp->c_ovp = NULL;
288
289	/*
290	 * File was opened for write.
291	 */
292	if (flag & FWRITE)
293		--cp->c_owrite;
294	if (!IS_UNMOUNTING(cp))
295		error = venus_close(vtomi(vp), &cp->c_fid, flag, cred,
296		    td->td_proc);
297	else
298		error = ENODEV;
299	CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)););
300	return (error);
301}
302
303int
304coda_read(struct vop_read_args *ap)
305{
306
307	ENTRY;
308	return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, ap->a_ioflag,
309	    ap->a_cred, ap->a_uio->uio_td));
310}
311
312int
313coda_write(struct vop_write_args *ap)
314{
315
316	ENTRY;
317	return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, ap->a_ioflag,
318	    ap->a_cred, ap->a_uio->uio_td));
319}
320
321int
322coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag,
323    struct ucred *cred, struct thread *td)
324{
325	/* upcall decl */
326	/* NOTE: container file operation!!! */
327	/* locals */
328	struct cnode *cp = VTOC(vp);
329	struct vnode *cfvp = cp->c_ovp;
330	int opened_internally = 0;
331	int error = 0;
332
333	MARK_ENTRY(CODA_RDWR_STATS);
334	CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %zd, %lld, %d)\n",
335	    rw, (void *)uiop->uio_iov->iov_base, uiop->uio_resid,
336	    (long long)uiop->uio_offset, uiop->uio_segflg)););
337
338	/*
339	 * Check for rdwr of control object.
340	 */
341	if (IS_CTL_VP(vp)) {
342		MARK_INT_FAIL(CODA_RDWR_STATS);
343		return (EINVAL);
344	}
345
346	/*
347	 * If file is not already open this must be a page {read,write}
348	 * request and we should open it internally.
349	 */
350	if (cfvp == NULL) {
351		opened_internally = 1;
352		MARK_INT_GEN(CODA_OPEN_STATS);
353		error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred,
354		    td, NULL);
355#ifdef CODA_VERBOSE
356		printf("coda_rdwr: Internally Opening %p\n", vp);
357#endif
358		if (error) {
359			printf("coda_rdwr: VOP_OPEN on container failed "
360			    "%d\n", error);
361			return (error);
362		}
363		cfvp = cp->c_ovp;
364	}
365
366	/*
367	 * Have UFS handle the call.
368	 */
369	CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = "
370	    "%d\n", coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)););
371	vn_lock(cfvp, LK_EXCLUSIVE | LK_RETRY);
372	if (rw == UIO_READ) {
373		error = VOP_READ(cfvp, uiop, ioflag, cred);
374	} else {
375		error = VOP_WRITE(cfvp, uiop, ioflag, cred);
376		/*
377		 * ufs_write updates the vnode_pager_setsize for the
378		 * vnode/object.
379		 *
380		 * XXX: Since we now share vm objects between layers, this is
381		 * probably unnecessary.
382		 */
383		{
384			struct vattr attr;
385			if (VOP_GETATTR(cfvp, &attr, cred) == 0)
386				vnode_pager_setsize(vp, attr.va_size);
387		}
388	}
389	VOP_UNLOCK(cfvp, 0);
390	if (error)
391		MARK_INT_FAIL(CODA_RDWR_STATS);
392	else
393		MARK_INT_SAT(CODA_RDWR_STATS);
394
395	/*
396	 * Do an internal close if necessary.
397	 */
398	if (opened_internally) {
399		MARK_INT_GEN(CODA_CLOSE_STATS);
400		(void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred,
401		    td);
402	}
403
404	/*
405	 * Invalidate cached attributes if writing.
406	 */
407	if (rw == UIO_WRITE)
408		cp->c_flags &= ~C_VATTR;
409	return (error);
410}
411
412int
413coda_ioctl(struct vop_ioctl_args *ap)
414{
415	/* true args */
416	struct vnode *vp = ap->a_vp;
417	int com = ap->a_command;
418	caddr_t data = ap->a_data;
419	int flag = ap->a_fflag;
420	struct ucred *cred = ap->a_cred;
421	struct thread *td = ap->a_td;
422	/* locals */
423	int error;
424	struct vnode *tvp;
425	struct nameidata ndp;
426	struct PioctlData *iap = (struct PioctlData *)data;
427
428	MARK_ENTRY(CODA_IOCTL_STATS);
429	CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path)););
430
431	/*
432	 * Don't check for operation on a dying object, for ctlvp it
433	 * shouldn't matter.
434	 *
435	 * Must be control object to succeed.
436	 */
437	if (!IS_CTL_VP(vp)) {
438		MARK_INT_FAIL(CODA_IOCTL_STATS);
439		CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != "
440		    "ctlvp")););
441		return (EOPNOTSUPP);
442	}
443
444	/*
445	 * Look up the pathname.
446	 *
447	 * Should we use the name cache here? It would get it from lookupname
448	 * sooner or later anyway, right?
449	 */
450	NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW),
451	    UIO_USERSPACE, iap->path, td);
452	error = namei(&ndp);
453	tvp = ndp.ni_vp;
454	if (error) {
455		MARK_INT_FAIL(CODA_IOCTL_STATS);
456		CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup "
457		    "returns %d\n", error)););
458		return (error);
459	}
460
461	/*
462	 * Make sure this is a coda style cnode, but it may be a different
463	 * vfsp.
464	 */
465	if (tvp->v_op != &coda_vnodeops) {
466		vrele(tvp);
467		NDFREE(&ndp, NDF_ONLY_PNBUF);
468		MARK_INT_FAIL(CODA_IOCTL_STATS);
469		CODADEBUG(CODA_IOCTL,
470		myprintf(("coda_ioctl error: %s not a coda object\n",
471		    iap->path)););
472		return (EINVAL);
473	}
474	if (iap->vi.in_size > VC_MAXDATASIZE ||
475	    iap->vi.out_size > VC_MAXDATASIZE) {
476		NDFREE(&ndp, 0);
477		return (EINVAL);
478	}
479	error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag,
480	    data, cred, td->td_proc);
481	if (error)
482		MARK_INT_FAIL(CODA_IOCTL_STATS);
483	else
484		CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n",
485		    error)););
486	vrele(tvp);
487	NDFREE(&ndp, NDF_ONLY_PNBUF);
488	return (error);
489}
490
491/*
492 * To reduce the cost of a user-level venus;we cache attributes in the
493 * kernel.  Each cnode has storage allocated for an attribute.  If c_vattr is
494 * valid, return a reference to it.  Otherwise, get the attributes from venus
495 * and store them in the cnode.  There is some question if this method is a
496 * security leak.  But I think that in order to make this call, the user must
497 * have done a lookup and opened the file, and therefore should already have
498 * access.
499 */
500int
501coda_getattr(struct vop_getattr_args *ap)
502{
503	/* true args */
504	struct vnode *vp = ap->a_vp;
505	struct cnode *cp = VTOC(vp);
506	struct vattr *vap = ap->a_vap;
507	struct ucred *cred = ap->a_cred;
508	/* locals */
509    	struct vnode *convp;
510	int error, size;
511
512	MARK_ENTRY(CODA_GETATTR_STATS);
513	if (IS_UNMOUNTING(cp))
514		return (ENODEV);
515
516	/*
517	 * Check for getattr of control object.
518	 */
519	if (IS_CTL_VP(vp)) {
520		MARK_INT_FAIL(CODA_GETATTR_STATS);
521		return (ENOENT);
522	}
523
524	/*
525	 * Check to see if the attributes have already been cached.
526	 */
527	if (VALID_VATTR(cp)) {
528		CODADEBUG(CODA_GETATTR, myprintf(("attr cache hit: %s\n",
529		    coda_f2s(&cp->c_fid))););
530		CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR))
531		    coda_print_vattr(&cp->c_vattr););
532		*vap = cp->c_vattr;
533		MARK_INT_SAT(CODA_GETATTR_STATS);
534		return (0);
535	}
536    	error = venus_getattr(vtomi(vp), &cp->c_fid, cred, vap);
537	if (!error) {
538		CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result "
539		    "%d\n", coda_f2s(&cp->c_fid), error)););
540		CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR))
541		    coda_print_vattr(vap););
542
543		/*
544		 * XXX: Since we now share vm objects between layers, this is
545		 * probably unnecessary.
546		 */
547		size = vap->va_size;
548    		convp = cp->c_ovp;
549		if (convp != NULL)
550			vnode_pager_setsize(convp, size);
551
552		/*
553		 * If not open for write, store attributes in cnode.
554		 */
555		if ((cp->c_owrite == 0) && (coda_attr_cache)) {
556			cp->c_vattr = *vap;
557			cp->c_flags |= C_VATTR;
558		}
559	}
560	return (error);
561}
562
563int
564coda_setattr(struct vop_setattr_args *ap)
565{
566	/* true args */
567	struct vnode *vp = ap->a_vp;
568	struct cnode *cp = VTOC(vp);
569	struct vattr *vap = ap->a_vap;
570	struct ucred *cred = ap->a_cred;
571	/* locals */
572    	struct vnode *convp;
573	int error, size;
574
575	MARK_ENTRY(CODA_SETATTR_STATS);
576
577	/*
578	 * Check for setattr of control object.
579	 */
580	if (IS_CTL_VP(vp)) {
581		MARK_INT_FAIL(CODA_SETATTR_STATS);
582		return (ENOENT);
583	}
584	if (codadebug & CODADBGMSK(CODA_SETATTR))
585		coda_print_vattr(vap);
586	error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred);
587	if (!error)
588		cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
589
590	/*
591	 * XXX: Since we now share vm objects between layers, this is
592	 * probably unnecessary.
593	 *
594	 * XXX: Shouldn't we only be doing this "set" if C_VATTR remains
595	 * valid after venus_setattr()?
596	 */
597	size = vap->va_size;
598    	convp = cp->c_ovp;
599	if (size != VNOVAL && convp != NULL)
600		vnode_pager_setsize(convp, size);
601	CODADEBUG(CODA_SETATTR,	myprintf(("setattr %d\n", error)););
602	return (error);
603}
604
605int
606coda_access(struct vop_access_args *ap)
607{
608	/* true args */
609	struct vnode *vp = ap->a_vp;
610	struct cnode *cp = VTOC(vp);
611	accmode_t accmode = ap->a_accmode;
612	struct ucred *cred = ap->a_cred;
613	struct thread *td = ap->a_td;
614	/* locals */
615	int error;
616
617	MARK_ENTRY(CODA_ACCESS_STATS);
618
619	/*
620	 * Check for access of control object.  Only read access is allowed
621	 * on it.
622	 */
623	if (IS_CTL_VP(vp)) {
624		/*
625		 * Bogus hack - all will be marked as successes.
626		 */
627		MARK_INT_SAT(CODA_ACCESS_STATS);
628		return (((accmode & VREAD) && !(accmode & (VWRITE | VEXEC)))
629		    ? 0 : EACCES);
630	}
631
632	/*
633	 * We maintain a one-entry LRU positive access cache with each cnode.
634	 * In principle we could also track negative results, and for more
635	 * than one uid, but we don't yet.  Venus is responsible for
636	 * invalidating this cache as required.
637	 */
638	if (coda_access_cache && VALID_ACCCACHE(cp) &&
639	    (cred->cr_uid == cp->c_cached_uid) &&
640	    (accmode & cp->c_cached_mode) == accmode) {
641		MARK_INT_SAT(CODA_ACCESS_STATS);
642		return (0);
643	}
644	error = venus_access(vtomi(vp), &cp->c_fid, accmode, cred, td->td_proc);
645	if (error == 0 && coda_access_cache) {
646		/*-
647		 * When we have a new successful request, we consider three
648		 * cases:
649		 *
650		 * - No initialized access cache, in which case cache the
651		 *   result.
652		 * - Cached result for a different user, in which case we
653		 *   replace the entry.
654		 * - Cached result for the same user, in which case we add
655		 *   any newly granted rights to the cached mode.
656		 *
657		 * XXXRW: If we ever move to something more interesting than
658		 * uid-based token lookup, we'll need to change this.
659		 */
660		cp->c_flags |= C_ACCCACHE;
661		if (cp->c_cached_uid != cred->cr_uid) {
662			cp->c_cached_mode = accmode;
663			cp->c_cached_uid = cred->cr_uid;
664		} else
665			cp->c_cached_mode |= accmode;
666	}
667	return (error);
668}
669
670int
671coda_readlink(struct vop_readlink_args *ap)
672{
673	/* true args */
674	struct vnode *vp = ap->a_vp;
675	struct cnode *cp = VTOC(vp);
676	struct uio *uiop = ap->a_uio;
677	struct ucred *cred = ap->a_cred;
678	struct thread *td = ap->a_uio->uio_td;
679	/* locals */
680	int error;
681	char *str;
682	int len;
683
684	MARK_ENTRY(CODA_READLINK_STATS);
685
686	/*
687	 * Check for readlink of control object.
688	 */
689	if (IS_CTL_VP(vp)) {
690		MARK_INT_FAIL(CODA_READLINK_STATS);
691		return (ENOENT);
692	}
693	if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) {
694		/*
695		 * Symlink was cached.
696		 */
697		uiop->uio_rw = UIO_READ;
698		error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop);
699		if (error)
700			MARK_INT_FAIL(CODA_READLINK_STATS);
701		else
702			MARK_INT_SAT(CODA_READLINK_STATS);
703		return (error);
704	}
705	error = venus_readlink(vtomi(vp), &cp->c_fid, cred, td != NULL ?
706	    td->td_proc : NULL, &str, &len);
707	if (!error) {
708		uiop->uio_rw = UIO_READ;
709		error = uiomove(str, len, uiop);
710		if (coda_symlink_cache) {
711			cp->c_symlink = str;
712			cp->c_symlen = len;
713			cp->c_flags |= C_SYMLINK;
714		} else
715			CODA_FREE(str, len);
716	}
717	CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",
718	    error)););
719	return (error);
720}
721
722int
723coda_fsync(struct vop_fsync_args *ap)
724{
725	/* true args */
726	struct vnode *vp = ap->a_vp;
727	struct cnode *cp = VTOC(vp);
728	struct thread *td = ap->a_td;
729	/* locals */
730	struct vnode *convp = cp->c_ovp;
731	int error;
732
733	MARK_ENTRY(CODA_FSYNC_STATS);
734
735	/*
736	 * Check for fsync on an unmounting object.
737	 *
738	 * XXX: Is this comment true on FreeBSD?  It seems likely, since
739	 * unmounting is fairly non-atomic.
740	 *
741	 * The NetBSD kernel, in it's infinite wisdom, can try to fsync after
742	 * an unmount has been initiated.  This is a Bad Thing, which we have
743	 * to avoid.  Not a legitimate failure for stats.
744	 */
745	if (IS_UNMOUNTING(cp))
746		return (ENODEV);
747
748	/*
749	 * Check for fsync of control object.
750	 */
751	if (IS_CTL_VP(vp)) {
752		MARK_INT_SAT(CODA_FSYNC_STATS);
753		return (0);
754	}
755	if (convp != NULL) {
756		vn_lock(convp, LK_EXCLUSIVE | LK_RETRY);
757		VOP_FSYNC(convp, MNT_WAIT, td);
758		VOP_UNLOCK(convp, 0);
759	}
760
761	/*
762	 * We see fsyncs with usecount == 1 then usecount == 0.  For now we
763	 * ignore them.
764	 */
765#if 0
766	VI_LOCK(vp);
767	if (!vp->v_usecount) {
768		printf("coda_fsync on vnode %p with %d usecount.  "
769		    "c_flags = %x (%x)\n", vp, vp->v_usecount, cp->c_flags,
770		    cp->c_flags&C_PURGING);
771	}
772	VI_UNLOCK(vp);
773#endif
774
775	/*
776	 * We can expect fsync on any vnode at all if venus is purging it.
777	 * Venus can't very well answer the fsync request, now can it?
778	 * Hopefully, it won't have to, because hopefully, venus preserves
779	 * the (possibly untrue) invariant that it never purges an open
780	 * vnode.  Hopefully.
781	 */
782	if (cp->c_flags & C_PURGING)
783		return (0);
784
785	/* XXX: needs research */
786	return (0);
787	error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc);
788	CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n", error)););
789	return (error);
790}
791
792int
793coda_inactive(struct vop_inactive_args *ap)
794{
795	/*
796	 * XXX - at the moment, inactive doesn't look at cred, and doesn't
797	 * have a proc pointer.  Oops.
798	 */
799	/* true args */
800	struct vnode *vp = ap->a_vp;
801	struct cnode *cp = VTOC(vp);
802	struct ucred *cred __attribute__((unused)) = NULL;
803	struct thread *td __attribute__((unused)) = curthread;
804	/* upcall decl */
805	/* locals */
806
807	/*
808	 * We don't need to send inactive to venus - DCS.
809	 */
810	MARK_ENTRY(CODA_INACTIVE_STATS);
811	CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n",
812	    coda_f2s(&cp->c_fid), vp->v_mount)););
813	vp->v_object = NULL;
814
815	/*
816	 * If an array has been allocated to hold the symlink, deallocate it.
817	 */
818	if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) {
819		if (cp->c_symlink == NULL)
820			panic("coda_inactive: null symlink pointer in cnode");
821		CODA_FREE(cp->c_symlink, cp->c_symlen);
822		cp->c_flags &= ~C_SYMLINK;
823		cp->c_symlen = 0;
824	}
825
826	/*
827	 * Remove it from the table so it can't be found.
828	 */
829	coda_unsave(cp);
830	if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) {
831		myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p "
832		    "wasn't dying\n", vp));
833		panic("badness in coda_inactive\n");
834	}
835	if (IS_UNMOUNTING(cp)) {
836#ifdef	DEBUG
837		printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n",
838		    vrefcnt(vp), vp, cp);
839		if (cp->c_ovp != NULL)
840			printf("coda_inactive: cp->ovp != NULL use %d: vp "
841			    "%p, cp %p\n", vrefcnt(vp), vp, cp);
842#endif
843	} else
844		vgone(vp);
845	MARK_INT_SAT(CODA_INACTIVE_STATS);
846	return (0);
847}
848
849/*
850 * Remote filesystem operations having to do with directory manipulation.
851 */
852
853/*
854 * In FreeBSD, lookup returns the vnode locked.
855 */
856int
857coda_lookup(struct vop_cachedlookup_args *ap)
858{
859	/* true args */
860	struct vnode *dvp = ap->a_dvp;
861	struct cnode *dcp = VTOC(dvp);
862	struct vnode **vpp = ap->a_vpp;
863	/*
864	 * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest of
865	 * the string to xlate, and that we must try to get at least
866	 * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth.  I
867	 * could be wrong.
868	 */
869	struct componentname  *cnp = ap->a_cnp;
870	struct ucred *cred = cnp->cn_cred;
871	struct thread *td = cnp->cn_thread;
872	/* locals */
873	struct cnode *cp;
874	const char *nm = cnp->cn_nameptr;
875	int len = cnp->cn_namelen;
876	struct CodaFid VFid;
877	int vtype;
878	int error = 0;
879
880	MARK_ENTRY(CODA_LOOKUP_STATS);
881	CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", nm,
882	    coda_f2s(&dcp->c_fid))););
883
884	/*
885	 * Check for lookup of control object.
886	 */
887	if (IS_CTL_NAME(dvp, nm, len)) {
888		*vpp = coda_ctlvp;
889		vref(*vpp);
890		MARK_INT_SAT(CODA_LOOKUP_STATS);
891		goto exit;
892	}
893	if (len+1 > CODA_MAXNAMLEN) {
894		MARK_INT_FAIL(CODA_LOOKUP_STATS);
895		CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, "
896		    "%s (%s)\n", coda_f2s(&dcp->c_fid), nm)););
897		*vpp = NULL;
898		error = EINVAL;
899		goto exit;
900	}
901
902	error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred,
903	    td->td_proc, &VFid, &vtype);
904	if (error) {
905		MARK_INT_FAIL(CODA_LOOKUP_STATS);
906		CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s "
907		    "(%s)%d\n", coda_f2s(&dcp->c_fid), nm, error)););
908		*vpp = NULL;
909	} else {
910		MARK_INT_SAT(CODA_LOOKUP_STATS);
911		CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s type %o "
912		    "result %d\n", coda_f2s(&VFid), vtype, error)););
913		cp = make_coda_node(&VFid, dvp->v_mount, vtype);
914    		*vpp = CTOV(cp);
915
916    		/*
917		 * Enter the new vnode in the namecache only if the top bit
918		 * isn't set.
919		 *
920		 * And don't enter a new vnode for an invalid one!
921		 */
922		if (!(vtype & CODA_NOCACHE) && (cnp->cn_flags & MAKEENTRY))
923			cache_enter(dvp, *vpp, cnp);
924	}
925exit:
926	/*
927	 * If we are creating, and this was the last name to be looked up,
928	 * and the error was ENOENT, then there really shouldn't be an error
929	 * and we can make the leaf NULL and return success.  Since this is
930	 * supposed to work under Mach as well as FreeBSD, we're leaving this
931	 * fn wrapped.  We also must tell lookup/namei that we need to save
932	 * the last component of the name.  (Create will have to free the
933	 * name buffer later...lucky us...).
934	 */
935	if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME))
936	    && (cnp->cn_flags & ISLASTCN) && (error == ENOENT)) {
937		error = EJUSTRETURN;
938		cnp->cn_flags |= SAVENAME;
939		*ap->a_vpp = NULL;
940	}
941
942	/*
943	 * If we are removing, and we are at the last element, and we found
944	 * it, then we need to keep the name around so that the removal will
945	 * go ahead as planned.  Unfortunately, this will probably also lock
946	 * the to-be-removed vnode, which may or may not be a good idea.
947	 * I'll have to look at the bits of coda_remove to make sure.  We'll
948	 * only save the name if we did in fact find the name, otherwise
949	 * coda_remove won't have a chance to free the pathname.
950	 */
951	if ((cnp->cn_nameiop == DELETE) && (cnp->cn_flags & ISLASTCN)
952	    && !error)
953		cnp->cn_flags |= SAVENAME;
954
955	/*
956	 * If the lookup went well, we need to (potentially?) unlock the
957	 * parent, and lock the child.  We are only responsible for checking
958	 * to see if the parent is supposed to be unlocked before we return.
959	 * We must always lock the child (provided there is one, and (the
960	 * parent isn't locked or it isn't the same as the parent.)  Simple,
961	 * huh?  We can never leave the parent locked unless we are ISLASTCN.
962	 */
963	if (!error || (error == EJUSTRETURN)) {
964		if (cnp->cn_flags & ISDOTDOT) {
965			VOP_UNLOCK(dvp, 0);
966			/*
967			 * The parent is unlocked.  As long as there is a
968			 * child, lock it without bothering to check anything
969			 * else.
970			 */
971			if (*ap->a_vpp)
972				vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY);
973			vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE);
974		} else {
975			/*
976			 * The parent is locked, and may be the same as the
977			 * child.  If different, go ahead and lock it.
978			 */
979			if (*ap->a_vpp && (*ap->a_vpp != dvp))
980				vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY);
981		}
982	} else {
983		/*
984		 * If the lookup failed, we need to ensure that the leaf is
985		 * NULL.
986		 *
987		 * Don't change any locking?
988		 */
989		*ap->a_vpp = NULL;
990	}
991	return (error);
992}
993
994/*ARGSUSED*/
995int
996coda_create(struct vop_create_args *ap)
997{
998	/* true args */
999	struct vnode *dvp = ap->a_dvp;
1000	struct cnode *dcp = VTOC(dvp);
1001	struct vattr *va = ap->a_vap;
1002	int exclusive = 1;
1003	int mode = ap->a_vap->va_mode;
1004	struct vnode **vpp = ap->a_vpp;
1005	struct componentname  *cnp = ap->a_cnp;
1006	struct ucred *cred = cnp->cn_cred;
1007	struct thread *td = cnp->cn_thread;
1008	/* locals */
1009	int error;
1010	struct cnode *cp;
1011	const char *nm = cnp->cn_nameptr;
1012	int len = cnp->cn_namelen;
1013	struct CodaFid VFid;
1014	struct vattr attr;
1015
1016	MARK_ENTRY(CODA_CREATE_STATS);
1017
1018	/*
1019	 * All creates are exclusive XXX.
1020	 *
1021	 * I'm assuming the 'mode' argument is the file mode bits XXX.
1022	 *
1023	 * Check for create of control object.
1024	 */
1025	if (IS_CTL_NAME(dvp, nm, len)) {
1026		*vpp = (struct vnode *)0;
1027		MARK_INT_FAIL(CODA_CREATE_STATS);
1028		return (EACCES);
1029	}
1030	error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive,
1031	    mode, va, cred, td->td_proc, &VFid, &attr);
1032	if (!error) {
1033		/*
1034		 * If this is an exclusive create, panic if the file already
1035		 * exists.
1036		 *
1037		 * Venus should have detected the file and reported EEXIST.
1038		 */
1039		if ((exclusive == 1) && (coda_find(&VFid) != NULL))
1040	  	  	panic("cnode existed for newly created file!");
1041		cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type);
1042		*vpp = CTOV(cp);
1043
1044		/*
1045		 * Update va to reflect the new attributes.
1046		 */
1047		(*va) = attr;
1048
1049		/*
1050		 * Update the attribute cache and mark it as valid.
1051		 */
1052		if (coda_attr_cache) {
1053			VTOC(*vpp)->c_vattr = attr;
1054			VTOC(*vpp)->c_flags |= C_VATTR;
1055		}
1056
1057		/*
1058		 * Invalidate the parent's attr cache, the modification time
1059		 * has changed.
1060		 */
1061		VTOC(dvp)->c_flags &= ~C_VATTR;
1062		cache_enter(dvp, *vpp, cnp);
1063		CODADEBUG(CODA_CREATE, myprintf(("create: %s, result %d\n",
1064		    coda_f2s(&VFid), error)););
1065	} else {
1066		*vpp = (struct vnode *)0;
1067		CODADEBUG(CODA_CREATE, myprintf(("create error %d\n",
1068		    error)););
1069	}
1070	if (!error) {
1071		if (cnp->cn_flags & MAKEENTRY)
1072			cache_enter(dvp, *vpp, cnp);
1073		if (cnp->cn_flags & LOCKLEAF)
1074			vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY);
1075	} else if (error == ENOENT) {
1076		/*
1077		 * XXXRW: We only enter a negative entry if ENOENT is
1078		 * returned, not other errors.  But will Venus invalidate dvp
1079		 * properly in all cases when new files appear via the
1080		 * network rather than a local operation?
1081		 */
1082		if (cnp->cn_flags & MAKEENTRY)
1083			cache_enter(dvp, NULL, cnp);
1084	}
1085	return (error);
1086}
1087
1088int
1089coda_remove(struct vop_remove_args *ap)
1090{
1091	/* true args */
1092	struct vnode *vp = ap->a_vp;
1093	struct vnode *dvp = ap->a_dvp;
1094	struct cnode *cp = VTOC(dvp);
1095	struct componentname  *cnp = ap->a_cnp;
1096	struct ucred *cred = cnp->cn_cred;
1097	struct thread *td = cnp->cn_thread;
1098	/* locals */
1099	int error;
1100	const char *nm = cnp->cn_nameptr;
1101	int len = cnp->cn_namelen;
1102#if 0
1103	struct cnode *tp;
1104#endif
1105
1106	MARK_ENTRY(CODA_REMOVE_STATS);
1107	CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", nm,
1108	    coda_f2s(&cp->c_fid))););
1109
1110	/*
1111	 * Check for remove of control object.
1112	 */
1113	if (IS_CTL_NAME(dvp, nm, len)) {
1114		MARK_INT_FAIL(CODA_REMOVE_STATS);
1115		return (ENOENT);
1116	}
1117
1118	/*
1119	 * Invalidate the parent's attr cache, the modification time has
1120	 * changed.  We don't yet know if the last reference to the file is
1121	 * being removed, but we do know the reference count on the child has
1122	 * changed, so invalidate its attr cache also.
1123	 */
1124	VTOC(dvp)->c_flags &= ~C_VATTR;
1125	VTOC(vp)->c_flags &= ~(C_VATTR | C_ACCCACHE);
1126	error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred,
1127	    td->td_proc);
1128	cache_purge(vp);
1129	CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)););
1130	return (error);
1131}
1132
1133int
1134coda_link(struct vop_link_args *ap)
1135{
1136	/* true args */
1137	struct vnode *vp = ap->a_vp;
1138	struct cnode *cp = VTOC(vp);
1139	struct vnode *tdvp = ap->a_tdvp;
1140	struct cnode *tdcp = VTOC(tdvp);
1141	struct componentname *cnp = ap->a_cnp;
1142	struct ucred *cred = cnp->cn_cred;
1143	struct thread *td = cnp->cn_thread;
1144	/* locals */
1145	int error;
1146	const char *nm = cnp->cn_nameptr;
1147	int len = cnp->cn_namelen;
1148
1149	MARK_ENTRY(CODA_LINK_STATS);
1150
1151	if (codadebug & CODADBGMSK(CODA_LINK)) {
1152		myprintf(("nb_link:   vp fid: %s\n", coda_f2s(&cp->c_fid)));
1153		myprintf(("nb_link: tdvp fid: %s)\n",
1154		    coda_f2s(&tdcp->c_fid)));
1155	}
1156	if (codadebug & CODADBGMSK(CODA_LINK)) {
1157		myprintf(("link:   vp fid: %s\n", coda_f2s(&cp->c_fid)));
1158		myprintf(("link: tdvp fid: %s\n", coda_f2s(&tdcp->c_fid)));
1159	}
1160
1161	/*
1162	 * Check for link to/from control object.
1163	 */
1164	if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) {
1165		MARK_INT_FAIL(CODA_LINK_STATS);
1166		return (EACCES);
1167	}
1168	error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len,
1169	    cred, td->td_proc);
1170
1171	/*
1172	 * Invalidate the parent's attr cache, the modification time has
1173	 * changed.
1174	 */
1175	VTOC(tdvp)->c_flags &= ~C_VATTR;
1176	VTOC(vp)->c_flags &= ~C_VATTR;
1177	CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)););
1178	return (error);
1179}
1180
1181int
1182coda_rename(struct vop_rename_args *ap)
1183{
1184	/* true args */
1185	struct vnode *fvp = ap->a_fvp;
1186	struct vnode *tvp = ap->a_tvp;
1187	struct vnode *odvp = ap->a_fdvp;
1188	struct cnode *odcp = VTOC(odvp);
1189	struct componentname  *fcnp = ap->a_fcnp;
1190	struct vnode *ndvp = ap->a_tdvp;
1191	struct cnode *ndcp = VTOC(ndvp);
1192	struct componentname  *tcnp = ap->a_tcnp;
1193	struct ucred *cred = fcnp->cn_cred;
1194	struct thread *td = fcnp->cn_thread;
1195	/* true args */
1196	int error;
1197	const char *fnm = fcnp->cn_nameptr;
1198	int flen = fcnp->cn_namelen;
1199	const char *tnm = tcnp->cn_nameptr;
1200	int tlen = tcnp->cn_namelen;
1201
1202	MARK_ENTRY(CODA_RENAME_STATS);
1203
1204	/*
1205	 * Check for rename involving control object.
1206	 */
1207	if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) {
1208		MARK_INT_FAIL(CODA_RENAME_STATS);
1209		return (EACCES);
1210	}
1211
1212	/*
1213	 * Remove the entries for both source and target directories, which
1214	 * should catch references to the children.  Perhaps we could purge
1215	 * less?
1216	 */
1217	cache_purge(odvp);
1218	cache_purge(ndvp);
1219
1220	/*
1221	 * Invalidate parent directories as modification times have changed.
1222	 * Invalidate access cache on renamed file as rights may have
1223	 * changed.
1224	 */
1225	VTOC(odvp)->c_flags &= ~C_VATTR;
1226	VTOC(ndvp)->c_flags &= ~C_VATTR;
1227	VTOC(fvp)->c_flags &= ~C_ACCCACHE;
1228	if (flen+1 > CODA_MAXNAMLEN) {
1229		MARK_INT_FAIL(CODA_RENAME_STATS);
1230		error = EINVAL;
1231		goto exit;
1232	}
1233	if (tlen+1 > CODA_MAXNAMLEN) {
1234		MARK_INT_FAIL(CODA_RENAME_STATS);
1235		error = EINVAL;
1236		goto exit;
1237	}
1238	error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm,
1239	    flen, tnm, tlen, cred, td->td_proc);
1240exit:
1241	CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error)););
1242
1243	/*
1244	 * Update namecache to reflect that the names of various objects may
1245	 * have changed (or gone away entirely).
1246	 */
1247	cache_purge(fvp);
1248	cache_purge(tvp);
1249
1250	/*
1251	 * Release parents first, then children.
1252	 */
1253	vrele(odvp);
1254	if (tvp) {
1255		if (tvp == ndvp)
1256			vrele(ndvp);
1257		else
1258			vput(ndvp);
1259		vput(tvp);
1260	} else
1261		vput(ndvp);
1262	vrele(fvp);
1263	return (error);
1264}
1265
1266int
1267coda_mkdir(struct vop_mkdir_args *ap)
1268{
1269	/* true args */
1270	struct vnode *dvp = ap->a_dvp;
1271	struct cnode *dcp = VTOC(dvp);
1272	struct componentname  *cnp = ap->a_cnp;
1273	struct vattr *va = ap->a_vap;
1274	struct vnode **vpp = ap->a_vpp;
1275	struct ucred *cred = cnp->cn_cred;
1276	struct thread *td = cnp->cn_thread;
1277	/* locals */
1278	int error;
1279	const char *nm = cnp->cn_nameptr;
1280	int len = cnp->cn_namelen;
1281	struct cnode *cp;
1282	struct CodaFid VFid;
1283	struct vattr ova;
1284
1285	MARK_ENTRY(CODA_MKDIR_STATS);
1286
1287	/*
1288	 * Check for mkdir of target object.
1289	 */
1290	if (IS_CTL_NAME(dvp, nm, len)) {
1291		*vpp = (struct vnode *)0;
1292		MARK_INT_FAIL(CODA_MKDIR_STATS);
1293		return (EACCES);
1294	}
1295	if (len+1 > CODA_MAXNAMLEN) {
1296		*vpp = (struct vnode *)0;
1297		MARK_INT_FAIL(CODA_MKDIR_STATS);
1298		return (EACCES);
1299	}
1300	error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred,
1301	    td->td_proc, &VFid, &ova);
1302	if (!error) {
1303		if (coda_find(&VFid) != NULL)
1304			panic("cnode existed for newly created directory!");
1305		cp =  make_coda_node(&VFid, dvp->v_mount, va->va_type);
1306		*vpp = CTOV(cp);
1307
1308		/*
1309		 * Enter the new vnode in the Name Cache.
1310		 */
1311		if (cnp->cn_flags & MAKEENTRY)
1312			cache_enter(dvp, *vpp, cnp);
1313
1314		/*
1315		 * Update the attr cache and mark as valid.
1316		 */
1317		if (coda_attr_cache) {
1318			VTOC(*vpp)->c_vattr = ova;
1319			VTOC(*vpp)->c_flags |= C_VATTR;
1320		}
1321
1322		/*
1323		 * Invalidate the parent's attr cache, the modification time
1324		 * has changed.
1325		 */
1326		VTOC(dvp)->c_flags &= ~C_VATTR;
1327		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
1328		CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n",
1329		    coda_f2s(&VFid), error)););
1330	} else {
1331		*vpp = NULL;
1332		CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error)););
1333	}
1334	return (error);
1335}
1336
1337int
1338coda_rmdir(struct vop_rmdir_args *ap)
1339{
1340	/* true args */
1341	struct vnode *vp = ap->a_vp;
1342	struct vnode *dvp = ap->a_dvp;
1343	struct cnode *dcp = VTOC(dvp);
1344	struct componentname  *cnp = ap->a_cnp;
1345	struct ucred *cred = cnp->cn_cred;
1346	struct thread *td = cnp->cn_thread;
1347	/* true args */
1348	int error;
1349	const char *nm = cnp->cn_nameptr;
1350	int len = cnp->cn_namelen;
1351#if 0
1352	struct cnode *cp;
1353#endif
1354
1355	MARK_ENTRY(CODA_RMDIR_STATS);
1356
1357	/*
1358	 * Check for rmdir of control object.
1359	 */
1360	if (IS_CTL_NAME(dvp, nm, len)) {
1361		MARK_INT_FAIL(CODA_RMDIR_STATS);
1362		return (ENOENT);
1363	}
1364
1365	/*
1366	 * Possibly somewhat conservative purging, perhaps we just need to
1367	 * purge vp?
1368	 */
1369	cache_purge(dvp);
1370	cache_purge(vp);
1371
1372	/*
1373	 * Invalidate the parent's attr cache, the modification time has
1374	 * changed.
1375	 */
1376	dcp->c_flags &= ~C_VATTR;
1377	error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred,
1378	    td->td_proc);
1379	CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)););
1380	return (error);
1381}
1382
1383int
1384coda_symlink(struct vop_symlink_args *ap)
1385{
1386	/* true args */
1387	struct vnode *tdvp = ap->a_dvp;
1388	struct cnode *tdcp = VTOC(tdvp);
1389	struct componentname *cnp = ap->a_cnp;
1390	struct vattr *tva = ap->a_vap;
1391	char *path = ap->a_target;
1392	struct ucred *cred = cnp->cn_cred;
1393	struct thread *td = cnp->cn_thread;
1394	struct vnode **vpp = ap->a_vpp;
1395	/* locals */
1396	int error;
1397
1398	/*-
1399	 * XXX I'm assuming the following things about coda_symlink's
1400	 * arguments:
1401	 *       t(foo) is the new name/parent/etc being created.
1402	 *       lname is the contents of the new symlink.
1403	 */
1404	char *nm = cnp->cn_nameptr;
1405	int len = cnp->cn_namelen;
1406	int plen = strlen(path);
1407
1408	/*
1409	 * Here's the strategy for the moment: perform the symlink, then do a
1410	 * lookup to grab the resulting vnode.  I know this requires two
1411	 * communications with Venus for a new sybolic link, but that's the
1412	 * way the ball bounces.  I don't yet want to change the way the Mach
1413	 * symlink works.  When Mach support is deprecated, we should change
1414	 * symlink so that the common case returns the resultant vnode in a
1415	 * vpp argument.
1416	 */
1417	MARK_ENTRY(CODA_SYMLINK_STATS);
1418
1419	/*
1420	 * Check for symlink of control object.
1421	 */
1422	if (IS_CTL_NAME(tdvp, nm, len)) {
1423		MARK_INT_FAIL(CODA_SYMLINK_STATS);
1424		return (EACCES);
1425	}
1426	if (plen+1 > CODA_MAXPATHLEN) {
1427		MARK_INT_FAIL(CODA_SYMLINK_STATS);
1428		return (EINVAL);
1429	}
1430	if (len+1 > CODA_MAXNAMLEN) {
1431		MARK_INT_FAIL(CODA_SYMLINK_STATS);
1432		error = EINVAL;
1433		goto exit;
1434	}
1435	error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len,
1436	    tva, cred, td->td_proc);
1437
1438	/*
1439	 * Invalidate the parent's attr cache, the modification time has
1440	 * changed.
1441	 */
1442	tdcp->c_flags &= ~C_VATTR;
1443	if (error == 0)
1444		error = VOP_LOOKUP(tdvp, vpp, cnp);
1445exit:
1446	CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)););
1447	return (error);
1448}
1449
1450/*
1451 * Read directory entries.
1452 *
1453 * XXX: This forwards the operator straight to the cache vnode using
1454 * VOP_READDIR(), rather than calling venus_readdir().  Why?
1455 */
1456int
1457coda_readdir(struct vop_readdir_args *ap)
1458{
1459	/* true args */
1460	struct vnode *vp = ap->a_vp;
1461	struct cnode *cp = VTOC(vp);
1462	struct uio *uiop = ap->a_uio;
1463	struct ucred *cred = ap->a_cred;
1464	int *eofflag = ap->a_eofflag;
1465	u_long **cookies = ap->a_cookies;
1466	int *ncookies = ap->a_ncookies;
1467	struct thread *td = ap->a_uio->uio_td;
1468	/* upcall decl */
1469	/* locals */
1470	int error = 0;
1471	int opened_internally = 0;
1472
1473	MARK_ENTRY(CODA_READDIR_STATS);
1474	CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %zd, %lld, %d)\n",
1475	    (void *)uiop->uio_iov->iov_base, uiop->uio_resid,
1476	    (long long)uiop->uio_offset, uiop->uio_segflg)););
1477
1478	/*
1479	 * Check for readdir of control object.
1480	 */
1481	if (IS_CTL_VP(vp)) {
1482		MARK_INT_FAIL(CODA_READDIR_STATS);
1483		return (ENOENT);
1484	}
1485
1486	/*
1487	 * If directory is not already open do an "internal open" on it.
1488	 *
1489	 * XXX: Why would this happen?  For files, there's memory mapping,
1490	 * execution, and other kernel access paths such as ktrace.  For
1491	 * directories, it is less clear.
1492	 */
1493	if (cp->c_ovp == NULL) {
1494		opened_internally = 1;
1495		MARK_INT_GEN(CODA_OPEN_STATS);
1496		error = VOP_OPEN(vp, FREAD, cred, td, NULL);
1497		printf("coda_readdir: Internally Opening %p\n", vp);
1498		if (error) {
1499			printf("coda_readdir: VOP_OPEN on container failed "
1500			   "%d\n", error);
1501			return (error);
1502		}
1503	}
1504
1505	/*
1506	 * Have UFS handle the call.
1507	 */
1508	CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, "
1509	    "refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount)););
1510	vn_lock(cp->c_ovp, LK_SHARED | LK_RETRY);
1511	error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies,
1512	    cookies);
1513	VOP_UNLOCK(cp->c_ovp, 0);
1514	if (error)
1515		MARK_INT_FAIL(CODA_READDIR_STATS);
1516	else
1517		MARK_INT_SAT(CODA_READDIR_STATS);
1518
1519	/*
1520	 * Do an "internal close" if necessary.
1521	 */
1522	if (opened_internally) {
1523		MARK_INT_GEN(CODA_CLOSE_STATS);
1524		(void)VOP_CLOSE(vp, FREAD, cred, td);
1525	}
1526	return (error);
1527}
1528
1529int
1530coda_reclaim(struct vop_reclaim_args *ap)
1531{
1532	/* true args */
1533	struct vnode *vp = ap->a_vp;
1534	struct cnode *cp = VTOC(vp);
1535	/* upcall decl */
1536	/* locals */
1537
1538	/*
1539	 * Forced unmount/flush will let vnodes with non-zero use be
1540	 * destroyed!
1541	 */
1542	ENTRY;
1543
1544	if (IS_UNMOUNTING(cp)) {
1545#ifdef	DEBUG
1546		if (VTOC(vp)->c_ovp) {
1547			if (IS_UNMOUNTING(cp))
1548				printf("coda_reclaim: c_ovp not void: vp "
1549				    "%p, cp %p\n", vp, cp);
1550		}
1551#endif
1552	}
1553	cache_purge(vp);
1554	coda_free(VTOC(vp));
1555	vp->v_data = NULL;
1556	vp->v_object = NULL;
1557	return (0);
1558}
1559
1560int
1561coda_lock(struct vop_lock1_args *ap)
1562{
1563	/* true args */
1564	struct vnode *vp = ap->a_vp;
1565	struct cnode *cp = VTOC(vp);
1566	/* upcall decl */
1567	/* locals */
1568
1569	ENTRY;
1570	if ((ap->a_flags & LK_INTERLOCK) == 0) {
1571		VI_LOCK(vp);
1572		ap->a_flags |= LK_INTERLOCK;
1573	}
1574	if (coda_lockdebug)
1575		myprintf(("Attempting lock on %s\n", coda_f2s(&cp->c_fid)));
1576	return (vop_stdlock(ap));
1577}
1578
1579int
1580coda_unlock(struct vop_unlock_args *ap)
1581{
1582	/* true args */
1583	struct vnode *vp = ap->a_vp;
1584	struct cnode *cp = VTOC(vp);
1585	/* upcall decl */
1586	/* locals */
1587
1588	ENTRY;
1589	if (coda_lockdebug)
1590		myprintf(("Attempting unlock on %s\n",
1591		    coda_f2s(&cp->c_fid)));
1592	return (vop_stdunlock(ap));
1593}
1594
1595int
1596coda_islocked(struct vop_islocked_args *ap)
1597{
1598	/* true args */
1599
1600	ENTRY;
1601	return (vop_stdislocked(ap));
1602}
1603
1604static void
1605coda_print_vattr(struct vattr *attr)
1606{
1607	char *typestr;
1608
1609	switch (attr->va_type) {
1610	case VNON:
1611		typestr = "VNON";
1612		break;
1613
1614	case VREG:
1615		typestr = "VREG";
1616		break;
1617
1618	case VDIR:
1619		typestr = "VDIR";
1620		break;
1621
1622	case VBLK:
1623		typestr = "VBLK";
1624		break;
1625
1626	case VCHR:
1627		typestr = "VCHR";
1628		break;
1629
1630	case VLNK:
1631		typestr = "VLNK";
1632		break;
1633
1634	case VSOCK:
1635		typestr = "VSCK";
1636		break;
1637
1638	case VFIFO:
1639		typestr = "VFFO";
1640		break;
1641
1642	case VBAD:
1643		typestr = "VBAD";
1644		break;
1645
1646	default:
1647		typestr = "????";
1648		break;
1649	}
1650	myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n",
1651	    typestr, (int)attr->va_mode, (int)attr->va_uid,
1652	    (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev));
1653	myprintf(("      fileid %d nlink %d size %d blocksize %d bytes %d\n",
1654	    (int)attr->va_fileid, (int)attr->va_nlink, (int)attr->va_size,
1655	    (int)attr->va_blocksize,(int)attr->va_bytes));
1656	myprintf(("      gen %ld flags %ld vaflags %d\n", attr->va_gen,
1657	    attr->va_flags, attr->va_vaflags));
1658	myprintf(("      atime sec %d nsec %d\n", (int)attr->va_atime.tv_sec,
1659	    (int)attr->va_atime.tv_nsec));
1660	myprintf(("      mtime sec %d nsec %d\n", (int)attr->va_mtime.tv_sec,
1661	    (int)attr->va_mtime.tv_nsec));
1662	myprintf(("      ctime sec %d nsec %d\n", (int)attr->va_ctime.tv_sec,
1663	    (int)attr->va_ctime.tv_nsec));
1664}
1665
1666/*
1667 * How to print a ucred.
1668 */
1669void
1670coda_print_cred(struct ucred *cred)
1671{
1672	int i;
1673
1674	myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid));
1675	for (i=0; i < cred->cr_ngroups; i++)
1676		myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i]));
1677	myprintf(("\n"));
1678}
1679
1680/*
1681 * Return a vnode for the given fid.  If no cnode exists for this fid create
1682 * one and put it in a table hashed by coda_f2i().  If the cnode for this fid
1683 * is already in the table return it (ref count is incremented by coda_find.
1684 * The cnode will be flushed from the table when coda_inactive calls
1685 * coda_unsave.
1686 */
1687struct cnode *
1688make_coda_node(struct CodaFid *fid, struct mount *vfsp, short type)
1689{
1690	struct cnode *cp;
1691	struct vnode *vp;
1692	int err;
1693
1694	/*
1695	 * XXXRW: This really needs a moderate amount of reworking.  We need
1696	 * to properly tolerate failures of getnewvnode() and insmntque(),
1697	 * and callers need to be able to accept an error back from
1698	 * make_coda_node.  There may also be more general issues in how we
1699	 * handle forced unmount.  Finally, if/when Coda loses its dependency
1700	 * on Giant, the ordering of this needs rethinking.
1701	 */
1702	cp = coda_find(fid);
1703	if (cp != NULL) {
1704		vref(CTOV(cp));
1705		return (cp);
1706	}
1707	cp = coda_alloc();
1708	cp->c_fid = *fid;
1709	err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp);
1710	if (err)
1711		panic("coda: getnewvnode returned error %d\n", err);
1712	vp->v_data = cp;
1713	vp->v_type = type;
1714	cp->c_vnode = vp;
1715	coda_save(cp);
1716	err = insmntque(vp, vfsp);
1717	if (err != 0)
1718		printf("coda: insmntque failed: error %d", err);
1719	return (cp);
1720}
1721
1722int
1723coda_pathconf(struct vop_pathconf_args *ap)
1724{
1725
1726	switch (ap->a_name) {
1727	case _PC_NAME_MAX:
1728		*ap->a_retval = CODA_MAXNAMLEN;
1729		return (0);
1730
1731	case _PC_PATH_MAX:
1732		*ap->a_retval = CODA_MAXPATHLEN;
1733		return (0);
1734
1735	default:
1736		return (vop_stdpathconf(ap));
1737	}
1738}
1739