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