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