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