2 * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
8 #include <afs/sysincludes.h> /* Standard vendor system headers */
9 #include <afsincludes.h> /* Afs-based standard headers */
10 #include <afs/afs_stats.h> /* statistics */
11 #include <sys/malloc.h>
12 #include <sys/namei.h>
14 #include <vfs/vfs_support.h>
15 #ifdef AFS_DARWIN80_ENV
16 #include <sys/vnode_if.h>
17 #include <sys/kauth.h>
20 #ifdef AFS_DARWIN80_ENV
21 #define VOPPREF(x) &vnop_ ## x
22 #define VOPPROT(x) vnop_ ## x
23 #define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
24 ubc_upl_abort_range((pl), (offset), (size), (flags))
25 #define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
26 ubc_upl_commit_range((pl), (offset), (size), (flags))
27 #define OSI_UPL_MAP(upl, offset) ubc_upl_map((upl), (offset))
28 #define OSI_UPL_UNMAP(upl) ubc_upl_unmap((upl))
29 #define VOP_ABORTOP(x, y)
31 #define VOPPREF(x) &vop_ ## x
32 #define VOPPROT(x) vop_ ## x
33 #define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
34 kernel_upl_abort_range((pl), (offset), (size), (flags))
35 #define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
36 kernel_upl_commit_range((pl), (offset), (size), (flags), \
37 UPL_GET_INTERNAL_PAGE_LIST((pl)),\
39 #define OSI_UPL_MAP(upl, offset) kernel_upl_map(kernel_map, (upl), (offset))
40 #define OSI_UPL_UNMAP(upl) kernel_upl_unmap(kernel_map, (upl))
43 extern char afs_zeros
[AFS_ZEROS
];
45 int afs_vop_lookup(struct VOPPROT(lookup_args
) *);
46 int afs_vop_create(struct VOPPROT(create_args
) *);
47 int afs_vop_mknod(struct VOPPROT(mknod_args
) *);
48 int afs_vop_open(struct VOPPROT(open_args
) *);
49 int afs_vop_close(struct VOPPROT(close_args
) *);
50 int afs_vop_access(struct VOPPROT(access_args
) *);
51 int afs_vop_getattr(struct VOPPROT(getattr_args
) *);
52 int afs_vop_setattr(struct VOPPROT(setattr_args
) *);
53 int afs_vop_read(struct VOPPROT(read_args
) *);
54 int afs_vop_write(struct VOPPROT(write_args
) *);
55 int afs_vop_pagein(struct VOPPROT(pagein_args
) *);
56 int afs_vop_pageout(struct VOPPROT(pageout_args
) *);
57 int afs_vop_ioctl(struct VOPPROT(ioctl_args
) *);
58 int afs_vop_select(struct VOPPROT(select_args
) *);
59 int afs_vop_mmap(struct VOPPROT(mmap_args
) *);
60 int afs_vop_fsync(struct VOPPROT(fsync_args
) *);
61 int afs_vop_remove(struct VOPPROT(remove_args
) *);
62 int afs_vop_link(struct VOPPROT(link_args
) *);
63 int afs_vop_rename(struct VOPPROT(rename_args
) *);
64 int afs_vop_mkdir(struct VOPPROT(mkdir_args
) *);
65 int afs_vop_rmdir(struct VOPPROT(rmdir_args
) *);
66 int afs_vop_symlink(struct VOPPROT(symlink_args
) *);
67 int afs_vop_readdir(struct VOPPROT(readdir_args
) *);
68 int afs_vop_readlink(struct VOPPROT(readlink_args
) *);
69 int afs_vop_inactive(struct VOPPROT(inactive_args
) *);
70 int afs_vop_reclaim(struct VOPPROT(reclaim_args
) *);
71 int afs_vop_strategy(struct VOPPROT(strategy_args
) *);
72 int afs_vop_pathconf(struct VOPPROT(pathconf_args
) *);
73 int afs_vop_advlock(struct VOPPROT(advlock_args
) *);
74 int afs_vop_blktooff
__P((struct VOPPROT(blktooff_args
) *));
75 int afs_vop_offtoblk
__P((struct VOPPROT(offtoblk_args
) *));
76 #ifndef AFS_DARWIN80_ENV
77 int afs_vop_truncate(struct VOPPROT(truncate_args
) *);
78 int afs_vop_update(struct VOPPROT(update_args
) *);
79 int afs_vop_lock(struct VOPPROT(lock_args
) *);
80 int afs_vop_unlock(struct VOPPROT(unlock_args
) *);
81 int afs_vop_bmap(struct VOPPROT(bmap_args
) *);
82 int afs_vop_seek(struct VOPPROT(seek_args
) *);
83 int afs_vop_cmap
__P((struct VOPPROT(cmap_args
) *));
84 int afs_vop_print(struct VOPPROT(print_args
) *);
85 int afs_vop_islocked(struct VOPPROT(islocked_args
) *);
88 #define afs_vop_opnotsupp \
89 ((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
90 #define afs_vop_valloc afs_vop_opnotsupp
91 #define afs_vop_vfree afs_vop_opnotsupp
92 #define afs_vop_blkatoff afs_vop_opnotsupp
93 #define afs_vop_reallocblks afs_vop_opnotsupp
95 /* Global vfs data structures for AFS. */
96 int (**afs_vnodeop_p
) ();
98 #define VOPFUNC int (*)(void *)
100 struct vnodeopv_entry_desc afs_vnodeop_entries
[] = {
101 {VOPPREF(default_desc
), (VOPFUNC
)vn_default_error
},
102 {VOPPREF(lookup_desc
), (VOPFUNC
)afs_vop_lookup
}, /* lookup */
103 {VOPPREF(create_desc
), (VOPFUNC
)afs_vop_create
}, /* create */
104 {VOPPREF(mknod_desc
), (VOPFUNC
)afs_vop_mknod
}, /* mknod */
105 {VOPPREF(open_desc
), (VOPFUNC
)afs_vop_open
}, /* open */
106 {VOPPREF(close_desc
), (VOPFUNC
)afs_vop_close
}, /* close */
107 {VOPPREF(access_desc
), (VOPFUNC
)afs_vop_access
}, /* access */
108 {VOPPREF(getattr_desc
), (VOPFUNC
)afs_vop_getattr
}, /* getattr */
109 {VOPPREF(setattr_desc
), (VOPFUNC
)afs_vop_setattr
}, /* setattr */
110 {VOPPREF(read_desc
), (VOPFUNC
)afs_vop_read
}, /* read */
111 {VOPPREF(write_desc
), (VOPFUNC
)afs_vop_write
}, /* write */
112 {VOPPREF(pagein_desc
), (VOPFUNC
)afs_vop_pagein
}, /* read */
113 {VOPPREF(pageout_desc
), (VOPFUNC
)afs_vop_pageout
}, /* write */
114 {VOPPREF(ioctl_desc
), (VOPFUNC
)afs_vop_ioctl
}, /* XXX ioctl */
115 {VOPPREF(select_desc
), (VOPFUNC
)afs_vop_select
}, /* select */
116 {VOPPREF(mmap_desc
), (VOPFUNC
)afs_vop_mmap
}, /* mmap */
117 {VOPPREF(fsync_desc
), (VOPFUNC
)afs_vop_fsync
}, /* fsync */
118 #ifndef AFS_DARWIN80_ENV
119 {VOPPREF(seek_desc
), (VOPFUNC
)afs_vop_seek
}, /* seek */
121 {VOPPREF(remove_desc
), (VOPFUNC
)afs_vop_remove
}, /* remove */
122 {VOPPREF(link_desc
), (VOPFUNC
)afs_vop_link
}, /* link */
123 {VOPPREF(rename_desc
), (VOPFUNC
)afs_vop_rename
}, /* rename */
124 {VOPPREF(mkdir_desc
), (VOPFUNC
)afs_vop_mkdir
}, /* mkdir */
125 {VOPPREF(rmdir_desc
), (VOPFUNC
)afs_vop_rmdir
}, /* rmdir */
126 {VOPPREF(symlink_desc
), (VOPFUNC
)afs_vop_symlink
}, /* symlink */
127 {VOPPREF(readdir_desc
), (VOPFUNC
)afs_vop_readdir
}, /* readdir */
128 {VOPPREF(readlink_desc
), (VOPFUNC
)afs_vop_readlink
}, /* readlink */
129 #ifndef AFS_DARWIN80_ENV
130 {VOPPREF(abortop_desc
), (VOPFUNC
)nop_abortop
}, /* abortop */
132 {VOPPREF(inactive_desc
), (VOPFUNC
)afs_vop_inactive
}, /* inactive */
133 {VOPPREF(reclaim_desc
), (VOPFUNC
)afs_vop_reclaim
}, /* reclaim */
134 #ifndef AFS_DARWIN80_ENV
135 {VOPPREF(lock_desc
), (VOPFUNC
)afs_vop_lock
}, /* lock */
136 {VOPPREF(unlock_desc
), (VOPFUNC
)afs_vop_unlock
}, /* unlock */
137 {VOPPREF(bmap_desc
), (VOPFUNC
)afs_vop_bmap
}, /* bmap */
139 #ifdef AFS_DARWIN80_ENV
140 {VOPPREF(strategy_desc
), (VOPFUNC
)err_strategy
}, /* strategy */
142 {VOPPREF(strategy_desc
), (VOPFUNC
)afs_vop_strategy
}, /* strategy */
144 #ifndef AFS_DARWIN80_ENV
145 {VOPPREF(print_desc
), (VOPFUNC
)afs_vop_print
}, /* print */
146 {VOPPREF(islocked_desc
), (VOPFUNC
)afs_vop_islocked
}, /* islocked */
148 {VOPPREF(pathconf_desc
), (VOPFUNC
)afs_vop_pathconf
}, /* pathconf */
149 {VOPPREF(advlock_desc
), (VOPFUNC
)afs_vop_advlock
}, /* advlock */
150 #ifndef AFS_DARWIN80_ENV
151 {VOPPREF(blkatoff_desc
), (VOPFUNC
)afs_vop_blkatoff
}, /* blkatoff */
152 {VOPPREF(valloc_desc
), (VOPFUNC
)afs_vop_valloc
}, /* valloc */
153 {VOPPREF(reallocblks_desc
), (VOPFUNC
)afs_vop_reallocblks
}, /* reallocblks */
154 {VOPPREF(vfree_desc
), (VOPFUNC
)afs_vop_vfree
}, /* vfree */
155 {VOPPREF(update_desc
), (VOPFUNC
)afs_vop_update
}, /* update */
156 {VOPPREF(cmap_desc
), (VOPFUNC
)afs_vop_cmap
}, /* cmap */
157 {VOPPREF(truncate_desc
), (VOPFUNC
)afs_vop_truncate
}, /* truncate */
159 {VOPPREF(blktooff_desc
), (VOPFUNC
)afs_vop_blktooff
}, /* blktooff */
160 {VOPPREF(offtoblk_desc
), (VOPFUNC
)afs_vop_offtoblk
}, /* offtoblk */
161 {VOPPREF(bwrite_desc
), (VOPFUNC
)vn_bwrite
},
162 {NULL
, (void (*)())NULL
}
164 struct vnodeopv_desc afs_vnodeop_opv_desc
=
165 { &afs_vnodeop_p
, afs_vnodeop_entries
};
167 #ifdef AFS_DARWIN80_ENV
168 /* vfs structures for incompletely initialized vnodes */
169 int (**afs_dead_vnodeop_p
) ();
171 struct vnodeopv_entry_desc afs_dead_vnodeop_entries
[] = {
172 {VOPPREF(default_desc
), (VOPFUNC
)vn_default_error
},
173 {VOPPREF(lookup_desc
), (VOPFUNC
)vn_default_error
}, /* lookup */
174 {VOPPREF(create_desc
), (VOPFUNC
)err_create
}, /* create */
175 {VOPPREF(mknod_desc
), (VOPFUNC
)err_mknod
}, /* mknod */
176 {VOPPREF(open_desc
), (VOPFUNC
)err_open
}, /* open */
177 {VOPPREF(close_desc
), (VOPFUNC
)err_close
}, /* close */
178 {VOPPREF(access_desc
), (VOPFUNC
)err_access
}, /* access */
179 {VOPPREF(getattr_desc
), (VOPFUNC
)err_getattr
}, /* getattr */
180 {VOPPREF(setattr_desc
), (VOPFUNC
)err_setattr
}, /* setattr */
181 {VOPPREF(read_desc
), (VOPFUNC
)err_read
}, /* read */
182 {VOPPREF(write_desc
), (VOPFUNC
)err_write
}, /* write */
183 {VOPPREF(pagein_desc
), (VOPFUNC
)err_pagein
}, /* read */
184 {VOPPREF(pageout_desc
), (VOPFUNC
)err_pageout
}, /* write */
185 {VOPPREF(ioctl_desc
), (VOPFUNC
)err_ioctl
}, /* XXX ioctl */
186 {VOPPREF(select_desc
), (VOPFUNC
)nop_select
}, /* select */
187 {VOPPREF(mmap_desc
), (VOPFUNC
)err_mmap
}, /* mmap */
188 {VOPPREF(fsync_desc
), (VOPFUNC
)err_fsync
}, /* fsync */
189 {VOPPREF(remove_desc
), (VOPFUNC
)err_remove
}, /* remove */
190 {VOPPREF(link_desc
), (VOPFUNC
)err_link
}, /* link */
191 {VOPPREF(rename_desc
), (VOPFUNC
)err_rename
}, /* rename */
192 {VOPPREF(mkdir_desc
), (VOPFUNC
)err_mkdir
}, /* mkdir */
193 {VOPPREF(rmdir_desc
), (VOPFUNC
)err_rmdir
}, /* rmdir */
194 {VOPPREF(symlink_desc
), (VOPFUNC
)err_symlink
}, /* symlink */
195 {VOPPREF(readdir_desc
), (VOPFUNC
)err_readdir
}, /* readdir */
196 {VOPPREF(readlink_desc
), (VOPFUNC
)err_readlink
}, /* readlink */
197 {VOPPREF(inactive_desc
), (VOPFUNC
)afs_vop_inactive
}, /* inactive */
198 {VOPPREF(reclaim_desc
), (VOPFUNC
)afs_vop_reclaim
}, /* reclaim */
199 {VOPPREF(strategy_desc
), (VOPFUNC
)err_strategy
}, /* strategy */
200 {VOPPREF(pathconf_desc
), (VOPFUNC
)err_pathconf
}, /* pathconf */
201 {VOPPREF(advlock_desc
), (VOPFUNC
)err_advlock
}, /* advlock */
202 {VOPPREF(blktooff_desc
), (VOPFUNC
)err_blktooff
}, /* blktooff */
203 {VOPPREF(offtoblk_desc
), (VOPFUNC
)err_offtoblk
}, /* offtoblk */
204 {VOPPREF(bwrite_desc
), (VOPFUNC
)err_bwrite
},
205 {NULL
, (void (*)())NULL
}
207 struct vnodeopv_desc afs_dead_vnodeop_opv_desc
=
208 { &afs_dead_vnodeop_p
, afs_dead_vnodeop_entries
};
212 struct componentname *cnp = ap->a_cnp; \
214 MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
215 memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
216 name[cnp->cn_namelen] = '\0'
218 #define DROPNAME() FREE(name, M_TEMP)
221 darwin_vn_hold(struct vnode
*vp
)
223 int haveGlock
=ISAFS_GLOCK();
224 struct vcache
*tvc
= VTOAFS(vp
);
226 #ifndef AFS_DARWIN80_ENV
227 tvc
->f
.states
|= CUBCinit
;
229 #ifdef AFS_DARWIN80_ENV
230 osi_Assert((tvc
->f
.states
& CVInit
) == 0);
231 if (tvc
->f
.states
& CDeadVnode
)
232 osi_Assert(!vnode_isinuse(vp
, 1));
234 if (haveGlock
) AFS_GUNLOCK();
236 #ifdef AFS_DARWIN80_ENV
238 /* being terminated. kernel won't give us a ref. Now what? our
239 callers don't expect us to fail */
240 if (haveGlock
) AFS_GLOCK();
245 if (haveGlock
) AFS_GLOCK();
250 /* vget needed for 0 ref'd vnode in GetVCache to not panic in vref.
251 vref needed for multiref'd vnode in vnop_remove not to deadlock
252 ourselves during vop_inactive, except we also need to not reinst
253 the ubc... so we just call VREF there now anyway. */
255 if (VREFCOUNT_GT(tvc
, 0))
256 VREF(((struct vnode
*)(vp
)));
258 afs_vget(afs_globalVFS
, 0, (vp
));
261 #ifndef AFS_DARWIN80_ENV
262 if (UBCINFOMISSING(vp
) || UBCINFORECLAIMED(vp
)) {
267 if (haveGlock
) AFS_GLOCK();
268 #ifndef AFS_DARWIN80_ENV
269 tvc
->f
.states
&= ~CUBCinit
;
274 struct VOPPROT(lookup_args
)/* {
275 * struct vnodeop_desc * a_desc;
276 * struct vnode *a_dvp;
277 * struct vnode **a_vpp;
278 * struct componentname *a_cnp;
283 struct vnode
*vp
, *dvp
;
284 int flags
= ap
->a_cnp
->cn_flags
;
285 int lockparent
; /* 1 => lockparent flag is set */
286 int wantparent
; /* 1 => wantparent or lockparent flag */
288 #ifdef AFS_DARWIN80_ENV
289 vcp
= VTOAFS(ap
->a_dvp
);
291 * ._ file attribute mirroring touches this.
292 * we can't flag the vcache as there is none, so fail here.
293 * needed for fsevents support.
295 if (ap
->a_context
== afs_osi_ctxtp
)
297 if (vcp
->mvstat
!= AFS_MVSTAT_MTPT
) {
298 error
= cache_lookup(ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
);
309 lockparent
= flags
& LOCKPARENT
;
310 wantparent
= flags
& (LOCKPARENT
| WANTPARENT
);
312 if (!vnode_isdir(ap
->a_dvp
)) {
318 #ifndef AFS_DARWIN80_ENV
319 if (flags
& ISDOTDOT
)
320 VOP_UNLOCK(dvp
, 0, p
);
323 error
= afs_lookup(VTOAFS(dvp
), name
, &vcp
, vop_cn_cred
);
326 #ifndef AFS_DARWIN80_ENV
327 if (flags
& ISDOTDOT
)
328 VOP_LOCK(dvp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
330 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
)
331 && (flags
& ISLASTCN
) && error
== ENOENT
)
333 #ifndef AFS_DARWIN80_ENV
334 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
335 cnp
->cn_flags
|= SAVENAME
;
341 #ifdef AFS_DARWIN80_ENV
342 if ((error
=afs_darwin_finalizevnode(vcp
, ap
->a_dvp
, ap
->a_cnp
, 0, 0))) {
348 vp
= AFSTOV(vcp
); /* always get a node if no error */
349 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
350 vp
->v_vfsp
= dvp
->v_vfsp
;
352 if (UBCINFOMISSING(vp
) ||
353 UBCINFORECLAIMED(vp
)) {
358 #ifndef AFS_DARWIN80_ENV
359 /* The parent directory comes in locked. We unlock it on return
360 * unless the caller wants it left locked.
361 * we also always return the vnode locked. */
363 if (flags
& ISDOTDOT
) {
364 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
365 /* always return the child locked */
366 if (lockparent
&& (flags
& ISLASTCN
)
367 && (error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
))) {
372 } else if (vp
== dvp
) {
373 /* they're the same; afs_lookup() already ref'ed the leaf.
374 * It came in locked, so we don't need to ref OR lock it */
376 if (!lockparent
|| !(flags
& ISLASTCN
))
377 VOP_UNLOCK(dvp
, 0, p
); /* done with parent. */
378 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
379 /* always return the child locked */
384 #ifndef AFS_DARWIN80_ENV
385 if ((cnp
->cn_nameiop
== RENAME
&& wantparent
&& (flags
& ISLASTCN
)
386 || (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))))
387 cnp
->cn_flags
|= SAVENAME
;
396 struct VOPPROT(create_args
) /* {
397 * struct vnode *a_dvp;
398 * struct vnode **a_vpp;
399 * struct componentname *a_cnp;
400 * struct vattr *a_vap;
405 struct vnode
*dvp
= ap
->a_dvp
;
410 /* vnode layer handles excl/nonexcl */
413 afs_create(VTOAFS(dvp
), name
, ap
->a_vap
, NONEXCL
, ap
->a_vap
->va_mode
,
417 #ifndef AFS_DARWIN80_ENV
418 VOP_ABORTOP(dvp
, cnp
);
426 #ifdef AFS_DARWIN80_ENV
427 if ((error
=afs_darwin_finalizevnode(vcp
, ap
->a_dvp
, ap
->a_cnp
, 0, 0))) {
433 *ap
->a_vpp
= AFSTOV(vcp
);
434 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
435 (*ap
->a_vpp
)->v_vfsp
= dvp
->v_vfsp
;
436 vn_lock(*ap
->a_vpp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
437 if (UBCINFOMISSING(*ap
->a_vpp
) || UBCINFORECLAIMED(*ap
->a_vpp
)) {
438 vcp
->f
.states
|= CUBCinit
;
439 ubc_info_init(*ap
->a_vpp
);
440 vcp
->f
.states
&= ~CUBCinit
;
446 #ifndef AFS_DARWIN80_ENV
447 if ((cnp
->cn_flags
& SAVESTART
) == 0)
448 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
457 struct VOPPROT(mknod_args
) /* {
458 * struct vnode *a_dvp;
459 * struct vnode **a_vpp;
460 * struct componentname *a_cnp;
461 * struct vattr *a_vap;
464 #ifndef AFS_DARWIN80_ENV
465 FREE_ZONE(ap
->a_cnp
->cn_pnbuf
, ap
->a_cnp
->cn_pnlen
, M_NAMEI
);
473 struct VOPPROT(open_args
) /* {
474 * struct vnode *a_vp;
476 * struct ucred *a_cred;
481 struct vnode
*vp
= ap
->a_vp
;
482 struct vcache
*vc
= VTOAFS(vp
);
483 #if !defined(AFS_DARWIN80_ENV)
485 /*----------------------------------------------------------------
486 * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
487 * can later be passed to vn_open(), which will skip the call to
488 * ubc_hold(), and when the ubcinfo is later added, the ui_refcount
489 * will be off. So we compensate by calling ubc_hold() ourselves
490 * when ui_refcount is less than 2. If an error occurs in afs_open()
491 * we must call ubc_rele(), which is what vn_open() would do if it
492 * was able to call ubc_hold() in the first place.
493 *----------------------------------------------------------------*/
494 if (vp
->v_type
== VREG
&& !(vp
->v_flag
& VSYSTEM
)
495 && vp
->v_ubcinfo
->ui_refcount
< 2)
496 didhold
= ubc_hold(vp
);
497 #endif /* !AFS_DARWIN80_ENV */
499 error
= afs_open(&vc
, ap
->a_mode
, vop_cred
);
501 if (AFSTOV(vc
) != vp
)
502 panic("AFS open changed vnode!");
504 osi_FlushPages(vc
, vop_cred
);
506 #if !defined(AFS_DARWIN80_ENV)
507 if (error
&& didhold
)
509 #endif /* !AFS_DARWIN80_ENV */
515 struct VOPPROT(close_args
) /* {
516 * struct vnode *a_vp;
518 * struct ucred *a_cred;
523 struct vnode
*vp
= ap
->a_vp
;
524 struct vcache
*avc
= VTOAFS(vp
);
525 /* allows faking FSE_CONTENT_MODIFIED */
526 if (afs_osi_ctxtp
== ap
->a_context
)
530 code
= afs_close(avc
, ap
->a_fflag
, vop_cred
);
532 code
= afs_close(avc
, ap
->a_fflag
, &afs_osi_cred
);
533 osi_FlushPages(avc
, vop_cred
); /* hold GLOCK, but not basic vnode lock */
534 /* This is legit; it just forces the fstrace event to happen */
535 code
= afs_CheckCode(code
, NULL
, 60);
541 #ifdef AFS_DARWIN80_ENV
542 extern int afs_fakestat_enable
;
546 struct VOPPROT(access_args
) /* {
547 * struct vnode *a_vp;
549 * vfs_context_t a_context;
553 struct vrequest treq
;
554 struct afs_fakestat_state fakestate
;
555 struct vcache
* tvc
= VTOAFS(ap
->a_vp
);
557 int cmb
= CHECK_MODE_BITS
;
558 #ifdef AFS_DARWIN80_ENV
560 * needed for fsevents. ._ file attribute mirroring touches this.
561 * we can't flag the vcache, as there is none, so fail here.
563 if (ap
->a_context
== afs_osi_ctxtp
)
567 afs_InitFakeStat(&fakestate
);
568 if ((code
= afs_InitReq(&treq
, vop_cred
)))
571 code
= afs_TryEvalFakeStat(&tvc
, &fakestate
, &treq
);
573 code
= afs_CheckCode(code
, &treq
, 55);
577 code
= afs_VerifyVCache(tvc
, &treq
);
579 code
= afs_CheckCode(code
, &treq
, 56);
582 if (afs_fakestat_enable
&& tvc
->mvstat
!= AFS_MVSTAT_FILE
&& !(tvc
->f
.states
& CStatd
)) {
586 if (vnode_isdir(ap
->a_vp
)) {
587 if (ap
->a_action
& KAUTH_VNODE_LIST_DIRECTORY
)
588 bits
|= PRSFS_LOOKUP
;
589 if (ap
->a_action
& KAUTH_VNODE_ADD_FILE
)
590 bits
|= PRSFS_INSERT
;
591 if (ap
->a_action
& KAUTH_VNODE_SEARCH
)
592 bits
|= PRSFS_LOOKUP
;
593 if (ap
->a_action
& KAUTH_VNODE_DELETE
)
594 bits
|= PRSFS_DELETE
;
595 if (ap
->a_action
& KAUTH_VNODE_ADD_SUBDIRECTORY
)
596 bits
|= PRSFS_INSERT
;
597 if (ap
->a_action
& KAUTH_VNODE_DELETE_CHILD
)
598 bits
|= PRSFS_DELETE
;
599 #if 0 /* I'd argue this should be enforced on the parent. But that's ugly */
600 if (ap
->a_action
& KAUTH_VNODE_READ_ATTRIBUTES
)
601 bits
|= PRSFS_LOOKUP
;
602 if (ap
->a_action
& KAUTH_VNODE_READ_SECURITY
) /* mode bits/gid, not afs acl */
603 bits
|= PRSFS_LOOKUP
;
606 if (ap
->a_action
& KAUTH_VNODE_READ_DATA
)
608 if (ap
->a_action
& KAUTH_VNODE_WRITE_DATA
)
610 if (ap
->a_action
& KAUTH_VNODE_EXECUTE
)
611 bits
|= PRSFS_READ
; /* and mode bits.... */
612 if (ap
->a_action
& KAUTH_VNODE_READ_ATTRIBUTES
)
613 bits
|= PRSFS_LOOKUP
;
614 if (ap
->a_action
& KAUTH_VNODE_READ_SECURITY
) /* mode bits/gid, not afs acl */
615 bits
|= PRSFS_LOOKUP
;
616 if ((ap
->a_action
& ((1 << 25) - 1)) == KAUTH_VNODE_EXECUTE
)
617 /* if only exec, don't check for read mode bit */
618 /* high bits of ap->a_action are not for 'generic rights bits', and
619 so should not be checked (KAUTH_VNODE_ACCESS is often present
620 and needs to be masked off) */
621 cmb
|= CMB_ALLOW_EXEC_AS_READ
;
623 if (ap
->a_action
& KAUTH_VNODE_WRITE_ATTRIBUTES
)
625 #if 0 /* no extended attributes */
626 if (ap
->a_action
& KAUTH_VNODE_READ_EXTATTRIBUTES
)
628 if (ap
->a_action
& KAUTH_VNODE_WRITE_EXTATTRIBUTES
)
631 if (ap
->a_action
& KAUTH_VNODE_WRITE_SECURITY
)
633 /* we can't check for KAUTH_VNODE_TAKE_OWNERSHIP, so we always permit it */
635 code
= afs_AccessOK(tvc
, bits
, &treq
, cmb
);
637 * Special cased dropbox handling:
638 * cp on 10.4 behaves badly, looping on EACCES
639 * Finder may reopen the file. Let it.
641 if (code
== 0 && ((bits
&~(PRSFS_READ
|PRSFS_WRITE
)) == 0))
642 code
= afs_AccessOK(tvc
, PRSFS_ADMINISTER
|PRSFS_INSERT
|bits
, &treq
, cmb
);
643 /* Finder also treats dropboxes as insert+delete. fake it out. */
644 if (code
== 0 && (bits
== (PRSFS_INSERT
|PRSFS_DELETE
)))
645 code
= afs_AccessOK(tvc
, PRSFS_INSERT
, &treq
, cmb
);
647 if (code
== 1 && vnode_vtype(ap
->a_vp
) == VREG
&&
648 ap
->a_action
& KAUTH_VNODE_EXECUTE
&&
649 (tvc
->f
.m
.Mode
& 0100) != 0100) {
653 code
= 0; /* if access is ok */
655 code
= afs_CheckCode(EACCES
, &treq
, 57); /* failure code */
658 afs_PutFakeStat(&fakestate
);
666 struct VOPPROT(access_args
) /* {
667 * struct vnode *a_vp;
669 * struct ucred *a_cred;
675 code
= afs_access(VTOAFS(ap
->a_vp
), ap
->a_mode
, vop_cred
);
683 struct VOPPROT(getattr_args
) /* {
684 * struct vnode *a_vp;
685 * struct vattr *a_vap;
686 * struct ucred *a_cred;
692 #ifdef AFS_DARWIN80_ENV
693 /* CEvent excludes the fsevent. our context excludes the ._ */
694 if ((VTOAFS(ap
->a_vp
)->f
.states
& CEvent
) ||
695 (ap
->a_context
== afs_osi_ctxtp
)){
696 struct vcache
*avc
= VTOAFS(ap
->a_vp
);
697 int isglock
= ISAFS_GLOCK();
699 /* this is needed because of how and when we re-enter */
702 /* do minimal work to return fake result for fsevents */
703 if (afs_fakestat_enable
&& VTOAFS(ap
->a_vp
)->mvstat
== AFS_MVSTAT_MTPT
) {
704 struct afs_fakestat_state fakestat
;
705 struct vrequest treq
;
707 code
= afs_InitReq(&treq
, vop_cred
);
713 afs_InitFakeStat(&fakestat
);
715 code
= afs_TryEvalFakeStat(&avc
, &fakestat
, &treq
);
719 afs_PutFakeStat(&fakestat
);
723 code
= afs_CopyOutAttrs(avc
, ap
->a_vap
);
727 /* tweak things so finder will recheck */
728 (ap
->a_vap
)->va_gid
= ((ap
->a_vap
)->va_gid
== 1) ? 2 : 1;
729 (ap
->a_vap
)->va_mode
&= ~(VSGID
);
735 code
= afs_getattr(VTOAFS(ap
->a_vp
), ap
->a_vap
, vop_cred
);
736 /* This is legit; it just forces the fstrace event to happen */
737 code
= afs_CheckCode(code
, NULL
, 58);
740 #ifdef AFS_DARWIN80_ENV
741 VATTR_SET_SUPPORTED(ap
->a_vap
, va_type
);
742 VATTR_SET_SUPPORTED(ap
->a_vap
, va_mode
);
743 VATTR_SET_SUPPORTED(ap
->a_vap
, va_uid
);
744 VATTR_SET_SUPPORTED(ap
->a_vap
, va_gid
);
745 VATTR_SET_SUPPORTED(ap
->a_vap
, va_fsid
);
746 VATTR_SET_SUPPORTED(ap
->a_vap
, va_fileid
);
747 VATTR_SET_SUPPORTED(ap
->a_vap
, va_nlink
);
748 VATTR_SET_SUPPORTED(ap
->a_vap
, va_data_size
);
749 VATTR_SET_SUPPORTED(ap
->a_vap
, va_access_time
);
750 VATTR_SET_SUPPORTED(ap
->a_vap
, va_modify_time
);
751 VATTR_SET_SUPPORTED(ap
->a_vap
, va_change_time
);
752 VATTR_SET_SUPPORTED(ap
->a_vap
, va_gen
);
753 VATTR_SET_SUPPORTED(ap
->a_vap
, va_flags
);
754 VATTR_SET_SUPPORTED(ap
->a_vap
, va_iosize
);
755 VATTR_SET_SUPPORTED(ap
->a_vap
, va_total_alloc
);
762 struct VOPPROT(setattr_args
) /* {
763 * struct vnode *a_vp;
764 * struct vattr *a_vap;
765 * struct ucred *a_cred;
770 struct vcache
*avc
= VTOAFS(ap
->a_vp
);
771 #ifdef AFS_DARWIN80_ENV
772 /* fsevents tries to set attributes. drop it. */
773 if (ap
->a_context
== afs_osi_ctxtp
)
778 code
= afs_setattr(avc
, ap
->a_vap
, vop_cred
);
779 /* This is legit; it just forces the fstrace event to happen */
780 code
= afs_CheckCode(code
, NULL
, 59);
781 if (!pass
&& code
== EINVAL
&& (VATTR_IS_ACTIVE(ap
->a_vap
, va_mode
) &&
782 (vType(avc
) == VLNK
))) {
783 VATTR_CLEAR_ACTIVE(ap
->a_vap
, va_mode
);
793 struct VOPPROT(read_args
) /* {
794 * struct vnode *a_vp;
797 * struct ucred *a_cred;
801 struct vnode
*vp
= ap
->a_vp
;
802 struct vcache
*avc
= VTOAFS(vp
);
804 if (vnode_isdir(ap
->a_vp
))
806 #ifdef AFS_DARWIN80_ENV
807 ubc_msync_range(ap
->a_vp
, AFS_UIO_OFFSET(ap
->a_uio
), AFS_UIO_OFFSET(ap
->a_uio
) + AFS_UIO_RESID(ap
->a_uio
), UBC_PUSHDIRTY
);
809 if (UBCINFOEXISTS(ap
->a_vp
)) {
810 ubc_clean(ap
->a_vp
, 0);
814 osi_FlushPages(avc
, vop_cred
); /* hold GLOCK, but not basic vnode lock */
815 code
= afs_read(avc
, ap
->a_uio
, vop_cred
, 0);
822 struct VOPPROT(pagein_args
) /* {
823 * struct vnode *a_vp;
825 * vm_offset_t a_pl_offset;
828 * struct ucred *a_cred;
832 struct vnode
*vp
= ap
->a_vp
;
834 size_t size
= ap
->a_size
;
835 off_t f_offset
= ap
->a_f_offset
;
836 vm_offset_t pl_offset
= ap
->a_pl_offset
;
837 int flags
= ap
->a_flags
;
841 struct vcache
*tvc
= VTOAFS(vp
);
842 int nocommit
= flags
& UPL_NOCOMMIT
;
843 #ifdef AFS_DARWIN80_ENV
848 struct uio
*uio
= &auio
;
850 memset(&auio
, 0, sizeof(auio
));
851 memset(&aiov
, 0, sizeof(aiov
));
854 #ifndef AFS_DARWIN80_ENV
855 if (UBCINVALID(vp
)) {
857 panic("afs_vop_pagein: invalid vp");
858 #endif /* DIAGNOSTIC */
862 UBCINFOCHECK("afs_vop_pagein", vp
);
864 if (pl
== (upl_t
) NULL
) {
865 panic("afs_vop_pagein: no upl");
868 cred
= ubc_getcred(vp
);
874 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
875 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
880 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
881 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
884 if (f_offset
& PAGE_MASK
)
885 panic("afs_vop_pagein: offset not page aligned");
887 OSI_UPL_MAP(pl
, &ioaddr
);
889 #ifdef AFS_DARWIN80_ENV
890 uio
= uio_create(1, f_offset
, UIO_SYSSPACE32
, UIO_READ
);
891 uio_addiov(uio
, CAST_USER_ADDR_T(ioaddr
), size
);
893 auio
.uio_iov
= &aiov
;
895 auio
.uio_offset
= f_offset
;
896 auio
.uio_segflg
= UIO_SYSSPACE
;
897 auio
.uio_rw
= UIO_READ
;
898 auio
.uio_procp
= NULL
;
899 auio
.uio_resid
= aiov
.iov_len
= size
;
900 aiov
.iov_base
= (caddr_t
) ioaddr
;
903 osi_FlushPages(tvc
, vop_cred
); /* hold GLOCK, but not basic vnode lock */
904 code
= afs_read(tvc
, uio
, cred
, 0);
906 ObtainWriteLock(&tvc
->lock
, 2);
907 tvc
->f
.states
|= CMAPPED
;
908 ReleaseWriteLock(&tvc
->lock
);
912 /* Zero out rest of last page if there wasn't enough data in the file */
913 if (code
== 0 && AFS_UIO_RESID(uio
) > 0) {
914 #ifdef AFS_DARWIN80_ENV
915 memset(((caddr_t
)ioaddr
) + (size
- AFS_UIO_RESID(uio
)), 0,
918 memset(aiov
.iov_base
, 0, auio
.uio_resid
);
925 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
926 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
928 OSI_UPL_COMMIT_RANGE(pl
, pl_offset
, size
,
929 UPL_COMMIT_CLEAR_DIRTY
|
930 UPL_COMMIT_FREE_ON_EMPTY
);
932 #ifdef AFS_DARWIN80_ENV
940 struct VOPPROT(write_args
) /* {
941 * struct vnode *a_vp;
944 * struct ucred *a_cred;
948 struct vcache
*avc
= VTOAFS(ap
->a_vp
);
950 #ifdef AFS_DARWIN80_ENV
951 ubc_msync_range(ap
->a_vp
, AFS_UIO_OFFSET(ap
->a_uio
), AFS_UIO_OFFSET(ap
->a_uio
) + AFS_UIO_RESID(ap
->a_uio
), UBC_INVALIDATE
);
953 if (UBCINFOEXISTS(ap
->a_vp
)) {
954 ubc_clean(ap
->a_vp
, 1);
956 if (UBCINFOEXISTS(ap
->a_vp
))
957 osi_VM_NukePages(ap
->a_vp
, AFS_UIO_OFFSET(ap
->a_uio
),
958 AFS_UIO_RESID(ap
->a_uio
));
961 osi_FlushPages(avc
, vop_cred
); /* hold GLOCK, but not basic vnode lock */
963 afs_write(VTOAFS(ap
->a_vp
), ap
->a_uio
, ap
->a_ioflag
, vop_cred
, 0);
970 struct VOPPROT(pageout_args
) /* {
971 * struct vnode *a_vp;
973 * vm_offset_t a_pl_offset,
976 * struct ucred *a_cred,
980 struct vnode
*vp
= ap
->a_vp
;
982 size_t size
= ap
->a_size
;
983 off_t f_offset
= ap
->a_f_offset
;
984 vm_offset_t pl_offset
= ap
->a_pl_offset
;
985 int flags
= ap
->a_flags
;
988 int nocommit
= flags
& UPL_NOCOMMIT
;
991 struct vcache
*tvc
= VTOAFS(vp
);
992 #ifdef AFS_DARWIN80_ENV
997 struct uio
*uio
= &auio
;
999 memset(&auio
, 0, sizeof(auio
));
1000 memset(&aiov
, 0, sizeof(aiov
));
1003 #ifndef AFS_DARWIN80_ENV
1004 if (UBCINVALID(vp
)) {
1006 panic("afs_vop_pageout: invalid vp");
1007 #endif /* DIAGNOSTIC */
1011 UBCINFOCHECK("afs_vop_pageout", vp
);
1013 if (pl
== (upl_t
) NULL
) {
1014 panic("afs_vop_pageout: no upl");
1016 #if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
1018 layer doesn't have them anymore? In any case,
1019 we can't just copy code from nfs... */
1023 int biosize
= DEV_BSIZE
;
1025 lbn
= f_offset
/ DEV_BSIZE
;
1027 for (iosize
= size
; iosize
> 0; iosize
-= biosize
, lbn
++) {
1030 if (bp
= incore(vp
, lbn
)) {
1031 if (ISSET(bp
->b_flags
, B_BUSY
))
1032 panic("nfs_pageout: found BUSY buffer incore\n");
1035 SET(bp
->b_flags
, (B_BUSY
| B_INVAL
));
1042 cred
= ubc_getcred(vp
);
1048 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
1049 UPL_ABORT_FREE_ON_EMPTY
);
1052 if (flags
& (IO_APPEND
| IO_SYNC
))
1053 panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
1056 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
1057 UPL_ABORT_FREE_ON_EMPTY
);
1060 if (f_offset
>= tvc
->f
.m
.Length
) {
1062 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
1063 UPL_ABORT_FREE_ON_EMPTY
);
1067 if (f_offset
& PAGE_MASK
)
1068 panic("afs_vop_pageout: offset not page aligned");
1070 /* size will always be a multiple of PAGE_SIZE */
1071 /* pageout isn't supposed to extend files */
1072 if (f_offset
+ size
> tvc
->f
.m
.Length
)
1073 iosize
= tvc
->f
.m
.Length
- f_offset
;
1077 if (size
> (iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
&& !nocommit
) {
1078 int iosize_rnd
=(iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
;
1079 OSI_UPL_ABORT_RANGE(pl
, pl_offset
+ iosize_rnd
,
1081 UPL_ABORT_FREE_ON_EMPTY
);
1083 OSI_UPL_MAP(pl
, &ioaddr
);
1084 ioaddr
+= pl_offset
;
1085 #ifdef AFS_DARWIN80_ENV
1086 uio
= uio_create(1, f_offset
, UIO_SYSSPACE32
, UIO_READ
);
1087 uio_addiov(uio
, CAST_USER_ADDR_T(ioaddr
), size
);
1089 auio
.uio_iov
= &aiov
;
1090 auio
.uio_iovcnt
= 1;
1091 auio
.uio_offset
= f_offset
;
1092 auio
.uio_segflg
= UIO_SYSSPACE
;
1093 auio
.uio_rw
= UIO_WRITE
;
1094 auio
.uio_procp
= NULL
;
1095 auio
.uio_resid
= aiov
.iov_len
= iosize
;
1096 aiov
.iov_base
= (caddr_t
) ioaddr
;
1100 * check for partial page and clear the
1101 * contents past end of the file before
1102 * releasing it in the VM page cache
1104 if ((f_offset
< tvc
->f
.m
.Length
) && (f_offset
+ size
) > tvc
->f
.m
.Length
) {
1105 size_t io
= tvc
->f
.m
.Length
- f_offset
;
1107 memset((caddr_t
) (ioaddr
+ pl_offset
+ io
), 0, size
- io
);
1112 osi_FlushPages(tvc
, vop_cred
); /* hold GLOCK, but not basic vnode lock */
1113 ObtainWriteLock(&tvc
->lock
, 1);
1115 ReleaseWriteLock(&tvc
->lock
);
1117 code
= afs_write(tvc
, uio
, flags
, cred
, 0);
1119 ObtainWriteLock(&tvc
->lock
, 1);
1120 afs_FakeClose(tvc
, cred
);
1121 ReleaseWriteLock(&tvc
->lock
);
1126 OSI_UPL_ABORT_RANGE(pl
, pl_offset
, size
,
1127 UPL_ABORT_FREE_ON_EMPTY
);
1129 OSI_UPL_COMMIT_RANGE(pl
, pl_offset
, size
,
1130 UPL_COMMIT_CLEAR_DIRTY
|
1131 UPL_COMMIT_FREE_ON_EMPTY
);
1134 #ifdef AFS_DARWIN80_ENV
1142 struct VOPPROT(ioctl_args
) /* {
1143 * struct vnode *a_vp;
1147 * struct ucred *a_cred;
1151 struct vcache
*tvc
= VTOAFS(ap
->a_vp
);
1152 struct afs_ioctl data
;
1155 /* in case we ever get in here... */
1157 AFS_STATCNT(afs_ioctl
);
1158 if (((ap
->a_command
>> 8) & 0xff) == 'V') {
1159 /* This is a VICEIOCTL call */
1161 error
= HandleIoctl(tvc
, ap
->a_command
, ap
->a_data
);
1165 /* No-op call; just return. */
1173 struct VOPPROT(select_args
) /* {
1174 * struct vnode *a_vp;
1177 * struct ucred *a_cred;
1182 * We should really check to see if I/O is possible.
1190 * NB Currently unsupported.
1195 struct VOPPROT(mmap_args
) /* {
1196 * struct vnode *a_vp;
1198 * struct ucred *a_cred;
1207 struct VOPPROT(fsync_args
) /* {
1208 * struct vnode *a_vp;
1209 * struct ucred *a_cred;
1214 int wait
= ap
->a_waitfor
== MNT_WAIT
;
1216 struct vnode
*vp
= ap
->a_vp
;
1217 int haveGlock
= ISAFS_GLOCK();
1219 /* in order to recycle faked vnodes for bulkstat */
1220 if (VTOAFS(vp
) == NULL
)
1223 /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
1224 if (!haveGlock
) AFS_GLOCK();
1226 error
= afs_fsync(VTOAFS(vp
), vop_cred
);
1228 error
= afs_fsync(VTOAFS(vp
), &afs_osi_cred
);
1229 if (!haveGlock
) AFS_GUNLOCK();
1233 #ifndef AFS_DARWIN80_ENV
1236 struct VOPPROT(seek_args
) /* {
1237 * struct vnode *a_vp;
1240 * struct ucred *a_cred;
1243 if (ap
->a_newoff
> ULONG_MAX
) /* AFS doesn't support 64-bit offsets */
1251 struct VOPPROT(remove_args
) /* {
1252 * struct vnode *a_dvp;
1253 * struct vnode *a_vp;
1254 * struct componentname *a_cnp;
1258 struct vnode
*vp
= ap
->a_vp
;
1259 struct vnode
*dvp
= ap
->a_dvp
;
1261 #ifdef AFS_DARWIN80_ENV
1262 if (ap
->a_flags
& VNODE_REMOVE_NODELETEBUSY
) {
1263 /* Caller requested Carbon delete semantics */
1264 if (vnode_isinuse(vp
, 0)) {
1272 error
= afs_remove(VTOAFS(dvp
), name
, vop_cn_cred
);
1273 error
= afs_CheckCode(error
, NULL
, 61);
1277 #ifdef AFS_DARWIN80_ENV
1278 struct vcache
*tvc
= VTOAFS(vp
);
1280 if (!(tvc
->f
.states
& CUnlinked
)) {
1281 ubc_setsize(vp
, (off_t
)0);
1285 /* necessary so we don't deadlock ourselves in vclean */
1286 VOP_UNLOCK(vp
, 0, cnp
->cn_proc
);
1288 /* If crashes continue in ubc_hold, comment this out */
1289 (void)ubc_uncache(vp
);
1292 /* should check for PRSFS_INSERT and not PRSFS_DELETE, but the
1293 goal here is to deal with Finder's unhappiness with resource
1294 forks that have no resources in a dropbox setting */
1295 if (name
[0] == '.' && name
[1] == '_' && error
== EACCES
)
1299 #ifndef AFS_DARWIN80_ENV
1307 #ifndef AFS_DARWIN80_ENV
1308 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1316 struct VOPPROT(link_args
) /* {
1317 * struct vnode *a_vp;
1318 * struct vnode *a_tdvp;
1319 * struct componentname *a_cnp;
1323 struct vnode
*dvp
= ap
->a_tdvp
;
1324 struct vnode
*vp
= ap
->a_vp
;
1329 if (vnode_isdir(vp
)) {
1330 VOP_ABORTOP(vp
, cnp
);
1334 #ifndef AFS_DARWIN80_ENV
1335 if (error
= vn_lock(vp
, LK_EXCLUSIVE
, p
)) {
1336 VOP_ABORTOP(dvp
, cnp
);
1341 error
= afs_link(VTOAFS(vp
), VTOAFS(dvp
), name
, vop_cn_cred
);
1343 #ifndef AFS_DARWIN80_ENV
1344 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1346 #ifndef AFS_DARWIN80_ENV
1348 VOP_UNLOCK(vp
, 0, p
);
1351 #ifndef AFS_DARWIN80_ENV
1360 struct VOPPROT(rename_args
) /* {
1361 * struct vnode *a_fdvp;
1362 * struct vnode *a_fvp;
1363 * struct componentname *a_fcnp;
1364 * struct vnode *a_tdvp;
1365 * struct vnode *a_tvp;
1366 * struct componentname *a_tcnp;
1370 struct componentname
*fcnp
= ap
->a_fcnp
;
1372 struct componentname
*tcnp
= ap
->a_tcnp
;
1374 struct vnode
*tvp
= ap
->a_tvp
;
1375 struct vnode
*tdvp
= ap
->a_tdvp
;
1376 struct vnode
*fvp
= ap
->a_fvp
;
1377 struct vnode
*fdvp
= ap
->a_fdvp
;
1382 #ifdef AFS_DARWIN80_ENV
1384 * generic code tests for v_mount equality, so we don't have to, but we
1385 * don't get the multiple-mount "benefits" of the old behavior
1386 * the generic code doesn't do this, so we really should, but all the
1387 * vrele's are wrong...
1390 /* Check for cross-device rename.
1391 * For AFS, this means anything not in AFS-space
1393 if ((0 != strcmp(tdvp
->v_mount
->mnt_stat
.f_fstypename
, "afs")) ||
1394 (tvp
&& (0 != strcmp(tvp
->v_mount
->mnt_stat
.f_fstypename
, "afs")))) {
1400 * if fvp == tvp, we're just removing one name of a pair of
1401 * directory entries for the same element. convert call into rename.
1402 ( (pinched from NetBSD 1.0's ufs_rename())
1405 if (vnode_isdir(fvp
)) {
1408 VOP_ABORTOP(tdvp
, tcnp
); /* XXX, why not in NFS? */
1415 VOP_ABORTOP(fdvp
, fcnp
); /* XXX, why not in NFS? */
1421 /* Release destination completely. */
1422 VOP_ABORTOP(tdvp
, tcnp
);
1425 /* Delete source. */
1428 fcnp
->cn_flags
&= ~MODMASK
;
1429 fcnp
->cn_flags
|= LOCKPARENT
| LOCKLEAF
;
1430 if ((fcnp
->cn_flags
& SAVESTART
) == 0)
1431 panic("afs_rename: lost from startdir");
1432 fcnp
->cn_nameiop
= DELETE
;
1435 error
=relookup(fdvp
, &fvp
, fcnp
);
1441 error
=VOP_REMOVE(fdvp
, fvp
, fcnp
);
1450 if (error
= vn_lock(fvp
, LK_EXCLUSIVE
, p
))
1454 MALLOC(fname
, char *, fcnp
->cn_namelen
+ 1, M_TEMP
, M_WAITOK
);
1455 memcpy(fname
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
);
1456 fname
[fcnp
->cn_namelen
] = '\0';
1457 MALLOC(tname
, char *, tcnp
->cn_namelen
+ 1, M_TEMP
, M_WAITOK
);
1458 memcpy(tname
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
);
1459 tname
[tcnp
->cn_namelen
] = '\0';
1463 /* XXX use "from" or "to" creds? NFS uses "to" creds */
1465 afs_rename(VTOAFS(fdvp
), fname
, VTOAFS(tdvp
), tname
, cn_cred(tcnp
));
1467 #if !defined(AFS_DARWIN80_ENV)
1469 VOP_UNLOCK(fvp
, 0, p
);
1471 goto abortit
; /* XXX */
1481 if (error
== EXDEV
) {
1482 struct brequest
*tb
;
1483 struct afs_uspc_param mvReq
;
1485 struct vcache
*fvc
= VTOAFS(fdvp
);
1487 struct afs_fakestat_state fakestate
;
1488 int fakestatdone
= 0;
1492 /* unrewritten mount point? */
1493 if (tvc
->mvstat
== AFS_MVSTAT_MTPT
) {
1494 if (tvc
->mvid
.target_root
&& (tvc
->f
.states
& CMValid
)) {
1495 struct vrequest treq
;
1497 afs_InitFakeStat(&fakestate
);
1498 code
= afs_InitReq(&treq
, vop_cred
);
1501 code
= afs_EvalFakeStat(&tvc
, &fakestate
, &treq
);
1503 afs_PutFakeStat(&fakestate
);
1508 /* at some point in the future we should allow other types */
1509 mvReq
.reqtype
= AFS_USPC_UMV
;
1510 mvReq
.req
.umv
.id
= afs_cr_uid(cn_cred(tcnp
));
1511 mvReq
.req
.umv
.idtype
= IDTYPE_UID
;
1512 mvReq
.req
.umv
.sCell
= fvc
->f
.fid
.Cell
;
1513 mvReq
.req
.umv
.sVolume
= fvc
->f
.fid
.Fid
.Volume
;
1514 mvReq
.req
.umv
.sVnode
= fvc
->f
.fid
.Fid
.Vnode
;
1515 mvReq
.req
.umv
.sUnique
= fvc
->f
.fid
.Fid
.Unique
;
1516 mvReq
.req
.umv
.dCell
= tvc
->f
.fid
.Cell
;
1517 mvReq
.req
.umv
.dVolume
= tvc
->f
.fid
.Fid
.Volume
;
1518 mvReq
.req
.umv
.dVnode
= tvc
->f
.fid
.Fid
.Vnode
;
1519 mvReq
.req
.umv
.dUnique
= tvc
->f
.fid
.Fid
.Unique
;
1522 * su %d -c mv /afs/.:mount/%d:%d:%d:%d/%s
1523 * /afs/.:mount/%d:%d:%d:%d/%s where:
1524 * mvReq.req.umv.id, fvc->f.fid.Cell, fvc->f.fid.Fid.Volume,
1525 * fvc->f.fid.Fid.Vnode, fvc->f.fid.Fid.Unique, fname,
1526 * tvc->f.fid.Cell, tvc->f.fid.Fid.Volume, tvc->f.fid.Fid.Vnode,
1527 * tvc->f.fid.Fid.Unique, tname
1530 tb
= afs_BQueue(BOP_MOVE
, NULL
, 0, 1, cn_cred(tcnp
),
1531 0L, 0L, &mvReq
, fname
, tname
);
1532 /* wait to collect result */
1533 while ((tb
->flags
& BUVALID
) == 0) {
1534 tb
->flags
|= BUWAIT
;
1537 /* if we succeeded, clear the error. otherwise, EXDEV */
1538 if (mvReq
.retval
== 0)
1545 afs_PutFakeStat(&fakestate
);
1559 cache_enter(tdvp
, fvp
, tcnp
);
1561 FREE(fname
, M_TEMP
);
1562 FREE(tname
, M_TEMP
);
1568 struct VOPPROT(mkdir_args
) /* {
1569 * struct vnode *a_dvp;
1570 * struct vnode **a_vpp;
1571 * struct componentname *a_cnp;
1572 * struct vattr *a_vap;
1575 struct vnode
*dvp
= ap
->a_dvp
;
1576 struct vattr
*vap
= ap
->a_vap
;
1583 #if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
1584 if ((cnp
->cn_flags
& HASBUF
) == 0)
1585 panic("afs_vop_mkdir: no name");
1588 error
= afs_mkdir(VTOAFS(dvp
), name
, vap
, &vcp
, vop_cn_cred
);
1591 #ifndef AFS_DARWIN80_ENV
1592 VOP_ABORTOP(dvp
, cnp
);
1599 #ifdef AFS_DARWIN80_ENV
1600 afs_darwin_finalizevnode(vcp
, ap
->a_dvp
, ap
->a_cnp
, 0, 0);
1602 *ap
->a_vpp
= AFSTOV(vcp
);
1603 #ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
1604 (*ap
->a_vpp
)->v_vfsp
= dvp
->v_vfsp
;
1605 vn_lock(*ap
->a_vpp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
1610 #ifndef AFS_DARWIN80_ENV
1611 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1619 struct VOPPROT(rmdir_args
) /* {
1620 * struct vnode *a_dvp;
1621 * struct vnode *a_vp;
1622 * struct componentname *a_cnp;
1626 struct vnode
*vp
= ap
->a_vp
;
1627 struct vnode
*dvp
= ap
->a_dvp
;
1631 #ifndef AFS_DARWIN80_ENV
1634 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1641 error
= afs_rmdir(VTOAFS(dvp
), name
, vop_cn_cred
);
1646 #ifndef AFS_DARWIN80_ENV
1655 struct VOPPROT(symlink_args
) /* {
1656 * struct vnode *a_dvp;
1657 * struct vnode **a_vpp;
1658 * struct componentname *a_cnp;
1659 * struct vattr *a_vap;
1663 struct vnode
*dvp
= ap
->a_dvp
;
1664 struct vcache
*pvc
= NULL
;
1669 error
= afs_symlink(VTOAFS(dvp
), name
, ap
->a_vap
, ap
->a_target
, &pvc
,
1672 #ifndef AFS_DARWIN80_ENV
1673 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1678 error
= afs_darwin_finalizevnode(pvc
, dvp
, ap
->a_cnp
, 0, 0);
1680 *ap
->a_vpp
= AFSTOV(pvc
);
1688 struct VOPPROT(readdir_args
) /* {
1689 * struct vnode *a_vp;
1690 * struct uio *a_uio;
1691 * struct ucred *a_cred;
1693 * u_long *a_cookies;
1699 /* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1701 #ifdef AFS_DARWIN80_ENV
1702 /* too much work for now */
1703 /* should only break nfs exports */
1704 if (ap
->a_flags
& (VNODE_READDIR_EXTENDED
| VNODE_READDIR_REQSEEKOFF
))
1707 off
= AFS_UIO_OFFSET(ap
->a_uio
);
1710 afs_readdir(VTOAFS(ap
->a_vp
), ap
->a_uio
, vop_cred
, ap
->a_eofflag
);
1712 #ifndef AFS_DARWIN80_ENV
1713 if (!error
&& ap
->a_ncookies
!= NULL
) {
1714 struct uio
*uio
= ap
->a_uio
;
1715 const struct dirent
*dp
, *dp_start
, *dp_end
;
1717 u_long
*cookies
, *cookiep
;
1719 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
1720 panic("afs_readdir: burned cookies");
1721 dp
= (const struct dirent
*)
1722 ((const char *)uio
->uio_iov
->iov_base
- (uio
->uio_offset
- off
));
1724 dp_end
= (const struct dirent
*)uio
->uio_iov
->iov_base
;
1725 for (dp_start
= dp
, ncookies
= 0; dp
< dp_end
;
1726 dp
= (const struct dirent
*)((const char *)dp
+ dp
->d_reclen
))
1729 MALLOC(cookies
, u_long
*, ncookies
* sizeof(u_long
), M_TEMP
,
1731 for (dp
= dp_start
, cookiep
= cookies
; dp
< dp_end
;
1732 dp
= (const struct dirent
*)((const char *)dp
+ dp
->d_reclen
)) {
1733 off
+= dp
->d_reclen
;
1736 *ap
->a_cookies
= cookies
;
1737 *ap
->a_ncookies
= ncookies
;
1745 afs_vop_readlink(ap
)
1746 struct VOPPROT(readlink_args
) /* {
1747 * struct vnode *a_vp;
1748 * struct uio *a_uio;
1749 * struct ucred *a_cred;
1753 /* printf("readlink %x\n", ap->a_vp);*/
1755 error
= afs_readlink(VTOAFS(ap
->a_vp
), ap
->a_uio
, vop_cred
);
1760 extern int prtactive
;
1763 afs_vop_inactive(ap
)
1764 struct VOPPROT(inactive_args
) /* {
1765 * struct vnode *a_vp;
1769 struct vnode
*vp
= ap
->a_vp
;
1770 struct vcache
*tvc
= VTOAFS(vp
);
1771 #ifndef AFS_DARWIN80_ENV
1772 if (prtactive
&& vp
->v_usecount
!= 0)
1773 vprint("afs_vop_inactive(): pushing active", vp
);
1776 #ifdef AFS_DARWIN80_ENV
1777 int unlinked
= tvc
->f
.states
& CUnlinked
;
1780 afs_InactiveVCache(tvc
, 0); /* decrs ref counts */
1782 #ifdef AFS_DARWIN80_ENV
1789 #ifndef AFS_DARWIN80_ENV
1790 VOP_UNLOCK(vp
, 0, ap
->a_p
);
1797 struct VOPPROT(reclaim_args
) /* {
1798 * struct vnode *a_vp;
1802 int sl
, writelocked
;
1803 struct vnode
*vp
= ap
->a_vp
;
1804 struct vcache
*tvc
= VTOAFS(vp
);
1806 osi_Assert(!ISAFS_GLOCK());
1807 cache_purge(vp
); /* just in case... */
1810 writelocked
= (0 == NBObtainWriteLock(&afs_xvcache
, 335));
1812 ObtainWriteLock(&afs_xvreclaim
, 176);
1813 #ifdef AFS_DARWIN80_ENV
1814 vnode_clearfsnode(AFSTOV(tvc
));
1815 vnode_removefsref(AFSTOV(tvc
));
1817 tvc
->v
->v_data
= NULL
; /* remove from vnode */
1819 AFSTOV(tvc
) = NULL
; /* also drop the ptr to vnode */
1820 tvc
->f
.states
|= CVInit
; /* also CDeadVnode? */
1821 tvc
->nextfree
= ReclaimedVCList
;
1822 ReclaimedVCList
= tvc
;
1823 ReleaseWriteLock(&afs_xvreclaim
);
1825 error
= afs_FlushVCache(tvc
, &sl
); /* toss our stuff from vnode */
1826 if (tvc
->f
.states
& (CVInit
1827 #ifdef AFS_DARWIN80_ENV
1831 tvc
->f
.states
&= ~(CVInit
1832 #ifdef AFS_DARWIN80_ENV
1836 afs_osi_Wakeup(&tvc
->f
.states
);
1838 if (!error
&& vnode_fsnode(vp
))
1839 panic("afs_reclaim: vnode not cleaned");
1840 if (!error
&& (tvc
->v
!= NULL
))
1841 panic("afs_reclaim: vcache not cleaned");
1842 ReleaseWriteLock(&afs_xvcache
);
1850 * Return POSIX pathconf information applicable to ufs filesystems.
1852 afs_vop_pathconf(ap
)
1853 struct VOPPROT(pathconf_args
) /* {
1854 * struct vnode *a_vp;
1859 AFS_STATCNT(afs_cntl
);
1860 switch (ap
->a_name
) {
1862 *ap
->a_retval
= LINK_MAX
;
1865 *ap
->a_retval
= NAME_MAX
;
1868 *ap
->a_retval
= PATH_MAX
;
1870 case _PC_CHOWN_RESTRICTED
:
1879 case _PC_NAME_CHARS_MAX
:
1880 *ap
->a_retval
= NAME_MAX
;
1882 case _PC_CASE_SENSITIVE
:
1885 case _PC_CASE_PRESERVING
:
1895 * Advisory record locking support (fcntl() POSIX style)
1899 struct VOPPROT(advlock_args
) /* {
1900 * struct vnode *a_vp;
1903 * struct flock *a_fl;
1911 #ifdef AFS_DARWIN80_ENV
1915 struct proc
*p
= current_proc();
1918 cr
= *p
->p_cred
->pc_ucred
;
1922 if (ap
->a_flags
& F_POSIX
) {
1923 #ifdef AFS_DARWIN80_ENV
1924 p
= (proc_t
) ap
->a_id
;
1927 p
= (struct proc
*) ap
->a_id
;
1931 clid
= (int)ap
->a_id
;
1933 if (ap
->a_op
== F_UNLCK
) {
1935 } else if (ap
->a_op
== F_SETLK
&& ap
->a_flags
& F_WAIT
) {
1941 error
= afs_lockctl(VTOAFS(ap
->a_vp
), ap
->a_fl
, op
, tcr
, clid
);
1947 afs_vop_blktooff(ap
)
1948 struct VOPPROT(blktooff_args
) /* {
1949 * struct vnode *a_vp;
1954 *ap
->a_offset
= (off_t
) (ap
->a_lblkno
* DEV_BSIZE
);
1959 afs_vop_offtoblk(ap
)
1960 struct VOPPROT(offtoblk_args
) /* {
1961 * struct vnode *a_vp;
1963 * daddr_t *a_lblkno;
1966 *ap
->a_lblkno
= (daddr_t
) (ap
->a_offset
/ DEV_BSIZE
);
1971 #ifndef AFS_DARWIN80_ENV
1974 struct VOPPROT(lock_args
) /* {
1975 * struct vnode *a_vp;
1978 struct vnode
*vp
= ap
->a_vp
;
1979 struct vcache
*avc
= VTOAFS(vp
);
1981 if (vp
->v_tag
== VT_NON
)
1984 return (lockmgr(&avc
->rwlock
, ap
->a_flags
, &vp
->v_interlock
, ap
->a_p
));
1989 struct VOPPROT(unlock_args
) /* {
1990 * struct vnode *a_vp;
1993 struct vnode
*vp
= ap
->a_vp
;
1994 struct vcache
*avc
= VTOAFS(vp
);
1997 (&avc
->rwlock
, ap
->a_flags
| LK_RELEASE
, &vp
->v_interlock
,
2003 afs_vop_truncate(ap
)
2004 struct VOPPROT(truncate_args
) /* {
2005 * struct vnode *a_vp;
2008 * struct ucred *a_cred;
2012 /* printf("stray afs_vop_truncate\n"); */
2018 struct VOPPROT(update_args
) /* {
2019 * struct vnode *a_vp;
2020 * struct timeval *a_access;
2021 * struct timeval *a_modify;
2025 /* printf("stray afs_vop_update\n"); */
2031 struct VOPPROT(bmap_args
) /* {
2032 * struct vnode *a_vp;
2034 * struct vnode **a_vpp;
2042 *ap
->a_bnp
= ap
->a_bn
* (PAGE_SIZE
/ DEV_BSIZE
);
2045 *ap
->a_vpp
= ap
->a_vp
;
2047 if (ap
->a_runp
!= NULL
)
2050 if (ap
->a_runb
!= NULL
)
2058 afs_vop_strategy(ap
)
2059 struct VOPPROT(strategy_args
) /* {
2065 error
= afs_ustrategy(ap
->a_bp
);
2072 struct VOPPROT(print_args
) /* {
2073 * struct vnode *a_vp;
2076 struct vnode
*vp
= ap
->a_vp
;
2077 struct vcache
*vc
= VTOAFS(ap
->a_vp
);
2078 int s
= vc
->f
.states
;
2079 printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp
->v_tag
,
2080 vc
->f
.fid
.Cell
, vc
->f
.fid
.Fid
.Volume
, vc
->f
.fid
.Fid
.Vnode
,
2081 vc
->f
.fid
.Fid
.Unique
, vc
->opens
, vc
->execsOrWriters
);
2082 printf("\n states%s%s%s%s%s", (s
& CStatd
) ? " statd" : "",
2083 (s
& CRO
) ? " readonly" : "", (s
& CDirty
) ? " dirty" : "",
2084 (s
& CMAPPED
) ? " mapped" : "",
2085 (s
& CVFlushed
) ? " flush in progress" : "");
2086 if (UBCISVALID(vp
)) {
2088 if (UBCINFOEXISTS(vp
)) {
2090 printf("refs %d%s%s", vp
->v_ubcinfo
->ui_refcount
,
2091 ubc_issetflags(vp
, UI_HASOBJREF
) ? " HASOBJREF" : "",
2092 ubc_issetflags(vp
, UI_WASMAPPED
) ? " WASMAPPED" : "");
2094 printf("does not exist");
2101 afs_vop_islocked(ap
)
2102 struct VOPPROT(islocked_args
) /* {
2103 * struct vnode *a_vp;
2106 struct vcache
*vc
= VTOAFS(ap
->a_vp
);
2107 return lockstatus(&vc
->rwlock
);
2112 struct VOPPROT(cmap_args
) /* {
2113 * struct vnode *a_vp;
2121 *ap
->a_bpn
= (daddr_t
) (ap
->a_foffset
/ DEV_BSIZE
);
2122 *ap
->a_run
= MAX(ap
->a_size
, AFS_CHUNKSIZE(ap
->a_foffset
));
2128 afs_darwin_getnewvnode(struct vcache
*avc
)
2130 #ifdef AFS_DARWIN80_ENV
2133 struct vnode_fsparam par
;
2135 memset(&par
, 0, sizeof(struct vnode_fsparam
));
2136 par
.vnfs_vtype
= VNON
;
2137 par
.vnfs_vops
= afs_dead_vnodeop_p
;
2138 par
.vnfs_flags
= VNFS_NOCACHE
|VNFS_CANTCACHE
;
2139 par
.vnfs_mp
= afs_globalVFS
;
2140 par
.vnfs_fsnode
= avc
;
2142 error
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &par
, &vp
);
2147 vnode_recycle(vp
); /* terminate as soon as iocount drops */
2148 avc
->f
.states
|= CDeadVnode
;
2152 while (getnewvnode(VT_AFS
, afs_globalVFS
, afs_vnodeop_p
, &avc
->v
)) {
2153 /* no vnodes available, force an alloc (limits be damned)! */
2154 printf("failed to get vnode\n");
2156 avc
->v
->v_data
= (void *)avc
;
2160 #ifdef AFS_DARWIN80_ENV
2161 /* if this fails, then tvc has been unrefed and may have been freed.
2164 afs_darwin_finalizevnode(struct vcache
*avc
, struct vnode
*dvp
,
2165 struct componentname
*cnp
, int isroot
, int locked
)
2170 struct vnode_fsparam par
;
2174 ObtainWriteLock(&avc
->lock
,325);
2178 if (!(avc
->f
.states
& CDeadVnode
) && vnode_vtype(ovp
) != VNON
) {
2180 #if 0 /* unsupported */
2182 vnode_update_identity(ovp
, dvp
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
2184 VNODE_UPDATE_PARENT
|VNODE_UPDATE_NAME
);
2186 /* Can end up in reclaim... drop GLOCK */
2190 ReleaseWriteLock(&avc
->lock
);
2196 if ((avc
->f
.states
& CDeadVnode
) && vnode_vtype(ovp
) != VNON
)
2197 panic("vcache %p should not be CDeadVnode", avc
);
2199 memset(&par
, 0, sizeof(struct vnode_fsparam
));
2200 par
.vnfs_mp
= afs_globalVFS
;
2201 par
.vnfs_vtype
= avc
->f
.m
.Type
;
2202 par
.vnfs_vops
= afs_vnodeop_p
;
2203 par
.vnfs_filesize
= avc
->f
.m
.Length
;
2204 par
.vnfs_fsnode
= avc
;
2206 if (cnp
&& (cnp
->cn_flags
& ISDOTDOT
) == 0)
2208 if (!dvp
|| !cnp
|| (cnp
->cn_flags
& MAKEENTRY
) == 0)
2209 par
.vnfs_flags
= VNFS_NOCACHE
;
2211 par
.vnfs_markroot
= 1;
2212 error
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &par
, &nvp
);
2214 vnode_addfsref(nvp
);
2215 if ((avc
->f
.states
& CDeadVnode
) && vnode_vtype(ovp
) != VNON
)
2216 printf("vcache %p should not be CDeadVnode", avc
);
2217 if (avc
->v
== ovp
) {
2218 if (!(avc
->f
.states
& CVInit
)) {
2219 vnode_clearfsnode(ovp
);
2220 vnode_removefsref(ovp
);
2222 /* we're discarding on a fixup. mark for recycle */
2223 if (!(avc
->f
.states
& CDeadVnode
))
2227 avc
->f
.states
&=~ CDeadVnode
;
2228 /* If we were carrying an extra ref for dirty, hold/push it. */
2229 if (avc
->f
.ddirty_flags
) {
2233 /* If we were carrying an extra ref for shadow, hold/push it. */
2234 if (avc
->f
.shadow
.vnode
) {
2239 /* Drop any extra dirty ref on the old vnode */
2240 if (avc
->f
.ddirty_flags
) {
2244 /* Drop any extra shadow ref on the old vnode */
2245 if (avc
->f
.shadow
.vnode
) {
2249 /* If it's ref'd still, unmark stat'd to force new lookup */
2250 if ((vnode_vtype(ovp
) != avc
->f
.m
.Type
) && VREFCOUNT_GT(avc
, 1))
2251 avc
->f
.states
&= ~CStatd
;
2257 ReleaseWriteLock(&avc
->lock
);
2259 afs_osi_Wakeup(&avc
->f
.states
);