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