macos103-20031024
[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     /*
903      * if fvp == tvp, we're just removing one name of a pair of
904      * directory entries for the same element.  convert call into rename.
905      ( (pinched from NetBSD 1.0's ufs_rename())
906      */
907     if (fvp == tvp) {
908         if (fvp->v_type == VDIR) {
909             error = EINVAL;
910           abortit:
911             VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
912             if (tdvp == tvp)
913                 vrele(tdvp);
914             else
915                 vput(tdvp);
916             if (tvp)
917                 vput(tvp);
918             VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
919             vrele(fdvp);
920             vrele(fvp);
921             return (error);
922         }
923
924         /* Release destination completely. */
925         VOP_ABORTOP(tdvp, tcnp);
926         vput(tdvp);
927         vput(tvp);
928
929         /* Delete source. */
930         vrele(fdvp);
931         vrele(fvp);
932         fcnp->cn_flags &= ~MODMASK;
933         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
934         if ((fcnp->cn_flags & SAVESTART) == 0)
935             panic("afs_rename: lost from startdir");
936         fcnp->cn_nameiop = DELETE;
937         (void)relookup(fdvp, &fvp, fcnp);
938         return (VOP_REMOVE(fdvp, fvp, fcnp));
939     }
940     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
941         goto abortit;
942
943     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
944     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
945     fname[fcnp->cn_namelen] = '\0';
946     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
947     memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
948     tname[tcnp->cn_namelen] = '\0';
949
950
951     AFS_GLOCK();
952     /* XXX use "from" or "to" creds? NFS uses "to" creds */
953     error =
954         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
955     AFS_GUNLOCK();
956
957     VOP_UNLOCK(fvp, 0, p);
958     FREE(fname, M_TEMP);
959     FREE(tname, M_TEMP);
960     if (error)
961         goto abortit;           /* XXX */
962     if (tdvp == tvp)
963         vrele(tdvp);
964     else
965         vput(tdvp);
966     if (tvp)
967         vput(tvp);
968     vrele(fdvp);
969     vrele(fvp);
970     return error;
971 }
972
973 int
974 afs_vop_mkdir(ap)
975      struct vop_mkdir_args      /* {
976                                  * struct vnode *a_dvp;
977                                  * struct vnode **a_vpp;
978                                  * struct componentname *a_cnp;
979                                  * struct vattr *a_vap;
980                                  * } */ *ap;
981 {
982     register struct vnode *dvp = ap->a_dvp;
983     register struct vattr *vap = ap->a_vap;
984     int error = 0;
985     struct vcache *vcp;
986     struct proc *p;
987
988     GETNAME();
989     p = cnp->cn_proc;
990 #ifdef DIAGNOSTIC
991     if ((cnp->cn_flags & HASBUF) == 0)
992         panic("afs_vop_mkdir: no name");
993 #endif
994     AFS_GLOCK();
995     error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
996     AFS_GUNLOCK();
997     if (error) {
998         VOP_ABORTOP(dvp, cnp);
999         vput(dvp);
1000         DROPNAME();
1001         return (error);
1002     }
1003     if (vcp) {
1004         *ap->a_vpp = AFSTOV(vcp);
1005         (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
1006         vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
1007     } else
1008         *ap->a_vpp = 0;
1009     DROPNAME();
1010     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1011     vput(dvp);
1012     return error;
1013 }
1014
1015 int
1016 afs_vop_rmdir(ap)
1017      struct vop_rmdir_args      /* {
1018                                  * struct vnode *a_dvp;
1019                                  * struct vnode *a_vp;
1020                                  * struct componentname *a_cnp;
1021                                  * } */ *ap;
1022 {
1023     int error = 0;
1024     register struct vnode *vp = ap->a_vp;
1025     register struct vnode *dvp = ap->a_dvp;
1026
1027     GETNAME();
1028     if (dvp == vp) {
1029         vrele(dvp);
1030         vput(vp);
1031         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1032         DROPNAME();
1033         return (EINVAL);
1034     }
1035
1036     AFS_GLOCK();
1037     error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
1038     AFS_GUNLOCK();
1039     DROPNAME();
1040     vput(dvp);
1041     vput(vp);
1042     return error;
1043 }
1044
1045 int
1046 afs_vop_symlink(ap)
1047      struct vop_symlink_args    /* {
1048                                  * struct vnode *a_dvp;
1049                                  * struct vnode **a_vpp;
1050                                  * struct componentname *a_cnp;
1051                                  * struct vattr *a_vap;
1052                                  * char *a_target;
1053                                  * } */ *ap;
1054 {
1055     register struct vnode *dvp = ap->a_dvp;
1056     int error = 0;
1057     /* NFS ignores a_vpp; so do we. */
1058
1059     GETNAME();
1060     AFS_GLOCK();
1061     error =
1062         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
1063     AFS_GUNLOCK();
1064     DROPNAME();
1065     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1066     vput(dvp);
1067     return error;
1068 }
1069
1070 int
1071 afs_vop_readdir(ap)
1072      struct vop_readdir_args    /* {
1073                                  * struct vnode *a_vp;
1074                                  * struct uio *a_uio;
1075                                  * struct ucred *a_cred;
1076                                  * int *a_eofflag;
1077                                  * u_long *a_cookies;
1078                                  * int ncookies;
1079                                  * } */ *ap;
1080 {
1081     int error;
1082     off_t off;
1083 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1084            ap->a_ncookies); */
1085     off = ap->a_uio->uio_offset;
1086     AFS_GLOCK();
1087     error =
1088         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
1089     AFS_GUNLOCK();
1090     if (!error && ap->a_ncookies != NULL) {
1091         struct uio *uio = ap->a_uio;
1092         const struct dirent *dp, *dp_start, *dp_end;
1093         int ncookies;
1094         u_long *cookies, *cookiep;
1095
1096         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1097             panic("afs_readdir: burned cookies");
1098         dp = (const struct dirent *)
1099             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1100
1101         dp_end = (const struct dirent *)uio->uio_iov->iov_base;
1102         for (dp_start = dp, ncookies = 0; dp < dp_end;
1103              dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
1104             ncookies++;
1105
1106         MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1107                M_WAITOK);
1108         for (dp = dp_start, cookiep = cookies; dp < dp_end;
1109              dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
1110             off += dp->d_reclen;
1111             *cookiep++ = off;
1112         }
1113         *ap->a_cookies = cookies;
1114         *ap->a_ncookies = ncookies;
1115     }
1116
1117     return error;
1118 }
1119
1120 int
1121 afs_vop_readlink(ap)
1122      struct vop_readlink_args   /* {
1123                                  * struct vnode *a_vp;
1124                                  * struct uio *a_uio;
1125                                  * struct ucred *a_cred;
1126                                  * } */ *ap;
1127 {
1128     int error;
1129 /*    printf("readlink %x\n", ap->a_vp);*/
1130     AFS_GLOCK();
1131     error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1132     AFS_GUNLOCK();
1133     return error;
1134 }
1135
1136 extern int prtactive;
1137
1138 int
1139 afs_vop_inactive(ap)
1140      struct vop_inactive_args   /* {
1141                                  * struct vnode *a_vp;
1142                                  * struct proc *a_p;
1143                                  * } */ *ap;
1144 {
1145     register struct vnode *vp = ap->a_vp;
1146
1147     if (prtactive && vp->v_usecount != 0)
1148         vprint("afs_vop_inactive(): pushing active", vp);
1149
1150     AFS_GLOCK();
1151     afs_InactiveVCache(VTOAFS(vp), 0);  /* decrs ref counts */
1152     AFS_GUNLOCK();
1153     VOP_UNLOCK(vp, 0, ap->a_p);
1154     return 0;
1155 }
1156
1157 int
1158 afs_vop_reclaim(ap)
1159      struct vop_reclaim_args    /* {
1160                                  * struct vnode *a_vp;
1161                                  * } */ *ap;
1162 {
1163     int error;
1164     int sl;
1165     register struct vnode *vp = ap->a_vp;
1166
1167     cache_purge(vp);            /* just in case... */
1168
1169 #if 0
1170     AFS_GLOCK();
1171     error = afs_FlushVCache(VTOAFS(vp), &sl);   /* tosses our stuff from vnode */
1172     AFS_GUNLOCK();
1173     ubc_unlink(vp);
1174     if (!error && vp->v_data)
1175         panic("afs_reclaim: vnode not cleaned");
1176     return error;
1177 #else
1178     if (vp->v_usecount == 2) {
1179         vprint("reclaim count==2", vp);
1180     } else if (vp->v_usecount == 1) {
1181         vprint("reclaim count==1", vp);
1182     } else
1183         vprint("reclaim bad count", vp);
1184
1185     return 0;
1186 #endif
1187 }
1188
1189 int
1190 afs_vop_lock(ap)
1191      struct vop_lock_args       /* {
1192                                  * struct vnode *a_vp;
1193                                  * } */ *ap;
1194 {
1195     register struct vnode *vp = ap->a_vp;
1196     register struct vcache *avc = VTOAFS(vp);
1197
1198     if (vp->v_tag == VT_NON)
1199         return (ENOENT);
1200     return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1201 }
1202
1203 int
1204 afs_vop_unlock(ap)
1205      struct vop_unlock_args     /* {
1206                                  * struct vnode *a_vp;
1207                                  * } */ *ap;
1208 {
1209     struct vnode *vp = ap->a_vp;
1210     struct vcache *avc = VTOAFS(vp);
1211     return (lockmgr
1212             (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1213              ap->a_p));
1214
1215 }
1216
1217 int
1218 afs_vop_bmap(ap)
1219      struct vop_bmap_args       /* {
1220                                  * struct vnode *a_vp;
1221                                  * daddr_t  a_bn;
1222                                  * struct vnode **a_vpp;
1223                                  * daddr_t *a_bnp;
1224                                  * int *a_runp;
1225                                  * int *a_runb;
1226                                  * } */ *ap;
1227 {
1228     struct vcache *vcp;
1229     int error;
1230     if (ap->a_bnp) {
1231         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1232     }
1233     if (ap->a_vpp) {
1234         *ap->a_vpp = ap->a_vp;
1235     }
1236     if (ap->a_runp != NULL)
1237         *ap->a_runp = 0;
1238 #ifdef notyet
1239     if (ap->a_runb != NULL)
1240         *ap->a_runb = 0;
1241 #endif
1242
1243     return 0;
1244 }
1245
1246 int
1247 afs_vop_strategy(ap)
1248      struct vop_strategy_args   /* {
1249                                  * struct buf *a_bp;
1250                                  * } */ *ap;
1251 {
1252     int error;
1253     AFS_GLOCK();
1254     error = afs_ustrategy(ap->a_bp);
1255     AFS_GUNLOCK();
1256     return error;
1257 }
1258
1259 int
1260 afs_vop_print(ap)
1261      struct vop_print_args      /* {
1262                                  * struct vnode *a_vp;
1263                                  * } */ *ap;
1264 {
1265     register struct vnode *vp = ap->a_vp;
1266     register struct vcache *vc = VTOAFS(ap->a_vp);
1267     int s = vc->states;
1268     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
1269            vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
1270            vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
1271     printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
1272            (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
1273            (s & CMAPPED) ? " mapped" : "",
1274            (s & CVFlushed) ? " flush in progress" : "");
1275     if (UBCISVALID(vp)) {
1276         printf("\n  UBC: ");
1277         if (UBCINFOEXISTS(vp)) {
1278             printf("exists, ");
1279 #ifdef AFS_DARWIN14_ENV
1280             printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1281                    ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1282                    ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1283 #else
1284             printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1285 #endif
1286         } else
1287             printf("does not exist");
1288     }
1289     printf("\n");
1290     return 0;
1291 }
1292
1293 int
1294 afs_vop_islocked(ap)
1295      struct vop_islocked_args   /* {
1296                                  * struct vnode *a_vp;
1297                                  * } */ *ap;
1298 {
1299     struct vcache *vc = VTOAFS(ap->a_vp);
1300     return lockstatus(&vc->rwlock);
1301 }
1302
1303 /*
1304  * Return POSIX pathconf information applicable to ufs filesystems.
1305  */
1306 afs_vop_pathconf(ap)
1307      struct vop_pathconf_args   /* {
1308                                  * struct vnode *a_vp;
1309                                  * int a_name;
1310                                  * int *a_retval;
1311                                  * } */ *ap;
1312 {
1313     AFS_STATCNT(afs_cntl);
1314     switch (ap->a_name) {
1315     case _PC_LINK_MAX:
1316         *ap->a_retval = LINK_MAX;
1317         break;
1318     case _PC_NAME_MAX:
1319         *ap->a_retval = NAME_MAX;
1320         break;
1321     case _PC_PATH_MAX:
1322         *ap->a_retval = PATH_MAX;
1323         break;
1324     case _PC_CHOWN_RESTRICTED:
1325         *ap->a_retval = 1;
1326         break;
1327     case _PC_NO_TRUNC:
1328         *ap->a_retval = 1;
1329         break;
1330     case _PC_PIPE_BUF:
1331         return EINVAL;
1332         break;
1333 #if defined(AFS_DARWIN70_ENV)
1334     case _PC_NAME_CHARS_MAX:
1335         *ap->a_retval = NAME_MAX;
1336         break;
1337     case _PC_CASE_SENSITIVE:
1338         *ap->a_retval = 1;
1339         break;
1340     case _PC_CASE_PRESERVING:
1341         *ap->a_retval = 1;
1342         break;
1343 #endif /* defined(AFS_DARWIN70_ENV) */
1344     default:
1345         return EINVAL;
1346     }
1347     return 0;
1348 }
1349
1350 /*
1351  * Advisory record locking support (fcntl() POSIX style)
1352  */
1353 int
1354 afs_vop_advlock(ap)
1355      struct vop_advlock_args    /* {
1356                                  * struct vnode *a_vp;
1357                                  * caddr_t  a_id;
1358                                  * int  a_op;
1359                                  * struct flock *a_fl;
1360                                  * int  a_flags;
1361                                  * } */ *ap;
1362 {
1363     int error;
1364     struct proc *p = current_proc();
1365     struct ucred cr;
1366     pcred_readlock(p);
1367     cr = *p->p_cred->pc_ucred;
1368     pcred_unlock(p);
1369     AFS_GLOCK();
1370     error =
1371         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
1372     AFS_GUNLOCK();
1373     return error;
1374 }
1375
1376 int
1377 afs_vop_truncate(ap)
1378      struct vop_truncate_args   /* {
1379                                  * struct vnode *a_vp;
1380                                  * off_t a_length;
1381                                  * int a_flags;
1382                                  * struct ucred *a_cred;
1383                                  * struct proc *a_p;
1384                                  * } */ *ap;
1385 {
1386     printf("stray afs_vop_truncate\n");
1387     return EOPNOTSUPP;
1388 }
1389
1390 int
1391 afs_vop_update(ap)
1392      struct vop_update_args     /* {
1393                                  * struct vnode *a_vp;
1394                                  * struct timeval *a_access;
1395                                  * struct timeval *a_modify;
1396                                  * int a_waitfor;
1397                                  * } */ *ap;
1398 {
1399     printf("stray afs_vop_update\n");
1400     return EOPNOTSUPP;
1401 }
1402
1403 int
1404 afs_vop_blktooff(ap)
1405      struct vop_blktooff_args   /* {
1406                                  * struct vnode *a_vp;
1407                                  * daddr_t a_lblkno;
1408                                  * off_t *a_offset;    
1409                                  * } */ *ap;
1410 {
1411     *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1412     return 0;
1413 }
1414
1415 int
1416 afs_vop_offtoblk(ap)
1417      struct vop_offtoblk_args   /* {
1418                                  * struct vnode *a_vp;
1419                                  * off_t a_offset;    
1420                                  * daddr_t *a_lblkno;
1421                                  * } */ *ap;
1422 {
1423     *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1424
1425     return (0);
1426 }
1427
1428 int
1429 afs_vop_cmap(ap)
1430      struct vop_cmap_args       /* {
1431                                  * struct vnode *a_vp;
1432                                  * off_t a_foffset;    
1433                                  * size_t a_size;
1434                                  * daddr_t *a_bpn;
1435                                  * size_t *a_run;
1436                                  * void *a_poff;
1437                                  * } */ *ap;
1438 {
1439     *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1440     *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1441     return 0;
1442 }