darwin-remunlink-20070320
[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         code = afs_CheckCode(EACCES, &treq, 57);        /* failure code */
647     }
648 out:
649      afs_PutFakeStat(&fakestate);
650 out2:
651     AFS_GUNLOCK();
652     return code;
653 }
654 #else
655 int
656 afs_vop_access(ap)
657      struct VOPPROT(access_args)        /* {
658                                  * struct vnode *a_vp;
659                                  * int  a_mode;
660                                  * struct ucred *a_cred;
661                                  * struct proc *a_p;
662                                  * } */ *ap;
663 {
664     int code;
665     AFS_GLOCK();
666     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, vop_cred);
667     AFS_GUNLOCK();
668     return code;
669 }
670 #endif
671
672 int
673 afs_vop_getattr(ap)
674      struct VOPPROT(getattr_args)       /* {
675                                  * struct vnode *a_vp;
676                                  * struct vattr *a_vap;
677                                  * struct ucred *a_cred;
678                                  * struct proc *a_p;
679                                  * } */ *ap;
680 {
681     int code;
682
683     AFS_GLOCK();
684     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
685     AFS_GUNLOCK();
686 #ifdef AFS_DARWIN80_ENV
687     VATTR_SET_SUPPORTED(ap->a_vap, va_type);
688     VATTR_SET_SUPPORTED(ap->a_vap, va_mode);
689     VATTR_SET_SUPPORTED(ap->a_vap, va_uid);
690     VATTR_SET_SUPPORTED(ap->a_vap, va_gid);
691     VATTR_SET_SUPPORTED(ap->a_vap, va_fileid);
692     VATTR_SET_SUPPORTED(ap->a_vap, va_nlink);
693     VATTR_SET_SUPPORTED(ap->a_vap, va_data_size);
694     VATTR_SET_SUPPORTED(ap->a_vap, va_access_time);
695     VATTR_SET_SUPPORTED(ap->a_vap, va_modify_time);
696     VATTR_SET_SUPPORTED(ap->a_vap, va_change_time);
697     VATTR_SET_SUPPORTED(ap->a_vap, va_gen);
698     VATTR_SET_SUPPORTED(ap->a_vap, va_flags);
699     VATTR_SET_SUPPORTED(ap->a_vap, va_iosize);
700     VATTR_SET_SUPPORTED(ap->a_vap, va_total_alloc);
701 #endif
702     return code;
703 }
704
705 int
706 afs_vop_setattr(ap)
707      struct VOPPROT(setattr_args)       /* {
708                                  * struct vnode *a_vp;
709                                  * struct vattr *a_vap;
710                                  * struct ucred *a_cred;
711                                  * struct proc *a_p;
712                                  * } */ *ap;
713 {
714     int code;
715     AFS_GLOCK();
716     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
717     AFS_GUNLOCK();
718     return code;
719 }
720
721 int
722 afs_vop_read(ap)
723      struct VOPPROT(read_args)  /* {
724                                  * struct vnode *a_vp;
725                                  * struct uio *a_uio;
726                                  * int a_ioflag;
727                                  * struct ucred *a_cred;
728                                  * } */ *ap;
729 {
730     int code;
731     struct vnode *vp = ap->a_vp;
732     struct vcache *avc = VTOAFS(vp);
733 #ifdef AFS_DARWIN80_ENV
734     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);
735 #else
736     if (UBCINFOEXISTS(ap->a_vp)) {
737         ubc_clean(ap->a_vp, 0);
738     }
739 #endif
740     AFS_GLOCK();
741     osi_FlushPages(avc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
742     code = afs_read(avc, ap->a_uio, vop_cred, 0, 0, 0);
743     AFS_GUNLOCK();
744     return code;
745 }
746
747 int
748 afs_vop_pagein(ap)
749      struct VOPPROT(pagein_args)        /* {
750                                  * struct vnode *a_vp;
751                                  * upl_t a_pl;
752                                  * vm_offset_t a_pl_offset;
753                                  * off_t a_f_offset;
754                                  * size_t a_size;
755                                  * struct ucred *a_cred;
756                                  * int a_flags;
757                                  * } */ *ap;
758 {
759     register struct vnode *vp = ap->a_vp;
760     upl_t pl = ap->a_pl;
761     size_t size = ap->a_size;
762     off_t f_offset = ap->a_f_offset;
763     vm_offset_t pl_offset = ap->a_pl_offset;
764     int flags = ap->a_flags;
765     struct ucred *cred;
766     vm_offset_t ioaddr;
767 #ifdef AFS_DARWIN80_ENV
768     struct uio *uio;
769 #else
770     struct uio auio;
771     struct iovec aiov;
772     struct uio *uio = &auio;
773 #endif
774     int nocommit = flags & UPL_NOCOMMIT;
775
776     int code;
777     struct vcache *tvc = VTOAFS(vp);
778 #ifndef AFS_DARWIN80_ENV
779     if (UBCINVALID(vp)) {
780 #if DIAGNOSTIC
781         panic("afs_vop_pagein: invalid vp");
782 #endif /* DIAGNOSTIC */
783         return (EPERM);
784     }
785
786     UBCINFOCHECK("afs_vop_pagein", vp);
787 #endif
788     if (pl == (upl_t) NULL) {
789         panic("afs_vop_pagein: no upl");
790     }
791
792     cred = ubc_getcred(vp);
793     if (cred == NOCRED)
794         cred = vop_cred;
795
796     if (size == 0) {
797         if (!nocommit)
798             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
799                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
800         return (0);
801     }
802     if (f_offset < 0) {
803         if (!nocommit)
804             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
805                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
806         return (EINVAL);
807     }
808     if (f_offset & PAGE_MASK)
809         panic("afs_vop_pagein: offset not page aligned");
810
811     OSI_UPL_MAP(pl, &ioaddr);
812     ioaddr += pl_offset;
813 #ifdef AFS_DARWIN80_ENV
814     uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
815     uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
816 #else
817     auio.uio_iov = &aiov;
818     auio.uio_iovcnt = 1;
819     auio.uio_offset = f_offset;
820     auio.uio_segflg = UIO_SYSSPACE;
821     auio.uio_rw = UIO_READ;
822     auio.uio_procp = NULL;
823     auio.uio_resid = aiov.iov_len = size;
824     aiov.iov_base = (caddr_t) ioaddr;
825 #endif
826     AFS_GLOCK();
827     osi_FlushPages(tvc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
828     code = afs_read(tvc, uio, cred, 0, 0, 0);
829     if (code == 0) {
830         ObtainWriteLock(&tvc->lock, 2);
831         tvc->states |= CMAPPED;
832         ReleaseWriteLock(&tvc->lock);
833     }
834     AFS_GUNLOCK();
835
836     /* Zero out rest of last page if there wasn't enough data in the file */
837     if (code == 0 && AFS_UIO_RESID(uio) > 0) {
838 #ifdef AFS_DARWIN80_ENV
839         memset(((caddr_t)ioaddr) + (size - AFS_UIO_RESID(uio)), 0,
840                AFS_UIO_RESID(uio));
841 #else
842         memset(aiov.iov_base, 0, auio.uio_resid);
843 #endif
844     }
845
846     OSI_UPL_UNMAP(pl);
847     if (!nocommit) {
848         if (code)
849             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
850                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
851         else
852             OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
853                                     UPL_COMMIT_CLEAR_DIRTY |
854                                     UPL_COMMIT_FREE_ON_EMPTY);
855     }
856 #ifdef AFS_DARWIN80_ENV
857     uio_free(uio);
858 #endif
859     return code;
860 }
861
862 int
863 afs_vop_write(ap)
864      struct VOPPROT(write_args) /* {
865                                  * struct vnode *a_vp;
866                                  * struct uio *a_uio;
867                                  * int a_ioflag;
868                                  * struct ucred *a_cred;
869                                  * } */ *ap;
870 {
871     int code;
872     struct vcache *avc = VTOAFS(ap->a_vp);
873     void *object;
874 #ifdef AFS_DARWIN80_ENV
875     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);
876 #else
877     if (UBCINFOEXISTS(ap->a_vp)) {
878         ubc_clean(ap->a_vp, 1);
879     }
880     if (UBCINFOEXISTS(ap->a_vp))
881         osi_VM_NukePages(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio),
882                          AFS_UIO_RESID(ap->a_uio));
883 #endif
884     AFS_GLOCK();
885     osi_FlushPages(avc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
886     code =
887         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, vop_cred, 0);
888     AFS_GUNLOCK();
889     return code;
890 }
891
892 int
893 afs_vop_pageout(ap)
894      struct VOPPROT(pageout_args)       /* {
895                                  * struct vnode *a_vp;
896                                  * upl_t   a_pl,
897                                  * vm_offset_t   a_pl_offset,
898                                  * off_t         a_f_offset,
899                                  * size_t        a_size,
900                                  * struct ucred *a_cred,
901                                  * int           a_flags
902                                  * } */ *ap;
903 {
904     register struct vnode *vp = ap->a_vp;
905     upl_t pl = ap->a_pl;
906     size_t size = ap->a_size;
907     off_t f_offset = ap->a_f_offset;
908     vm_offset_t pl_offset = ap->a_pl_offset;
909     int flags = ap->a_flags;
910     struct ucred *cred;
911     vm_offset_t ioaddr;
912 #ifdef AFS_DARWIN80_ENV
913     struct uio *uio;
914 #else
915     struct uio auio;
916     struct iovec aiov;
917     struct uio *uio = &auio;
918 #endif
919     int nocommit = flags & UPL_NOCOMMIT;
920     int iosize;
921
922     int code;
923     struct vcache *tvc = VTOAFS(vp);
924 #ifndef AFS_DARWIN80_ENV
925     if (UBCINVALID(vp)) {
926 #if DIAGNOSTIC
927         panic("afs_vop_pageout: invalid vp");
928 #endif /* DIAGNOSTIC */
929         return (EPERM);
930     }
931
932     UBCINFOCHECK("afs_vop_pageout", vp);
933 #endif
934     if (pl == (upl_t) NULL) {
935         panic("afs_vop_pageout: no upl");
936     }
937 #if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
938                                   maybe the generic
939                                   layer doesn't have them anymore? In any case,
940                                   we can't just copy code from nfs... */
941     {
942         int lbn, s;
943         struct buf *bp;
944         int biosize = DEV_BSIZE;
945
946         lbn = f_offset / DEV_BSIZE;
947
948         for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
949
950             s = splbio();
951             if (bp = incore(vp, lbn)) {
952                 if (ISSET(bp->b_flags, B_BUSY))
953                     panic("nfs_pageout: found BUSY buffer incore\n");
954
955                 bremfree(bp);
956                 SET(bp->b_flags, (B_BUSY | B_INVAL));
957                 brelse(bp);
958             }
959             splx(s);
960         }
961     }
962 #endif
963     cred = ubc_getcred(vp);
964     if (cred == NOCRED)
965         cred = vop_cred;
966
967     if (size == 0) {
968         if (!nocommit)
969             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
970                                    UPL_ABORT_FREE_ON_EMPTY);
971         return (0);
972     }
973     if (flags & (IO_APPEND | IO_SYNC))
974         panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
975     if (f_offset < 0) {
976         if (!nocommit)
977             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
978                                    UPL_ABORT_FREE_ON_EMPTY);
979         return (EINVAL);
980     }
981     if (f_offset >= tvc->m.Length) {
982         if (!nocommit)
983             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
984                                    UPL_ABORT_FREE_ON_EMPTY);
985         return (EINVAL);
986     }
987
988     if (f_offset & PAGE_MASK)
989         panic("afs_vop_pageout: offset not page aligned");
990
991     /* size will always be a multiple of PAGE_SIZE */
992     /* pageout isn't supposed to extend files */
993     if (f_offset + size > tvc->m.Length) 
994         iosize = tvc->m.Length - f_offset;
995     else
996         iosize = size;
997
998     if (size > (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK && !nocommit)  {
999             int iosize_rnd=(iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
1000             OSI_UPL_ABORT_RANGE(pl, pl_offset + iosize_rnd,
1001                                    size - iosize_rnd,
1002                                    UPL_ABORT_FREE_ON_EMPTY);
1003     }
1004     OSI_UPL_MAP(pl, &ioaddr);
1005     ioaddr += pl_offset;
1006 #ifdef AFS_DARWIN80_ENV
1007     uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
1008     uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
1009 #else
1010     auio.uio_iov = &aiov;
1011     auio.uio_iovcnt = 1;
1012     auio.uio_offset = f_offset;
1013     auio.uio_segflg = UIO_SYSSPACE;
1014     auio.uio_rw = UIO_WRITE;
1015     auio.uio_procp = NULL;
1016     auio.uio_resid = aiov.iov_len = iosize;
1017     aiov.iov_base = (caddr_t) ioaddr;
1018 #endif
1019 #if 1                           /* USV [ */
1020     {
1021         /* 
1022          * check for partial page and clear the
1023          * contents past end of the file before
1024          * releasing it in the VM page cache
1025          */
1026         if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
1027             size_t io = tvc->m.Length - f_offset;
1028
1029             memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
1030         }
1031     }
1032 #endif /* ] USV */
1033
1034     AFS_GLOCK();
1035     osi_FlushPages(tvc, vop_cred);      /* hold bozon lock, but not basic vnode lock */
1036     ObtainWriteLock(&tvc->lock, 1);
1037     afs_FakeOpen(tvc);
1038     ReleaseWriteLock(&tvc->lock);
1039
1040     code = afs_write(tvc, uio, flags, cred, 0);
1041
1042     ObtainWriteLock(&tvc->lock, 1);
1043     afs_FakeClose(tvc, cred);
1044     ReleaseWriteLock(&tvc->lock);
1045     AFS_GUNLOCK();
1046     OSI_UPL_UNMAP(pl);
1047     if (!nocommit) {
1048         if (code)
1049             OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
1050                                    UPL_ABORT_FREE_ON_EMPTY);
1051         else
1052             OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
1053                                     UPL_COMMIT_CLEAR_DIRTY |
1054                                     UPL_COMMIT_FREE_ON_EMPTY);
1055     }
1056
1057 #ifdef AFS_DARWIN80_ENV
1058     uio_free(uio);
1059 #endif
1060     return code;
1061 }
1062
1063 int
1064 afs_vop_ioctl(ap)
1065      struct VOPPROT(ioctl_args) /* {
1066                                  * struct vnode *a_vp;
1067                                  * int  a_command;
1068                                  * caddr_t  a_data;
1069                                  * int  a_fflag;
1070                                  * struct ucred *a_cred;
1071                                  * struct proc *a_p;
1072                                  * } */ *ap;
1073 {
1074     struct vcache *tvc = VTOAFS(ap->a_vp);
1075     struct afs_ioctl data;
1076     int error = 0;
1077
1078     /* in case we ever get in here... */
1079
1080     AFS_STATCNT(afs_ioctl);
1081     if (((ap->a_command >> 8) & 0xff) == 'V') {
1082         /* This is a VICEIOCTL call */
1083         AFS_GLOCK();
1084         error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
1085                             ap->a_command, ap->a_data);
1086         AFS_GUNLOCK();
1087         return (error);
1088     } else {
1089         /* No-op call; just return. */
1090         return (ENOTTY);
1091     }
1092 }
1093
1094 /* ARGSUSED */
1095 int
1096 afs_vop_select(ap)
1097      struct VOPPROT(select_args)        /* {
1098                                  * struct vnode *a_vp;
1099                                  * int  a_which;
1100                                  * int  a_fflags;
1101                                  * struct ucred *a_cred;
1102                                  * struct proc *a_p;
1103                                  * } */ *ap;
1104 {
1105     /*
1106      * We should really check to see if I/O is possible.
1107      */
1108     return (1);
1109 }
1110
1111 /*
1112  * Mmap a file
1113  *
1114  * NB Currently unsupported.
1115  */
1116 /* ARGSUSED */
1117 int
1118 afs_vop_mmap(ap)
1119      struct VOPPROT(mmap_args)  /* {
1120                                  * struct vnode *a_vp;
1121                                  * int  a_fflags;
1122                                  * struct ucred *a_cred;
1123                                  * struct proc *a_p;
1124                                  * } */ *ap;
1125 {
1126     return (EINVAL);
1127 }
1128
1129 int
1130 afs_vop_fsync(ap)
1131      struct VOPPROT(fsync_args) /* {
1132                                  * struct vnode *a_vp;
1133                                  * struct ucred *a_cred;
1134                                  * int a_waitfor;
1135                                  * struct proc *a_p;
1136                                  * } */ *ap;
1137 {
1138     int wait = ap->a_waitfor == MNT_WAIT;
1139     int error;
1140     register struct vnode *vp = ap->a_vp;
1141     int haveGlock = ISAFS_GLOCK();
1142
1143     /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
1144     if (!haveGlock) AFS_GLOCK();
1145     if (vop_cred)
1146         error = afs_fsync(VTOAFS(vp), vop_cred);
1147     else
1148         error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
1149     if (!haveGlock) AFS_GUNLOCK();
1150     return error;
1151 }
1152
1153 #ifndef AFS_DARWIN80_ENV
1154 int
1155 afs_vop_seek(ap)
1156      struct VOPPROT(seek_args)  /* {
1157                                  * struct vnode *a_vp;
1158                                  * off_t  a_oldoff;
1159                                  * off_t  a_newoff;
1160                                  * struct ucred *a_cred;
1161                                  * } */ *ap;
1162 {
1163     if (ap->a_newoff > ULONG_MAX)       /* AFS doesn't support 64-bit offsets */
1164         return EINVAL;
1165     return (0);
1166 }
1167 #endif
1168
1169 int
1170 afs_vop_remove(ap)
1171      struct VOPPROT(remove_args)        /* {
1172                                  * struct vnode *a_dvp;
1173                                  * struct vnode *a_vp;
1174                                  * struct componentname *a_cnp;
1175                                  * } */ *ap;
1176 {
1177     int error = 0;
1178     register struct vnode *vp = ap->a_vp;
1179     register struct vnode *dvp = ap->a_dvp;
1180
1181 #ifdef AFS_DARWIN80_ENV
1182     if (ap->a_flags & VNODE_REMOVE_NODELETEBUSY) {
1183             /* Caller requested Carbon delete semantics */
1184             if (vnode_isinuse(vp, 0)) {
1185                     return EBUSY;
1186             }
1187     }
1188 #endif
1189
1190     GETNAME();
1191     AFS_GLOCK();
1192     error = afs_remove(VTOAFS(dvp), name, vop_cn_cred);
1193     AFS_GUNLOCK();
1194     cache_purge(vp);
1195     if (!error) {
1196 #ifdef AFS_DARWIN80_ENV
1197         struct vcache *tvc = VTOAFS(vp);
1198         
1199         if (!(tvc->states & CUnlinked)) {
1200             ubc_setsize(vp, (off_t)0);
1201             vnode_recycle(vp);
1202         }
1203 #else
1204         /* necessary so we don't deadlock ourselves in vclean */
1205         VOP_UNLOCK(vp, 0, cnp->cn_proc);
1206
1207         /* If crashes continue in ubc_hold, comment this out */
1208         (void)ubc_uncache(vp);
1209 #endif
1210     }
1211
1212 #ifndef AFS_DARWIN80_ENV
1213     vput(dvp);
1214     if (dvp == vp)
1215         vrele(vp);
1216     else
1217         vput(vp);
1218 #endif
1219
1220 #ifndef AFS_DARWIN80_ENV
1221     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1222 #endif
1223     DROPNAME();
1224     return error;
1225 }
1226
1227 int
1228 afs_vop_link(ap)
1229      struct VOPPROT(link_args)  /* {
1230                                  * struct vnode *a_vp;
1231                                  * struct vnode *a_tdvp;
1232                                  * struct componentname *a_cnp;
1233                                  * } */ *ap;
1234 {
1235     int error = 0;
1236     register struct vnode *dvp = ap->a_tdvp;
1237     register struct vnode *vp = ap->a_vp;
1238     struct proc *p;
1239
1240     GETNAME();
1241     p = vop_cn_proc;
1242     if (vnode_isdir(vp)) {
1243         VOP_ABORTOP(vp, cnp);
1244         error = EISDIR;
1245         goto out;
1246     }
1247 #ifndef AFS_DARWIN80_ENV
1248     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
1249         VOP_ABORTOP(dvp, cnp);
1250         goto out;
1251     }
1252 #endif
1253     AFS_GLOCK();
1254     error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, vop_cn_cred);
1255     AFS_GUNLOCK();
1256 #ifndef AFS_DARWIN80_ENV
1257     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1258 #endif
1259 #ifndef AFS_DARWIN80_ENV
1260     if (dvp != vp)
1261         VOP_UNLOCK(vp, 0, p);
1262 #endif
1263   out:
1264 #ifndef AFS_DARWIN80_ENV
1265     vput(dvp);
1266 #endif
1267     DROPNAME();
1268     return error;
1269 }
1270
1271 int
1272 afs_vop_rename(ap)
1273      struct VOPPROT(rename_args)        /* {
1274                                  * struct vnode *a_fdvp;
1275                                  * struct vnode *a_fvp;
1276                                  * struct componentname *a_fcnp;
1277                                  * struct vnode *a_tdvp;
1278                                  * struct vnode *a_tvp;
1279                                  * struct componentname *a_tcnp;
1280                                  * } */ *ap;
1281 {
1282     int error = 0;
1283     struct componentname *fcnp = ap->a_fcnp;
1284     char *fname;
1285     struct componentname *tcnp = ap->a_tcnp;
1286     char *tname;
1287     struct vnode *tvp = ap->a_tvp;
1288     register struct vnode *tdvp = ap->a_tdvp;
1289     struct vnode *fvp = ap->a_fvp;
1290     register struct vnode *fdvp = ap->a_fdvp;
1291     struct proc *p; 
1292
1293     p = cn_proc(fcnp);
1294
1295 #ifdef AFS_DARWIN80_ENV
1296 /* generic code tests for v_mount equality, so we don't have to, but we don't
1297    get the multiple-mount "benefits" of the old behavior
1298 */
1299 #else
1300     /* Check for cross-device rename.
1301      * For AFS, this means anything not in AFS-space
1302      */
1303     if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
1304         (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
1305         error = EXDEV;
1306         goto abortit;
1307     }
1308 #endif
1309
1310 #ifdef AFS_DARWIN80_ENV
1311    /* the generic code doesn't do this, so we really should, but all the
1312       vrele's are wrong... */
1313 #else
1314     /*
1315      * if fvp == tvp, we're just removing one name of a pair of
1316      * directory entries for the same element.  convert call into rename.
1317      ( (pinched from NetBSD 1.0's ufs_rename())
1318      */
1319     if (fvp == tvp) {
1320         if (vnode_isdir(fvp)) {
1321             error = EINVAL;
1322           abortit:
1323             VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
1324             if (tdvp == tvp)
1325                 vrele(tdvp);
1326             else
1327                 vput(tdvp);
1328             if (tvp)
1329                 vput(tvp);
1330             VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
1331             vrele(fdvp);
1332             vrele(fvp);
1333             return (error);
1334         }
1335
1336         /* Release destination completely. */
1337         VOP_ABORTOP(tdvp, tcnp);
1338         vput(tdvp);
1339         vput(tvp);
1340         /* Delete source. */
1341 #if defined(AFS_DARWIN80_ENV) 
1342
1343         MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1344         memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
1345         fname[fcnp->cn_namelen] = '\0';
1346         AFS_GLOCK();
1347         error = afs_remove(VTOAFS(fdvp), fname, vop_cn_cred);
1348         AFS_GUNLOCK();
1349         FREE(fname, M_TEMP);
1350         cache_purge(fvp);
1351 #else
1352         vrele(fdvp);
1353         vrele(fvp);
1354         fcnp->cn_flags &= ~MODMASK;
1355         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1356         if ((fcnp->cn_flags & SAVESTART) == 0)
1357             panic("afs_rename: lost from startdir");
1358         fcnp->cn_nameiop = DELETE;
1359
1360         VREF(fdvp); 
1361         error=relookup(fdvp, &fvp, fcnp);
1362         if (error == 0)
1363             vrele(fdvp);
1364         if (fvp == NULL) {
1365             return (ENOENT);
1366         }
1367         error=VOP_REMOVE(fdvp, fvp, fcnp);
1368 #endif
1369         
1370         if (fdvp == fvp)
1371             vrele(fdvp);
1372         else
1373             vput(fdvp);
1374         vput(fvp);
1375         return (error);
1376     }
1377 #endif
1378 #if !defined(AFS_DARWIN80_ENV) 
1379     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
1380         goto abortit;
1381 #endif
1382
1383     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1384     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
1385     fname[fcnp->cn_namelen] = '\0';
1386     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
1387     memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
1388     tname[tcnp->cn_namelen] = '\0';
1389
1390
1391     AFS_GLOCK();
1392     /* XXX use "from" or "to" creds? NFS uses "to" creds */
1393     error =
1394         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, cn_cred(tcnp));
1395     AFS_GUNLOCK();
1396
1397 #if !defined(AFS_DARWIN80_ENV) 
1398     VOP_UNLOCK(fvp, 0, p);
1399 #endif
1400     FREE(fname, M_TEMP);
1401     FREE(tname, M_TEMP);
1402 #ifdef AFS_DARWIN80_ENV
1403     cache_purge(fdvp);
1404     cache_purge(fvp);
1405     cache_purge(tdvp);
1406     if (tvp) {
1407        cache_purge(tvp);
1408        if (!error) {
1409           vnode_recycle(tvp);
1410        }
1411     }
1412     if (!error)
1413        cache_enter(tdvp, fvp, tcnp);
1414 #else
1415     if (error)
1416         goto abortit;           /* XXX */
1417     if (tdvp == tvp)
1418         vrele(tdvp);
1419     else
1420         vput(tdvp);
1421     if (tvp)
1422         vput(tvp);
1423     vrele(fdvp);
1424     vrele(fvp);
1425 #endif
1426     return error;
1427 }
1428
1429 int
1430 afs_vop_mkdir(ap)
1431      struct VOPPROT(mkdir_args) /* {
1432                                  * struct vnode *a_dvp;
1433                                  * struct vnode **a_vpp;
1434                                  * struct componentname *a_cnp;
1435                                  * struct vattr *a_vap;
1436                                  * } */ *ap;
1437 {
1438     register struct vnode *dvp = ap->a_dvp;
1439     register struct vattr *vap = ap->a_vap;
1440     int error = 0;
1441     struct vcache *vcp;
1442     struct proc *p;
1443
1444     GETNAME();
1445     p = vop_cn_proc;
1446 #if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
1447     if ((cnp->cn_flags & HASBUF) == 0)
1448         panic("afs_vop_mkdir: no name");
1449 #endif
1450     AFS_GLOCK();
1451     error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, vop_cn_cred);
1452     AFS_GUNLOCK();
1453     if (error) {
1454 #ifndef AFS_DARWIN80_ENV
1455         VOP_ABORTOP(dvp, cnp);
1456         vput(dvp);
1457 #endif
1458         DROPNAME();
1459         return (error);
1460     }
1461     if (vcp) {
1462 #ifdef AFS_DARWIN80_ENV
1463         afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0);
1464 #endif
1465         *ap->a_vpp = AFSTOV(vcp);
1466 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
1467         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
1468         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
1469 #endif
1470     } else
1471         *ap->a_vpp = 0;
1472     DROPNAME();
1473 #ifndef AFS_DARWIN80_ENV
1474     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1475     vput(dvp);
1476 #endif
1477     return error;
1478 }
1479
1480 int
1481 afs_vop_rmdir(ap)
1482      struct VOPPROT(rmdir_args) /* {
1483                                  * struct vnode *a_dvp;
1484                                  * struct vnode *a_vp;
1485                                  * struct componentname *a_cnp;
1486                                  * } */ *ap;
1487 {
1488     int error = 0;
1489     register struct vnode *vp = ap->a_vp;
1490     register struct vnode *dvp = ap->a_dvp;
1491
1492     GETNAME();
1493     if (dvp == vp) {
1494 #ifndef AFS_DARWIN80_ENV
1495         vrele(dvp);
1496         vput(vp);
1497         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1498 #endif
1499         DROPNAME();
1500         return (EINVAL);
1501     }
1502
1503     AFS_GLOCK();
1504     error = afs_rmdir(VTOAFS(dvp), name, vop_cn_cred);
1505     AFS_GUNLOCK();
1506     DROPNAME();
1507     cache_purge(dvp);
1508     cache_purge(vp);
1509 #ifndef AFS_DARWIN80_ENV
1510     vput(dvp);
1511     vput(vp);
1512 #endif
1513     return error;
1514 }
1515
1516 int
1517 afs_vop_symlink(ap)
1518      struct VOPPROT(symlink_args)       /* {
1519                                  * struct vnode *a_dvp;
1520                                  * struct vnode **a_vpp;
1521                                  * struct componentname *a_cnp;
1522                                  * struct vattr *a_vap;
1523                                  * char *a_target;
1524                                  * } */ *ap;
1525 {
1526     register struct vnode *dvp = ap->a_dvp;
1527     int error = 0;
1528     /* NFS ignores a_vpp; so do we. */
1529
1530     GETNAME();
1531     AFS_GLOCK();
1532     error =
1533         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
1534     AFS_GUNLOCK();
1535     DROPNAME();
1536 #ifndef AFS_DARWIN80_ENV
1537     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1538     vput(dvp);
1539 #endif
1540     return error;
1541 }
1542
1543 int
1544 afs_vop_readdir(ap)
1545      struct VOPPROT(readdir_args)       /* {
1546                                  * struct vnode *a_vp;
1547                                  * struct uio *a_uio;
1548                                  * struct ucred *a_cred;
1549                                  * int *a_eofflag;
1550                                  * u_long *a_cookies;
1551                                  * int ncookies;
1552                                  * } */ *ap;
1553 {
1554     int error;
1555     off_t off;
1556 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1557            ap->a_ncookies); */
1558 #ifdef AFS_DARWIN80_ENV
1559     /* too much work for now */
1560     /* should only break nfs exports */
1561     if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
1562          return (EINVAL);
1563 #endif
1564     off = AFS_UIO_OFFSET(ap->a_uio);
1565     AFS_GLOCK();
1566     error =
1567         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, vop_cred, ap->a_eofflag);
1568     AFS_GUNLOCK();
1569 #ifndef AFS_DARWIN80_ENV
1570     if (!error && ap->a_ncookies != NULL) {
1571         struct uio *uio = ap->a_uio;
1572         const struct dirent *dp, *dp_start, *dp_end;
1573         int ncookies;
1574         u_long *cookies, *cookiep;
1575
1576         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1577             panic("afs_readdir: burned cookies");
1578         dp = (const struct dirent *)
1579             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1580
1581         dp_end = (const struct dirent *)uio->uio_iov->iov_base;
1582         for (dp_start = dp, ncookies = 0; dp < dp_end;
1583              dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
1584             ncookies++;
1585
1586         MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1587                M_WAITOK);
1588         for (dp = dp_start, cookiep = cookies; dp < dp_end;
1589              dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
1590             off += dp->d_reclen;
1591             *cookiep++ = off;
1592         }
1593         *ap->a_cookies = cookies;
1594         *ap->a_ncookies = ncookies;
1595     }
1596 #endif
1597
1598     return error;
1599 }
1600
1601 int
1602 afs_vop_readlink(ap)
1603      struct VOPPROT(readlink_args)      /* {
1604                                  * struct vnode *a_vp;
1605                                  * struct uio *a_uio;
1606                                  * struct ucred *a_cred;
1607                                  * } */ *ap;
1608 {
1609     int error;
1610 /*    printf("readlink %x\n", ap->a_vp);*/
1611     AFS_GLOCK();
1612     error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, vop_cred);
1613     AFS_GUNLOCK();
1614     return error;
1615 }
1616
1617 extern int prtactive;
1618
1619 int
1620 afs_vop_inactive(ap)
1621      struct VOPPROT(inactive_args)      /* {
1622                                  * struct vnode *a_vp;
1623                                  * struct proc *a_p;
1624                                  * } */ *ap;
1625 {
1626     register struct vnode *vp = ap->a_vp;
1627     struct vcache *tvc = VTOAFS(vp);
1628 #ifndef AFS_DARWIN80_ENV
1629     if (prtactive && vp->v_usecount != 0)
1630         vprint("afs_vop_inactive(): pushing active", vp);
1631 #endif
1632     if (tvc) {
1633 #ifdef AFS_DARWIN80_ENV
1634         int unlinked = tvc->states & CUnlinked;
1635 #endif
1636         AFS_GLOCK();
1637         afs_InactiveVCache(tvc, 0);     /* decrs ref counts */
1638         AFS_GUNLOCK();
1639 #ifdef AFS_DARWIN80_ENV
1640         if (unlinked) {
1641             vnode_recycle(vp);
1642             cache_purge(vp);
1643         }
1644 #endif
1645     }
1646 #ifndef AFS_DARWIN80_ENV
1647     VOP_UNLOCK(vp, 0, ap->a_p);
1648 #endif
1649     return 0;
1650 }
1651
1652 int
1653 afs_vop_reclaim(ap)
1654      struct VOPPROT(reclaim_args)       /* {
1655                                  * struct vnode *a_vp;
1656                                  * } */ *ap;
1657 {
1658     int error = 0;
1659     int sl, writelocked;
1660     register struct vnode *vp = ap->a_vp;
1661     struct vcache *tvc = VTOAFS(vp);
1662
1663     osi_Assert(!ISAFS_GLOCK());
1664     cache_purge(vp);            /* just in case... */
1665     if (tvc) {
1666        AFS_GLOCK();
1667        writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
1668        if (!writelocked) {
1669            ObtainWriteLock(&afs_xvreclaim, 176);
1670 #ifdef AFS_DARWIN80_ENV
1671            vnode_clearfsnode(AFSTOV(tvc));
1672            vnode_removefsref(AFSTOV(tvc));
1673 #else
1674            tvc->v->v_data = NULL;  /* remove from vnode */
1675 #endif
1676            AFSTOV(tvc) = NULL;             /* also drop the ptr to vnode */
1677            tvc->states |= CVInit; /* also CDeadVnode? */
1678            tvc->nextfree = ReclaimedVCList;
1679            ReclaimedVCList = tvc;
1680            ReleaseWriteLock(&afs_xvreclaim);
1681        } else {
1682            error = afs_FlushVCache(tvc, &sl);   /* toss our stuff from vnode */
1683            if (tvc->states & (CVInit
1684 #ifdef AFS_DARWIN80_ENV
1685                               | CDeadVnode
1686 #endif
1687                    )) {
1688                tvc->states &= ~(CVInit
1689 #ifdef AFS_DARWIN80_ENV
1690                                 | CDeadVnode
1691 #endif
1692                    );
1693                afs_osi_Wakeup(&tvc->states);
1694            }
1695            if (!error && vnode_fsnode(vp))
1696                panic("afs_reclaim: vnode not cleaned");
1697            if (!error && (tvc->v != NULL)) 
1698                panic("afs_reclaim: vcache not cleaned");
1699            ReleaseWriteLock(&afs_xvcache);
1700        }
1701        AFS_GUNLOCK();
1702     }
1703     return error;
1704 }
1705
1706 /*
1707  * Return POSIX pathconf information applicable to ufs filesystems.
1708  */
1709 afs_vop_pathconf(ap)
1710      struct VOPPROT(pathconf_args)      /* {
1711                                  * struct vnode *a_vp;
1712                                  * int a_name;
1713                                  * int *a_retval;
1714                                  * } */ *ap;
1715 {
1716     AFS_STATCNT(afs_cntl);
1717     switch (ap->a_name) {
1718     case _PC_LINK_MAX:
1719         *ap->a_retval = LINK_MAX;
1720         break;
1721     case _PC_NAME_MAX:
1722         *ap->a_retval = NAME_MAX;
1723         break;
1724     case _PC_PATH_MAX:
1725         *ap->a_retval = PATH_MAX;
1726         break;
1727     case _PC_CHOWN_RESTRICTED:
1728         *ap->a_retval = 1;
1729         break;
1730     case _PC_NO_TRUNC:
1731         *ap->a_retval = 1;
1732         break;
1733     case _PC_PIPE_BUF:
1734         return EINVAL;
1735         break;
1736 #if defined(AFS_DARWIN70_ENV)
1737     case _PC_NAME_CHARS_MAX:
1738         *ap->a_retval = NAME_MAX;
1739         break;
1740     case _PC_CASE_SENSITIVE:
1741         *ap->a_retval = 1;
1742         break;
1743     case _PC_CASE_PRESERVING:
1744         *ap->a_retval = 1;
1745         break;
1746 #endif /* defined(AFS_DARWIN70_ENV) */
1747     default:
1748         return EINVAL;
1749     }
1750     return 0;
1751 }
1752
1753 /*
1754  * Advisory record locking support (fcntl() POSIX style)
1755  */
1756 int
1757 afs_vop_advlock(ap)
1758      struct VOPPROT(advlock_args)       /* {
1759                                  * struct vnode *a_vp;
1760                                  * caddr_t  a_id;
1761                                  * int  a_op;
1762                                  * struct flock *a_fl;
1763                                  * int  a_flags;
1764                                  * } */ *ap;
1765 {
1766     int error;
1767     struct ucred *tcr;
1768     int clid;
1769     int op;
1770 #ifdef AFS_DARWIN80_ENV
1771     proc_t p;
1772     tcr=vop_cred;
1773 #else
1774     struct proc *p = current_proc();
1775     struct ucred cr;
1776     pcred_readlock(p);
1777     cr = *p->p_cred->pc_ucred;
1778     pcred_unlock(p);
1779     tcr=&cr;
1780 #endif
1781     if (ap->a_flags & F_POSIX) {
1782 #ifdef AFS_DARWIN80_ENV
1783         p = (proc_t) ap->a_id;
1784         clid = proc_pid(p);
1785 #else
1786         p = (struct proc *) ap->a_id;
1787         clid = p->p_pid;
1788 #endif
1789     } else {
1790         clid = (int)ap->a_id;
1791     }
1792     if (ap->a_op == F_UNLCK) {
1793         op = F_SETLK;
1794     } else if (ap->a_op == F_SETLK && ap->a_flags & F_WAIT) {
1795         op = F_SETLKW;
1796     } else {
1797         op = ap->a_op;
1798     }
1799     AFS_GLOCK();
1800     error = afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, op, tcr, clid);
1801     AFS_GUNLOCK();
1802     return error;
1803 }
1804
1805 int
1806 afs_vop_blktooff(ap)
1807      struct VOPPROT(blktooff_args)      /* {
1808                                  * struct vnode *a_vp;
1809                                  * daddr_t a_lblkno;
1810                                  * off_t *a_offset;    
1811                                  * } */ *ap;
1812 {
1813     *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1814     return 0;
1815 }
1816
1817 int
1818 afs_vop_offtoblk(ap)
1819      struct VOPPROT(offtoblk_args)      /* {
1820                                  * struct vnode *a_vp;
1821                                  * off_t a_offset;    
1822                                  * daddr_t *a_lblkno;
1823                                  * } */ *ap;
1824 {
1825     *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1826
1827     return (0);
1828 }
1829
1830 #ifndef AFS_DARWIN80_ENV
1831 int
1832 afs_vop_lock(ap)
1833      struct VOPPROT(lock_args)  /* {
1834                                  * struct vnode *a_vp;
1835                                  * } */ *ap;
1836 {
1837     register struct vnode *vp = ap->a_vp;
1838     register struct vcache *avc = VTOAFS(vp);
1839
1840     if (vp->v_tag == VT_NON)
1841         return (ENOENT);
1842
1843     return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1844 }
1845
1846 int
1847 afs_vop_unlock(ap)
1848      struct VOPPROT(unlock_args)        /* {
1849                                  * struct vnode *a_vp;
1850                                  * } */ *ap;
1851 {
1852     struct vnode *vp = ap->a_vp;
1853     struct vcache *avc = VTOAFS(vp);
1854
1855     return (lockmgr
1856             (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1857              ap->a_p));
1858
1859 }
1860
1861 int
1862 afs_vop_truncate(ap)
1863      struct VOPPROT(truncate_args)      /* {
1864                                  * struct vnode *a_vp;
1865                                  * off_t a_length;
1866                                  * int a_flags;
1867                                  * struct ucred *a_cred;
1868                                  * struct proc *a_p;
1869                                  * } */ *ap;
1870 {
1871     printf("stray afs_vop_truncate\n");
1872     return EOPNOTSUPP;
1873 }
1874
1875 int
1876 afs_vop_update(ap)
1877      struct VOPPROT(update_args)        /* {
1878                                  * struct vnode *a_vp;
1879                                  * struct timeval *a_access;
1880                                  * struct timeval *a_modify;
1881                                  * int a_waitfor;
1882                                  * } */ *ap;
1883 {
1884     printf("stray afs_vop_update\n");
1885     return EOPNOTSUPP;
1886 }
1887
1888 int
1889 afs_vop_bmap(ap)
1890      struct VOPPROT(bmap_args)  /* {
1891                                  * struct vnode *a_vp;
1892                                  * daddr_t  a_bn;
1893                                  * struct vnode **a_vpp;
1894                                  * daddr_t *a_bnp;
1895                                  * int *a_runp;
1896                                  * int *a_runb;
1897                                  * } */ *ap;
1898 {
1899     int error;
1900     if (ap->a_bnp) {
1901         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1902     }
1903     if (ap->a_vpp) {
1904         *ap->a_vpp = ap->a_vp;
1905     }
1906     if (ap->a_runp != NULL)
1907         *ap->a_runp = 0;
1908 #ifdef notyet
1909     if (ap->a_runb != NULL)
1910         *ap->a_runb = 0;
1911 #endif
1912
1913     return 0;
1914 }
1915
1916 int
1917 afs_vop_strategy(ap)
1918      struct VOPPROT(strategy_args)      /* {
1919                                  * struct buf *a_bp;
1920                                  * } */ *ap;
1921 {
1922     int error;
1923     AFS_GLOCK();
1924     error = afs_ustrategy(ap->a_bp);
1925     AFS_GUNLOCK();
1926     return error;
1927 }
1928
1929 int
1930 afs_vop_print(ap)
1931      struct VOPPROT(print_args) /* {
1932                                  * struct vnode *a_vp;
1933                                  * } */ *ap;
1934 {
1935     register struct vnode *vp = ap->a_vp;
1936     register struct vcache *vc = VTOAFS(ap->a_vp);
1937     int s = vc->states;
1938     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
1939            vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
1940            vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
1941     printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
1942            (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
1943            (s & CMAPPED) ? " mapped" : "",
1944            (s & CVFlushed) ? " flush in progress" : "");
1945     if (UBCISVALID(vp)) {
1946         printf("\n  UBC: ");
1947         if (UBCINFOEXISTS(vp)) {
1948             printf("exists, ");
1949 #ifdef AFS_DARWIN14_ENV
1950             printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1951                    ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1952                    ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1953 #else
1954             printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1955 #endif
1956         } else
1957             printf("does not exist");
1958     }
1959     printf("\n");
1960     return 0;
1961 }
1962
1963 int
1964 afs_vop_islocked(ap)
1965      struct VOPPROT(islocked_args)      /* {
1966                                  * struct vnode *a_vp;
1967                                  * } */ *ap;
1968 {
1969     struct vcache *vc = VTOAFS(ap->a_vp);
1970     return lockstatus(&vc->rwlock);
1971 }
1972
1973 int
1974 afs_vop_cmap(ap)
1975      struct VOPPROT(cmap_args)  /* {
1976                                  * struct vnode *a_vp;
1977                                  * off_t a_foffset;    
1978                                  * size_t a_size;
1979                                  * daddr_t *a_bpn;
1980                                  * size_t *a_run;
1981                                  * void *a_poff;
1982                                  * } */ *ap;
1983 {
1984     *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1985     *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1986     return 0;
1987 }
1988 #endif
1989
1990 int
1991 afs_darwin_getnewvnode(struct vcache *avc)
1992 {
1993 #ifdef AFS_DARWIN80_ENV
1994     vnode_t vp;
1995     int error, dead;
1996     struct vnode_fsparam par;
1997
1998     memset(&par, 0, sizeof(struct vnode_fsparam));
1999 #if 0
2000     AFS_GLOCK();
2001     ObtainWriteLock(&avc->lock,342);
2002     if (avc->states & CStatd) { 
2003        par.vnfs_vtype = avc->m.Type;
2004        par.vnfs_vops = afs_vnodeop_p;
2005        par.vnfs_filesize = avc->m.Length;
2006        if (!ac->cnp)
2007            par.vnfs_flags = VNFS_NOCACHE;
2008        dead = 0;
2009     } else {
2010        par.vnfs_vtype = VNON;
2011        par.vnfs_vops = afs_dead_vnodeop_p;
2012        par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
2013        dead = 1;
2014     }
2015     ReleaseWriteLock(&avc->lock);
2016     AFS_GUNLOCK();
2017     par.vnfs_dvp = ac->dvp;
2018     par.vnfs_cnp = ac->cnp;
2019     par.vnfs_markroot = ac->markroot;
2020 #else
2021     par.vnfs_vtype = VNON;
2022     par.vnfs_vops = afs_dead_vnodeop_p;
2023     par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
2024 #endif
2025     par.vnfs_mp = afs_globalVFS;
2026     par.vnfs_fsnode = avc;
2027
2028     error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &vp);
2029     if (!error) {
2030       vnode_addfsref(vp);
2031       vnode_ref(vp);
2032       avc->v = vp;
2033 #if 0
2034       if (dead) {
2035          vnode_recycle(vp); /* terminate as soon as iocount drops */
2036          avc->states |= CDeadVnode;
2037       } else if (!ac->markroot && !ac->cnp) {
2038        /* the caller doesn't know anything about this vnode. if markroot
2039           should have been set and wasn't, bad things may happen, so encourage
2040           it to recycle */
2041           vnode_recycle(vp);
2042       }
2043 #else
2044       vnode_recycle(vp); /* terminate as soon as iocount drops */
2045       avc->states |= CDeadVnode;
2046 #endif
2047     }
2048     return error;
2049 #else
2050     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &avc->v)) {
2051         /* no vnodes available, force an alloc (limits be damned)! */
2052         printf("failed to get vnode\n");
2053     }
2054     avc->v->v_data = (void *)avc;
2055     return 0;
2056 #endif
2057 }
2058 #ifdef AFS_DARWIN80_ENV
2059 /* if this fails, then tvc has been unrefed and may have been freed. 
2060    Don't touch! */
2061 int 
2062 afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct componentname *cnp, int isroot) {
2063    vnode_t ovp = AFSTOV(avc);
2064    vnode_t nvp;
2065    int error;
2066    struct vnode_fsparam par;
2067    AFS_GLOCK();
2068    ObtainWriteLock(&avc->lock,325);
2069    if (!(avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
2070         ReleaseWriteLock(&avc->lock);
2071         AFS_GUNLOCK();
2072 #if 0 /* unsupported */
2073         if (dvp && cnp)
2074         vnode_update_identity(ovp, dvp, cnp->cn_nameptr, cnp->cn_namelen,
2075                               cnp->cn_hash,
2076                               VNODE_UPDATE_PARENT|VNODE_UPDATE_NAME);
2077 #endif
2078         vnode_rele(ovp);
2079         return 0;
2080    }
2081    if ((avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON) 
2082        panic("vcache %p should not be CDeadVnode", avc);
2083    AFS_GUNLOCK();
2084    memset(&par, 0, sizeof(struct vnode_fsparam));
2085    par.vnfs_mp = afs_globalVFS;
2086    par.vnfs_vtype = avc->m.Type;
2087    par.vnfs_vops = afs_vnodeop_p;
2088    par.vnfs_filesize = avc->m.Length;
2089    par.vnfs_fsnode = avc;
2090    par.vnfs_dvp = dvp;
2091    if (cnp && (cnp->cn_flags & ISDOTDOT) == 0)
2092        par.vnfs_cnp = cnp;
2093    if (!dvp || !cnp || (cnp->cn_flags & MAKEENTRY) == 0)
2094        par.vnfs_flags = VNFS_NOCACHE;
2095    if (isroot)
2096        par.vnfs_markroot = 1;
2097    error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &nvp);
2098    if (!error) {
2099      vnode_addfsref(nvp);
2100      avc->v = nvp;
2101      avc->states &=~ CDeadVnode;
2102      vnode_clearfsnode(ovp);
2103      vnode_removefsref(ovp);
2104    }
2105    AFS_GLOCK();
2106    ReleaseWriteLock(&avc->lock);
2107    if (!error)
2108       afs_osi_Wakeup(&avc->states);
2109    AFS_GUNLOCK();
2110    vnode_put(ovp);
2111    vnode_rele(ovp);
2112    return error;
2113 }
2114 #endif