darwin-avoid-hang-on-rename-20040202
[openafs.git] / src / afs / DARWIN / osi_vnodeops.c
1 /*
2  * Portions Copyright (c) 2003 Apple Computer, Inc.  All rights reserved.
3  */
4 #include <afsconfig.h>
5 #include <afs/param.h>
6
7 RCSID
8     ("$Header$");
9
10 #include <afs/sysincludes.h>    /* Standard vendor system headers */
11 #include <afsincludes.h>        /* Afs-based standard headers */
12 #include <afs/afs_stats.h>      /* statistics */
13 #include <sys/malloc.h>
14 #include <sys/namei.h>
15 #include <sys/ubc.h>
16 #if defined(AFS_DARWIN70_ENV)
17 #include <vfs/vfs_support.h>
18 #endif /* defined(AFS_DARWIN70_ENV) */
19
20 int afs_vop_lookup(struct vop_lookup_args *);
21 int afs_vop_create(struct vop_create_args *);
22 int afs_vop_mknod(struct vop_mknod_args *);
23 int afs_vop_open(struct vop_open_args *);
24 int afs_vop_close(struct vop_close_args *);
25 int afs_vop_access(struct vop_access_args *);
26 int afs_vop_getattr(struct vop_getattr_args *);
27 int afs_vop_setattr(struct vop_setattr_args *);
28 int afs_vop_read(struct vop_read_args *);
29 int afs_vop_write(struct vop_write_args *);
30 int afs_vop_pagein(struct vop_pagein_args *);
31 int afs_vop_pageout(struct vop_pageout_args *);
32 int afs_vop_ioctl(struct vop_ioctl_args *);
33 int afs_vop_select(struct vop_select_args *);
34 int afs_vop_mmap(struct vop_mmap_args *);
35 int afs_vop_fsync(struct vop_fsync_args *);
36 int afs_vop_seek(struct vop_seek_args *);
37 int afs_vop_remove(struct vop_remove_args *);
38 int afs_vop_link(struct vop_link_args *);
39 int afs_vop_rename(struct vop_rename_args *);
40 int afs_vop_mkdir(struct vop_mkdir_args *);
41 int afs_vop_rmdir(struct vop_rmdir_args *);
42 int afs_vop_symlink(struct vop_symlink_args *);
43 int afs_vop_readdir(struct vop_readdir_args *);
44 int afs_vop_readlink(struct vop_readlink_args *);
45 #if !defined(AFS_DARWIN70_ENV)
46 extern int ufs_abortop(struct vop_abortop_args *);
47 #endif /* !defined(AFS_DARWIN70_ENV) */
48 int afs_vop_inactive(struct vop_inactive_args *);
49 int afs_vop_reclaim(struct vop_reclaim_args *);
50 int afs_vop_lock(struct vop_lock_args *);
51 int afs_vop_unlock(struct vop_unlock_args *);
52 int afs_vop_bmap(struct vop_bmap_args *);
53 int afs_vop_strategy(struct vop_strategy_args *);
54 int afs_vop_print(struct vop_print_args *);
55 int afs_vop_islocked(struct vop_islocked_args *);
56 int afs_vop_pathconf(struct vop_pathconf_args *);
57 int afs_vop_advlock(struct vop_advlock_args *);
58 int afs_vop_truncate(struct vop_truncate_args *);
59 int afs_vop_update(struct vop_update_args *);
60 int afs_vop_blktooff __P((struct vop_blktooff_args *));
61 int afs_vop_offtoblk __P((struct vop_offtoblk_args *));
62 int afs_vop_cmap __P((struct vop_cmap_args *));
63
64
65 #define afs_vop_opnotsupp \
66         ((int (*) __P((struct  vop_reallocblks_args *)))eopnotsupp)
67 #define afs_vop_valloc afs_vop_opnotsupp
68 #define afs_vop_vfree afs_vop_opnotsupp
69 #define afs_vop_blkatoff afs_vop_opnotsupp
70 #define afs_vop_reallocblks afs_vop_opnotsupp
71
72 /* Global vfs data structures for AFS. */
73 int (**afs_vnodeop_p) ();
74 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
75     {&vop_default_desc, vn_default_error},
76     {&vop_lookup_desc, afs_vop_lookup}, /* lookup */
77     {&vop_create_desc, afs_vop_create}, /* create */
78     {&vop_mknod_desc, afs_vop_mknod},   /* mknod */
79     {&vop_open_desc, afs_vop_open},     /* open */
80     {&vop_close_desc, afs_vop_close},   /* close */
81     {&vop_access_desc, afs_vop_access}, /* access */
82     {&vop_getattr_desc, afs_vop_getattr},       /* getattr */
83     {&vop_setattr_desc, afs_vop_setattr},       /* setattr */
84     {&vop_read_desc, afs_vop_read},     /* read */
85     {&vop_write_desc, afs_vop_write},   /* write */
86     {&vop_pagein_desc, afs_vop_pagein}, /* read */
87     {&vop_pageout_desc, afs_vop_pageout},       /* write */
88     {&vop_ioctl_desc, afs_vop_ioctl},   /* XXX ioctl */
89     {&vop_select_desc, afs_vop_select}, /* select */
90     {&vop_mmap_desc, afs_vop_mmap},     /* mmap */
91     {&vop_fsync_desc, afs_vop_fsync},   /* fsync */
92     {&vop_seek_desc, afs_vop_seek},     /* seek */
93     {&vop_remove_desc, afs_vop_remove}, /* remove */
94     {&vop_link_desc, afs_vop_link},     /* link */
95     {&vop_rename_desc, afs_vop_rename}, /* rename */
96     {&vop_mkdir_desc, afs_vop_mkdir},   /* mkdir */
97     {&vop_rmdir_desc, afs_vop_rmdir},   /* rmdir */
98     {&vop_symlink_desc, afs_vop_symlink},       /* symlink */
99     {&vop_readdir_desc, afs_vop_readdir},       /* readdir */
100     {&vop_readlink_desc, afs_vop_readlink},     /* readlink */
101 #if defined(AFS_DARWIN70_ENV)
102     { &vop_abortop_desc, nop_abortop },             /* abortop */
103 #else /* ! defined(AFS_DARWIN70_ENV) */
104     /* Yes, we use the ufs_abortop call.  It just releases the namei
105      * buffer stuff */
106     {&vop_abortop_desc, ufs_abortop},   /* abortop */
107 #endif /* defined(AFS_DARWIN70_ENV) */
108     {&vop_inactive_desc, afs_vop_inactive},     /* inactive */
109     {&vop_reclaim_desc, afs_vop_reclaim},       /* reclaim */
110     {&vop_lock_desc, afs_vop_lock},     /* lock */
111     {&vop_unlock_desc, afs_vop_unlock}, /* unlock */
112     {&vop_bmap_desc, afs_vop_bmap},     /* bmap */
113     {&vop_strategy_desc, afs_vop_strategy},     /* strategy */
114     {&vop_print_desc, afs_vop_print},   /* print */
115     {&vop_islocked_desc, afs_vop_islocked},     /* islocked */
116     {&vop_pathconf_desc, afs_vop_pathconf},     /* pathconf */
117     {&vop_advlock_desc, afs_vop_advlock},       /* advlock */
118     {&vop_blkatoff_desc, afs_vop_blkatoff},     /* blkatoff */
119     {&vop_valloc_desc, afs_vop_valloc}, /* valloc */
120     {&vop_reallocblks_desc, afs_vop_reallocblks},       /* reallocblks */
121     {&vop_vfree_desc, afs_vop_vfree},   /* vfree */
122     {&vop_truncate_desc, afs_vop_truncate},     /* truncate */
123     {&vop_update_desc, afs_vop_update}, /* update */
124     {&vop_blktooff_desc, afs_vop_blktooff},     /* blktooff */
125     {&vop_offtoblk_desc, afs_vop_offtoblk},     /* offtoblk */
126     {&vop_cmap_desc, afs_vop_cmap},     /* cmap */
127     {&vop_bwrite_desc, vn_bwrite},
128     {(struct vnodeop_desc *)NULL, (int (*)())NULL}
129 };
130 struct vnodeopv_desc afs_vnodeop_opv_desc =
131     { &afs_vnodeop_p, afs_vnodeop_entries };
132
133 #define GETNAME()       \
134     struct componentname *cnp = ap->a_cnp; \
135     char *name; \
136     MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
137     memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
138     name[cnp->cn_namelen] = '\0'
139
140 #define DROPNAME() FREE(name, M_TEMP)
141
142
143
144 int
145 afs_vop_lookup(ap)
146      struct vop_lookup_args     /* {
147                                  * struct vnodeop_desc * a_desc;
148                                  * struct vnode *a_dvp;
149                                  * struct vnode **a_vpp;
150                                  * struct componentname *a_cnp;
151                                  * } */ *ap;
152 {
153     int error;
154     struct vcache *vcp;
155     struct vnode *vp, *dvp;
156     register int flags = ap->a_cnp->cn_flags;
157     int lockparent;             /* 1 => lockparent flag is set */
158     int wantparent;             /* 1 => wantparent or lockparent flag */
159     struct proc *p;
160     GETNAME();
161     p = cnp->cn_proc;
162     lockparent = flags & LOCKPARENT;
163     wantparent = flags & (LOCKPARENT | WANTPARENT);
164
165     if (ap->a_dvp->v_type != VDIR) {
166         *ap->a_vpp = 0;
167         DROPNAME();
168         return ENOTDIR;
169     }
170     dvp = ap->a_dvp;
171     if (flags & ISDOTDOT)
172         VOP_UNLOCK(dvp, 0, p);
173     AFS_GLOCK();
174     error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
175     AFS_GUNLOCK();
176     if (error) {
177         if (flags & ISDOTDOT)
178             VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
179         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
180             && (flags & ISLASTCN) && error == ENOENT)
181             error = EJUSTRETURN;
182         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
183             cnp->cn_flags |= SAVENAME;
184         DROPNAME();
185         *ap->a_vpp = 0;
186         return (error);
187     }
188     vp = AFSTOV(vcp);           /* always get a node if no error */
189     vp->v_vfsp = dvp->v_vfsp;
190
191     /* The parent directory comes in locked.  We unlock it on return
192      * unless the caller wants it left locked.
193      * we also always return the vnode locked. */
194
195     if (flags & ISDOTDOT) {
196         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
197         /* always return the child locked */
198         if (lockparent && (flags & ISLASTCN)
199             && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
200             vput(vp);
201             DROPNAME();
202             return (error);
203         }
204     } else if (vp == dvp) {
205         /* they're the same; afs_lookup() already ref'ed the leaf.
206          * It came in locked, so we don't need to ref OR lock it */
207     } else {
208         if (!lockparent || !(flags & ISLASTCN))
209             VOP_UNLOCK(dvp, 0, p);      /* done with parent. */
210         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
211         /* always return the child locked */
212     }
213     *ap->a_vpp = vp;
214
215     if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
216          || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
217         cnp->cn_flags |= SAVENAME;
218
219     DROPNAME();
220     return error;
221 }
222
223 int
224 afs_vop_create(ap)
225      struct vop_create_args     /* {
226                                  * struct vnode *a_dvp;
227                                  * struct vnode **a_vpp;
228                                  * struct componentname *a_cnp;
229                                  * struct vattr *a_vap;
230                                  * } */ *ap;
231 {
232     int error = 0;
233     struct vcache *vcp;
234     register struct vnode *dvp = ap->a_dvp;
235     struct proc *p;
236     GETNAME();
237     p = cnp->cn_proc;
238
239     /* vnode layer handles excl/nonexcl */
240     AFS_GLOCK();
241     error =
242         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
243                    &vcp, cnp->cn_cred);
244     AFS_GUNLOCK();
245     if (error) {
246         VOP_ABORTOP(dvp, cnp);
247         vput(dvp);
248         DROPNAME();
249         return (error);
250     }
251
252     if (vcp) {
253         *ap->a_vpp = AFSTOV(vcp);
254         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
255         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
256         if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp))
257             ubc_info_init(*ap->a_vpp);
258     } else
259         *ap->a_vpp = 0;
260
261     if ((cnp->cn_flags & SAVESTART) == 0)
262         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
263     vput(dvp);
264     DROPNAME();
265     return error;
266 }
267
268 int
269 afs_vop_mknod(ap)
270      struct vop_mknod_args      /* {
271                                  * struct vnode *a_dvp;
272                                  * struct vnode **a_vpp;
273                                  * struct componentname *a_cnp;
274                                  * struct vattr *a_vap;
275                                  * } */ *ap;
276 {
277     FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
278     vput(ap->a_dvp);
279     return (ENODEV);
280 }
281
282 int
283 afs_vop_open(ap)
284      struct vop_open_args       /* {
285                                  * struct vnode *a_vp;
286                                  * int  a_mode;
287                                  * struct ucred *a_cred;
288                                  * struct proc *a_p;
289                                  * } */ *ap;
290 {
291     int error;
292     struct vnode *vp = ap->a_vp;
293     struct vcache *vc = VTOAFS(vp);
294 #ifdef AFS_DARWIN14_ENV
295     int didhold = 0;
296     /*----------------------------------------------------------------
297      * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
298      * can later be passed to vn_open(), which will skip the call to
299      * ubc_hold(), and when the ubcinfo is later added, the ui_refcount
300      * will be off.  So we compensate by calling ubc_hold() ourselves
301      * when ui_refcount is less than 2.  If an error occurs in afs_open()
302      * we must call ubc_rele(), which is what vn_open() would do if it
303      * was able to call ubc_hold() in the first place.
304      *----------------------------------------------------------------*/
305     if (vp->v_type == VREG && !(vp->v_flag & VSYSTEM)
306       && vp->v_ubcinfo->ui_refcount < 2)
307         didhold = ubc_hold(vp);
308 #endif /* AFS_DARWIN14_ENV */
309     AFS_GLOCK();
310     error = afs_open(&vc, ap->a_mode, ap->a_cred);
311 #ifdef DIAGNOSTIC
312     if (AFSTOV(vc) != vp)
313         panic("AFS open changed vnode!");
314 #endif
315     afs_BozonLock(&vc->pvnLock, vc);
316     osi_FlushPages(vc, ap->a_cred);
317     afs_BozonUnlock(&vc->pvnLock, vc);
318     AFS_GUNLOCK();
319 #ifdef AFS_DARWIN14_ENV
320     if (error && didhold)
321         ubc_rele(vp);
322 #endif /* AFS_DARWIN14_ENV */
323     return error;
324 }
325
326 int
327 afs_vop_close(ap)
328      struct vop_close_args      /* {
329                                  * struct vnode *a_vp;
330                                  * int  a_fflag;
331                                  * struct ucred *a_cred;
332                                  * struct proc *a_p;
333                                  * } */ *ap;
334 {
335     int code;
336     struct vcache *avc = ap->a_vp;
337     AFS_GLOCK();
338     if (ap->a_cred)
339         code = afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p);
340     else
341         code = afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p);
342     afs_BozonLock(&avc->pvnLock, avc);
343     osi_FlushPages(avc, ap->a_cred);    /* hold bozon lock, but not basic vnode lock */
344     afs_BozonUnlock(&avc->pvnLock, avc);
345     AFS_GUNLOCK();
346 #ifdef AFS_DARWIN14_ENV
347     if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
348         ubc_hold(ap->a_vp);
349         if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
350             printf("afs: Imminent ui_refcount panic\n");
351         } else {
352             printf("afs: WARNING: ui_refcount panic averted\n");
353         }
354     }
355 #endif
356
357     return code;
358 }
359
360 int
361 afs_vop_access(ap)
362      struct vop_access_args     /* {
363                                  * struct vnode *a_vp;
364                                  * int  a_mode;
365                                  * struct ucred *a_cred;
366                                  * struct proc *a_p;
367                                  * } */ *ap;
368 {
369     int code;
370     AFS_GLOCK();
371     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
372     AFS_GUNLOCK();
373     return code;
374 }
375
376 int
377 afs_vop_getattr(ap)
378      struct vop_getattr_args    /* {
379                                  * struct vnode *a_vp;
380                                  * struct vattr *a_vap;
381                                  * struct ucred *a_cred;
382                                  * struct proc *a_p;
383                                  * } */ *ap;
384 {
385     int code;
386     AFS_GLOCK();
387     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
388     AFS_GUNLOCK();
389     return code;
390 }
391
392 int
393 afs_vop_setattr(ap)
394      struct vop_setattr_args    /* {
395                                  * struct vnode *a_vp;
396                                  * struct vattr *a_vap;
397                                  * struct ucred *a_cred;
398                                  * struct proc *a_p;
399                                  * } */ *ap;
400 {
401     int code;
402     AFS_GLOCK();
403     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
404     AFS_GUNLOCK();
405     return code;
406 }
407
408 int
409 afs_vop_read(ap)
410      struct vop_read_args       /* {
411                                  * struct vnode *a_vp;
412                                  * struct uio *a_uio;
413                                  * int a_ioflag;
414                                  * struct ucred *a_cred;
415                                  * } */ *ap;
416 {
417     int code;
418     struct vcache *avc = VTOAFS(ap->a_vp);
419     AFS_GLOCK();
420     afs_BozonLock(&avc->pvnLock, avc);
421     osi_FlushPages(avc, ap->a_cred);    /* hold bozon lock, but not basic vnode lock */
422     code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
423     afs_BozonUnlock(&avc->pvnLock, avc);
424     AFS_GUNLOCK();
425     return code;
426 }
427
428 int
429 afs_vop_pagein(ap)
430      struct vop_pagein_args     /* {
431                                  * struct vnode *a_vp;
432                                  * upl_t a_pl;
433                                  * vm_offset_t a_pl_offset;
434                                  * off_t a_f_offset;
435                                  * size_t a_size;
436                                  * struct ucred *a_cred;
437                                  * int a_flags;
438                                  * } */ *ap;
439 {
440     register struct vnode *vp = ap->a_vp;
441     upl_t pl = ap->a_pl;
442     size_t size = ap->a_size;
443     off_t f_offset = ap->a_f_offset;
444     vm_offset_t pl_offset = ap->a_pl_offset;
445     int flags = ap->a_flags;
446     struct ucred *cred;
447     vm_offset_t ioaddr;
448     struct uio auio;
449     struct iovec aiov;
450     struct uio *uio = &auio;
451     int nocommit = flags & UPL_NOCOMMIT;
452
453     int code;
454     struct vcache *tvc = VTOAFS(vp);
455
456     if (UBCINVALID(vp)) {
457 #if DIAGNOSTIC
458         panic("afs_vop_pagein: invalid vp");
459 #endif /* DIAGNOSTIC */
460         return (EPERM);
461     }
462
463     UBCINFOCHECK("afs_vop_pagein", vp);
464     if (pl == (upl_t) NULL) {
465         panic("afs_vop_pagein: no upl");
466     }
467
468     cred = ubc_getcred(vp);
469     if (cred == NOCRED)
470         cred = ap->a_cred;
471
472     if (size == 0) {
473         if (!nocommit)
474             kernel_upl_abort_range(pl, pl_offset, size,
475                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
476         return (0);
477     }
478     if (f_offset < 0) {
479         if (!nocommit)
480             kernel_upl_abort_range(pl, pl_offset, size,
481                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
482         return (EINVAL);
483     }
484     if (f_offset & PAGE_MASK)
485         panic("afs_vop_pagein: offset not page aligned");
486
487     auio.uio_iov = &aiov;
488     auio.uio_iovcnt = 1;
489     auio.uio_offset = f_offset;
490     auio.uio_segflg = UIO_SYSSPACE;
491     auio.uio_rw = UIO_READ;
492     auio.uio_procp = NULL;
493     kernel_upl_map(kernel_map, pl, &ioaddr);
494     ioaddr += pl_offset;
495     auio.uio_resid = aiov.iov_len = size;
496     aiov.iov_base = (caddr_t) ioaddr;
497     AFS_GLOCK();
498     afs_BozonLock(&tvc->pvnLock, tvc);
499     osi_FlushPages(tvc, ap->a_cred);    /* hold bozon lock, but not basic vnode lock */
500     code = afs_read(tvc, uio, cred, 0, 0, 0);
501     if (code == 0) {
502         ObtainWriteLock(&tvc->lock, 2);
503         tvc->states |= CMAPPED;
504         ReleaseWriteLock(&tvc->lock);
505     }
506     afs_BozonUnlock(&tvc->pvnLock, tvc);
507     AFS_GUNLOCK();
508
509     /* Zero out rest of last page if there wasn't enough data in the file */
510     if (code == 0 && auio.uio_resid > 0)
511         memset(aiov.iov_base, 0, auio.uio_resid);
512
513     kernel_upl_unmap(kernel_map, pl);
514     if (!nocommit) {
515         if (code)
516             kernel_upl_abort_range(pl, pl_offset, size,
517                                    UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
518         else
519             kernel_upl_commit_range(pl, pl_offset, size,
520                                     UPL_COMMIT_CLEAR_DIRTY |
521                                     UPL_COMMIT_FREE_ON_EMPTY,
522                                     UPL_GET_INTERNAL_PAGE_LIST(pl),
523                                     MAX_UPL_TRANSFER);
524     }
525     return code;
526 }
527
528 int
529 afs_vop_write(ap)
530      struct vop_write_args      /* {
531                                  * struct vnode *a_vp;
532                                  * struct uio *a_uio;
533                                  * int a_ioflag;
534                                  * struct ucred *a_cred;
535                                  * } */ *ap;
536 {
537     int code;
538     struct vcache *avc = VTOAFS(ap->a_vp);
539     void *object;
540     AFS_GLOCK();
541     afs_BozonLock(&avc->pvnLock, avc);
542     osi_FlushPages(avc, ap->a_cred);    /* hold bozon lock, but not basic vnode lock */
543     if (UBCINFOEXISTS(ap->a_vp))
544         ubc_clean(ap->a_vp, 1);
545     if (UBCINFOEXISTS(ap->a_vp))
546         osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset,
547                          ap->a_uio->uio_resid);
548     code =
549         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
550     afs_BozonUnlock(&avc->pvnLock, avc);
551     AFS_GUNLOCK();
552     return code;
553 }
554
555 int
556 afs_vop_pageout(ap)
557      struct vop_pageout_args    /* {
558                                  * struct vnode *a_vp;
559                                  * upl_t   a_pl,
560                                  * vm_offset_t   a_pl_offset,
561                                  * off_t         a_f_offset,
562                                  * size_t        a_size,
563                                  * struct ucred *a_cred,
564                                  * int           a_flags
565                                  * } */ *ap;
566 {
567     register struct vnode *vp = ap->a_vp;
568     upl_t pl = ap->a_pl;
569     size_t size = ap->a_size;
570     off_t f_offset = ap->a_f_offset;
571     vm_offset_t pl_offset = ap->a_pl_offset;
572     int flags = ap->a_flags;
573     struct ucred *cred;
574     vm_offset_t ioaddr;
575     struct uio auio;
576     struct iovec aiov;
577     struct uio *uio = &auio;
578     int nocommit = flags & UPL_NOCOMMIT;
579
580     int code;
581     struct vcache *tvc = VTOAFS(vp);
582
583     if (UBCINVALID(vp)) {
584 #if DIAGNOSTIC
585         panic("afs_vop_pageout: invalid vp");
586 #endif /* DIAGNOSTIC */
587         return (EPERM);
588     }
589
590     UBCINFOCHECK("afs_vop_pageout", vp);
591     if (pl == (upl_t) NULL) {
592         panic("afs_vop_pageout: no upl");
593     }
594 #if 1
595     {
596         int lbn, iosize, s;
597         struct buf *bp;
598         int biosize = DEV_BSIZE;
599
600         lbn = f_offset / DEV_BSIZE;
601
602         for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
603
604             s = splbio();
605             if (bp = incore(vp, lbn)) {
606                 if (ISSET(bp->b_flags, B_BUSY))
607                     panic("nfs_pageout: found BUSY buffer incore\n");
608
609                 bremfree(bp);
610                 SET(bp->b_flags, (B_BUSY | B_INVAL));
611                 brelse(bp);
612             }
613             splx(s);
614         }
615     }
616 #endif
617     cred = ubc_getcred(vp);
618     if (cred == NOCRED)
619         cred = ap->a_cred;
620
621     if (size == 0) {
622         if (!nocommit)
623             kernel_upl_abort_range(pl, pl_offset, size,
624                                    UPL_ABORT_FREE_ON_EMPTY);
625         return (0);
626     }
627     if (flags & (IO_APPEND | IO_SYNC))
628         panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
629     if (f_offset < 0) {
630         if (!nocommit)
631             kernel_upl_abort_range(pl, pl_offset, size,
632                                    UPL_ABORT_FREE_ON_EMPTY);
633         return (EINVAL);
634     }
635     if (f_offset >= tvc->m.Length) {
636         if (!nocommit)
637             kernel_upl_abort_range(pl, pl_offset, size,
638                                    UPL_ABORT_FREE_ON_EMPTY);
639         return (EINVAL);
640     }
641
642     if (f_offset & PAGE_MASK)
643         panic("afs_vop_pageout: offset not page aligned");
644
645     auio.uio_iov = &aiov;
646     auio.uio_iovcnt = 1;
647     auio.uio_offset = f_offset;
648     auio.uio_segflg = UIO_SYSSPACE;
649     auio.uio_rw = UIO_WRITE;
650     auio.uio_procp = NULL;
651     kernel_upl_map(kernel_map, pl, &ioaddr);
652     ioaddr += pl_offset;
653     auio.uio_resid = aiov.iov_len = size;
654     aiov.iov_base = (caddr_t) ioaddr;
655 #if 1                           /* USV [ */
656     {
657         /* 
658          * check for partial page and clear the
659          * contents past end of the file before
660          * releasing it in the VM page cache
661          */
662         if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
663             size_t io = tvc->m.Length - f_offset;
664
665             memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
666         }
667     }
668 #endif /* ] USV */
669
670     AFS_GLOCK();
671     afs_BozonLock(&tvc->pvnLock, tvc);
672     osi_FlushPages(tvc, ap->a_cred);    /* hold bozon lock, but not basic vnode lock */
673     ObtainWriteLock(&tvc->lock, 1);
674     afs_FakeOpen(tvc);
675     ReleaseWriteLock(&tvc->lock);
676
677     code = afs_write(tvc, uio, flags, cred, 0);
678
679     ObtainWriteLock(&tvc->lock, 1);
680     afs_FakeClose(tvc, cred);
681     ReleaseWriteLock(&tvc->lock);
682     afs_BozonUnlock(&tvc->pvnLock, tvc);
683     AFS_GUNLOCK();
684     kernel_upl_unmap(kernel_map, pl);
685     if (!nocommit) {
686         if (code)
687             kernel_upl_abort_range(pl, pl_offset, size,
688                                    UPL_ABORT_FREE_ON_EMPTY);
689         else
690             kernel_upl_commit_range(pl, pl_offset, size,
691                                     UPL_COMMIT_CLEAR_DIRTY |
692                                     UPL_COMMIT_FREE_ON_EMPTY,
693                                     UPL_GET_INTERNAL_PAGE_LIST(pl),
694                                     MAX_UPL_TRANSFER);
695     }
696
697     return code;
698 }
699
700 int
701 afs_vop_ioctl(ap)
702      struct vop_ioctl_args      /* {
703                                  * struct vnode *a_vp;
704                                  * int  a_command;
705                                  * caddr_t  a_data;
706                                  * int  a_fflag;
707                                  * struct ucred *a_cred;
708                                  * struct proc *a_p;
709                                  * } */ *ap;
710 {
711     struct vcache *tvc = VTOAFS(ap->a_vp);
712     struct afs_ioctl data;
713     int error = 0;
714
715     /* in case we ever get in here... */
716
717     AFS_STATCNT(afs_ioctl);
718     if (((ap->a_command >> 8) & 0xff) == 'V') {
719         /* This is a VICEIOCTL call */
720         AFS_GLOCK();
721         error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
722                             ap->a_command, ap->a_data);
723         AFS_GUNLOCK();
724         return (error);
725     } else {
726         /* No-op call; just return. */
727         return (ENOTTY);
728     }
729 }
730
731 /* ARGSUSED */
732 int
733 afs_vop_select(ap)
734      struct vop_select_args     /* {
735                                  * struct vnode *a_vp;
736                                  * int  a_which;
737                                  * int  a_fflags;
738                                  * struct ucred *a_cred;
739                                  * struct proc *a_p;
740                                  * } */ *ap;
741 {
742     /*
743      * We should really check to see if I/O is possible.
744      */
745     return (1);
746 }
747
748 /*
749  * Mmap a file
750  *
751  * NB Currently unsupported.
752  */
753 /* ARGSUSED */
754 int
755 afs_vop_mmap(ap)
756      struct vop_mmap_args       /* {
757                                  * struct vnode *a_vp;
758                                  * int  a_fflags;
759                                  * struct ucred *a_cred;
760                                  * struct proc *a_p;
761                                  * } */ *ap;
762 {
763     return (EINVAL);
764 }
765
766 int
767 afs_vop_fsync(ap)
768      struct vop_fsync_args      /* {
769                                  * struct vnode *a_vp;
770                                  * struct ucred *a_cred;
771                                  * int a_waitfor;
772                                  * struct proc *a_p;
773                                  * } */ *ap;
774 {
775     int wait = ap->a_waitfor == MNT_WAIT;
776     int error;
777     register struct vnode *vp = ap->a_vp;
778
779     AFS_GLOCK();
780     /*vflushbuf(vp, wait); */
781     if (ap->a_cred)
782         error = afs_fsync(VTOAFS(vp), ap->a_cred);
783     else
784         error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
785     AFS_GUNLOCK();
786     return error;
787 }
788
789 int
790 afs_vop_seek(ap)
791      struct vop_seek_args       /* {
792                                  * struct vnode *a_vp;
793                                  * off_t  a_oldoff;
794                                  * off_t  a_newoff;
795                                  * struct ucred *a_cred;
796                                  * } */ *ap;
797 {
798     if (ap->a_newoff > ULONG_MAX)       /* AFS doesn't support 64-bit offsets */
799         return EINVAL;
800     return (0);
801 }
802
803 int
804 afs_vop_remove(ap)
805      struct vop_remove_args     /* {
806                                  * struct vnode *a_dvp;
807                                  * struct vnode *a_vp;
808                                  * struct componentname *a_cnp;
809                                  * } */ *ap;
810 {
811     int error = 0;
812     register struct vnode *vp = ap->a_vp;
813     register struct vnode *dvp = ap->a_dvp;
814
815     GETNAME();
816     AFS_GLOCK();
817     error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
818     AFS_GUNLOCK();
819     cache_purge(vp);
820     if (!error && UBCINFOEXISTS(vp)) {
821 #ifdef AFS_DARWIN14_ENV
822         (void)ubc_uncache(vp);
823 #else
824         int wasmapped = ubc_issetflags(vp, UI_WASMAPPED);
825         int hasobjref = ubc_issetflags(vp, UI_HASOBJREF);
826         if (wasmapped)
827             (void)ubc_uncache(vp);
828         if (hasobjref)
829             ubc_release(vp);
830         /* WARNING vp may not be valid after this */
831 #endif
832     }
833     if (dvp == vp)
834         vrele(vp);
835     else
836         vput(vp);
837     vput(dvp);
838
839     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
840     DROPNAME();
841     return error;
842 }
843
844 int
845 afs_vop_link(ap)
846      struct vop_link_args       /* {
847                                  * struct vnode *a_vp;
848                                  * struct vnode *a_tdvp;
849                                  * struct componentname *a_cnp;
850                                  * } */ *ap;
851 {
852     int error = 0;
853     register struct vnode *dvp = ap->a_tdvp;
854     register struct vnode *vp = ap->a_vp;
855     struct proc *p;
856
857     GETNAME();
858     p = cnp->cn_proc;
859     if (vp->v_type == VDIR) {
860         VOP_ABORTOP(vp, cnp);
861         error = EISDIR;
862         goto out;
863     }
864     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
865         VOP_ABORTOP(dvp, cnp);
866         goto out;
867     }
868     AFS_GLOCK();
869     error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
870     AFS_GUNLOCK();
871     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
872     if (dvp != vp)
873         VOP_UNLOCK(vp, 0, p);
874   out:
875     vput(dvp);
876     DROPNAME();
877     return error;
878 }
879
880 int
881 afs_vop_rename(ap)
882      struct vop_rename_args     /* {
883                                  * struct vnode *a_fdvp;
884                                  * struct vnode *a_fvp;
885                                  * struct componentname *a_fcnp;
886                                  * struct vnode *a_tdvp;
887                                  * struct vnode *a_tvp;
888                                  * struct componentname *a_tcnp;
889                                  * } */ *ap;
890 {
891     int error = 0;
892     struct componentname *fcnp = ap->a_fcnp;
893     char *fname;
894     struct componentname *tcnp = ap->a_tcnp;
895     char *tname;
896     struct vnode *tvp = ap->a_tvp;
897     register struct vnode *tdvp = ap->a_tdvp;
898     struct vnode *fvp = ap->a_fvp;
899     register struct vnode *fdvp = ap->a_fdvp;
900     struct proc *p = fcnp->cn_proc;
901
902         /* Check for cross-device rename.
903          * For AFS, this means anything not in AFS-space
904          */
905         if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
906                 (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
907                         error = EXDEV;
908                         goto abortit;
909         }
910
911     /*
912      * if fvp == tvp, we're just removing one name of a pair of
913      * directory entries for the same element.  convert call into rename.
914      ( (pinched from NetBSD 1.0's ufs_rename())
915      */
916     if (fvp == tvp) {
917         if (fvp->v_type == VDIR) {
918             error = EINVAL;
919           abortit:
920             VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
921             if (tdvp == tvp)
922                 vrele(tdvp);
923             else
924                 vput(tdvp);
925             if (tvp)
926                 vput(tvp);
927             VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
928             vrele(fdvp);
929             vrele(fvp);
930             return (error);
931         }
932
933         /* Release destination completely. */
934         VOP_ABORTOP(tdvp, tcnp);
935         vput(tdvp);
936         vput(tvp);
937
938         /* Delete source. */
939         vrele(fdvp);
940         vrele(fvp);
941         fcnp->cn_flags &= ~MODMASK;
942         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
943         if ((fcnp->cn_flags & SAVESTART) == 0)
944             panic("afs_rename: lost from startdir");
945         fcnp->cn_nameiop = DELETE;
946         (void)relookup(fdvp, &fvp, fcnp);
947         return (VOP_REMOVE(fdvp, fvp, fcnp));
948     }
949     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
950         goto abortit;
951
952     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
953     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
954     fname[fcnp->cn_namelen] = '\0';
955     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
956     memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
957     tname[tcnp->cn_namelen] = '\0';
958
959
960     AFS_GLOCK();
961     /* XXX use "from" or "to" creds? NFS uses "to" creds */
962     error =
963         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
964     AFS_GUNLOCK();
965
966     VOP_UNLOCK(fvp, 0, p);
967     FREE(fname, M_TEMP);
968     FREE(tname, M_TEMP);
969     if (error)
970         goto abortit;           /* XXX */
971     if (tdvp == tvp)
972         vrele(tdvp);
973     else
974         vput(tdvp);
975     if (tvp)
976         vput(tvp);
977     vrele(fdvp);
978     vrele(fvp);
979     return error;
980 }
981
982 int
983 afs_vop_mkdir(ap)
984      struct vop_mkdir_args      /* {
985                                  * struct vnode *a_dvp;
986                                  * struct vnode **a_vpp;
987                                  * struct componentname *a_cnp;
988                                  * struct vattr *a_vap;
989                                  * } */ *ap;
990 {
991     register struct vnode *dvp = ap->a_dvp;
992     register struct vattr *vap = ap->a_vap;
993     int error = 0;
994     struct vcache *vcp;
995     struct proc *p;
996
997     GETNAME();
998     p = cnp->cn_proc;
999 #ifdef DIAGNOSTIC
1000     if ((cnp->cn_flags & HASBUF) == 0)
1001         panic("afs_vop_mkdir: no name");
1002 #endif
1003     AFS_GLOCK();
1004     error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
1005     AFS_GUNLOCK();
1006     if (error) {
1007         VOP_ABORTOP(dvp, cnp);
1008         vput(dvp);
1009         DROPNAME();
1010         return (error);
1011     }
1012     if (vcp) {
1013         *ap->a_vpp = AFSTOV(vcp);
1014         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
1015         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
1016     } else
1017         *ap->a_vpp = 0;
1018     DROPNAME();
1019     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1020     vput(dvp);
1021     return error;
1022 }
1023
1024 int
1025 afs_vop_rmdir(ap)
1026      struct vop_rmdir_args      /* {
1027                                  * struct vnode *a_dvp;
1028                                  * struct vnode *a_vp;
1029                                  * struct componentname *a_cnp;
1030                                  * } */ *ap;
1031 {
1032     int error = 0;
1033     register struct vnode *vp = ap->a_vp;
1034     register struct vnode *dvp = ap->a_dvp;
1035
1036     GETNAME();
1037     if (dvp == vp) {
1038         vrele(dvp);
1039         vput(vp);
1040         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1041         DROPNAME();
1042         return (EINVAL);
1043     }
1044
1045     AFS_GLOCK();
1046     error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
1047     AFS_GUNLOCK();
1048     DROPNAME();
1049     vput(dvp);
1050     vput(vp);
1051     return error;
1052 }
1053
1054 int
1055 afs_vop_symlink(ap)
1056      struct vop_symlink_args    /* {
1057                                  * struct vnode *a_dvp;
1058                                  * struct vnode **a_vpp;
1059                                  * struct componentname *a_cnp;
1060                                  * struct vattr *a_vap;
1061                                  * char *a_target;
1062                                  * } */ *ap;
1063 {
1064     register struct vnode *dvp = ap->a_dvp;
1065     int error = 0;
1066     /* NFS ignores a_vpp; so do we. */
1067
1068     GETNAME();
1069     AFS_GLOCK();
1070     error =
1071         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
1072     AFS_GUNLOCK();
1073     DROPNAME();
1074     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1075     vput(dvp);
1076     return error;
1077 }
1078
1079 int
1080 afs_vop_readdir(ap)
1081      struct vop_readdir_args    /* {
1082                                  * struct vnode *a_vp;
1083                                  * struct uio *a_uio;
1084                                  * struct ucred *a_cred;
1085                                  * int *a_eofflag;
1086                                  * u_long *a_cookies;
1087                                  * int ncookies;
1088                                  * } */ *ap;
1089 {
1090     int error;
1091     off_t off;
1092 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1093            ap->a_ncookies); */
1094     off = ap->a_uio->uio_offset;
1095     AFS_GLOCK();
1096     error =
1097         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
1098     AFS_GUNLOCK();
1099     if (!error && ap->a_ncookies != NULL) {
1100         struct uio *uio = ap->a_uio;
1101         const struct dirent *dp, *dp_start, *dp_end;
1102         int ncookies;
1103         u_long *cookies, *cookiep;
1104
1105         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1106             panic("afs_readdir: burned cookies");
1107         dp = (const struct dirent *)
1108             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1109
1110         dp_end = (const struct dirent *)uio->uio_iov->iov_base;
1111         for (dp_start = dp, ncookies = 0; dp < dp_end;
1112              dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
1113             ncookies++;
1114
1115         MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1116                M_WAITOK);
1117         for (dp = dp_start, cookiep = cookies; dp < dp_end;
1118              dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
1119             off += dp->d_reclen;
1120             *cookiep++ = off;
1121         }
1122         *ap->a_cookies = cookies;
1123         *ap->a_ncookies = ncookies;
1124     }
1125
1126     return error;
1127 }
1128
1129 int
1130 afs_vop_readlink(ap)
1131      struct vop_readlink_args   /* {
1132                                  * struct vnode *a_vp;
1133                                  * struct uio *a_uio;
1134                                  * struct ucred *a_cred;
1135                                  * } */ *ap;
1136 {
1137     int error;
1138 /*    printf("readlink %x\n", ap->a_vp);*/
1139     AFS_GLOCK();
1140     error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1141     AFS_GUNLOCK();
1142     return error;
1143 }
1144
1145 extern int prtactive;
1146
1147 int
1148 afs_vop_inactive(ap)
1149      struct vop_inactive_args   /* {
1150                                  * struct vnode *a_vp;
1151                                  * struct proc *a_p;
1152                                  * } */ *ap;
1153 {
1154     register struct vnode *vp = ap->a_vp;
1155
1156     if (prtactive && vp->v_usecount != 0)
1157         vprint("afs_vop_inactive(): pushing active", vp);
1158
1159     AFS_GLOCK();
1160     afs_InactiveVCache(VTOAFS(vp), 0);  /* decrs ref counts */
1161     AFS_GUNLOCK();
1162     VOP_UNLOCK(vp, 0, ap->a_p);
1163     return 0;
1164 }
1165
1166 int
1167 afs_vop_reclaim(ap)
1168      struct vop_reclaim_args    /* {
1169                                  * struct vnode *a_vp;
1170                                  * } */ *ap;
1171 {
1172     int error;
1173     int sl;
1174     register struct vnode *vp = ap->a_vp;
1175
1176     cache_purge(vp);            /* just in case... */
1177
1178 #if 0
1179     AFS_GLOCK();
1180     error = afs_FlushVCache(VTOAFS(vp), &sl);   /* tosses our stuff from vnode */
1181     AFS_GUNLOCK();
1182     ubc_unlink(vp);
1183     if (!error && vp->v_data)
1184         panic("afs_reclaim: vnode not cleaned");
1185     return error;
1186 #else
1187     if (vp->v_usecount == 2) {
1188         vprint("reclaim count==2", vp);
1189     } else if (vp->v_usecount == 1) {
1190         vprint("reclaim count==1", vp);
1191     } else
1192         vprint("reclaim bad count", vp);
1193
1194     return 0;
1195 #endif
1196 }
1197
1198 int
1199 afs_vop_lock(ap)
1200      struct vop_lock_args       /* {
1201                                  * struct vnode *a_vp;
1202                                  * } */ *ap;
1203 {
1204     register struct vnode *vp = ap->a_vp;
1205     register struct vcache *avc = VTOAFS(vp);
1206
1207     if (vp->v_tag == VT_NON)
1208         return (ENOENT);
1209     return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1210 }
1211
1212 int
1213 afs_vop_unlock(ap)
1214      struct vop_unlock_args     /* {
1215                                  * struct vnode *a_vp;
1216                                  * } */ *ap;
1217 {
1218     struct vnode *vp = ap->a_vp;
1219     struct vcache *avc = VTOAFS(vp);
1220     return (lockmgr
1221             (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1222              ap->a_p));
1223
1224 }
1225
1226 int
1227 afs_vop_bmap(ap)
1228      struct vop_bmap_args       /* {
1229                                  * struct vnode *a_vp;
1230                                  * daddr_t  a_bn;
1231                                  * struct vnode **a_vpp;
1232                                  * daddr_t *a_bnp;
1233                                  * int *a_runp;
1234                                  * int *a_runb;
1235                                  * } */ *ap;
1236 {
1237     struct vcache *vcp;
1238     int error;
1239     if (ap->a_bnp) {
1240         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1241     }
1242     if (ap->a_vpp) {
1243         *ap->a_vpp = ap->a_vp;
1244     }
1245     if (ap->a_runp != NULL)
1246         *ap->a_runp = 0;
1247 #ifdef notyet
1248     if (ap->a_runb != NULL)
1249         *ap->a_runb = 0;
1250 #endif
1251
1252     return 0;
1253 }
1254
1255 int
1256 afs_vop_strategy(ap)
1257      struct vop_strategy_args   /* {
1258                                  * struct buf *a_bp;
1259                                  * } */ *ap;
1260 {
1261     int error;
1262     AFS_GLOCK();
1263     error = afs_ustrategy(ap->a_bp);
1264     AFS_GUNLOCK();
1265     return error;
1266 }
1267
1268 int
1269 afs_vop_print(ap)
1270      struct vop_print_args      /* {
1271                                  * struct vnode *a_vp;
1272                                  * } */ *ap;
1273 {
1274     register struct vnode *vp = ap->a_vp;
1275     register struct vcache *vc = VTOAFS(ap->a_vp);
1276     int s = vc->states;
1277     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
1278            vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
1279            vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
1280     printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
1281            (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
1282            (s & CMAPPED) ? " mapped" : "",
1283            (s & CVFlushed) ? " flush in progress" : "");
1284     if (UBCISVALID(vp)) {
1285         printf("\n  UBC: ");
1286         if (UBCINFOEXISTS(vp)) {
1287             printf("exists, ");
1288 #ifdef AFS_DARWIN14_ENV
1289             printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1290                    ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1291                    ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1292 #else
1293             printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1294 #endif
1295         } else
1296             printf("does not exist");
1297     }
1298     printf("\n");
1299     return 0;
1300 }
1301
1302 int
1303 afs_vop_islocked(ap)
1304      struct vop_islocked_args   /* {
1305                                  * struct vnode *a_vp;
1306                                  * } */ *ap;
1307 {
1308     struct vcache *vc = VTOAFS(ap->a_vp);
1309     return lockstatus(&vc->rwlock);
1310 }
1311
1312 /*
1313  * Return POSIX pathconf information applicable to ufs filesystems.
1314  */
1315 afs_vop_pathconf(ap)
1316      struct vop_pathconf_args   /* {
1317                                  * struct vnode *a_vp;
1318                                  * int a_name;
1319                                  * int *a_retval;
1320                                  * } */ *ap;
1321 {
1322     AFS_STATCNT(afs_cntl);
1323     switch (ap->a_name) {
1324     case _PC_LINK_MAX:
1325         *ap->a_retval = LINK_MAX;
1326         break;
1327     case _PC_NAME_MAX:
1328         *ap->a_retval = NAME_MAX;
1329         break;
1330     case _PC_PATH_MAX:
1331         *ap->a_retval = PATH_MAX;
1332         break;
1333     case _PC_CHOWN_RESTRICTED:
1334         *ap->a_retval = 1;
1335         break;
1336     case _PC_NO_TRUNC:
1337         *ap->a_retval = 1;
1338         break;
1339     case _PC_PIPE_BUF:
1340         return EINVAL;
1341         break;
1342 #if defined(AFS_DARWIN70_ENV)
1343     case _PC_NAME_CHARS_MAX:
1344         *ap->a_retval = NAME_MAX;
1345         break;
1346     case _PC_CASE_SENSITIVE:
1347         *ap->a_retval = 1;
1348         break;
1349     case _PC_CASE_PRESERVING:
1350         *ap->a_retval = 1;
1351         break;
1352 #endif /* defined(AFS_DARWIN70_ENV) */
1353     default:
1354         return EINVAL;
1355     }
1356     return 0;
1357 }
1358
1359 /*
1360  * Advisory record locking support (fcntl() POSIX style)
1361  */
1362 int
1363 afs_vop_advlock(ap)
1364      struct vop_advlock_args    /* {
1365                                  * struct vnode *a_vp;
1366                                  * caddr_t  a_id;
1367                                  * int  a_op;
1368                                  * struct flock *a_fl;
1369                                  * int  a_flags;
1370                                  * } */ *ap;
1371 {
1372     int error;
1373     struct proc *p = current_proc();
1374     struct ucred cr;
1375     pcred_readlock(p);
1376     cr = *p->p_cred->pc_ucred;
1377     pcred_unlock(p);
1378     AFS_GLOCK();
1379     error =
1380         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
1381     AFS_GUNLOCK();
1382     return error;
1383 }
1384
1385 int
1386 afs_vop_truncate(ap)
1387      struct vop_truncate_args   /* {
1388                                  * struct vnode *a_vp;
1389                                  * off_t a_length;
1390                                  * int a_flags;
1391                                  * struct ucred *a_cred;
1392                                  * struct proc *a_p;
1393                                  * } */ *ap;
1394 {
1395     printf("stray afs_vop_truncate\n");
1396     return EOPNOTSUPP;
1397 }
1398
1399 int
1400 afs_vop_update(ap)
1401      struct vop_update_args     /* {
1402                                  * struct vnode *a_vp;
1403                                  * struct timeval *a_access;
1404                                  * struct timeval *a_modify;
1405                                  * int a_waitfor;
1406                                  * } */ *ap;
1407 {
1408     printf("stray afs_vop_update\n");
1409     return EOPNOTSUPP;
1410 }
1411
1412 int
1413 afs_vop_blktooff(ap)
1414      struct vop_blktooff_args   /* {
1415                                  * struct vnode *a_vp;
1416                                  * daddr_t a_lblkno;
1417                                  * off_t *a_offset;    
1418                                  * } */ *ap;
1419 {
1420     *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1421     return 0;
1422 }
1423
1424 int
1425 afs_vop_offtoblk(ap)
1426      struct vop_offtoblk_args   /* {
1427                                  * struct vnode *a_vp;
1428                                  * off_t a_offset;    
1429                                  * daddr_t *a_lblkno;
1430                                  * } */ *ap;
1431 {
1432     *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1433
1434     return (0);
1435 }
1436
1437 int
1438 afs_vop_cmap(ap)
1439      struct vop_cmap_args       /* {
1440                                  * struct vnode *a_vp;
1441                                  * off_t a_foffset;    
1442                                  * size_t a_size;
1443                                  * daddr_t *a_bpn;
1444                                  * size_t *a_run;
1445                                  * void *a_poff;
1446                                  * } */ *ap;
1447 {
1448     *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1449     *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1450     return 0;
1451 }