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