darwin-access-avoid-confusing-cp-20071015
[openafs.git] / src / afs / DARWIN / osi_vnodeops.c
1 /*
2  * Portions Copyright (c) 2003 Apple Computer, Inc.  All rights reserved.
3  */
4 #include <afsconfig.h>
5 #include <afs/param.h>
6
7 RCSID
8     ("$Header$");
9
10 #include <afs/sysincludes.h>    /* Standard vendor system headers */
11 #include <afsincludes.h>        /* Afs-based standard headers */
12 #include <afs/afs_stats.h>      /* statistics */
13 #include <sys/malloc.h>
14 #include <sys/namei.h>
15 #include <sys/ubc.h>
16 #if defined(AFS_DARWIN70_ENV)
17 #include <vfs/vfs_support.h>
18 #endif /* defined(AFS_DARWIN70_ENV) */
19 #ifdef AFS_DARWIN80_ENV
20 #include <sys/vnode_if.h>
21 #include <sys/kauth.h>
22 #endif
23
24 #ifdef AFS_DARWIN80_ENV
25 #define VOPPREF(x) &vnop_ ## x
26 #define VOPPROT(x) vnop_ ## x
27 #define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
28   ubc_upl_abort_range((pl), (offset), (size), (flags))
29 #define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
30   ubc_upl_commit_range((pl), (offset), (size), (flags))
31 #define OSI_UPL_MAP(upl, offset) ubc_upl_map((upl), (offset))
32 #define OSI_UPL_UNMAP(upl) ubc_upl_unmap((upl))
33 #define VOP_ABORTOP(x, y)
34 #else
35 #define VOPPREF(x) &vop_ ## x
36 #define VOPPROT(x) vop_ ## x
37 #define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
38   kernel_upl_abort_range((pl), (offset), (size), (flags))
39 #define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
40   kernel_upl_commit_range((pl), (offset), (size), (flags), \
41                           UPL_GET_INTERNAL_PAGE_LIST((pl)),\
42                                     MAX_UPL_TRANSFER)
43 #define OSI_UPL_MAP(upl, offset) kernel_upl_map(kernel_map, (upl), (offset))
44 #define OSI_UPL_UNMAP(upl) kernel_upl_unmap(kernel_map, (upl))
45 #endif
46
47 extern char afs_zeros[AFS_ZEROS];
48
49 int afs_vop_lookup(struct VOPPROT(lookup_args) *);
50 int afs_vop_create(struct VOPPROT(create_args) *);
51 int afs_vop_mknod(struct VOPPROT(mknod_args) *);
52 int afs_vop_open(struct VOPPROT(open_args) *);
53 int afs_vop_close(struct VOPPROT(close_args) *);
54 int afs_vop_access(struct VOPPROT(access_args) *);
55 int afs_vop_getattr(struct VOPPROT(getattr_args) *);
56 int afs_vop_setattr(struct VOPPROT(setattr_args) *);
57 int afs_vop_read(struct VOPPROT(read_args) *);
58 int afs_vop_write(struct VOPPROT(write_args) *);
59 int afs_vop_pagein(struct VOPPROT(pagein_args) *);
60 int afs_vop_pageout(struct VOPPROT(pageout_args) *);
61 int afs_vop_ioctl(struct VOPPROT(ioctl_args) *);
62 int afs_vop_select(struct VOPPROT(select_args) *);
63 int afs_vop_mmap(struct VOPPROT(mmap_args) *);
64 int afs_vop_fsync(struct VOPPROT(fsync_args) *);
65 int afs_vop_remove(struct VOPPROT(remove_args) *);
66 int afs_vop_link(struct VOPPROT(link_args) *);
67 int afs_vop_rename(struct VOPPROT(rename_args) *);
68 int afs_vop_mkdir(struct VOPPROT(mkdir_args) *);
69 int afs_vop_rmdir(struct VOPPROT(rmdir_args) *);
70 int afs_vop_symlink(struct VOPPROT(symlink_args) *);
71 int afs_vop_readdir(struct VOPPROT(readdir_args) *);
72 int afs_vop_readlink(struct VOPPROT(readlink_args) *);
73 #if !defined(AFS_DARWIN70_ENV)
74 extern int ufs_abortop(struct vop_abortop_args *);
75 #endif /* !defined(AFS_DARWIN70_ENV) */
76 int afs_vop_inactive(struct VOPPROT(inactive_args) *);
77 int afs_vop_reclaim(struct VOPPROT(reclaim_args) *);
78 int afs_vop_strategy(struct VOPPROT(strategy_args) *);
79 int afs_vop_pathconf(struct VOPPROT(pathconf_args) *);
80 int afs_vop_advlock(struct VOPPROT(advlock_args) *);
81 int afs_vop_blktooff __P((struct VOPPROT(blktooff_args) *));
82 int afs_vop_offtoblk __P((struct VOPPROT(offtoblk_args) *));
83 #ifndef AFS_DARWIN80_ENV
84 int afs_vop_truncate(struct VOPPROT(truncate_args) *);
85 int afs_vop_update(struct VOPPROT(update_args) *);
86 int afs_vop_lock(struct VOPPROT(lock_args) *);
87 int afs_vop_unlock(struct VOPPROT(unlock_args) *);
88 int afs_vop_bmap(struct VOPPROT(bmap_args) *);
89 int afs_vop_seek(struct VOPPROT(seek_args) *);
90 int afs_vop_cmap __P((struct VOPPROT(cmap_args) *));
91 int afs_vop_print(struct VOPPROT(print_args) *);
92 int afs_vop_islocked(struct VOPPROT(islocked_args) *);
93 #endif
94
95 #define afs_vop_opnotsupp \
96         ((int (*) __P((struct  vop_reallocblks_args *)))eopnotsupp)
97 #define afs_vop_valloc afs_vop_opnotsupp
98 #define afs_vop_vfree afs_vop_opnotsupp
99 #define afs_vop_blkatoff afs_vop_opnotsupp
100 #define afs_vop_reallocblks afs_vop_opnotsupp
101
102 /* Global vfs data structures for AFS. */
103 int (**afs_vnodeop_p) ();
104
105 #define VOPFUNC int (*)(void *)
106
107 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
108     {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
109     {VOPPREF(lookup_desc), (VOPFUNC)afs_vop_lookup},    /* lookup */
110     {VOPPREF(create_desc), (VOPFUNC)afs_vop_create},    /* create */
111     {VOPPREF(mknod_desc), (VOPFUNC)afs_vop_mknod},      /* mknod */
112     {VOPPREF(open_desc), (VOPFUNC)afs_vop_open},        /* open */
113     {VOPPREF(close_desc), (VOPFUNC)afs_vop_close},      /* close */
114     {VOPPREF(access_desc), (VOPFUNC)afs_vop_access},    /* access */
115     {VOPPREF(getattr_desc), (VOPFUNC)afs_vop_getattr},  /* getattr */
116     {VOPPREF(setattr_desc), (VOPFUNC)afs_vop_setattr},  /* setattr */
117     {VOPPREF(read_desc), (VOPFUNC)afs_vop_read},        /* read */
118     {VOPPREF(write_desc), (VOPFUNC)afs_vop_write},      /* write */
119     {VOPPREF(pagein_desc), (VOPFUNC)afs_vop_pagein},    /* read */
120     {VOPPREF(pageout_desc), (VOPFUNC)afs_vop_pageout},  /* write */
121     {VOPPREF(ioctl_desc), (VOPFUNC)afs_vop_ioctl},      /* XXX ioctl */
122     {VOPPREF(select_desc), (VOPFUNC)afs_vop_select},    /* select */
123     {VOPPREF(mmap_desc), (VOPFUNC)afs_vop_mmap},        /* mmap */
124     {VOPPREF(fsync_desc), (VOPFUNC)afs_vop_fsync},      /* fsync */
125 #ifndef AFS_DARWIN80_ENV
126     {VOPPREF(seek_desc), (VOPFUNC)afs_vop_seek},        /* seek */
127 #endif
128     {VOPPREF(remove_desc), (VOPFUNC)afs_vop_remove},    /* remove */
129     {VOPPREF(link_desc), (VOPFUNC)afs_vop_link},        /* link */
130     {VOPPREF(rename_desc), (VOPFUNC)afs_vop_rename},    /* rename */
131     {VOPPREF(mkdir_desc), (VOPFUNC)afs_vop_mkdir},      /* mkdir */
132     {VOPPREF(rmdir_desc), (VOPFUNC)afs_vop_rmdir},      /* rmdir */
133     {VOPPREF(symlink_desc), (VOPFUNC)afs_vop_symlink},  /* symlink */
134     {VOPPREF(readdir_desc), (VOPFUNC)afs_vop_readdir},  /* readdir */
135     {VOPPREF(readlink_desc), (VOPFUNC)afs_vop_readlink},        /* readlink */
136 #ifndef AFS_DARWIN80_ENV
137 #if defined(AFS_DARWIN70_ENV)
138     {VOPPREF(abortop_desc), (VOPFUNC)nop_abortop },             /* abortop */
139 #else /* ! defined(AFS_DARWIN70_ENV) */
140     /* Yes, we use the ufs_abortop call.  It just releases the namei
141      * buffer stuff */
142     {VOPPREF(abortop_desc), (VOPFUNC)ufs_abortop},      /* abortop */
143 #endif /* defined(AFS_DARWIN70_ENV) */
144 #endif
145     {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive},        /* inactive */
146     {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim},  /* reclaim */
147 #ifndef AFS_DARWIN80_ENV
148     {VOPPREF(lock_desc), (VOPFUNC)afs_vop_lock},        /* lock */
149     {VOPPREF(unlock_desc), (VOPFUNC)afs_vop_unlock},    /* unlock */
150     {VOPPREF(bmap_desc), (VOPFUNC)afs_vop_bmap},        /* bmap */
151 #endif
152 #ifdef AFS_DARWIN80_ENV
153     {VOPPREF(strategy_desc), (VOPFUNC)err_strategy},    /* strategy */
154 #else
155     {VOPPREF(strategy_desc), (VOPFUNC)afs_vop_strategy},        /* strategy */
156 #endif
157 #ifndef AFS_DARWIN80_ENV
158     {VOPPREF(print_desc), (VOPFUNC)afs_vop_print},      /* print */
159     {VOPPREF(islocked_desc), (VOPFUNC)afs_vop_islocked},        /* islocked */
160 #endif
161     {VOPPREF(pathconf_desc), (VOPFUNC)afs_vop_pathconf},        /* pathconf */
162     {VOPPREF(advlock_desc), (VOPFUNC)afs_vop_advlock},  /* advlock */
163 #ifndef AFS_DARWIN80_ENV
164     {VOPPREF(blkatoff_desc), (VOPFUNC)afs_vop_blkatoff},        /* blkatoff */
165     {VOPPREF(valloc_desc), (VOPFUNC)afs_vop_valloc},    /* valloc */
166     {VOPPREF(reallocblks_desc), (VOPFUNC)afs_vop_reallocblks},  /* reallocblks */
167     {VOPPREF(vfree_desc), (VOPFUNC)afs_vop_vfree},      /* vfree */
168     {VOPPREF(update_desc), (VOPFUNC)afs_vop_update},    /* update */
169     {VOPPREF(cmap_desc), (VOPFUNC)afs_vop_cmap},        /* cmap */
170     {VOPPREF(truncate_desc), (VOPFUNC)afs_vop_truncate},        /* truncate */
171 #endif
172     {VOPPREF(blktooff_desc), (VOPFUNC)afs_vop_blktooff},        /* blktooff */
173     {VOPPREF(offtoblk_desc), (VOPFUNC)afs_vop_offtoblk},        /* offtoblk */
174     {VOPPREF(bwrite_desc), (VOPFUNC)vn_bwrite},
175     {(struct vnodeop_desc *)NULL, (void (*)())NULL}
176 };
177 struct vnodeopv_desc afs_vnodeop_opv_desc =
178     { &afs_vnodeop_p, afs_vnodeop_entries };
179
180 #ifdef AFS_DARWIN80_ENV
181 /* vfs structures for incompletely initialized vnodes */
182 int (**afs_dead_vnodeop_p) ();
183
184 struct vnodeopv_entry_desc afs_dead_vnodeop_entries[] = {
185     {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
186     {VOPPREF(lookup_desc), (VOPFUNC)vn_default_error},  /* lookup */
187     {VOPPREF(create_desc), (VOPFUNC)err_create},        /* create */
188     {VOPPREF(mknod_desc), (VOPFUNC)err_mknod},  /* mknod */
189     {VOPPREF(open_desc), (VOPFUNC)err_open},    /* open */
190     {VOPPREF(close_desc), (VOPFUNC)err_close},  /* close */
191     {VOPPREF(access_desc), (VOPFUNC)err_access},        /* access */
192     {VOPPREF(getattr_desc), (VOPFUNC)err_getattr},      /* getattr */
193     {VOPPREF(setattr_desc), (VOPFUNC)err_setattr},      /* setattr */
194     {VOPPREF(read_desc), (VOPFUNC)err_read},    /* read */
195     {VOPPREF(write_desc), (VOPFUNC)err_write},  /* write */
196     {VOPPREF(pagein_desc), (VOPFUNC)err_pagein},        /* read */
197     {VOPPREF(pageout_desc), (VOPFUNC)err_pageout},      /* write */
198     {VOPPREF(ioctl_desc), (VOPFUNC)err_ioctl},  /* XXX ioctl */
199     {VOPPREF(select_desc), (VOPFUNC)nop_select},        /* select */
200     {VOPPREF(mmap_desc), (VOPFUNC)err_mmap},    /* mmap */
201     {VOPPREF(fsync_desc), (VOPFUNC)err_fsync},  /* fsync */
202     {VOPPREF(remove_desc), (VOPFUNC)err_remove},        /* remove */
203     {VOPPREF(link_desc), (VOPFUNC)err_link},    /* link */
204     {VOPPREF(rename_desc), (VOPFUNC)err_rename},        /* rename */
205     {VOPPREF(mkdir_desc), (VOPFUNC)err_mkdir},  /* mkdir */
206     {VOPPREF(rmdir_desc), (VOPFUNC)err_rmdir},  /* rmdir */
207     {VOPPREF(symlink_desc), (VOPFUNC)err_symlink},      /* symlink */
208     {VOPPREF(readdir_desc), (VOPFUNC)err_readdir},      /* readdir */
209     {VOPPREF(readlink_desc), (VOPFUNC)err_readlink},    /* readlink */
210     {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive},        /* inactive */
211     {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim},  /* reclaim */
212     {VOPPREF(strategy_desc), (VOPFUNC)err_strategy},    /* strategy */
213     {VOPPREF(pathconf_desc), (VOPFUNC)err_pathconf},    /* pathconf */
214     {VOPPREF(advlock_desc), (VOPFUNC)err_advlock},      /* advlock */
215     {VOPPREF(blktooff_desc), (VOPFUNC)err_blktooff},    /* blktooff */
216     {VOPPREF(offtoblk_desc), (VOPFUNC)err_offtoblk},    /* offtoblk */
217     {VOPPREF(bwrite_desc), (VOPFUNC)err_bwrite},
218     {(struct vnodeop_desc *)NULL, (void (*)())NULL}
219 };
220 struct vnodeopv_desc afs_dead_vnodeop_opv_desc =
221     { &afs_dead_vnodeop_p, afs_dead_vnodeop_entries };
222 #endif
223
224 #define GETNAME()       \
225     struct componentname *cnp = ap->a_cnp; \
226     char *name; \
227     MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
228     memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
229     name[cnp->cn_namelen] = '\0'
230
231 #define DROPNAME() FREE(name, M_TEMP)
232
233 void 
234 darwin_vn_hold(struct vnode *vp)
235 {
236     int haveGlock=ISAFS_GLOCK(); 
237     struct vcache *tvc = VTOAFS(vp);
238
239 #ifndef AFS_DARWIN80_ENV
240     tvc->states |= CUBCinit;
241 #endif
242 #ifdef AFS_DARWIN80_ENV
243     osi_Assert((tvc->states & CVInit) == 0);
244     if (tvc->states & CDeadVnode)
245        osi_Assert(!vnode_isinuse(vp, 1));
246 #endif
247     if (haveGlock) AFS_GUNLOCK(); 
248
249 #ifdef AFS_DARWIN80_ENV
250         if (vnode_get(vp)) {
251            /* being terminated. kernel won't give us a ref. Now what? our
252               callers don't expect us to fail */
253 #if 1
254            panic("vn_hold on terminating vnode");
255 #else           
256            if (haveGlock) AFS_GLOCK(); 
257            return;
258 #endif
259         }
260         if (vnode_ref(vp)) {
261 #if 1
262             panic("vn_hold on terminating vnode");
263 #else           
264             vnode_put(vp);
265             if (haveGlock) AFS_GLOCK(); 
266             return;
267 #endif
268         }
269         vnode_put(vp);
270 #else
271     /* vget needed for 0 ref'd vnode in GetVCache to not panic in vref.
272        vref needed for multiref'd vnode in vnop_remove not to deadlock
273        ourselves during vop_inactive, except we also need to not reinst
274        the ubc... so we just call VREF there now anyway. */
275
276     if (VREFCOUNT_GT(tvc, 0))
277         VREF(((struct vnode *)(vp))); 
278      else 
279         afs_vget(afs_globalVFS, 0, (vp));
280 #endif
281
282 #ifndef AFS_DARWIN80_ENV
283     if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) {
284         ubc_info_init(vp); 
285     }
286 #endif
287
288     if (haveGlock) AFS_GLOCK(); 
289 #ifndef AFS_DARWIN80_ENV
290     tvc->states &= ~CUBCinit;
291 #endif
292 }
293 int
294 afs_vop_lookup(ap)
295      struct VOPPROT(lookup_args)/* {
296                                  * struct vnodeop_desc * a_desc;
297                                  * struct vnode *a_dvp;
298                                  * struct vnode **a_vpp;
299                                  * struct componentname *a_cnp;
300                                  * } */ *ap;
301 {
302     int error;
303     struct vcache *vcp;
304     struct vnode *vp, *dvp;
305     register int flags = ap->a_cnp->cn_flags;
306     int lockparent;             /* 1 => lockparent flag is set */
307     int wantparent;             /* 1 => wantparent or lockparent flag */
308     struct proc *p;
309 #ifdef AFS_DARWIN80_ENV
310     vcp = VTOAFS(ap->a_dvp);
311     if (vcp->mvstat != 1) {
312         error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
313         if (error == -1) 
314             return 0;
315         if (error == ENOENT) 
316             return error;
317     }
318 #endif
319
320     GETNAME();
321     p = vop_cn_proc;
322
323     lockparent = flags & LOCKPARENT;
324     wantparent = flags & (LOCKPARENT | WANTPARENT);
325
326     if (!vnode_isdir(ap->a_dvp)) {
327         *ap->a_vpp = 0;
328         DROPNAME();
329         return ENOTDIR;
330     }
331     dvp = ap->a_dvp;
332 #ifndef AFS_DARWIN80_ENV
333     if (flags & ISDOTDOT)
334         VOP_UNLOCK(dvp, 0, p);
335 #endif
336     AFS_GLOCK();
337     error = afs_lookup(VTOAFS(dvp), name, &vcp, vop_cn_cred);
338     AFS_GUNLOCK();
339     if (error) {
340 #ifndef AFS_DARWIN80_ENV
341         if (flags & ISDOTDOT)
342             VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
343 #endif
344         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
345             && (flags & ISLASTCN) && error == ENOENT)
346             error = EJUSTRETURN;
347 #ifndef AFS_DARWIN80_ENV
348         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
349             cnp->cn_flags |= SAVENAME;
350 #endif
351         DROPNAME();
352         *ap->a_vpp = 0;
353         return (error);
354     }
355 #ifdef AFS_DARWIN80_ENV
356     if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
357         DROPNAME();
358         *ap->a_vpp = 0;
359         return error;
360     }
361 #endif
362     vp = AFSTOV(vcp);           /* always get a node if no error */
363 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
364     vp->v_vfsp = dvp->v_vfsp;
365
366     if (UBCINFOMISSING(vp) ||
367         UBCINFORECLAIMED(vp)) {
368             ubc_info_init(vp);
369     }
370 #endif
371
372 #ifndef AFS_DARWIN80_ENV
373     /* The parent directory comes in locked.  We unlock it on return
374      * unless the caller wants it left locked.
375      * we also always return the vnode locked. */
376
377     if (flags & ISDOTDOT) {
378         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
379         /* always return the child locked */
380         if (lockparent && (flags & ISLASTCN)
381             && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
382             vput(vp);
383             DROPNAME();
384             return (error);
385         }
386     } else if (vp == dvp) {
387         /* they're the same; afs_lookup() already ref'ed the leaf.
388          * It came in locked, so we don't need to ref OR lock it */
389     } else {
390         if (!lockparent || !(flags & ISLASTCN))
391             VOP_UNLOCK(dvp, 0, p);      /* done with parent. */
392         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
393         /* always return the child locked */
394     }
395 #endif
396     *ap->a_vpp = vp;
397
398 #ifndef AFS_DARWIN80_ENV
399     if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
400          || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
401         cnp->cn_flags |= SAVENAME;
402 #endif
403
404     DROPNAME();
405     return error;
406 }
407
408 int
409 afs_vop_create(ap)
410      struct VOPPROT(create_args)        /* {
411                                  * struct vnode *a_dvp;
412                                  * struct vnode **a_vpp;
413                                  * struct componentname *a_cnp;
414                                  * struct vattr *a_vap;
415                                  * } */ *ap;
416 {
417     int error = 0;
418     struct vcache *vcp;
419     register struct vnode *dvp = ap->a_dvp;
420     struct proc *p;
421     GETNAME();
422     p = vop_cn_proc;
423
424     /* vnode layer handles excl/nonexcl */
425     AFS_GLOCK();
426     error =
427         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
428                    &vcp, vop_cn_cred);
429     AFS_GUNLOCK();
430     if (error) {
431 #ifndef AFS_DARWIN80_ENV
432         VOP_ABORTOP(dvp, cnp);
433         vput(dvp);
434 #endif
435         DROPNAME();
436         return (error);
437     }
438
439     if (vcp) {
440 #ifdef AFS_DARWIN80_ENV
441         if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
442             DROPNAME();
443             *ap->a_vpp=0;
444             return error;
445         }
446 #endif
447         *ap->a_vpp = AFSTOV(vcp);
448 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
449         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
450         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
451         if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp)) {
452             vcp->states |= CUBCinit;
453             ubc_info_init(*ap->a_vpp);
454             vcp->states &= ~CUBCinit;
455         }
456 #endif
457     } else
458         *ap->a_vpp = 0;
459
460 #ifndef AFS_DARWIN80_ENV
461     if ((cnp->cn_flags & SAVESTART) == 0)
462         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
463     vput(dvp);
464 #endif
465     DROPNAME();
466     return error;
467 }
468
469 int
470 afs_vop_mknod(ap)
471      struct VOPPROT(mknod_args) /* {
472                                  * struct vnode *a_dvp;
473                                  * struct vnode **a_vpp;
474                                  * struct componentname *a_cnp;
475                                  * struct vattr *a_vap;
476                                  * } */ *ap;
477 {
478 #ifndef AFS_DARWIN80_ENV
479     FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
480     vput(ap->a_dvp);
481 #endif
482     return (ENODEV);
483 }
484
485 int
486 afs_vop_open(ap)
487      struct VOPPROT(open_args)  /* {
488                                  * struct vnode *a_vp;
489                                  * int  a_mode;
490                                  * struct ucred *a_cred;
491                                  * struct proc *a_p;
492                                  * } */ *ap;
493 {
494     int error;
495     struct vnode *vp = ap->a_vp;
496     struct vcache *vc = VTOAFS(vp);
497 #if defined(AFS_DARWIN14_ENV) && !defined(AFS_DARWIN80_ENV)
498     int didhold = 0;
499     /*----------------------------------------------------------------
500      * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
501      * can later be passed to vn_open(), which will skip the call to
502      * ubc_hold(), and when the ubcinfo is later added, the ui_refcount
503      * will be off.  So we compensate by calling ubc_hold() ourselves
504      * when ui_refcount is less than 2.  If an error occurs in afs_open()
505      * we must call ubc_rele(), which is what vn_open() would do if it
506      * was able to call ubc_hold() in the first place.
507      *----------------------------------------------------------------*/
508     if (vp->v_type == VREG && !(vp->v_flag & VSYSTEM)
509       && vp->v_ubcinfo->ui_refcount < 2)
510         didhold = ubc_hold(vp);
511 #endif /* AFS_DARWIN14_ENV */
512     AFS_GLOCK();
513     error = afs_open(&vc, ap->a_mode, vop_cred);
514 #ifdef DIAGNOSTIC
515     if (AFSTOV(vc) != vp)
516         panic("AFS open changed vnode!");
517 #endif
518     osi_FlushPages(vc, vop_cred);
519     AFS_GUNLOCK();
520 #if defined(AFS_DARWIN14_ENV) && !defined(AFS_DARWIN80_ENV)
521     if (error && didhold)
522         ubc_rele(vp);
523 #endif /* AFS_DARWIN14_ENV */
524     return error;
525 }
526
527 int
528 afs_vop_close(ap)
529      struct VOPPROT(close_args) /* {
530                                  * struct vnode *a_vp;
531                                  * int  a_fflag;
532                                  * struct ucred *a_cred;
533                                  * struct proc *a_p;
534                                  * } */ *ap;
535 {
536     int code;
537     struct vnode *vp = ap->a_vp;
538     struct vcache *avc = VTOAFS(vp);
539     AFS_GLOCK();
540     if (vop_cred)
541         code = afs_close(avc, ap->a_fflag, vop_cred, vop_proc);
542     else
543         code = afs_close(avc, ap->a_fflag, &afs_osi_cred, vop_proc);
544     osi_FlushPages(avc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
545     AFS_GUNLOCK();
546
547     return code;
548 }
549
550 #ifdef AFS_DARWIN80_ENV
551 extern int afs_fakestat_enable;
552
553 int
554 afs_vop_access(ap)
555      struct VOPPROT(access_args)        /* {
556                                  * struct vnode *a_vp;
557                                  * int  a_action;
558                                  * vfs_context_t a_context;
559                                  * } */ *ap;
560 {
561     int code;
562     struct vrequest treq;
563     struct afs_fakestat_state fakestate;
564     struct vcache * tvc = VTOAFS(ap->a_vp);
565     int bits=0;
566     int cmb = CHECK_MODE_BITS;
567     AFS_GLOCK();
568     afs_InitFakeStat(&fakestate);
569     if ((code = afs_InitReq(&treq, vop_cred)))
570         goto out2;
571
572     code = afs_TryEvalFakeStat(&tvc, &fakestate, &treq);
573     if (code) {
574         code = afs_CheckCode(code, &treq, 55);
575         goto out;
576     }
577
578     code = afs_VerifyVCache(tvc, &treq);
579     if (code) {
580         code = afs_CheckCode(code, &treq, 56);
581         goto out;
582     }
583     if (afs_fakestat_enable && tvc->mvstat && !(tvc->states & CStatd)) {
584         code = 0;
585         goto out;
586     }
587     if (vnode_isdir(ap->a_vp)) {
588        if (ap->a_action & KAUTH_VNODE_LIST_DIRECTORY)
589           bits |= PRSFS_LOOKUP;
590        if (ap->a_action & KAUTH_VNODE_ADD_FILE)
591           bits |= PRSFS_INSERT;
592        if (ap->a_action & KAUTH_VNODE_SEARCH)
593           bits |= PRSFS_LOOKUP;
594        if (ap->a_action & KAUTH_VNODE_DELETE)
595           bits |= PRSFS_DELETE;
596        if (ap->a_action & KAUTH_VNODE_ADD_SUBDIRECTORY)
597           bits |= PRSFS_INSERT;
598        if (ap->a_action & KAUTH_VNODE_DELETE_CHILD)
599           bits |= PRSFS_DELETE;
600 #if 0 /* I'd argue this should be enforced on the parent. But that's ugly */
601        if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
602           bits |= PRSFS_LOOKUP;
603        if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
604           bits |= PRSFS_LOOKUP;
605 #endif
606     } else {
607        if (ap->a_action & KAUTH_VNODE_READ_DATA)
608           bits |= PRSFS_READ;
609        if (ap->a_action & KAUTH_VNODE_WRITE_DATA)
610           bits |= PRSFS_WRITE;
611        if (ap->a_action & KAUTH_VNODE_EXECUTE)
612           bits |= PRSFS_READ; /* and mode bits.... */
613        if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
614           bits |= PRSFS_LOOKUP;
615        if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
616           bits |= PRSFS_LOOKUP;
617        if ((ap->a_action & ((1 << 25) - 1)) == KAUTH_VNODE_EXECUTE)
618           /* if only exec, don't check for read mode bit */
619           /* high bits of ap->a_action are not for 'generic rights bits', and
620              so should not be checked (KAUTH_VNODE_ACCESS is often present
621              and needs to be masked off) */
622           cmb |= CMB_ALLOW_EXEC_AS_READ;
623     }
624     if (ap->a_action & KAUTH_VNODE_WRITE_ATTRIBUTES)
625        bits |= PRSFS_WRITE;
626 #if 0 /* no extended attributes */
627     if (ap->a_action & KAUTH_VNODE_READ_EXTATTRIBUTES)
628        bits |= PRSFS_READ;
629     if (ap->a_action & KAUTH_VNODE_WRITE_EXTATTRIBUTES)
630        bits |= PRSFS_WRITE;
631 #endif
632     if (ap->a_action & KAUTH_VNODE_WRITE_SECURITY)
633        bits |= PRSFS_WRITE;
634     /* we can't check for KAUTH_VNODE_TAKE_OWNERSHIP, so we always permit it */
635     
636     code = afs_AccessOK(tvc, bits, &treq, cmb);
637
638     if (code == 1 && vnode_vtype(ap->a_vp) == VREG &&
639         ap->a_action & KAUTH_VNODE_EXECUTE &&
640         (tvc->m.Mode & 0100) != 0100) {
641         code = 0;
642      }
643     if (code) {
644         code= 0;               /* if access is ok */
645     } else {
646         /* In 10.4 cp will loop forever on EACCES */
647         code = afs_CheckCode(EPERM, &treq, 57);        /* failure code */
648     }
649 out:
650      afs_PutFakeStat(&fakestate);
651 out2:
652     AFS_GUNLOCK();
653     return code;
654 }
655 #else
656 int
657 afs_vop_access(ap)
658      struct VOPPROT(access_args)        /* {
659                                  * struct vnode *a_vp;
660                                  * int  a_mode;
661                                  * struct ucred *a_cred;
662                                  * struct proc *a_p;
663                                  * } */ *ap;
664 {
665     int code;
666     AFS_GLOCK();
667     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, vop_cred);
668     AFS_GUNLOCK();
669     return code;
670 }
671 #endif
672
673 int
674 afs_vop_getattr(ap)
675      struct VOPPROT(getattr_args)       /* {
676                                  * struct vnode *a_vp;
677                                  * struct vattr *a_vap;
678                                  * struct ucred *a_cred;
679                                  * struct proc *a_p;
680                                  * } */ *ap;
681 {
682     int code;
683
684     AFS_GLOCK();
685     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
686     AFS_GUNLOCK();
687 #ifdef AFS_DARWIN80_ENV
688     VATTR_SET_SUPPORTED(ap->a_vap, va_type);
689     VATTR_SET_SUPPORTED(ap->a_vap, va_mode);
690     VATTR_SET_SUPPORTED(ap->a_vap, va_uid);
691     VATTR_SET_SUPPORTED(ap->a_vap, va_gid);
692     VATTR_SET_SUPPORTED(ap->a_vap, va_fileid);
693     VATTR_SET_SUPPORTED(ap->a_vap, va_nlink);
694     VATTR_SET_SUPPORTED(ap->a_vap, va_data_size);
695     VATTR_SET_SUPPORTED(ap->a_vap, va_access_time);
696     VATTR_SET_SUPPORTED(ap->a_vap, va_modify_time);
697     VATTR_SET_SUPPORTED(ap->a_vap, va_change_time);
698     VATTR_SET_SUPPORTED(ap->a_vap, va_gen);
699     VATTR_SET_SUPPORTED(ap->a_vap, va_flags);
700     VATTR_SET_SUPPORTED(ap->a_vap, va_iosize);
701     VATTR_SET_SUPPORTED(ap->a_vap, va_total_alloc);
702 #endif
703     return code;
704 }
705
706 int
707 afs_vop_setattr(ap)
708      struct VOPPROT(setattr_args)       /* {
709                                  * struct vnode *a_vp;
710                                  * struct vattr *a_vap;
711                                  * struct ucred *a_cred;
712                                  * struct proc *a_p;
713                                  * } */ *ap;
714 {
715     int code;
716     AFS_GLOCK();
717     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
718     AFS_GUNLOCK();
719     return code;
720 }
721
722 int
723 afs_vop_read(ap)
724      struct VOPPROT(read_args)  /* {
725                                  * struct vnode *a_vp;
726                                  * struct uio *a_uio;
727                                  * int a_ioflag;
728                                  * struct ucred *a_cred;
729                                  * } */ *ap;
730 {
731     int code;
732     struct vnode *vp = ap->a_vp;
733     struct vcache *avc = VTOAFS(vp);
734 #ifdef AFS_DARWIN80_ENV
735     ubc_sync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_PUSHDIRTY);
736 #else
737     if (UBCINFOEXISTS(ap->a_vp)) {
738         ubc_clean(ap->a_vp, 0);
739     }
740 #endif
741     AFS_GLOCK();
742     osi_FlushPages(avc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
743     code = afs_read(avc, ap->a_uio, vop_cred, 0, 0, 0);
744     AFS_GUNLOCK();
745     return code;
746 }
747
748 int
749 afs_vop_pagein(ap)
750      struct VOPPROT(pagein_args)        /* {
751                                  * struct vnode *a_vp;
752                                  * upl_t a_pl;
753                                  * vm_offset_t a_pl_offset;
754                                  * off_t a_f_offset;
755                                  * size_t a_size;
756                                  * struct ucred *a_cred;
757                                  * int a_flags;
758                                  * } */ *ap;
759 {
760     register struct vnode *vp = ap->a_vp;
761     upl_t pl = ap->a_pl;
762     size_t size = ap->a_size;
763     off_t f_offset = ap->a_f_offset;
764     vm_offset_t pl_offset = ap->a_pl_offset;
765     int flags = ap->a_flags;
766     struct ucred *cred;
767     vm_offset_t ioaddr;
768 #ifdef AFS_DARWIN80_ENV
769     struct uio *uio;
770 #else
771     struct uio auio;
772     struct iovec aiov;
773     struct uio *uio = &auio;
774 #endif
775     int nocommit = flags & UPL_NOCOMMIT;
776
777     int code;
778     struct vcache *tvc = VTOAFS(vp);
779 #ifndef AFS_DARWIN80_ENV
780     if (UBCINVALID(vp)) {
781 #if DIAGNOSTIC
782         panic("afs_vop_pagein: invalid vp");
783 #endif /* DIAGNOSTIC */
784         return (EPERM);
785     }
786
787     UBCINFOCHECK("afs_vop_pagein", vp);
788 #endif
789     if (pl == (upl_t) NULL) {
790         panic("afs_vop_pagein: no upl");
791     }
792
793     cred = ubc_getcred(vp);
794     if (cred == NOCRED)
795         cred = vop_cred;
796
797     if (size == 0) {
798         if (!nocommit)
799             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
800                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
801         return (0);
802     }
803     if (f_offset < 0) {
804         if (!nocommit)
805             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
806                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
807         return (EINVAL);
808     }
809     if (f_offset & PAGE_MASK)
810         panic("afs_vop_pagein: offset not page aligned");
811
812     OSI_UPL_MAP(pl, &ioaddr);
813     ioaddr += pl_offset;
814 #ifdef AFS_DARWIN80_ENV
815     uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
816     uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
817 #else
818     auio.uio_iov = &aiov;
819     auio.uio_iovcnt = 1;
820     auio.uio_offset = f_offset;
821     auio.uio_segflg = UIO_SYSSPACE;
822     auio.uio_rw = UIO_READ;
823     auio.uio_procp = NULL;
824     auio.uio_resid = aiov.iov_len = size;
825     aiov.iov_base = (caddr_t) ioaddr;
826 #endif
827     AFS_GLOCK();
828     osi_FlushPages(tvc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
829     code = afs_read(tvc, uio, cred, 0, 0, 0);
830     if (code == 0) {
831         ObtainWriteLock(&tvc->lock, 2);
832         tvc->states |= CMAPPED;
833         ReleaseWriteLock(&tvc->lock);
834     }
835     AFS_GUNLOCK();
836
837     /* Zero out rest of last page if there wasn't enough data in the file */
838     if (code == 0 && AFS_UIO_RESID(uio) > 0) {
839 #ifdef AFS_DARWIN80_ENV
840         memset(((caddr_t)ioaddr) + (size - AFS_UIO_RESID(uio)), 0,
841                AFS_UIO_RESID(uio));
842 #else
843         memset(aiov.iov_base, 0, auio.uio_resid);
844 #endif
845     }
846
847     OSI_UPL_UNMAP(pl);
848     if (!nocommit) {
849         if (code)
850             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
851                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
852         else
853             OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
854                                     UPL_COMMIT_CLEAR_DIRTY |
855                                     UPL_COMMIT_FREE_ON_EMPTY);
856     }
857 #ifdef AFS_DARWIN80_ENV
858     uio_free(uio);
859 #endif
860     return code;
861 }
862
863 int
864 afs_vop_write(ap)
865      struct VOPPROT(write_args) /* {
866                                  * struct vnode *a_vp;
867                                  * struct uio *a_uio;
868                                  * int a_ioflag;
869                                  * struct ucred *a_cred;
870                                  * } */ *ap;
871 {
872     int code;
873     struct vcache *avc = VTOAFS(ap->a_vp);
874     void *object;
875 #ifdef AFS_DARWIN80_ENV
876     ubc_sync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_INVALIDATE);
877 #else
878     if (UBCINFOEXISTS(ap->a_vp)) {
879         ubc_clean(ap->a_vp, 1);
880     }
881     if (UBCINFOEXISTS(ap->a_vp))
882         osi_VM_NukePages(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio),
883                          AFS_UIO_RESID(ap->a_uio));
884 #endif
885     AFS_GLOCK();
886     osi_FlushPages(avc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
887     code =
888         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, vop_cred, 0);
889     AFS_GUNLOCK();
890     return code;
891 }
892
893 int
894 afs_vop_pageout(ap)
895      struct VOPPROT(pageout_args)       /* {
896                                  * struct vnode *a_vp;
897                                  * upl_t   a_pl,
898                                  * vm_offset_t   a_pl_offset,
899                                  * off_t         a_f_offset,
900                                  * size_t        a_size,
901                                  * struct ucred *a_cred,
902                                  * int           a_flags
903                                  * } */ *ap;
904 {
905     register struct vnode *vp = ap->a_vp;
906     upl_t pl = ap->a_pl;
907     size_t size = ap->a_size;
908     off_t f_offset = ap->a_f_offset;
909     vm_offset_t pl_offset = ap->a_pl_offset;
910     int flags = ap->a_flags;
911     struct ucred *cred;
912     vm_offset_t ioaddr;
913 #ifdef AFS_DARWIN80_ENV
914     struct uio *uio;
915 #else
916     struct uio auio;
917     struct iovec aiov;
918     struct uio *uio = &auio;
919 #endif
920     int nocommit = flags & UPL_NOCOMMIT;
921     int iosize;
922
923     int code;
924     struct vcache *tvc = VTOAFS(vp);
925 #ifndef AFS_DARWIN80_ENV
926     if (UBCINVALID(vp)) {
927 #if DIAGNOSTIC
928         panic("afs_vop_pageout: invalid vp");
929 #endif /* DIAGNOSTIC */
930         return (EPERM);
931     }
932
933     UBCINFOCHECK("afs_vop_pageout", vp);
934 #endif
935     if (pl == (upl_t) NULL) {
936         panic("afs_vop_pageout: no upl");
937     }
938 #if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
939                                   maybe the generic
940                                   layer doesn't have them anymore? In any case,
941                                   we can't just copy code from nfs... */
942     {
943         int lbn, s;
944         struct buf *bp;
945         int biosize = DEV_BSIZE;
946
947         lbn = f_offset / DEV_BSIZE;
948
949         for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
950
951             s = splbio();
952             if (bp = incore(vp, lbn)) {
953                 if (ISSET(bp->b_flags, B_BUSY))
954                     panic("nfs_pageout: found BUSY buffer incore\n");
955
956                 bremfree(bp);
957                 SET(bp->b_flags, (B_BUSY | B_INVAL));
958                 brelse(bp);
959             }
960             splx(s);
961         }
962     }
963 #endif
964     cred = ubc_getcred(vp);
965     if (cred == NOCRED)
966         cred = vop_cred;
967
968     if (size == 0) {
969         if (!nocommit)
970             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
971                                    UPL_ABORT_FREE_ON_EMPTY);
972         return (0);
973     }
974     if (flags & (IO_APPEND | IO_SYNC))
975         panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
976     if (f_offset < 0) {
977         if (!nocommit)
978             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
979                                    UPL_ABORT_FREE_ON_EMPTY);
980         return (EINVAL);
981     }
982     if (f_offset >= tvc->m.Length) {
983         if (!nocommit)
984             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
985                                    UPL_ABORT_FREE_ON_EMPTY);
986         return (EINVAL);
987     }
988
989     if (f_offset & PAGE_MASK)
990         panic("afs_vop_pageout: offset not page aligned");
991
992     /* size will always be a multiple of PAGE_SIZE */
993     /* pageout isn't supposed to extend files */
994     if (f_offset + size > tvc->m.Length) 
995         iosize = tvc->m.Length - f_offset;
996     else
997         iosize = size;
998
999     if (size > (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK && !nocommit)  {
1000             int iosize_rnd=(iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
1001             OSI_UPL_ABORT_RANGE(pl, pl_offset + iosize_rnd,
1002                                    size - iosize_rnd,
1003                                    UPL_ABORT_FREE_ON_EMPTY);
1004     }
1005     OSI_UPL_MAP(pl, &ioaddr);
1006     ioaddr += pl_offset;
1007 #ifdef AFS_DARWIN80_ENV
1008     uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
1009     uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
1010 #else
1011     auio.uio_iov = &aiov;
1012     auio.uio_iovcnt = 1;
1013     auio.uio_offset = f_offset;
1014     auio.uio_segflg = UIO_SYSSPACE;
1015     auio.uio_rw = UIO_WRITE;
1016     auio.uio_procp = NULL;
1017     auio.uio_resid = aiov.iov_len = iosize;
1018     aiov.iov_base = (caddr_t) ioaddr;
1019 #endif
1020 #if 1                           /* USV [ */
1021     {
1022         /* 
1023          * check for partial page and clear the
1024          * contents past end of the file before
1025          * releasing it in the VM page cache
1026          */
1027         if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
1028             size_t io = tvc->m.Length - f_offset;
1029
1030             memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
1031         }
1032     }
1033 #endif /* ] USV */
1034
1035     AFS_GLOCK();
1036     osi_FlushPages(tvc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
1037     ObtainWriteLock(&tvc->lock, 1);
1038     afs_FakeOpen(tvc);
1039     ReleaseWriteLock(&tvc->lock);
1040
1041     code = afs_write(tvc, uio, flags, cred, 0);
1042
1043     ObtainWriteLock(&tvc->lock, 1);
1044     afs_FakeClose(tvc, cred);
1045     ReleaseWriteLock(&tvc->lock);
1046     AFS_GUNLOCK();
1047     OSI_UPL_UNMAP(pl);
1048     if (!nocommit) {
1049         if (code)
1050             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
1051                                    UPL_ABORT_FREE_ON_EMPTY);
1052         else
1053             OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
1054                                     UPL_COMMIT_CLEAR_DIRTY |
1055                                     UPL_COMMIT_FREE_ON_EMPTY);
1056     }
1057
1058 #ifdef AFS_DARWIN80_ENV
1059     uio_free(uio);
1060 #endif
1061     return code;
1062 }
1063
1064 int
1065 afs_vop_ioctl(ap)
1066      struct VOPPROT(ioctl_args) /* {
1067                                  * struct vnode *a_vp;
1068                                  * int  a_command;
1069                                  * caddr_t  a_data;
1070                                  * int  a_fflag;
1071                                  * struct ucred *a_cred;
1072                                  * struct proc *a_p;
1073                                  * } */ *ap;
1074 {
1075     struct vcache *tvc = VTOAFS(ap->a_vp);
1076     struct afs_ioctl data;
1077     int error = 0;
1078
1079     /* in case we ever get in here... */
1080
1081     AFS_STATCNT(afs_ioctl);
1082     if (((ap->a_command >> 8) & 0xff) == 'V') {
1083         /* This is a VICEIOCTL call */
1084         AFS_GLOCK();
1085         error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
1086                             ap->a_command, ap->a_data);
1087         AFS_GUNLOCK();
1088         return (error);
1089     } else {
1090         /* No-op call; just return. */
1091         return (ENOTTY);
1092     }
1093 }
1094
1095 /* ARGSUSED */
1096 int
1097 afs_vop_select(ap)
1098      struct VOPPROT(select_args)        /* {
1099                                  * struct vnode *a_vp;
1100                                  * int  a_which;
1101                                  * int  a_fflags;
1102                                  * struct ucred *a_cred;
1103                                  * struct proc *a_p;
1104                                  * } */ *ap;
1105 {
1106     /*
1107      * We should really check to see if I/O is possible.
1108      */
1109     return (1);
1110 }
1111
1112 /*
1113  * Mmap a file
1114  *
1115  * NB Currently unsupported.
1116  */
1117 /* ARGSUSED */
1118 int
1119 afs_vop_mmap(ap)
1120      struct VOPPROT(mmap_args)  /* {
1121                                  * struct vnode *a_vp;
1122                                  * int  a_fflags;
1123                                  * struct ucred *a_cred;
1124                                  * struct proc *a_p;
1125                                  * } */ *ap;
1126 {
1127     return (EINVAL);
1128 }
1129
1130 int
1131 afs_vop_fsync(ap)
1132      struct VOPPROT(fsync_args) /* {
1133                                  * struct vnode *a_vp;
1134                                  * struct ucred *a_cred;
1135                                  * int a_waitfor;
1136                                  * struct proc *a_p;
1137                                  * } */ *ap;
1138 {
1139     int wait = ap->a_waitfor == MNT_WAIT;
1140     int error;
1141     register struct vnode *vp = ap->a_vp;
1142     int haveGlock = ISAFS_GLOCK();
1143
1144     /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
1145     if (!haveGlock) AFS_GLOCK();
1146     if (vop_cred)
1147         error = afs_fsync(VTOAFS(vp), vop_cred);
1148     else
1149         error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
1150     if (!haveGlock) AFS_GUNLOCK();
1151     return error;
1152 }
1153
1154 #ifndef AFS_DARWIN80_ENV
1155 int
1156 afs_vop_seek(ap)
1157      struct VOPPROT(seek_args)  /* {
1158                                  * struct vnode *a_vp;
1159                                  * off_t  a_oldoff;
1160                                  * off_t  a_newoff;
1161                                  * struct ucred *a_cred;
1162                                  * } */ *ap;
1163 {
1164     if (ap->a_newoff > ULONG_MAX)       /* AFS doesn't support 64-bit offsets */
1165         return EINVAL;
1166     return (0);
1167 }
1168 #endif
1169
1170 int
1171 afs_vop_remove(ap)
1172      struct VOPPROT(remove_args)        /* {
1173                                  * struct vnode *a_dvp;
1174                                  * struct vnode *a_vp;
1175                                  * struct componentname *a_cnp;
1176                                  * } */ *ap;
1177 {
1178     int error = 0;
1179     register struct vnode *vp = ap->a_vp;
1180     register struct vnode *dvp = ap->a_dvp;
1181
1182 #ifdef AFS_DARWIN80_ENV
1183     if (ap->a_flags & VNODE_REMOVE_NODELETEBUSY) {
1184             /* Caller requested Carbon delete semantics */
1185             if (vnode_isinuse(vp, 0)) {
1186                     return EBUSY;
1187             }
1188     }
1189 #endif
1190
1191     GETNAME();
1192     AFS_GLOCK();
1193     error = afs_remove(VTOAFS(dvp), name, vop_cn_cred);
1194     AFS_GUNLOCK();
1195     cache_purge(vp);
1196     if (!error) {
1197 #ifdef AFS_DARWIN80_ENV
1198         struct vcache *tvc = VTOAFS(vp);
1199         
1200         if (!(tvc->states & CUnlinked)) {
1201             ubc_setsize(vp, (off_t)0);
1202             vnode_recycle(vp);
1203         }
1204 #else
1205         /* necessary so we don't deadlock ourselves in vclean */
1206         VOP_UNLOCK(vp, 0, cnp->cn_proc);
1207
1208         /* If crashes continue in ubc_hold, comment this out */
1209         (void)ubc_uncache(vp);
1210 #endif
1211     }
1212
1213 #ifndef AFS_DARWIN80_ENV
1214     vput(dvp);
1215     if (dvp == vp)
1216         vrele(vp);
1217     else
1218         vput(vp);
1219 #endif
1220
1221 #ifndef AFS_DARWIN80_ENV
1222     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1223 #endif
1224     DROPNAME();
1225     return error;
1226 }
1227
1228 int
1229 afs_vop_link(ap)
1230      struct VOPPROT(link_args)  /* {
1231                                  * struct vnode *a_vp;
1232                                  * struct vnode *a_tdvp;
1233                                  * struct componentname *a_cnp;
1234                                  * } */ *ap;
1235 {
1236     int error = 0;
1237     register struct vnode *dvp = ap->a_tdvp;
1238     register struct vnode *vp = ap->a_vp;
1239     struct proc *p;
1240
1241     GETNAME();
1242     p = vop_cn_proc;
1243     if (vnode_isdir(vp)) {
1244         VOP_ABORTOP(vp, cnp);
1245         error = EISDIR;
1246         goto out;
1247     }
1248 #ifndef AFS_DARWIN80_ENV
1249     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
1250         VOP_ABORTOP(dvp, cnp);
1251         goto out;
1252     }
1253 #endif
1254     AFS_GLOCK();
1255     error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, vop_cn_cred);
1256     AFS_GUNLOCK();
1257 #ifndef AFS_DARWIN80_ENV
1258     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1259 #endif
1260 #ifndef AFS_DARWIN80_ENV
1261     if (dvp != vp)
1262         VOP_UNLOCK(vp, 0, p);
1263 #endif
1264   out:
1265 #ifndef AFS_DARWIN80_ENV
1266     vput(dvp);
1267 #endif
1268     DROPNAME();
1269     return error;
1270 }
1271
1272 int
1273 afs_vop_rename(ap)
1274      struct VOPPROT(rename_args)        /* {
1275                                  * struct vnode *a_fdvp;
1276                                  * struct vnode *a_fvp;
1277                                  * struct componentname *a_fcnp;
1278                                  * struct vnode *a_tdvp;
1279                                  * struct vnode *a_tvp;
1280                                  * struct componentname *a_tcnp;
1281                                  * } */ *ap;
1282 {
1283     int error = 0;
1284     struct componentname *fcnp = ap->a_fcnp;
1285     char *fname;
1286     struct componentname *tcnp = ap->a_tcnp;
1287     char *tname;
1288     struct vnode *tvp = ap->a_tvp;
1289     register struct vnode *tdvp = ap->a_tdvp;
1290     struct vnode *fvp = ap->a_fvp;
1291     register struct vnode *fdvp = ap->a_fdvp;
1292     struct proc *p; 
1293
1294     p = cn_proc(fcnp);
1295
1296 #ifdef AFS_DARWIN80_ENV
1297 /* generic code tests for v_mount equality, so we don't have to, but we don't
1298    get the multiple-mount "benefits" of the old behavior
1299 */
1300 #else
1301     /* Check for cross-device rename.
1302      * For AFS, this means anything not in AFS-space
1303      */
1304     if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
1305         (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
1306         error = EXDEV;
1307         goto abortit;
1308     }
1309 #endif
1310
1311 #ifdef AFS_DARWIN80_ENV
1312    /* the generic code doesn't do this, so we really should, but all the
1313       vrele's are wrong... */
1314 #else
1315     /*
1316      * if fvp == tvp, we're just removing one name of a pair of
1317      * directory entries for the same element.  convert call into rename.
1318      ( (pinched from NetBSD 1.0's ufs_rename())
1319      */
1320     if (fvp == tvp) {
1321         if (vnode_isdir(fvp)) {
1322             error = EINVAL;
1323           abortit:
1324             VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
1325             if (tdvp == tvp)
1326                 vrele(tdvp);
1327             else
1328                 vput(tdvp);
1329             if (tvp)
1330                 vput(tvp);
1331             VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
1332             vrele(fdvp);
1333             vrele(fvp);
1334             return (error);
1335         }
1336
1337         /* Release destination completely. */
1338         VOP_ABORTOP(tdvp, tcnp);
1339         vput(tdvp);
1340         vput(tvp);
1341         /* Delete source. */
1342 #if defined(AFS_DARWIN80_ENV) 
1343
1344         MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1345         memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
1346         fname[fcnp->cn_namelen] = '\0';
1347         AFS_GLOCK();
1348         error = afs_remove(VTOAFS(fdvp), fname, vop_cn_cred);
1349         AFS_GUNLOCK();
1350         FREE(fname, M_TEMP);
1351         cache_purge(fvp);
1352 #else
1353         vrele(fdvp);
1354         vrele(fvp);
1355         fcnp->cn_flags &= ~MODMASK;
1356         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1357         if ((fcnp->cn_flags & SAVESTART) == 0)
1358             panic("afs_rename: lost from startdir");
1359         fcnp->cn_nameiop = DELETE;
1360
1361         VREF(fdvp); 
1362         error=relookup(fdvp, &fvp, fcnp);
1363         if (error == 0)
1364             vrele(fdvp);
1365         if (fvp == NULL) {
1366             return (ENOENT);
1367         }
1368         error=VOP_REMOVE(fdvp, fvp, fcnp);
1369 #endif
1370         
1371         if (fdvp == fvp)
1372             vrele(fdvp);
1373         else
1374             vput(fdvp);
1375         vput(fvp);
1376         return (error);
1377     }
1378 #endif
1379 #if !defined(AFS_DARWIN80_ENV) 
1380     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
1381         goto abortit;
1382 #endif
1383
1384     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1385     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
1386     fname[fcnp->cn_namelen] = '\0';
1387     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1388     memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
1389     tname[tcnp->cn_namelen] = '\0';
1390
1391
1392     AFS_GLOCK();
1393     /* XXX use "from" or "to" creds? NFS uses "to" creds */
1394     error =
1395         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, cn_cred(tcnp));
1396     AFS_GUNLOCK();
1397
1398 #if !defined(AFS_DARWIN80_ENV) 
1399     VOP_UNLOCK(fvp, 0, p);
1400 #endif
1401     FREE(fname, M_TEMP);
1402     FREE(tname, M_TEMP);
1403 #ifdef AFS_DARWIN80_ENV
1404     cache_purge(fdvp);
1405     cache_purge(fvp);
1406     cache_purge(tdvp);
1407     if (tvp) {
1408        cache_purge(tvp);
1409        if (!error) {
1410           vnode_recycle(tvp);
1411        }
1412     }
1413     if (!error)
1414        cache_enter(tdvp, fvp, tcnp);
1415 #else
1416     if (error)
1417         goto abortit;           /* XXX */
1418     if (tdvp == tvp)
1419         vrele(tdvp);
1420     else
1421         vput(tdvp);
1422     if (tvp)
1423         vput(tvp);
1424     vrele(fdvp);
1425     vrele(fvp);
1426 #endif
1427     return error;
1428 }
1429
1430 int
1431 afs_vop_mkdir(ap)
1432      struct VOPPROT(mkdir_args) /* {
1433                                  * struct vnode *a_dvp;
1434                                  * struct vnode **a_vpp;
1435                                  * struct componentname *a_cnp;
1436                                  * struct vattr *a_vap;
1437                                  * } */ *ap;
1438 {
1439     register struct vnode *dvp = ap->a_dvp;
1440     register struct vattr *vap = ap->a_vap;
1441     int error = 0;
1442     struct vcache *vcp;
1443     struct proc *p;
1444
1445     GETNAME();
1446     p = vop_cn_proc;
1447 #if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
1448     if ((cnp->cn_flags & HASBUF) == 0)
1449         panic("afs_vop_mkdir: no name");
1450 #endif
1451     AFS_GLOCK();
1452     error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, vop_cn_cred);
1453     AFS_GUNLOCK();
1454     if (error) {
1455 #ifndef AFS_DARWIN80_ENV
1456         VOP_ABORTOP(dvp, cnp);
1457         vput(dvp);
1458 #endif
1459         DROPNAME();
1460         return (error);
1461     }
1462     if (vcp) {
1463 #ifdef AFS_DARWIN80_ENV
1464         afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0);
1465 #endif
1466         *ap->a_vpp = AFSTOV(vcp);
1467 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
1468         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
1469         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
1470 #endif
1471     } else
1472         *ap->a_vpp = 0;
1473     DROPNAME();
1474 #ifndef AFS_DARWIN80_ENV
1475     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1476     vput(dvp);
1477 #endif
1478     return error;
1479 }
1480
1481 int
1482 afs_vop_rmdir(ap)
1483      struct VOPPROT(rmdir_args) /* {
1484                                  * struct vnode *a_dvp;
1485                                  * struct vnode *a_vp;
1486                                  * struct componentname *a_cnp;
1487                                  * } */ *ap;
1488 {
1489     int error = 0;
1490     register struct vnode *vp = ap->a_vp;
1491     register struct vnode *dvp = ap->a_dvp;
1492
1493     GETNAME();
1494     if (dvp == vp) {
1495 #ifndef AFS_DARWIN80_ENV
1496         vrele(dvp);
1497         vput(vp);
1498         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1499 #endif
1500         DROPNAME();
1501         return (EINVAL);
1502     }
1503
1504     AFS_GLOCK();
1505     error = afs_rmdir(VTOAFS(dvp), name, vop_cn_cred);
1506     AFS_GUNLOCK();
1507     DROPNAME();
1508     cache_purge(dvp);
1509     cache_purge(vp);
1510 #ifndef AFS_DARWIN80_ENV
1511     vput(dvp);
1512     vput(vp);
1513 #endif
1514     return error;
1515 }
1516
1517 int
1518 afs_vop_symlink(ap)
1519      struct VOPPROT(symlink_args)       /* {
1520                                  * struct vnode *a_dvp;
1521                                  * struct vnode **a_vpp;
1522                                  * struct componentname *a_cnp;
1523                                  * struct vattr *a_vap;
1524                                  * char *a_target;
1525                                  * } */ *ap;
1526 {
1527     register struct vnode *dvp = ap->a_dvp;
1528     int error = 0;
1529     /* NFS ignores a_vpp; so do we. */
1530
1531     GETNAME();
1532     AFS_GLOCK();
1533     error =
1534         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
1535     AFS_GUNLOCK();
1536     DROPNAME();
1537 #ifndef AFS_DARWIN80_ENV
1538     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1539     vput(dvp);
1540 #endif
1541     return error;
1542 }
1543
1544 int
1545 afs_vop_readdir(ap)
1546      struct VOPPROT(readdir_args)       /* {
1547                                  * struct vnode *a_vp;
1548                                  * struct uio *a_uio;
1549                                  * struct ucred *a_cred;
1550                                  * int *a_eofflag;
1551                                  * u_long *a_cookies;
1552                                  * int ncookies;
1553                                  * } */ *ap;
1554 {
1555     int error;
1556     off_t off;
1557 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1558            ap->a_ncookies); */
1559 #ifdef AFS_DARWIN80_ENV
1560     /* too much work for now */
1561     /* should only break nfs exports */
1562     if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
1563          return (EINVAL);
1564 #endif
1565     off = AFS_UIO_OFFSET(ap->a_uio);
1566     AFS_GLOCK();
1567     error =
1568         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, vop_cred, ap->a_eofflag);
1569     AFS_GUNLOCK();
1570 #ifndef AFS_DARWIN80_ENV
1571     if (!error && ap->a_ncookies != NULL) {
1572         struct uio *uio = ap->a_uio;
1573         const struct dirent *dp, *dp_start, *dp_end;
1574         int ncookies;
1575         u_long *cookies, *cookiep;
1576
1577         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1578             panic("afs_readdir: burned cookies");
1579         dp = (const struct dirent *)
1580             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1581
1582         dp_end = (const struct dirent *)uio->uio_iov->iov_base;
1583         for (dp_start = dp, ncookies = 0; dp < dp_end;
1584              dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
1585             ncookies++;
1586
1587         MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1588                M_WAITOK);
1589         for (dp = dp_start, cookiep = cookies; dp < dp_end;
1590              dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
1591             off += dp->d_reclen;
1592             *cookiep++ = off;
1593         }
1594         *ap->a_cookies = cookies;
1595         *ap->a_ncookies = ncookies;
1596     }
1597 #endif
1598
1599     return error;
1600 }
1601
1602 int
1603 afs_vop_readlink(ap)
1604      struct VOPPROT(readlink_args)      /* {
1605                                  * struct vnode *a_vp;
1606                                  * struct uio *a_uio;
1607                                  * struct ucred *a_cred;
1608                                  * } */ *ap;
1609 {
1610     int error;
1611 /*    printf("readlink %x\n", ap->a_vp);*/
1612     AFS_GLOCK();
1613     error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, vop_cred);
1614     AFS_GUNLOCK();
1615     return error;
1616 }
1617
1618 extern int prtactive;
1619
1620 int
1621 afs_vop_inactive(ap)
1622      struct VOPPROT(inactive_args)      /* {
1623                                  * struct vnode *a_vp;
1624                                  * struct proc *a_p;
1625                                  * } */ *ap;
1626 {
1627     register struct vnode *vp = ap->a_vp;
1628     struct vcache *tvc = VTOAFS(vp);
1629 #ifndef AFS_DARWIN80_ENV
1630     if (prtactive && vp->v_usecount != 0)
1631         vprint("afs_vop_inactive(): pushing active", vp);
1632 #endif
1633     if (tvc) {
1634 #ifdef AFS_DARWIN80_ENV
1635         int unlinked = tvc->states & CUnlinked;
1636 #endif
1637         AFS_GLOCK();
1638         afs_InactiveVCache(tvc, 0);     /* decrs ref counts */
1639         AFS_GUNLOCK();
1640 #ifdef AFS_DARWIN80_ENV
1641         if (unlinked) {
1642             vnode_recycle(vp);
1643             cache_purge(vp);
1644         }
1645 #endif
1646     }
1647 #ifndef AFS_DARWIN80_ENV
1648     VOP_UNLOCK(vp, 0, ap->a_p);
1649 #endif
1650     return 0;
1651 }
1652
1653 int
1654 afs_vop_reclaim(ap)
1655      struct VOPPROT(reclaim_args)       /* {
1656                                  * struct vnode *a_vp;
1657                                  * } */ *ap;
1658 {
1659     int error = 0;
1660     int sl, writelocked;
1661     register struct vnode *vp = ap->a_vp;
1662     struct vcache *tvc = VTOAFS(vp);
1663
1664     osi_Assert(!ISAFS_GLOCK());
1665     cache_purge(vp);            /* just in case... */
1666     if (tvc) {
1667        AFS_GLOCK();
1668        writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
1669        if (!writelocked) {
1670            ObtainWriteLock(&afs_xvreclaim, 176);
1671 #ifdef AFS_DARWIN80_ENV
1672            vnode_clearfsnode(AFSTOV(tvc));
1673            vnode_removefsref(AFSTOV(tvc));
1674 #else
1675            tvc->v->v_data = NULL;  /* remove from vnode */
1676 #endif
1677            AFSTOV(tvc) = NULL;             /* also drop the ptr to vnode */
1678            tvc->states |= CVInit; /* also CDeadVnode? */
1679            tvc->nextfree = ReclaimedVCList;
1680            ReclaimedVCList = tvc;
1681            ReleaseWriteLock(&afs_xvreclaim);
1682        } else {
1683            error = afs_FlushVCache(tvc, &sl);   /* toss our stuff from vnode */
1684            if (tvc->states & (CVInit
1685 #ifdef AFS_DARWIN80_ENV
1686                               | CDeadVnode
1687 #endif
1688                    )) {
1689                tvc->states &= ~(CVInit
1690 #ifdef AFS_DARWIN80_ENV
1691                                 | CDeadVnode
1692 #endif
1693                    );
1694                afs_osi_Wakeup(&tvc->states);
1695            }
1696            if (!error && vnode_fsnode(vp))
1697                panic("afs_reclaim: vnode not cleaned");
1698            if (!error && (tvc->v != NULL)) 
1699                panic("afs_reclaim: vcache not cleaned");
1700            ReleaseWriteLock(&afs_xvcache);
1701        }
1702        AFS_GUNLOCK();
1703     }
1704     return error;
1705 }
1706
1707 /*
1708  * Return POSIX pathconf information applicable to ufs filesystems.
1709  */
1710 afs_vop_pathconf(ap)
1711      struct VOPPROT(pathconf_args)      /* {
1712                                  * struct vnode *a_vp;
1713                                  * int a_name;
1714                                  * int *a_retval;
1715                                  * } */ *ap;
1716 {
1717     AFS_STATCNT(afs_cntl);
1718     switch (ap->a_name) {
1719     case _PC_LINK_MAX:
1720         *ap->a_retval = LINK_MAX;
1721         break;
1722     case _PC_NAME_MAX:
1723         *ap->a_retval = NAME_MAX;
1724         break;
1725     case _PC_PATH_MAX:
1726         *ap->a_retval = PATH_MAX;
1727         break;
1728     case _PC_CHOWN_RESTRICTED:
1729         *ap->a_retval = 1;
1730         break;
1731     case _PC_NO_TRUNC:
1732         *ap->a_retval = 1;
1733         break;
1734     case _PC_PIPE_BUF:
1735         return EINVAL;
1736         break;
1737 #if defined(AFS_DARWIN70_ENV)
1738     case _PC_NAME_CHARS_MAX:
1739         *ap->a_retval = NAME_MAX;
1740         break;
1741     case _PC_CASE_SENSITIVE:
1742         *ap->a_retval = 1;
1743         break;
1744     case _PC_CASE_PRESERVING:
1745         *ap->a_retval = 1;
1746         break;
1747 #endif /* defined(AFS_DARWIN70_ENV) */
1748     default:
1749         return EINVAL;
1750     }
1751     return 0;
1752 }
1753
1754 /*
1755  * Advisory record locking support (fcntl() POSIX style)
1756  */
1757 int
1758 afs_vop_advlock(ap)
1759      struct VOPPROT(advlock_args)       /* {
1760                                  * struct vnode *a_vp;
1761                                  * caddr_t  a_id;
1762                                  * int  a_op;
1763                                  * struct flock *a_fl;
1764                                  * int  a_flags;
1765                                  * } */ *ap;
1766 {
1767     int error;
1768     struct ucred *tcr;
1769     int clid;
1770     int op;
1771 #ifdef AFS_DARWIN80_ENV
1772     proc_t p;
1773     tcr=vop_cred;
1774 #else
1775     struct proc *p = current_proc();
1776     struct ucred cr;
1777     pcred_readlock(p);
1778     cr = *p->p_cred->pc_ucred;
1779     pcred_unlock(p);
1780     tcr=&cr;
1781 #endif
1782     if (ap->a_flags & F_POSIX) {
1783 #ifdef AFS_DARWIN80_ENV
1784         p = (proc_t) ap->a_id;
1785         clid = proc_pid(p);
1786 #else
1787         p = (struct proc *) ap->a_id;
1788         clid = p->p_pid;
1789 #endif
1790     } else {
1791         clid = (int)ap->a_id;
1792     }
1793     if (ap->a_op == F_UNLCK) {
1794         op = F_SETLK;
1795     } else if (ap->a_op == F_SETLK && ap->a_flags & F_WAIT) {
1796         op = F_SETLKW;
1797     } else {
1798         op = ap->a_op;
1799     }
1800     AFS_GLOCK();
1801     error = afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, op, tcr, clid);
1802     AFS_GUNLOCK();
1803     return error;
1804 }
1805
1806 int
1807 afs_vop_blktooff(ap)
1808      struct VOPPROT(blktooff_args)      /* {
1809                                  * struct vnode *a_vp;
1810                                  * daddr_t a_lblkno;
1811                                  * off_t *a_offset;    
1812                                  * } */ *ap;
1813 {
1814     *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1815     return 0;
1816 }
1817
1818 int
1819 afs_vop_offtoblk(ap)
1820      struct VOPPROT(offtoblk_args)      /* {
1821                                  * struct vnode *a_vp;
1822                                  * off_t a_offset;    
1823                                  * daddr_t *a_lblkno;
1824                                  * } */ *ap;
1825 {
1826     *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1827
1828     return (0);
1829 }
1830
1831 #ifndef AFS_DARWIN80_ENV
1832 int
1833 afs_vop_lock(ap)
1834      struct VOPPROT(lock_args)  /* {
1835                                  * struct vnode *a_vp;
1836                                  * } */ *ap;
1837 {
1838     register struct vnode *vp = ap->a_vp;
1839     register struct vcache *avc = VTOAFS(vp);
1840
1841     if (vp->v_tag == VT_NON)
1842         return (ENOENT);
1843
1844     return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1845 }
1846
1847 int
1848 afs_vop_unlock(ap)
1849      struct VOPPROT(unlock_args)        /* {
1850                                  * struct vnode *a_vp;
1851                                  * } */ *ap;
1852 {
1853     struct vnode *vp = ap->a_vp;
1854     struct vcache *avc = VTOAFS(vp);
1855
1856     return (lockmgr
1857             (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1858              ap->a_p));
1859
1860 }
1861
1862 int
1863 afs_vop_truncate(ap)
1864      struct VOPPROT(truncate_args)      /* {
1865                                  * struct vnode *a_vp;
1866                                  * off_t a_length;
1867                                  * int a_flags;
1868                                  * struct ucred *a_cred;
1869                                  * struct proc *a_p;
1870                                  * } */ *ap;
1871 {
1872     printf("stray afs_vop_truncate\n");
1873     return EOPNOTSUPP;
1874 }
1875
1876 int
1877 afs_vop_update(ap)
1878      struct VOPPROT(update_args)        /* {
1879                                  * struct vnode *a_vp;
1880                                  * struct timeval *a_access;
1881                                  * struct timeval *a_modify;
1882                                  * int a_waitfor;
1883                                  * } */ *ap;
1884 {
1885     printf("stray afs_vop_update\n");
1886     return EOPNOTSUPP;
1887 }
1888
1889 int
1890 afs_vop_bmap(ap)
1891      struct VOPPROT(bmap_args)  /* {
1892                                  * struct vnode *a_vp;
1893                                  * daddr_t  a_bn;
1894                                  * struct vnode **a_vpp;
1895                                  * daddr_t *a_bnp;
1896                                  * int *a_runp;
1897                                  * int *a_runb;
1898                                  * } */ *ap;
1899 {
1900     int error;
1901     if (ap->a_bnp) {
1902         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1903     }
1904     if (ap->a_vpp) {
1905         *ap->a_vpp = ap->a_vp;
1906     }
1907     if (ap->a_runp != NULL)
1908         *ap->a_runp = 0;
1909 #ifdef notyet
1910     if (ap->a_runb != NULL)
1911         *ap->a_runb = 0;
1912 #endif
1913
1914     return 0;
1915 }
1916
1917 int
1918 afs_vop_strategy(ap)
1919      struct VOPPROT(strategy_args)      /* {
1920                                  * struct buf *a_bp;
1921                                  * } */ *ap;
1922 {
1923     int error;
1924     AFS_GLOCK();
1925     error = afs_ustrategy(ap->a_bp);
1926     AFS_GUNLOCK();
1927     return error;
1928 }
1929
1930 int
1931 afs_vop_print(ap)
1932      struct VOPPROT(print_args) /* {
1933                                  * struct vnode *a_vp;
1934                                  * } */ *ap;
1935 {
1936     register struct vnode *vp = ap->a_vp;
1937     register struct vcache *vc = VTOAFS(ap->a_vp);
1938     int s = vc->states;
1939     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
1940            vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
1941            vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
1942     printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
1943            (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
1944            (s & CMAPPED) ? " mapped" : "",
1945            (s & CVFlushed) ? " flush in progress" : "");
1946     if (UBCISVALID(vp)) {
1947         printf("\n  UBC: ");
1948         if (UBCINFOEXISTS(vp)) {
1949             printf("exists, ");
1950 #ifdef AFS_DARWIN14_ENV
1951             printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1952                    ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1953                    ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1954 #else
1955             printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1956 #endif
1957         } else
1958             printf("does not exist");
1959     }
1960     printf("\n");
1961     return 0;
1962 }
1963
1964 int
1965 afs_vop_islocked(ap)
1966      struct VOPPROT(islocked_args)      /* {
1967                                  * struct vnode *a_vp;
1968                                  * } */ *ap;
1969 {
1970     struct vcache *vc = VTOAFS(ap->a_vp);
1971     return lockstatus(&vc->rwlock);
1972 }
1973
1974 int
1975 afs_vop_cmap(ap)
1976      struct VOPPROT(cmap_args)  /* {
1977                                  * struct vnode *a_vp;
1978                                  * off_t a_foffset;    
1979                                  * size_t a_size;
1980                                  * daddr_t *a_bpn;
1981                                  * size_t *a_run;
1982                                  * void *a_poff;
1983                                  * } */ *ap;
1984 {
1985     *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1986     *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1987     return 0;
1988 }
1989 #endif
1990
1991 int
1992 afs_darwin_getnewvnode(struct vcache *avc)
1993 {
1994 #ifdef AFS_DARWIN80_ENV
1995     vnode_t vp;
1996     int error, dead;
1997     struct vnode_fsparam par;
1998
1999     memset(&par, 0, sizeof(struct vnode_fsparam));
2000 #if 0
2001     AFS_GLOCK();
2002     ObtainWriteLock(&avc->lock,342);
2003     if (avc->states & CStatd) { 
2004        par.vnfs_vtype = avc->m.Type;
2005        par.vnfs_vops = afs_vnodeop_p;
2006        par.vnfs_filesize = avc->m.Length;
2007        if (!ac->cnp)
2008            par.vnfs_flags = VNFS_NOCACHE;
2009        dead = 0;
2010     } else {
2011        par.vnfs_vtype = VNON;
2012        par.vnfs_vops = afs_dead_vnodeop_p;
2013        par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
2014        dead = 1;
2015     }
2016     ReleaseWriteLock(&avc->lock);
2017     AFS_GUNLOCK();
2018     par.vnfs_dvp = ac->dvp;
2019     par.vnfs_cnp = ac->cnp;
2020     par.vnfs_markroot = ac->markroot;
2021 #else
2022     par.vnfs_vtype = VNON;
2023     par.vnfs_vops = afs_dead_vnodeop_p;
2024     par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
2025 #endif
2026     par.vnfs_mp = afs_globalVFS;
2027     par.vnfs_fsnode = avc;
2028
2029     error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &vp);
2030     if (!error) {
2031       vnode_addfsref(vp);
2032       vnode_ref(vp);
2033       avc->v = vp;
2034 #if 0
2035       if (dead) {
2036          vnode_recycle(vp); /* terminate as soon as iocount drops */
2037          avc->states |= CDeadVnode;
2038       } else if (!ac->markroot && !ac->cnp) {
2039        /* the caller doesn't know anything about this vnode. if markroot
2040           should have been set and wasn't, bad things may happen, so encourage
2041           it to recycle */
2042           vnode_recycle(vp);
2043       }
2044 #else
2045       vnode_recycle(vp); /* terminate as soon as iocount drops */
2046       avc->states |= CDeadVnode;
2047 #endif
2048     }
2049     return error;
2050 #else
2051     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &avc->v)) {
2052         /* no vnodes available, force an alloc (limits be damned)! */
2053         printf("failed to get vnode\n");
2054     }
2055     avc->v->v_data = (void *)avc;
2056     return 0;
2057 #endif
2058 }
2059 #ifdef AFS_DARWIN80_ENV
2060 /* if this fails, then tvc has been unrefed and may have been freed. 
2061    Don't touch! */
2062 int 
2063 afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct componentname *cnp, int isroot) {
2064    vnode_t ovp = AFSTOV(avc);
2065    vnode_t nvp;
2066    int error;
2067    struct vnode_fsparam par;
2068    AFS_GLOCK();
2069    ObtainWriteLock(&avc->lock,325);
2070    if (!(avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
2071         ReleaseWriteLock(&avc->lock);
2072         AFS_GUNLOCK();
2073 #if 0 /* unsupported */
2074         if (dvp && cnp)
2075         vnode_update_identity(ovp, dvp, cnp->cn_nameptr, cnp->cn_namelen,
2076                               cnp->cn_hash,
2077                               VNODE_UPDATE_PARENT|VNODE_UPDATE_NAME);
2078 #endif
2079         vnode_rele(ovp);
2080         return 0;
2081    }
2082    if ((avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON) 
2083        panic("vcache %p should not be CDeadVnode", avc);
2084    AFS_GUNLOCK();
2085    memset(&par, 0, sizeof(struct vnode_fsparam));
2086    par.vnfs_mp = afs_globalVFS;
2087    par.vnfs_vtype = avc->m.Type;
2088    par.vnfs_vops = afs_vnodeop_p;
2089    par.vnfs_filesize = avc->m.Length;
2090    par.vnfs_fsnode = avc;
2091    par.vnfs_dvp = dvp;
2092    if (cnp && (cnp->cn_flags & ISDOTDOT) == 0)
2093        par.vnfs_cnp = cnp;
2094    if (!dvp || !cnp || (cnp->cn_flags & MAKEENTRY) == 0)
2095        par.vnfs_flags = VNFS_NOCACHE;
2096    if (isroot)
2097        par.vnfs_markroot = 1;
2098    error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &nvp);
2099    if (!error) {
2100        vnode_addfsref(nvp);
2101        avc->v = nvp;
2102        avc->states &=~ CDeadVnode;
2103        if (!(avc->states & CVInit)) {
2104            vnode_clearfsnode(ovp);
2105            vnode_removefsref(ovp);
2106        }
2107    }
2108    AFS_GLOCK();
2109    ReleaseWriteLock(&avc->lock);
2110    if (!error)
2111       afs_osi_Wakeup(&avc->states);
2112    AFS_GUNLOCK();
2113    vnode_put(ovp);
2114    vnode_rele(ovp);
2115    return error;
2116 }
2117 #endif