2 * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
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>
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>
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)
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)),\
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))
47 extern char afs_zeros[AFS_ZEROS];
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) *);
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
102 /* Global vfs data structures for AFS. */
103 int (**afs_vnodeop_p) ();
105 #define VOPFUNC int (*)(void *)
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 */
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
142 {VOPPREF(abortop_desc), (VOPFUNC)ufs_abortop}, /* abortop */
143 #endif /* defined(AFS_DARWIN70_ENV) */
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 */
152 #ifdef AFS_DARWIN80_ENV
153 {VOPPREF(strategy_desc), (VOPFUNC)err_strategy}, /* strategy */
155 {VOPPREF(strategy_desc), (VOPFUNC)afs_vop_strategy}, /* strategy */
157 #ifndef AFS_DARWIN80_ENV
158 {VOPPREF(print_desc), (VOPFUNC)afs_vop_print}, /* print */
159 {VOPPREF(islocked_desc), (VOPFUNC)afs_vop_islocked}, /* islocked */
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 */
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}
177 struct vnodeopv_desc afs_vnodeop_opv_desc =
178 { &afs_vnodeop_p, afs_vnodeop_entries };
180 #ifdef AFS_DARWIN80_ENV
181 /* vfs structures for incompletely initialized vnodes */
182 int (**afs_dead_vnodeop_p) ();
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}
220 struct vnodeopv_desc afs_dead_vnodeop_opv_desc =
221 { &afs_dead_vnodeop_p, afs_dead_vnodeop_entries };
225 struct componentname *cnp = ap->a_cnp; \
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'
231 #define DROPNAME() FREE(name, M_TEMP)
234 darwin_vn_hold(struct vnode *vp)
236 int haveGlock=ISAFS_GLOCK();
237 struct vcache *tvc = VTOAFS(vp);
239 #ifndef AFS_DARWIN80_ENV
240 tvc->states |= CUBCinit;
242 #ifdef AFS_DARWIN80_ENV
243 if (tvc->states & CDeadVnode)
244 osi_Assert(!vnode_isinuse(vp, 1));
245 osi_Assert((tvc->states & CVInit) == 0);
247 if (haveGlock) AFS_GUNLOCK();
249 #ifdef AFS_DARWIN80_ENV
251 /* being terminated. kernel won't give us a ref. Now what? our
252 callers don't expect us to fail */
254 panic("vn_hold on terminating vnode");
256 if (haveGlock) AFS_GLOCK();
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. */
268 if (VREFCOUNT_GT(tvc, 0))
269 VREF(((struct vnode *)(vp)));
271 afs_vget(afs_globalVFS, 0, (vp));
274 #ifndef AFS_DARWIN80_ENV
275 if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) {
280 if (haveGlock) AFS_GLOCK();
281 #ifndef AFS_DARWIN80_ENV
282 tvc->states &= ~CUBCinit;
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;
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 */
301 #ifdef AFS_DARWIN80_ENV
302 error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
312 lockparent = flags & LOCKPARENT;
313 wantparent = flags & (LOCKPARENT | WANTPARENT);
315 if (!vnode_isdir(ap->a_dvp)) {
321 #ifndef AFS_DARWIN80_ENV
322 if (flags & ISDOTDOT)
323 VOP_UNLOCK(dvp, 0, p);
326 error = afs_lookup(VTOAFS(dvp), name, &vcp, vop_cn_cred);
329 #ifndef AFS_DARWIN80_ENV
330 if (flags & ISDOTDOT)
331 VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
333 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
334 && (flags & ISLASTCN) && error == ENOENT)
336 #ifndef AFS_DARWIN80_ENV
337 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
338 cnp->cn_flags |= SAVENAME;
344 #ifdef AFS_DARWIN80_ENV
345 if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
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;
354 if (UBCINFOMISSING(vp) ||
355 UBCINFORECLAIMED(vp)) {
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. */
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))) {
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 */
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 */
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;
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;
407 register struct vnode *dvp = ap->a_dvp;
412 /* vnode layer handles excl/nonexcl */
415 afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
419 #ifndef AFS_DARWIN80_ENV
420 VOP_ABORTOP(dvp, cnp);
428 #ifdef AFS_DARWIN80_ENV
429 if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
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;
447 #ifndef AFS_DARWIN80_ENV
448 if ((cnp->cn_flags & SAVESTART) == 0)
449 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
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;
465 #ifndef AFS_DARWIN80_ENV
466 FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
474 struct VOPPROT(open_args) /* {
475 * struct vnode *a_vp;
477 * struct ucred *a_cred;
482 struct vnode *vp = ap->a_vp;
483 struct vcache *vc = VTOAFS(vp);
484 #if defined(AFS_DARWIN14_ENV) && !defined(AFS_DARWIN80_ENV)
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 */
500 error = afs_open(&vc, ap->a_mode, vop_cred);
502 if (AFSTOV(vc) != vp)
503 panic("AFS open changed vnode!");
505 osi_FlushPages(vc, vop_cred);
507 #if defined(AFS_DARWIN14_ENV) && !defined(AFS_DARWIN80_ENV)
508 if (error && didhold)
510 #endif /* AFS_DARWIN14_ENV */
516 struct VOPPROT(close_args) /* {
517 * struct vnode *a_vp;
519 * struct ucred *a_cred;
524 struct vnode *vp = ap->a_vp;
525 struct vcache *avc = VTOAFS(vp);
528 code = afs_close(avc, ap->a_fflag, vop_cred, vop_proc);
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 */
537 #ifdef AFS_DARWIN80_ENV
538 extern int afs_fakestat_enable;
542 struct VOPPROT(access_args) /* {
543 * struct vnode *a_vp;
545 * vfs_context_t a_context;
549 struct vrequest treq;
550 struct afs_fakestat_state fakestate;
551 struct vcache * tvc = VTOAFS(ap->a_vp);
554 afs_InitFakeStat(&fakestate);
555 if ((code = afs_InitReq(&treq, vop_cred)))
558 code = afs_TryEvalFakeStat(&tvc, &fakestate, &treq);
560 code = afs_CheckCode(code, &treq, 55);
564 code = afs_VerifyVCache(tvc, &treq);
566 code = afs_CheckCode(code, &treq, 56);
569 if (afs_fakestat_enable && tvc->mvstat && !(tvc->states & CStatd)) {
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;
591 if (ap->a_action & KAUTH_VNODE_READ_DATA)
593 if (ap->a_action & KAUTH_VNODE_WRITE_DATA)
595 if (ap->a_action & KAUTH_VNODE_EXECUTE)
596 bits |= PRSFS_READ; /* and mode bits.... */
597 if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
599 if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
602 if (ap->a_action & KAUTH_VNODE_WRITE_ATTRIBUTES)
604 #if 0 /* no extended attributes */
605 if (ap->a_action & KAUTH_VNODE_READ_EXTATTRIBUTES)
607 if (ap->a_action & KAUTH_VNODE_WRITE_EXTATTRIBUTES)
610 if (ap->a_action & KAUTH_VNODE_WRITE_SECURITY)
612 /* we can't check for KAUTH_VNODE_TAKE_OWNERSHIP, so we always permit it */
614 code = afs_AccessOK(tvc, bits, &treq, CHECK_MODE_BITS);
616 if (code == 1 && vnode_vtype(ap->a_vp) == VREG &&
617 ap->a_action & KAUTH_VNODE_EXECUTE &&
618 (tvc->m.Mode & 0100) != 0100) {
622 code= 0; /* if access is ok */
624 code = afs_CheckCode(EACCES, &treq, 57); /* failure code */
627 afs_PutFakeStat(&fakestate);
635 struct VOPPROT(access_args) /* {
636 * struct vnode *a_vp;
638 * struct ucred *a_cred;
644 code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, vop_cred);
652 struct VOPPROT(getattr_args) /* {
653 * struct vnode *a_vp;
654 * struct vattr *a_vap;
655 * struct ucred *a_cred;
662 code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
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);
685 struct VOPPROT(setattr_args) /* {
686 * struct vnode *a_vp;
687 * struct vattr *a_vap;
688 * struct ucred *a_cred;
694 code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
701 struct VOPPROT(read_args) /* {
702 * struct vnode *a_vp;
705 * struct ucred *a_cred;
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);
714 if (UBCINFOEXISTS(ap->a_vp)) {
715 ubc_clean(ap->a_vp, 0);
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);
727 struct VOPPROT(pagein_args) /* {
728 * struct vnode *a_vp;
730 * vm_offset_t a_pl_offset;
733 * struct ucred *a_cred;
737 register struct vnode *vp = ap->a_vp;
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;
745 #ifdef AFS_DARWIN80_ENV
750 struct uio *uio = &auio;
752 int nocommit = flags & UPL_NOCOMMIT;
755 struct vcache *tvc = VTOAFS(vp);
756 #ifndef AFS_DARWIN80_ENV
757 if (UBCINVALID(vp)) {
759 panic("afs_vop_pagein: invalid vp");
760 #endif /* DIAGNOSTIC */
764 UBCINFOCHECK("afs_vop_pagein", vp);
766 if (pl == (upl_t) NULL) {
767 panic("afs_vop_pagein: no upl");
770 cred = ubc_getcred(vp);
776 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
777 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
782 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
783 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
786 if (f_offset & PAGE_MASK)
787 panic("afs_vop_pagein: offset not page aligned");
789 OSI_UPL_MAP(pl, &ioaddr);
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);
795 auio.uio_iov = &aiov;
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;
805 osi_FlushPages(tvc, vop_cred); /* hold bozon lock, but not basic vnode lock */
806 code = afs_read(tvc, uio, cred, 0, 0, 0);
808 ObtainWriteLock(&tvc->lock, 2);
809 tvc->states |= CMAPPED;
810 ReleaseWriteLock(&tvc->lock);
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,
820 memset(aiov.iov_base, 0, auio.uio_resid);
827 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
828 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
830 OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
831 UPL_COMMIT_CLEAR_DIRTY |
832 UPL_COMMIT_FREE_ON_EMPTY);
834 #ifdef AFS_DARWIN80_ENV
842 struct VOPPROT(write_args) /* {
843 * struct vnode *a_vp;
846 * struct ucred *a_cred;
850 struct vcache *avc = VTOAFS(ap->a_vp);
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);
855 if (UBCINFOEXISTS(ap->a_vp)) {
856 ubc_clean(ap->a_vp, 1);
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));
863 osi_FlushPages(avc, vop_cred); /* hold bozon lock, but not basic vnode lock */
865 afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, vop_cred, 0);
872 struct VOPPROT(pageout_args) /* {
873 * struct vnode *a_vp;
875 * vm_offset_t a_pl_offset,
878 * struct ucred *a_cred,
882 register struct vnode *vp = ap->a_vp;
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;
890 #ifdef AFS_DARWIN80_ENV
895 struct uio *uio = &auio;
897 int nocommit = flags & UPL_NOCOMMIT;
901 struct vcache *tvc = VTOAFS(vp);
902 #ifndef AFS_DARWIN80_ENV
903 if (UBCINVALID(vp)) {
905 panic("afs_vop_pageout: invalid vp");
906 #endif /* DIAGNOSTIC */
910 UBCINFOCHECK("afs_vop_pageout", vp);
912 if (pl == (upl_t) NULL) {
913 panic("afs_vop_pageout: no upl");
915 #if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
917 layer doesn't have them anymore? In any case,
918 we can't just copy code from nfs... */
922 int biosize = DEV_BSIZE;
924 lbn = f_offset / DEV_BSIZE;
926 for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
929 if (bp = incore(vp, lbn)) {
930 if (ISSET(bp->b_flags, B_BUSY))
931 panic("nfs_pageout: found BUSY buffer incore\n");
934 SET(bp->b_flags, (B_BUSY | B_INVAL));
941 cred = ubc_getcred(vp);
947 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
948 UPL_ABORT_FREE_ON_EMPTY);
951 if (flags & (IO_APPEND | IO_SYNC))
952 panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
955 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
956 UPL_ABORT_FREE_ON_EMPTY);
959 if (f_offset >= tvc->m.Length) {
961 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
962 UPL_ABORT_FREE_ON_EMPTY);
966 if (f_offset & PAGE_MASK)
967 panic("afs_vop_pageout: offset not page aligned");
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;
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,
980 UPL_ABORT_FREE_ON_EMPTY);
982 OSI_UPL_MAP(pl, &ioaddr);
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);
988 auio.uio_iov = &aiov;
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;
1000 * check for partial page and clear the
1001 * contents past end of the file before
1002 * releasing it in the VM page cache
1004 if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
1005 size_t io = tvc->m.Length - f_offset;
1007 memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
1013 osi_FlushPages(tvc, vop_cred); /* hold bozon lock, but not basic vnode lock */
1014 ObtainWriteLock(&tvc->lock, 1);
1016 ReleaseWriteLock(&tvc->lock);
1018 code = afs_write(tvc, uio, flags, cred, 0);
1020 ObtainWriteLock(&tvc->lock, 1);
1021 afs_FakeClose(tvc, cred);
1022 ReleaseWriteLock(&tvc->lock);
1027 OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
1028 UPL_ABORT_FREE_ON_EMPTY);
1030 OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
1031 UPL_COMMIT_CLEAR_DIRTY |
1032 UPL_COMMIT_FREE_ON_EMPTY);
1035 #ifdef AFS_DARWIN80_ENV
1043 struct VOPPROT(ioctl_args) /* {
1044 * struct vnode *a_vp;
1048 * struct ucred *a_cred;
1052 struct vcache *tvc = VTOAFS(ap->a_vp);
1053 struct afs_ioctl data;
1056 /* in case we ever get in here... */
1058 AFS_STATCNT(afs_ioctl);
1059 if (((ap->a_command >> 8) & 0xff) == 'V') {
1060 /* This is a VICEIOCTL call */
1062 error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
1063 ap->a_command, ap->a_data);
1067 /* No-op call; just return. */
1075 struct VOPPROT(select_args) /* {
1076 * struct vnode *a_vp;
1079 * struct ucred *a_cred;
1084 * We should really check to see if I/O is possible.
1092 * NB Currently unsupported.
1097 struct VOPPROT(mmap_args) /* {
1098 * struct vnode *a_vp;
1100 * struct ucred *a_cred;
1109 struct VOPPROT(fsync_args) /* {
1110 * struct vnode *a_vp;
1111 * struct ucred *a_cred;
1116 int wait = ap->a_waitfor == MNT_WAIT;
1118 register struct vnode *vp = ap->a_vp;
1119 int haveGlock = ISAFS_GLOCK();
1121 /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
1122 if (!haveGlock) AFS_GLOCK();
1124 error = afs_fsync(VTOAFS(vp), vop_cred);
1126 error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
1127 if (!haveGlock) AFS_GUNLOCK();
1131 #ifndef AFS_DARWIN80_ENV
1134 struct VOPPROT(seek_args) /* {
1135 * struct vnode *a_vp;
1138 * struct ucred *a_cred;
1141 if (ap->a_newoff > ULONG_MAX) /* AFS doesn't support 64-bit offsets */
1149 struct VOPPROT(remove_args) /* {
1150 * struct vnode *a_dvp;
1151 * struct vnode *a_vp;
1152 * struct componentname *a_cnp;
1156 register struct vnode *vp = ap->a_vp;
1157 register struct vnode *dvp = ap->a_dvp;
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)) {
1170 error = afs_remove(VTOAFS(dvp), name, vop_cn_cred);
1174 #ifdef AFS_DARWIN80_ENV
1175 ubc_setsize(vp, (off_t)0);
1178 /* necessary so we don't deadlock ourselves in vclean */
1179 VOP_UNLOCK(vp, 0, cnp->cn_proc);
1181 /* If crashes continue in ubc_hold, comment this out */
1182 (void)ubc_uncache(vp);
1186 #ifndef AFS_DARWIN80_ENV
1194 #ifndef AFS_DARWIN80_ENV
1195 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1203 struct VOPPROT(link_args) /* {
1204 * struct vnode *a_vp;
1205 * struct vnode *a_tdvp;
1206 * struct componentname *a_cnp;
1210 register struct vnode *dvp = ap->a_tdvp;
1211 register struct vnode *vp = ap->a_vp;
1216 if (vnode_isdir(vp)) {
1217 VOP_ABORTOP(vp, cnp);
1221 #ifndef AFS_DARWIN80_ENV
1222 if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
1223 VOP_ABORTOP(dvp, cnp);
1228 error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, vop_cn_cred);
1230 #ifndef AFS_DARWIN80_ENV
1231 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1233 #ifndef AFS_DARWIN80_ENV
1235 VOP_UNLOCK(vp, 0, p);
1238 #ifndef AFS_DARWIN80_ENV
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;
1257 struct componentname *fcnp = ap->a_fcnp;
1259 struct componentname *tcnp = ap->a_tcnp;
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;
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
1274 /* Check for cross-device rename.
1275 * For AFS, this means anything not in AFS-space
1277 if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
1278 (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
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... */
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())
1294 if (vnode_isdir(fvp)) {
1297 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
1304 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
1310 /* Release destination completely. */
1311 VOP_ABORTOP(tdvp, tcnp);
1314 /* Delete source. */
1315 #if defined(AFS_DARWIN80_ENV)
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';
1321 error = afs_remove(VTOAFS(fdvp), fname, vop_cn_cred);
1323 FREE(fname, M_TEMP);
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;
1335 error=relookup(fdvp, &fvp, fcnp);
1341 error=VOP_REMOVE(fdvp, fvp, fcnp);
1352 #if !defined(AFS_DARWIN80_ENV)
1353 if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
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';
1366 /* XXX use "from" or "to" creds? NFS uses "to" creds */
1368 afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, cn_cred(tcnp));
1371 #if !defined(AFS_DARWIN80_ENV)
1372 VOP_UNLOCK(fvp, 0, p);
1374 FREE(fname, M_TEMP);
1375 FREE(tname, M_TEMP);
1376 #ifdef AFS_DARWIN80_ENV
1387 cache_enter(tdvp, fvp, tcnp);
1390 goto abortit; /* XXX */
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;
1412 register struct vnode *dvp = ap->a_dvp;
1413 register struct vattr *vap = ap->a_vap;
1420 #if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
1421 if ((cnp->cn_flags & HASBUF) == 0)
1422 panic("afs_vop_mkdir: no name");
1425 error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, vop_cn_cred);
1428 VOP_ABORTOP(dvp, cnp);
1434 #ifdef AFS_DARWIN80_ENV
1435 afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0);
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);
1445 #ifndef AFS_DARWIN80_ENV
1446 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1454 struct VOPPROT(rmdir_args) /* {
1455 * struct vnode *a_dvp;
1456 * struct vnode *a_vp;
1457 * struct componentname *a_cnp;
1461 register struct vnode *vp = ap->a_vp;
1462 register struct vnode *dvp = ap->a_dvp;
1466 #ifndef AFS_DARWIN80_ENV
1469 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1476 error = afs_rmdir(VTOAFS(dvp), name, vop_cn_cred);
1481 #ifndef AFS_DARWIN80_ENV
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;
1498 register struct vnode *dvp = ap->a_dvp;
1500 /* NFS ignores a_vpp; so do we. */
1505 afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
1508 #ifndef AFS_DARWIN80_ENV
1509 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1517 struct VOPPROT(readdir_args) /* {
1518 * struct vnode *a_vp;
1519 * struct uio *a_uio;
1520 * struct ucred *a_cred;
1522 * u_long *a_cookies;
1528 /* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
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))
1536 off = AFS_UIO_OFFSET(ap->a_uio);
1539 afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, vop_cred, ap->a_eofflag);
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;
1546 u_long *cookies, *cookiep;
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));
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))
1558 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
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;
1565 *ap->a_cookies = cookies;
1566 *ap->a_ncookies = ncookies;
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;
1582 /* printf("readlink %x\n", ap->a_vp);*/
1584 error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, vop_cred);
1589 extern int prtactive;
1592 afs_vop_inactive(ap)
1593 struct VOPPROT(inactive_args) /* {
1594 * struct vnode *a_vp;
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);
1606 afs_InactiveVCache(tvc, 0); /* decrs ref counts */
1609 #ifndef AFS_DARWIN80_ENV
1610 VOP_UNLOCK(vp, 0, ap->a_p);
1617 struct VOPPROT(reclaim_args) /* {
1618 * struct vnode *a_vp;
1623 register struct vnode *vp = ap->a_vp;
1624 struct vcache *tvc = VTOAFS(vp);
1626 osi_Assert(!ISAFS_GLOCK());
1627 cache_purge(vp); /* just in case... */
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
1637 tvc->states &= ~(CVInit
1638 #ifdef AFS_DARWIN80_ENV
1642 afs_osi_Wakeup(&tvc->states);
1644 ReleaseWriteLock(&afs_xvcache);
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");
1655 * Return POSIX pathconf information applicable to ufs filesystems.
1657 afs_vop_pathconf(ap)
1658 struct VOPPROT(pathconf_args) /* {
1659 * struct vnode *a_vp;
1664 AFS_STATCNT(afs_cntl);
1665 switch (ap->a_name) {
1667 *ap->a_retval = LINK_MAX;
1670 *ap->a_retval = NAME_MAX;
1673 *ap->a_retval = PATH_MAX;
1675 case _PC_CHOWN_RESTRICTED:
1684 #if defined(AFS_DARWIN70_ENV)
1685 case _PC_NAME_CHARS_MAX:
1686 *ap->a_retval = NAME_MAX;
1688 case _PC_CASE_SENSITIVE:
1691 case _PC_CASE_PRESERVING:
1694 #endif /* defined(AFS_DARWIN70_ENV) */
1702 * Advisory record locking support (fcntl() POSIX style)
1706 struct VOPPROT(advlock_args) /* {
1707 * struct vnode *a_vp;
1710 * struct flock *a_fl;
1716 #ifdef AFS_DARWIN80_ENV
1719 struct proc *p = current_proc();
1722 cr = *p->p_cred->pc_ucred;
1728 afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, tcr, (int)ap->a_id);
1734 afs_vop_blktooff(ap)
1735 struct VOPPROT(blktooff_args) /* {
1736 * struct vnode *a_vp;
1741 *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1746 afs_vop_offtoblk(ap)
1747 struct VOPPROT(offtoblk_args) /* {
1748 * struct vnode *a_vp;
1750 * daddr_t *a_lblkno;
1753 *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1758 #ifndef AFS_DARWIN80_ENV
1761 struct VOPPROT(lock_args) /* {
1762 * struct vnode *a_vp;
1765 register struct vnode *vp = ap->a_vp;
1766 register struct vcache *avc = VTOAFS(vp);
1768 if (vp->v_tag == VT_NON)
1771 return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1776 struct VOPPROT(unlock_args) /* {
1777 * struct vnode *a_vp;
1780 struct vnode *vp = ap->a_vp;
1781 struct vcache *avc = VTOAFS(vp);
1784 (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1790 afs_vop_truncate(ap)
1791 struct VOPPROT(truncate_args) /* {
1792 * struct vnode *a_vp;
1795 * struct ucred *a_cred;
1799 printf("stray afs_vop_truncate\n");
1805 struct VOPPROT(update_args) /* {
1806 * struct vnode *a_vp;
1807 * struct timeval *a_access;
1808 * struct timeval *a_modify;
1812 printf("stray afs_vop_update\n");
1818 struct VOPPROT(bmap_args) /* {
1819 * struct vnode *a_vp;
1821 * struct vnode **a_vpp;
1829 *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1832 *ap->a_vpp = ap->a_vp;
1834 if (ap->a_runp != NULL)
1837 if (ap->a_runb != NULL)
1845 afs_vop_strategy(ap)
1846 struct VOPPROT(strategy_args) /* {
1852 error = afs_ustrategy(ap->a_bp);
1859 struct VOPPROT(print_args) /* {
1860 * struct vnode *a_vp;
1863 register struct vnode *vp = ap->a_vp;
1864 register struct vcache *vc = VTOAFS(ap->a_vp);
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)) {
1875 if (UBCINFOEXISTS(vp)) {
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" : "");
1882 printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1885 printf("does not exist");
1892 afs_vop_islocked(ap)
1893 struct VOPPROT(islocked_args) /* {
1894 * struct vnode *a_vp;
1897 struct vcache *vc = VTOAFS(ap->a_vp);
1898 return lockstatus(&vc->rwlock);
1903 struct VOPPROT(cmap_args) /* {
1904 * struct vnode *a_vp;
1912 *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1913 *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1919 afs_darwin_getnewvnode(struct vcache *avc)
1921 #ifdef AFS_DARWIN80_ENV
1924 struct vnode_fsparam par;
1926 memset(&par, 0, sizeof(struct vnode_fsparam));
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;
1935 par.vnfs_flags = VNFS_NOCACHE;
1938 par.vnfs_vtype = VNON;
1939 par.vnfs_vops = afs_dead_vnodeop_p;
1940 par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
1943 ReleaseWriteLock(&avc->lock);
1945 par.vnfs_dvp = ac->dvp;
1946 par.vnfs_cnp = ac->cnp;
1947 par.vnfs_markroot = ac->markroot;
1949 par.vnfs_vtype = VNON;
1950 par.vnfs_vops = afs_dead_vnodeop_p;
1951 par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
1953 par.vnfs_mp = afs_globalVFS;
1954 par.vnfs_fsnode = avc;
1956 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &vp);
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
1972 vnode_recycle(vp); /* terminate as soon as iocount drops */
1973 avc->states |= CDeadVnode;
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");
1982 avc->v->v_data = (void *)avc;
1986 #ifdef AFS_DARWIN80_ENV
1987 /* if this fails, then tvc has been unrefed and may have been freed.
1990 afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct componentname *cnp, int isroot) {
1991 vnode_t ovp = AFSTOV(avc);
1994 struct vnode_fsparam par;
1996 ObtainWriteLock(&avc->lock,325);
1997 if (!(avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
1998 ReleaseWriteLock(&avc->lock);
2000 #if 0 /* unsupported */
2002 vnode_update_identity(ovp, dvp, cnp->cn_nameptr, cnp->cn_namelen,
2004 VNODE_UPDATE_PARENT|VNODE_UPDATE_NAME);
2009 if ((avc->states & CDeadVnode) && vnode_vtype(ovp) != VNON)
2010 panic("vcache %p should not be CDeadVnode", avc);
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;
2021 par.vnfs_markroot = 1;
2022 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &nvp);
2024 vnode_addfsref(nvp);
2026 avc->states &=~ CDeadVnode;
2027 vnode_clearfsnode(ovp);
2028 vnode_removefsref(ovp);
2031 ReleaseWriteLock(&avc->lock);
2033 afs_osi_Wakeup(&avc->states);