61539f7d566a21dc517e500296c4c3a6904c7135
[openafs.git] / src / afs / DARWIN / osi_vnodeops.c
1 #include <afs/param.h>  /* Should be always first */
2 #include <afsconfig.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     bcopy(cnp->cn_nameptr, name, 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((struct vcache *)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 = (struct vnode *)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((struct vcache *)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 = (struct vnode *)vcp;
240         vn_lock((struct vnode *)vcp, LK_EXCLUSIVE| LK_RETRY, p);
241         if (UBCINFOMISSING((struct vnode *)vcp) ||
242             UBCINFORECLAIMED((struct vnode *)vcp))
243                 ubc_info_init((struct vnode *)vcp);
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 = (struct vcache *)ap->a_vp;
279     AFS_GLOCK();
280     error = afs_open(&vc, ap->a_mode, ap->a_cred);
281 #ifdef DIAGNOSTIC
282     if ((struct vnode *)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((struct vcache *)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((struct vcache *)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((struct vcache *)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=(struct vcache *)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=(struct vcache *)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=(struct vcache *)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((struct vcache *)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=(struct vcache *)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                         bzero((caddr_t)(ioaddr + pl_offset + io), 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 = (struct vcache *)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((struct vcache *)vp, ap->a_cred);
721     else
722       error=afs_fsync((struct vcache *)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((struct vcache *)dvp, name, cnp->cn_cred);
756     AFS_GUNLOCK();
757     cache_purge(vp);
758     if (dvp == vp)
759         vrele(vp);
760     else
761         vput(vp);
762     vput(dvp);
763     if (UBCINFOEXISTS(vp)) {
764              int wasmapped=ubc_issetflags(vp, UI_WASMAPPED);
765              int hasobjref=ubc_issetflags(vp, UI_HASOBJREF);
766              if (wasmapped)
767                 (void) ubc_uncache(vp); 
768              if (hasobjref)
769                 ubc_release(vp);
770              /* WARNING vp may not be valid after this */
771     }
772
773     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
774     DROPNAME();
775     return error;
776 }
777
778 int
779 afs_vop_link(ap)
780         struct vop_link_args /* {
781                 struct vnode *a_vp;
782                 struct vnode *a_tdvp;
783                 struct componentname *a_cnp;
784         } */ *ap;
785 {
786     int error = 0;
787     register struct vnode *dvp = ap->a_tdvp;
788     register struct vnode *vp = ap->a_vp;
789     struct proc *p;
790
791     GETNAME();
792     p=cnp->cn_proc;
793     if (dvp->v_mount != vp->v_mount) {
794         VOP_ABORTOP(vp, cnp);
795         error = EXDEV;
796         goto out;
797     }
798     if (vp->v_type == VDIR) {
799         VOP_ABORTOP(vp, cnp);
800         error = EISDIR;
801         goto out;
802     }
803     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
804         VOP_ABORTOP(dvp, cnp);
805         goto out;
806     }
807     AFS_GLOCK();
808     error = afs_link((struct vcache *)vp, (struct vcache *)dvp, name, cnp->cn_cred);
809     AFS_GUNLOCK();
810     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
811     if (dvp != vp)
812         VOP_UNLOCK(vp,0, p);
813 out:
814     vput(dvp);
815     DROPNAME();
816     return error;
817 }
818
819 int
820 afs_vop_rename(ap)
821         struct vop_rename_args  /* {
822                 struct vnode *a_fdvp;
823                 struct vnode *a_fvp;
824                 struct componentname *a_fcnp;
825                 struct vnode *a_tdvp;
826                 struct vnode *a_tvp;
827                 struct componentname *a_tcnp;
828         } */ *ap;
829 {
830     int error = 0;
831     struct componentname *fcnp = ap->a_fcnp;
832     char *fname;
833     struct componentname *tcnp = ap->a_tcnp;
834     char *tname;
835     struct vnode *tvp = ap->a_tvp;
836     register struct vnode *tdvp = ap->a_tdvp;
837     struct vnode *fvp = ap->a_fvp;
838     register struct vnode *fdvp = ap->a_fdvp;
839     struct proc *p=fcnp->cn_proc;
840
841     /*
842      * Check for cross-device rename.
843      */
844     if ((fvp->v_mount != tdvp->v_mount) ||
845         (tvp && (fvp->v_mount != tvp->v_mount))) {
846         error = EXDEV;
847 abortit:
848         VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
849         if (tdvp == tvp)
850             vrele(tdvp);
851         else
852             vput(tdvp);
853         if (tvp)
854             vput(tvp);
855         VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
856         vrele(fdvp);
857         vrele(fvp);
858         return (error);
859     }
860     /*
861      * if fvp == tvp, we're just removing one name of a pair of
862      * directory entries for the same element.  convert call into rename.
863      ( (pinched from NetBSD 1.0's ufs_rename())
864      */
865     if (fvp == tvp) {
866         if (fvp->v_type == VDIR) {
867             error = EINVAL;
868             goto abortit;
869         }
870
871         /* Release destination completely. */
872         VOP_ABORTOP(tdvp, tcnp);
873         vput(tdvp);
874         vput(tvp);
875
876         /* Delete source. */
877         vrele(fdvp);
878         vrele(fvp);
879         fcnp->cn_flags &= ~MODMASK;
880         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
881         if ((fcnp->cn_flags & SAVESTART) == 0)
882             panic("afs_rename: lost from startdir");
883         fcnp->cn_nameiop = DELETE;
884         (void) relookup(fdvp, &fvp, fcnp);
885         return (VOP_REMOVE(fdvp, fvp, fcnp));
886     }
887     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
888         goto abortit;
889
890     MALLOC(fname, char *, fcnp->cn_namelen+1, M_TEMP, M_WAITOK);
891     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
892     fname[fcnp->cn_namelen] = '\0';
893     MALLOC(tname, char *, tcnp->cn_namelen+1, M_TEMP, M_WAITOK);
894     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
895     tname[tcnp->cn_namelen] = '\0';
896
897
898     AFS_GLOCK();
899     /* XXX use "from" or "to" creds? NFS uses "to" creds */
900     error = afs_rename((struct vcache *)fdvp, fname, (struct vcache *)tdvp, tname, tcnp->cn_cred);
901     AFS_GUNLOCK();
902
903     VOP_UNLOCK(fvp, 0, p);
904     FREE(fname, M_TEMP);
905     FREE(tname, M_TEMP);
906     if (error)
907         goto abortit;                   /* XXX */
908     if (tdvp == tvp)
909         vrele(tdvp);
910     else
911         vput(tdvp);
912     if (tvp)
913         vput(tvp);
914     vrele(fdvp);
915     vrele(fvp);
916     return error;
917 }
918
919 int
920 afs_vop_mkdir(ap)
921         struct vop_mkdir_args /* {
922                 struct vnode *a_dvp;
923                 struct vnode **a_vpp;
924                 struct componentname *a_cnp;
925                 struct vattr *a_vap;
926         } */ *ap;
927 {
928     register struct vnode *dvp = ap->a_dvp;
929     register struct vattr *vap = ap->a_vap;
930     int error = 0;
931     struct vcache *vcp;
932     struct proc *p;
933
934     GETNAME();
935     p=cnp->cn_proc;
936 #ifdef DIAGNOSTIC
937     if ((cnp->cn_flags & HASBUF) == 0)
938         panic("afs_vop_mkdir: no name");
939 #endif
940     AFS_GLOCK();
941     error = afs_mkdir((struct vcache *)dvp, name, vap, &vcp, cnp->cn_cred);
942     AFS_GUNLOCK();
943     if (error) {
944         VOP_ABORTOP(dvp, cnp);
945         vput(dvp);
946         DROPNAME();
947         return(error);
948     }
949     if (vcp) {
950         *ap->a_vpp = (struct vnode *)vcp;
951         vn_lock((struct vnode *)vcp, LK_EXCLUSIVE|LK_RETRY, p);
952     } else
953         *ap->a_vpp = 0;
954     DROPNAME();
955     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
956     vput(dvp);
957     return error;
958 }
959
960 int
961 afs_vop_rmdir(ap)
962         struct vop_rmdir_args /* {
963                 struct vnode *a_dvp;
964                 struct vnode *a_vp;
965                 struct componentname *a_cnp;
966         } */ *ap;
967 {
968     int error = 0;
969     register struct vnode *vp = ap->a_vp;
970     register struct vnode *dvp = ap->a_dvp;
971
972     GETNAME();
973     if (dvp == vp) {
974         vrele(dvp);
975         vput(vp);
976         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
977         DROPNAME();
978         return (EINVAL);
979     }
980
981     AFS_GLOCK();
982     error = afs_rmdir((struct vcache *)dvp, name, cnp->cn_cred);
983     AFS_GUNLOCK();
984     DROPNAME();
985     vput(dvp);
986     vput(vp);
987     return error;
988 }
989
990 int
991 afs_vop_symlink(ap)
992         struct vop_symlink_args /* {
993                 struct vnode *a_dvp;
994                 struct vnode **a_vpp;
995                 struct componentname *a_cnp;
996                 struct vattr *a_vap;
997                 char *a_target;
998         } */ *ap;
999 {
1000     register struct vnode *dvp = ap->a_dvp;
1001     int error = 0;
1002     /* NFS ignores a_vpp; so do we. */
1003
1004     GETNAME();
1005     AFS_GLOCK();
1006     error = afs_symlink((struct vcache *)dvp, name, ap->a_vap, ap->a_target,
1007                         cnp->cn_cred);
1008     AFS_GUNLOCK();
1009     DROPNAME();
1010     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1011     vput(dvp);
1012     return error;
1013 }
1014
1015 int
1016 afs_vop_readdir(ap)
1017         struct vop_readdir_args /* {
1018                 struct vnode *a_vp;
1019                 struct uio *a_uio;
1020                 struct ucred *a_cred;
1021                 int *a_eofflag;
1022                 u_long *a_cookies;
1023                 int ncookies;
1024         } */ *ap;
1025 {
1026     int error;
1027     off_t off;
1028 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1029            ap->a_ncookies); */
1030     off=ap->a_uio->uio_offset;
1031     AFS_GLOCK();
1032     error= afs_readdir((struct vcache *)ap->a_vp, ap->a_uio, ap->a_cred,
1033                        ap->a_eofflag);
1034     AFS_GUNLOCK();
1035     if (!error && ap->a_ncookies != NULL) {
1036         struct uio *uio = ap->a_uio;
1037         const struct dirent *dp, *dp_start, *dp_end;
1038         int ncookies;
1039         u_long *cookies, *cookiep;
1040
1041         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1042             panic("afs_readdir: burned cookies");
1043         dp = (const struct dirent *)
1044             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1045
1046         dp_end = (const struct dirent *) uio->uio_iov->iov_base;
1047         for (dp_start = dp, ncookies = 0;
1048              dp < dp_end;
1049              dp = (const struct dirent *)((const char *) dp + dp->d_reclen))
1050             ncookies++;
1051
1052         MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
1053                M_TEMP, M_WAITOK);
1054         for (dp = dp_start, cookiep = cookies;
1055              dp < dp_end;
1056              dp = (const struct dirent *)((const char *) dp + dp->d_reclen)) {
1057             off += dp->d_reclen;
1058             *cookiep++ = off;
1059         }
1060         *ap->a_cookies = cookies;
1061         *ap->a_ncookies = ncookies;
1062     }
1063
1064     return error;
1065 }
1066
1067 int
1068 afs_vop_readlink(ap)
1069         struct vop_readlink_args /* {
1070                 struct vnode *a_vp;
1071                 struct uio *a_uio;
1072                 struct ucred *a_cred;
1073         } */ *ap;
1074 {
1075     int error;
1076 /*    printf("readlink %x\n", ap->a_vp);*/
1077     AFS_GLOCK();
1078     error= afs_readlink((struct vcache *)ap->a_vp, ap->a_uio, ap->a_cred);
1079     AFS_GUNLOCK();
1080     return error;
1081 }
1082
1083 extern int prtactive;
1084
1085 int
1086 afs_vop_inactive(ap)
1087         struct vop_inactive_args /* {
1088                 struct vnode *a_vp;
1089                 struct proc *a_p;
1090         } */ *ap;
1091 {
1092     register struct vnode *vp = ap->a_vp;
1093
1094     if (prtactive && vp->v_usecount != 0)
1095         vprint("afs_vop_inactive(): pushing active", vp);
1096
1097     AFS_GLOCK();
1098     afs_InactiveVCache((struct vcache *)vp, 0);   /* decrs ref counts */
1099     AFS_GUNLOCK();
1100     VOP_UNLOCK(vp, 0, ap->a_p);
1101     return 0;
1102 }
1103
1104 int
1105 afs_vop_reclaim(ap)
1106         struct vop_reclaim_args /* {
1107                 struct vnode *a_vp;
1108         } */ *ap;
1109 {
1110     int error;
1111     int sl;
1112     register struct vnode *vp = ap->a_vp;
1113
1114     cache_purge(vp);                    /* just in case... */
1115
1116 #if 0 
1117     AFS_GLOCK();
1118     error = afs_FlushVCache((struct vcache *)vp, &sl); /* tosses our stuff from vnode */
1119     AFS_GUNLOCK();
1120     ubc_unlink(vp);
1121     if (!error && vp->v_data)
1122         panic("afs_reclaim: vnode not cleaned");
1123     return error;
1124 #else
1125    if (vp->v_usecount == 2) {
1126         vprint("reclaim count==2", vp);
1127    } else if (vp->v_usecount == 1) {
1128         vprint("reclaim count==1", vp);
1129    } else 
1130         vprint("reclaim bad count", vp);
1131
1132    return 0;
1133 #endif
1134 }
1135
1136 int
1137 afs_vop_lock(ap)
1138         struct vop_lock_args /* {
1139                 struct vnode *a_vp;
1140         } */ *ap;
1141 {
1142         register struct vnode *vp = ap->a_vp;
1143         register struct vcache *avc = (struct vcache *)vp;
1144
1145         if (vp->v_tag == VT_NON)
1146                 return (ENOENT);
1147         return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock,
1148                 ap->a_p));
1149 }
1150
1151 int
1152 afs_vop_unlock(ap)
1153         struct vop_unlock_args /* {
1154                 struct vnode *a_vp;
1155         } */ *ap;
1156 {
1157     struct vnode *vp = ap->a_vp;
1158     struct vcache *avc = (struct vcache *)vp;
1159     return (lockmgr(&avc->rwlock, ap->a_flags | LK_RELEASE,
1160             &vp->v_interlock, ap->a_p));
1161
1162 }
1163
1164 int
1165 afs_vop_bmap(ap)
1166         struct vop_bmap_args /* {
1167                 struct vnode *a_vp;
1168                 daddr_t  a_bn;
1169                 struct vnode **a_vpp;
1170                 daddr_t *a_bnp;
1171                 int *a_runp;
1172                 int *a_runb;
1173         } */ *ap;
1174 {
1175     struct vcache *vcp;
1176     int error;
1177     if (ap->a_bnp) {
1178         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1179     }
1180     if (ap->a_vpp) {
1181         *ap->a_vpp = ap->a_vp;
1182     }
1183         if (ap->a_runp != NULL)
1184                 *ap->a_runp = 0;
1185 #ifdef notyet
1186         if (ap->a_runb != NULL)
1187                 *ap->a_runb = 0;
1188 #endif
1189  
1190     return 0;
1191 }
1192 int
1193 afs_vop_strategy(ap)
1194         struct vop_strategy_args /* {
1195                 struct buf *a_bp;
1196         } */ *ap;
1197 {
1198     int error;
1199     AFS_GLOCK();
1200     error= afs_ustrategy(ap->a_bp);
1201     AFS_GUNLOCK();
1202     return error;
1203 }
1204 int
1205 afs_vop_print(ap)
1206         struct vop_print_args /* {
1207                 struct vnode *a_vp;
1208         } */ *ap;
1209 {
1210     register struct vnode *vp = ap->a_vp;
1211     register struct vcache *vc = (struct vcache *)ap->a_vp;
1212     int s = vc->states;
1213     char buf[20];
1214     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag, vc->fid.Cell,
1215            vc->fid.Fid.Volume, vc->fid.Fid.Vnode, vc->fid.Fid.Unique, vc->opens,
1216            vc->execsOrWriters);
1217     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" : "");
1218     if (UBCISVALID(vp))
1219         printf("\n  UBC: %s%s",
1220                UBCINFOEXISTS(vp) ? "exists, " : "does not exist",
1221                UBCINFOEXISTS(vp) ?
1222                  sprintf(buf, "holdcnt %d", vp->v_ubcinfo->ui_holdcnt),buf : "");
1223     printf("\n");
1224     return 0;
1225 }
1226
1227 int
1228 afs_vop_islocked(ap)
1229         struct vop_islocked_args /* {
1230                 struct vnode *a_vp;
1231         } */ *ap;
1232 {
1233     struct vcache *vc = (struct vcache *)ap->a_vp;
1234     return lockstatus(&vc->rwlock);
1235 }
1236
1237 /*
1238  * Return POSIX pathconf information applicable to ufs filesystems.
1239  */
1240 afs_vop_pathconf(ap)
1241         struct vop_pathconf_args /* {
1242                 struct vnode *a_vp;
1243                 int a_name;
1244                 int *a_retval;
1245         } */ *ap;
1246 {
1247     AFS_STATCNT(afs_cntl);
1248     switch (ap->a_name) {
1249       case _PC_LINK_MAX:
1250         *ap->a_retval = LINK_MAX;
1251         break;
1252       case _PC_NAME_MAX:
1253         *ap->a_retval = NAME_MAX;
1254         break;
1255       case _PC_PATH_MAX:
1256         *ap->a_retval = PATH_MAX;
1257         break;
1258       case _PC_CHOWN_RESTRICTED:
1259         *ap->a_retval = 1;
1260         break;
1261       case _PC_NO_TRUNC:
1262         *ap->a_retval = 1;
1263         break;
1264       case _PC_PIPE_BUF:
1265         return EINVAL;
1266         break;
1267       default:
1268         return EINVAL;
1269     }
1270     return 0;
1271 }
1272
1273 /*
1274  * Advisory record locking support (fcntl() POSIX style)
1275  */
1276 int
1277 afs_vop_advlock(ap)
1278         struct vop_advlock_args /* {
1279                 struct vnode *a_vp;
1280                 caddr_t  a_id;
1281                 int  a_op;
1282                 struct flock *a_fl;
1283                 int  a_flags;
1284         } */ *ap;
1285 {
1286     int error;
1287     struct proc *p=current_proc();
1288     struct ucred cr;
1289     pcred_readlock(p);
1290     cr=*p->p_cred->pc_ucred;
1291     pcred_unlock(p);
1292     AFS_GLOCK();
1293     error= afs_lockctl((struct vcache *)ap->a_vp, ap->a_fl, ap->a_op, &cr,
1294                        (int) ap->a_id);
1295     AFS_GUNLOCK();
1296     return error;
1297 }
1298
1299 int
1300 afs_vop_truncate(ap)
1301         struct vop_truncate_args /* {
1302                 struct vnode *a_vp;
1303                 off_t a_length;
1304                 int a_flags;
1305                 struct ucred *a_cred;
1306                 struct proc *a_p;
1307         } */ *ap;
1308 {
1309     printf("stray afs_vop_truncate\n");
1310     return EOPNOTSUPP;
1311 }
1312
1313 int
1314 afs_vop_update(ap)
1315         struct vop_update_args /* {
1316                 struct vnode *a_vp;
1317                 struct timeval *a_access;
1318                 struct timeval *a_modify;
1319                 int a_waitfor;
1320         } */ *ap;
1321 {
1322     printf("stray afs_vop_update\n");
1323     return EOPNOTSUPP;
1324 }
1325
1326 int afs_vop_blktooff(ap)
1327         struct vop_blktooff_args /* {
1328                 struct vnode *a_vp;
1329                 daddr_t a_lblkno;
1330                 off_t *a_offset;    
1331         } */ *ap;
1332 {
1333         *ap->a_offset = (off_t)(ap->a_lblkno *  DEV_BSIZE);
1334         return 0;
1335 }
1336
1337 int afs_vop_offtoblk(ap)
1338         struct vop_offtoblk_args /* {
1339                 struct vnode *a_vp;
1340                 off_t a_offset;    
1341                 daddr_t *a_lblkno;
1342         } */ *ap;
1343 {
1344         *ap->a_lblkno = (daddr_t)(ap->a_offset /  DEV_BSIZE);
1345
1346         return (0);
1347 }
1348
1349 int afs_vop_cmap(ap)
1350         struct vop_cmap_args /* {
1351                 struct vnode *a_vp;
1352                 off_t a_foffset;    
1353                 size_t a_size;
1354                 daddr_t *a_bpn;
1355                 size_t *a_run;
1356                 void *a_poff;
1357         } */ *ap;
1358 {
1359         *ap->a_bpn = (daddr_t)(ap->a_foffset /  DEV_BSIZE);     
1360         *ap->a_run= MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1361         return 0;
1362 }
1363