darwin-head-build-fixes-20020821
[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, ap->a_cred);
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, ap->a_cred);        /* hold bozon lock, but not basic vnode lock */
310     afs_BozonUnlock(&avc->pvnLock, avc);
311     AFS_GUNLOCK();
312 #ifdef AFS_DARWIN14_ENV
313     if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
314       ubc_hold(ap->a_vp);
315       if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
316          printf("afs: Imminent ui_refcount panic\n");
317        } else {
318          printf("afs: WARNING: ui_refcount panic averted\n");
319        }
320     }
321 #endif
322
323     return code;
324 }
325
326 int
327 afs_vop_access(ap)
328         struct vop_access_args /* {
329                 struct vnode *a_vp;
330                 int  a_mode;
331                 struct ucred *a_cred;
332                 struct proc *a_p;
333         } */ *ap;
334 {
335     int code;
336     AFS_GLOCK();
337     code=afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
338     AFS_GUNLOCK();
339     return code;
340 }
341 int
342 afs_vop_getattr(ap)
343         struct vop_getattr_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_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
353     AFS_GUNLOCK();
354     return code;
355 }
356 int
357 afs_vop_setattr(ap)
358         struct vop_setattr_args /* {
359                 struct vnode *a_vp;
360                 struct vattr *a_vap;
361                 struct ucred *a_cred;
362                 struct proc *a_p;
363         } */ *ap;
364 {
365     int code;
366     AFS_GLOCK();
367     code=afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
368     AFS_GUNLOCK();
369     return code;
370 }
371 int
372 afs_vop_read(ap)
373         struct vop_read_args /* {
374                 struct vnode *a_vp;
375                 struct uio *a_uio;
376                 int a_ioflag;
377                 struct ucred *a_cred;
378         } */ *ap;
379 {
380     int code;
381     struct vcache *avc=VTOAFS(ap->a_vp);
382     AFS_GLOCK();
383     afs_BozonLock(&avc->pvnLock, avc);
384     osi_FlushPages(avc, ap->a_cred);        /* hold bozon lock, but not basic vnode lock */
385     code=afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
386     afs_BozonUnlock(&avc->pvnLock, avc);
387     AFS_GUNLOCK();
388     return code;
389 }
390 int
391 afs_vop_pagein(ap)
392         struct vop_pagein_args /* {
393                 struct vnode *a_vp;
394                 upl_t a_pl;
395                 vm_offset_t a_pl_offset;
396                 off_t a_f_offset;
397                 size_t a_size;
398                 struct ucred *a_cred;
399                 int a_flags;
400         } */ *ap;
401 {
402     register struct vnode *vp = ap->a_vp;
403     upl_t pl = ap->a_pl;
404     size_t size= ap->a_size;
405     off_t f_offset = ap->a_f_offset;
406     vm_offset_t pl_offset = ap->a_pl_offset;
407     int flags  = ap->a_flags;
408     struct ucred *cred;
409     vm_offset_t ioaddr;
410     struct uio      auio;
411     struct iovec    aiov;
412     struct uio * uio = &auio;
413     int nocommit = flags & UPL_NOCOMMIT;
414
415     int code;
416     struct vcache *tvc=VTOAFS(vp);
417
418     if (UBCINVALID(vp)) {
419 #if DIAGNOSTIC
420         panic("afs_vop_pagein: invalid vp");
421 #endif /* DIAGNOSTIC */
422         return (EPERM);
423     }
424
425     UBCINFOCHECK("afs_vop_pagein", vp);
426     if(pl == (upl_t)NULL) {
427             panic("afs_vop_pagein: no upl");
428     }
429
430     cred = ubc_getcred(vp);
431     if (cred == NOCRED)
432         cred = ap->a_cred;
433
434     if (size == 0) {
435             if (!nocommit)
436                     kernel_upl_abort_range(pl, pl_offset, size, 
437                             UPL_ABORT_ERROR |  UPL_ABORT_FREE_ON_EMPTY);
438             return (0);
439     }
440     if (f_offset < 0) {
441             if (!nocommit)
442                     kernel_upl_abort_range(pl, pl_offset, size, 
443                             UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
444             return (EINVAL);
445     }
446     if (f_offset & PAGE_MASK)
447             panic("afs_vop_pagein: offset not page aligned");
448
449     auio.uio_iov = &aiov;
450     auio.uio_iovcnt = 1;
451     auio.uio_offset = f_offset;
452     auio.uio_segflg = UIO_SYSSPACE;
453     auio.uio_rw = UIO_READ;
454     auio.uio_procp = NULL;
455     kernel_upl_map(kernel_map, pl, &ioaddr);
456     ioaddr += pl_offset;
457     auio.uio_resid = aiov.iov_len = size;
458     aiov.iov_base = (caddr_t)ioaddr;
459     AFS_GLOCK();
460     afs_BozonLock(&tvc->pvnLock, tvc);
461     osi_FlushPages(tvc, ap->a_cred);        /* hold bozon lock, but not basic vnode lock */
462     code=afs_read(tvc, uio, cred, 0, 0, 0);
463     if (code == 0) {
464       ObtainWriteLock(&tvc->lock, 2);
465       tvc->states |= CMAPPED;
466       ReleaseWriteLock(&tvc->lock);
467     }
468     afs_BozonUnlock(&tvc->pvnLock, tvc);
469     AFS_GUNLOCK();
470     kernel_upl_unmap(kernel_map, pl);
471     if (!nocommit) {
472       if (code)
473          kernel_upl_abort_range(pl, pl_offset, size, 
474                          UPL_ABORT_ERROR |  UPL_ABORT_FREE_ON_EMPTY);
475       else
476          kernel_upl_commit_range(pl, pl_offset, size,
477                           UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
478                           UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER);
479     }
480     return code;
481 }
482
483 int
484 afs_vop_write(ap)
485         struct vop_write_args /* {
486                 struct vnode *a_vp;
487                 struct uio *a_uio;
488                 int a_ioflag;
489                 struct ucred *a_cred;
490         } */ *ap;
491 {
492     int code;
493     struct vcache *avc=VTOAFS(ap->a_vp);
494     void *object;
495     AFS_GLOCK();
496     afs_BozonLock(&avc->pvnLock, avc);
497     osi_FlushPages(avc, ap->a_cred);        /* hold bozon lock, but not basic vnode lock */
498     if (UBCINFOEXISTS(ap->a_vp))
499        ubc_clean(ap->a_vp, 1);
500     if (UBCINFOEXISTS(ap->a_vp))
501        osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset, ap->a_uio->uio_resid);
502     code=afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
503     afs_BozonUnlock(&avc->pvnLock, avc);
504     AFS_GUNLOCK();
505     return code;
506 }
507
508 int
509 afs_vop_pageout(ap)
510         struct vop_pageout_args /* {
511                 struct vnode *a_vp;
512                 upl_t   a_pl,
513                 vm_offset_t   a_pl_offset,
514                 off_t         a_f_offset,
515                 size_t        a_size,
516                 struct ucred *a_cred,
517                 int           a_flags
518         } */ *ap;
519 {
520     register struct vnode *vp = ap->a_vp;
521     upl_t pl = ap->a_pl;
522     size_t size= ap->a_size;
523     off_t f_offset = ap->a_f_offset;
524     vm_offset_t pl_offset = ap->a_pl_offset;
525     int flags  = ap->a_flags;
526     struct ucred *cred;
527     vm_offset_t ioaddr;
528     struct uio      auio;
529     struct iovec    aiov;
530     struct uio * uio = &auio;
531     int nocommit = flags & UPL_NOCOMMIT;
532
533     int code;
534     struct vcache *tvc=VTOAFS(vp);
535
536     if (UBCINVALID(vp)) {
537 #if DIAGNOSTIC
538         panic("afs_vop_pageout: invalid vp");
539 #endif /* DIAGNOSTIC */
540         return (EPERM);
541     }
542
543     UBCINFOCHECK("afs_vop_pageout", vp);
544     if(pl == (upl_t)NULL) {
545             panic("afs_vop_pageout: no upl");
546     }
547 #if 1
548     { int lbn, iosize, s;
549       struct buf *bp;
550       int biosize = DEV_BSIZE;
551
552       lbn = f_offset / DEV_BSIZE;
553
554         for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
555
556                 s = splbio();
557                 if (bp = incore(vp, lbn)) {
558                         if (ISSET(bp->b_flags, B_BUSY))
559                                 panic("nfs_pageout: found BUSY buffer incore\n")
560 ;
561                         
562                         bremfree(bp);
563                         SET(bp->b_flags, (B_BUSY | B_INVAL));
564                         brelse(bp);
565                 }
566                 splx(s);
567         }
568     }
569 #endif
570     cred = ubc_getcred(vp);
571     if (cred == NOCRED)
572         cred = ap->a_cred;
573
574     if (size == 0) {
575             if (!nocommit)
576                     kernel_upl_abort_range(pl, pl_offset, size, 
577                             UPL_ABORT_FREE_ON_EMPTY);
578             return (0);
579     }
580     if (flags & (IO_APPEND | IO_SYNC))
581                 panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
582     if (f_offset < 0) {
583             if (!nocommit)
584                     kernel_upl_abort_range(pl, pl_offset, size, 
585                             UPL_ABORT_FREE_ON_EMPTY);
586             return (EINVAL);
587     }
588     if (f_offset >= tvc->m.Length) {
589             if (!nocommit)
590                     kernel_upl_abort_range(pl, pl_offset, size,
591                             UPL_ABORT_FREE_ON_EMPTY);
592             return (EINVAL);
593     }
594
595     if (f_offset & PAGE_MASK)
596             panic("afs_vop_pageout: offset not page aligned");
597
598     auio.uio_iov = &aiov;
599     auio.uio_iovcnt = 1;
600     auio.uio_offset = f_offset;
601     auio.uio_segflg = UIO_SYSSPACE;
602     auio.uio_rw = UIO_WRITE;
603     auio.uio_procp = NULL;
604     kernel_upl_map(kernel_map, pl, &ioaddr);
605     ioaddr += pl_offset;
606     auio.uio_resid = aiov.iov_len = size;
607     aiov.iov_base = (caddr_t)ioaddr;
608 #if 1 /* USV [ */
609         {
610                 /* 
611                  * check for partial page and clear the
612                  * contents past end of the file before
613                  * releasing it in the VM page cache
614                  */
615                 if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
616                         size_t io = tvc->m.Length - f_offset;
617
618                         memset((caddr_t)(ioaddr + pl_offset + io), 0, size - io);
619                 }
620         }
621 #endif /* ] USV */
622
623     AFS_GLOCK();
624     afs_BozonLock(&tvc->pvnLock, tvc);
625     osi_FlushPages(tvc, ap->a_cred);        /* hold bozon lock, but not basic vnode lock */
626     ObtainWriteLock(&tvc->lock, 1);
627     afs_FakeOpen(tvc);
628     ReleaseWriteLock(&tvc->lock);
629
630     code=afs_write(tvc, uio, flags, cred, 0);
631
632     ObtainWriteLock(&tvc->lock, 1);
633     afs_FakeClose(tvc, cred);
634     ReleaseWriteLock(&tvc->lock);
635     afs_BozonUnlock(&tvc->pvnLock, tvc);
636     AFS_GUNLOCK();
637     kernel_upl_unmap(kernel_map, pl);
638     if (!nocommit) {
639             if(code)
640                     kernel_upl_abort_range(pl, pl_offset, size, 
641                         UPL_ABORT_FREE_ON_EMPTY);
642             else
643                     kernel_upl_commit_range(pl, pl_offset, size,
644                          UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
645                          UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER);
646     }
647
648     return code;
649 }
650 int
651 afs_vop_ioctl(ap)
652         struct vop_ioctl_args /* {
653                 struct vnode *a_vp;
654                 int  a_command;
655                 caddr_t  a_data;
656                 int  a_fflag;
657                 struct ucred *a_cred;
658                 struct proc *a_p;
659         } */ *ap;
660 {
661     struct vcache *tvc = VTOAFS(ap->a_vp);
662     struct afs_ioctl data;
663     int error = 0;
664   
665     /* in case we ever get in here... */
666
667     AFS_STATCNT(afs_ioctl);
668     if (((ap->a_command >> 8) & 0xff) == 'V') {
669         /* This is a VICEIOCTL call */
670     AFS_GLOCK();
671         error = HandleIoctl(tvc, (struct file *)0/*Not used*/,
672                             ap->a_command, ap->a_data);
673     AFS_GUNLOCK();
674         return(error);
675     } else {
676         /* No-op call; just return. */
677         return(ENOTTY);
678     }
679 }
680
681 /* ARGSUSED */
682 int
683 afs_vop_select(ap)
684         struct vop_select_args /* {
685                 struct vnode *a_vp;
686                 int  a_which;
687                 int  a_fflags;
688                 struct ucred *a_cred;
689                 struct proc *a_p;
690         } */ *ap;
691 {
692         /*
693          * We should really check to see if I/O is possible.
694          */
695         return (1);
696 }
697 /*
698  * Mmap a file
699  *
700  * NB Currently unsupported.
701  */
702 /* ARGSUSED */
703 int
704 afs_vop_mmap(ap)
705         struct vop_mmap_args /* {
706                 struct vnode *a_vp;
707                 int  a_fflags;
708                 struct ucred *a_cred;
709                 struct proc *a_p;
710         } */ *ap;
711 {
712         return (EINVAL);
713 }
714
715 int
716 afs_vop_fsync(ap)
717         struct vop_fsync_args /* {
718                 struct vnode *a_vp;
719                 struct ucred *a_cred;
720                 int a_waitfor;
721                 struct proc *a_p;
722         } */ *ap;
723 {
724     int wait = ap->a_waitfor == MNT_WAIT;
725     int error;
726     register struct vnode *vp = ap->a_vp;
727
728     AFS_GLOCK();
729     /*vflushbuf(vp, wait);*/
730     if (ap->a_cred)
731       error=afs_fsync(VTOAFS(vp), ap->a_cred);
732     else
733       error=afs_fsync(VTOAFS(vp), &afs_osi_cred);
734     AFS_GUNLOCK();
735     return error;
736 }
737
738 int
739 afs_vop_seek(ap)
740         struct vop_seek_args /* {
741                 struct vnode *a_vp;
742                 off_t  a_oldoff;
743                 off_t  a_newoff;
744                 struct ucred *a_cred;
745         } */ *ap;
746 {
747     if (ap->a_newoff > ULONG_MAX)       /* AFS doesn't support 64-bit offsets */
748         return EINVAL;
749     return (0);
750 }
751
752 int
753 afs_vop_remove(ap)
754         struct vop_remove_args /* {
755                 struct vnode *a_dvp;
756                 struct vnode *a_vp;
757                 struct componentname *a_cnp;
758         } */ *ap;
759 {
760     int error = 0;
761     register struct vnode *vp = ap->a_vp;
762     register struct vnode *dvp = ap->a_dvp;
763
764     GETNAME();
765     AFS_GLOCK();
766     error =  afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
767     AFS_GUNLOCK();
768     cache_purge(vp);
769     if (!error && UBCINFOEXISTS(vp)) {
770 #ifdef AFS_DARWIN14_ENV
771              (void) ubc_uncache(vp); 
772 #else
773              int wasmapped=ubc_issetflags(vp, UI_WASMAPPED);
774              int hasobjref=ubc_issetflags(vp, UI_HASOBJREF);
775              if (wasmapped)
776                 (void) ubc_uncache(vp); 
777              if (hasobjref)
778                 ubc_release(vp);
779              /* WARNING vp may not be valid after this */
780 #endif
781     }
782     if (dvp == vp)
783         vrele(vp);
784     else
785         vput(vp);
786     vput(dvp);
787
788     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
789     DROPNAME();
790     return error;
791 }
792
793 int
794 afs_vop_link(ap)
795         struct vop_link_args /* {
796                 struct vnode *a_vp;
797                 struct vnode *a_tdvp;
798                 struct componentname *a_cnp;
799         } */ *ap;
800 {
801     int error = 0;
802     register struct vnode *dvp = ap->a_tdvp;
803     register struct vnode *vp = ap->a_vp;
804     struct proc *p;
805
806     GETNAME();
807     p=cnp->cn_proc;
808     if (dvp->v_mount != vp->v_mount) {
809         VOP_ABORTOP(vp, cnp);
810         error = EXDEV;
811         goto out;
812     }
813     if (vp->v_type == VDIR) {
814         VOP_ABORTOP(vp, cnp);
815         error = EISDIR;
816         goto out;
817     }
818     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
819         VOP_ABORTOP(dvp, cnp);
820         goto out;
821     }
822     AFS_GLOCK();
823     error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
824     AFS_GUNLOCK();
825     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
826     if (dvp != vp)
827         VOP_UNLOCK(vp,0, p);
828 out:
829     vput(dvp);
830     DROPNAME();
831     return error;
832 }
833
834 int
835 afs_vop_rename(ap)
836         struct vop_rename_args  /* {
837                 struct vnode *a_fdvp;
838                 struct vnode *a_fvp;
839                 struct componentname *a_fcnp;
840                 struct vnode *a_tdvp;
841                 struct vnode *a_tvp;
842                 struct componentname *a_tcnp;
843         } */ *ap;
844 {
845     int error = 0;
846     struct componentname *fcnp = ap->a_fcnp;
847     char *fname;
848     struct componentname *tcnp = ap->a_tcnp;
849     char *tname;
850     struct vnode *tvp = ap->a_tvp;
851     register struct vnode *tdvp = ap->a_tdvp;
852     struct vnode *fvp = ap->a_fvp;
853     register struct vnode *fdvp = ap->a_fdvp;
854     struct proc *p=fcnp->cn_proc;
855
856     /*
857      * Check for cross-device rename.
858      */
859     if ((fvp->v_mount != tdvp->v_mount) ||
860         (tvp && (fvp->v_mount != tvp->v_mount))) {
861         error = EXDEV;
862 abortit:
863         VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
864         if (tdvp == tvp)
865             vrele(tdvp);
866         else
867             vput(tdvp);
868         if (tvp)
869             vput(tvp);
870         VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
871         vrele(fdvp);
872         vrele(fvp);
873         return (error);
874     }
875     /*
876      * if fvp == tvp, we're just removing one name of a pair of
877      * directory entries for the same element.  convert call into rename.
878      ( (pinched from NetBSD 1.0's ufs_rename())
879      */
880     if (fvp == tvp) {
881         if (fvp->v_type == VDIR) {
882             error = EINVAL;
883             goto abortit;
884         }
885
886         /* Release destination completely. */
887         VOP_ABORTOP(tdvp, tcnp);
888         vput(tdvp);
889         vput(tvp);
890
891         /* Delete source. */
892         vrele(fdvp);
893         vrele(fvp);
894         fcnp->cn_flags &= ~MODMASK;
895         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
896         if ((fcnp->cn_flags & SAVESTART) == 0)
897             panic("afs_rename: lost from startdir");
898         fcnp->cn_nameiop = DELETE;
899         (void) relookup(fdvp, &fvp, fcnp);
900         return (VOP_REMOVE(fdvp, fvp, fcnp));
901     }
902     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
903         goto abortit;
904
905     MALLOC(fname, char *, fcnp->cn_namelen+1, M_TEMP, M_WAITOK);
906     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
907     fname[fcnp->cn_namelen] = '\0';
908     MALLOC(tname, char *, tcnp->cn_namelen+1, M_TEMP, M_WAITOK);
909     memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
910     tname[tcnp->cn_namelen] = '\0';
911
912
913     AFS_GLOCK();
914     /* XXX use "from" or "to" creds? NFS uses "to" creds */
915     error = afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
916     AFS_GUNLOCK();
917
918     VOP_UNLOCK(fvp, 0, p);
919     FREE(fname, M_TEMP);
920     FREE(tname, M_TEMP);
921     if (error)
922         goto abortit;                   /* XXX */
923     if (tdvp == tvp)
924         vrele(tdvp);
925     else
926         vput(tdvp);
927     if (tvp)
928         vput(tvp);
929     vrele(fdvp);
930     vrele(fvp);
931     return error;
932 }
933
934 int
935 afs_vop_mkdir(ap)
936         struct vop_mkdir_args /* {
937                 struct vnode *a_dvp;
938                 struct vnode **a_vpp;
939                 struct componentname *a_cnp;
940                 struct vattr *a_vap;
941         } */ *ap;
942 {
943     register struct vnode *dvp = ap->a_dvp;
944     register struct vattr *vap = ap->a_vap;
945     int error = 0;
946     struct vcache *vcp;
947     struct proc *p;
948
949     GETNAME();
950     p=cnp->cn_proc;
951 #ifdef DIAGNOSTIC
952     if ((cnp->cn_flags & HASBUF) == 0)
953         panic("afs_vop_mkdir: no name");
954 #endif
955     AFS_GLOCK();
956     error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
957     AFS_GUNLOCK();
958     if (error) {
959         VOP_ABORTOP(dvp, cnp);
960         vput(dvp);
961         DROPNAME();
962         return(error);
963     }
964     if (vcp) {
965         *ap->a_vpp = AFSTOV(vcp);
966         vn_lock(*ap->a_vpp, LK_EXCLUSIVE|LK_RETRY, p);
967     } else
968         *ap->a_vpp = 0;
969     DROPNAME();
970     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
971     vput(dvp);
972     return error;
973 }
974
975 int
976 afs_vop_rmdir(ap)
977         struct vop_rmdir_args /* {
978                 struct vnode *a_dvp;
979                 struct vnode *a_vp;
980                 struct componentname *a_cnp;
981         } */ *ap;
982 {
983     int error = 0;
984     register struct vnode *vp = ap->a_vp;
985     register struct vnode *dvp = ap->a_dvp;
986
987     GETNAME();
988     if (dvp == vp) {
989         vrele(dvp);
990         vput(vp);
991         FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
992         DROPNAME();
993         return (EINVAL);
994     }
995
996     AFS_GLOCK();
997     error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
998     AFS_GUNLOCK();
999     DROPNAME();
1000     vput(dvp);
1001     vput(vp);
1002     return error;
1003 }
1004
1005 int
1006 afs_vop_symlink(ap)
1007         struct vop_symlink_args /* {
1008                 struct vnode *a_dvp;
1009                 struct vnode **a_vpp;
1010                 struct componentname *a_cnp;
1011                 struct vattr *a_vap;
1012                 char *a_target;
1013         } */ *ap;
1014 {
1015     register struct vnode *dvp = ap->a_dvp;
1016     int error = 0;
1017     /* NFS ignores a_vpp; so do we. */
1018
1019     GETNAME();
1020     AFS_GLOCK();
1021     error = afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
1022                         cnp->cn_cred);
1023     AFS_GUNLOCK();
1024     DROPNAME();
1025     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1026     vput(dvp);
1027     return error;
1028 }
1029
1030 int
1031 afs_vop_readdir(ap)
1032         struct vop_readdir_args /* {
1033                 struct vnode *a_vp;
1034                 struct uio *a_uio;
1035                 struct ucred *a_cred;
1036                 int *a_eofflag;
1037                 u_long *a_cookies;
1038                 int ncookies;
1039         } */ *ap;
1040 {
1041     int error;
1042     off_t off;
1043 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1044            ap->a_ncookies); */
1045     off=ap->a_uio->uio_offset;
1046     AFS_GLOCK();
1047     error= afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred,
1048                        ap->a_eofflag);
1049     AFS_GUNLOCK();
1050     if (!error && ap->a_ncookies != NULL) {
1051         struct uio *uio = ap->a_uio;
1052         const struct dirent *dp, *dp_start, *dp_end;
1053         int ncookies;
1054         u_long *cookies, *cookiep;
1055
1056         if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1057             panic("afs_readdir: burned cookies");
1058         dp = (const struct dirent *)
1059             ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1060
1061         dp_end = (const struct dirent *) uio->uio_iov->iov_base;
1062         for (dp_start = dp, ncookies = 0;
1063              dp < dp_end;
1064              dp = (const struct dirent *)((const char *) dp + dp->d_reclen))
1065             ncookies++;
1066
1067         MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
1068                M_TEMP, M_WAITOK);
1069         for (dp = dp_start, cookiep = cookies;
1070              dp < dp_end;
1071              dp = (const struct dirent *)((const char *) dp + dp->d_reclen)) {
1072             off += dp->d_reclen;
1073             *cookiep++ = off;
1074         }
1075         *ap->a_cookies = cookies;
1076         *ap->a_ncookies = ncookies;
1077     }
1078
1079     return error;
1080 }
1081
1082 int
1083 afs_vop_readlink(ap)
1084         struct vop_readlink_args /* {
1085                 struct vnode *a_vp;
1086                 struct uio *a_uio;
1087                 struct ucred *a_cred;
1088         } */ *ap;
1089 {
1090     int error;
1091 /*    printf("readlink %x\n", ap->a_vp);*/
1092     AFS_GLOCK();
1093     error= afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1094     AFS_GUNLOCK();
1095     return error;
1096 }
1097
1098 extern int prtactive;
1099
1100 int
1101 afs_vop_inactive(ap)
1102         struct vop_inactive_args /* {
1103                 struct vnode *a_vp;
1104                 struct proc *a_p;
1105         } */ *ap;
1106 {
1107     register struct vnode *vp = ap->a_vp;
1108
1109     if (prtactive && vp->v_usecount != 0)
1110         vprint("afs_vop_inactive(): pushing active", vp);
1111
1112     AFS_GLOCK();
1113     afs_InactiveVCache(VTOAFS(vp), 0);   /* decrs ref counts */
1114     AFS_GUNLOCK();
1115     VOP_UNLOCK(vp, 0, ap->a_p);
1116     return 0;
1117 }
1118
1119 int
1120 afs_vop_reclaim(ap)
1121         struct vop_reclaim_args /* {
1122                 struct vnode *a_vp;
1123         } */ *ap;
1124 {
1125     int error;
1126     int sl;
1127     register struct vnode *vp = ap->a_vp;
1128
1129     cache_purge(vp);                    /* just in case... */
1130
1131 #if 0 
1132     AFS_GLOCK();
1133     error = afs_FlushVCache(VTOAFS(vp), &sl); /* tosses our stuff from vnode */
1134     AFS_GUNLOCK();
1135     ubc_unlink(vp);
1136     if (!error && vp->v_data)
1137         panic("afs_reclaim: vnode not cleaned");
1138     return error;
1139 #else
1140    if (vp->v_usecount == 2) {
1141         vprint("reclaim count==2", vp);
1142    } else if (vp->v_usecount == 1) {
1143         vprint("reclaim count==1", vp);
1144    } else 
1145         vprint("reclaim bad count", vp);
1146
1147    return 0;
1148 #endif
1149 }
1150
1151 int
1152 afs_vop_lock(ap)
1153         struct vop_lock_args /* {
1154                 struct vnode *a_vp;
1155         } */ *ap;
1156 {
1157         register struct vnode *vp = ap->a_vp;
1158         register struct vcache *avc = VTOAFS(vp);
1159
1160         if (vp->v_tag == VT_NON)
1161                 return (ENOENT);
1162         return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock,
1163                 ap->a_p));
1164 }
1165
1166 int
1167 afs_vop_unlock(ap)
1168         struct vop_unlock_args /* {
1169                 struct vnode *a_vp;
1170         } */ *ap;
1171 {
1172     struct vnode *vp = ap->a_vp;
1173     struct vcache *avc = VTOAFS(vp);
1174     return (lockmgr(&avc->rwlock, ap->a_flags | LK_RELEASE,
1175             &vp->v_interlock, ap->a_p));
1176
1177 }
1178
1179 int
1180 afs_vop_bmap(ap)
1181         struct vop_bmap_args /* {
1182                 struct vnode *a_vp;
1183                 daddr_t  a_bn;
1184                 struct vnode **a_vpp;
1185                 daddr_t *a_bnp;
1186                 int *a_runp;
1187                 int *a_runb;
1188         } */ *ap;
1189 {
1190     struct vcache *vcp;
1191     int error;
1192     if (ap->a_bnp) {
1193         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1194     }
1195     if (ap->a_vpp) {
1196         *ap->a_vpp = ap->a_vp;
1197     }
1198         if (ap->a_runp != NULL)
1199                 *ap->a_runp = 0;
1200 #ifdef notyet
1201         if (ap->a_runb != NULL)
1202                 *ap->a_runb = 0;
1203 #endif
1204  
1205     return 0;
1206 }
1207 int
1208 afs_vop_strategy(ap)
1209         struct vop_strategy_args /* {
1210                 struct buf *a_bp;
1211         } */ *ap;
1212 {
1213     int error;
1214     AFS_GLOCK();
1215     error= afs_ustrategy(ap->a_bp);
1216     AFS_GUNLOCK();
1217     return error;
1218 }
1219 int
1220 afs_vop_print(ap)
1221         struct vop_print_args /* {
1222                 struct vnode *a_vp;
1223         } */ *ap;
1224 {
1225     register struct vnode *vp = ap->a_vp;
1226     register struct vcache *vc = VTOAFS(ap->a_vp);
1227     int s = vc->states;
1228     printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag, vc->fid.Cell,
1229            vc->fid.Fid.Volume, vc->fid.Fid.Vnode, vc->fid.Fid.Unique, vc->opens,
1230            vc->execsOrWriters);
1231     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" : "");
1232     if (UBCISVALID(vp)) {
1233         printf("\n  UBC: ");
1234         if (UBCINFOEXISTS(vp)) {
1235                printf("exists, ") ;
1236 #ifdef AFS_DARWIN14_ENV
1237                  printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1238                          ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1239                          ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1240 #else
1241                  printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1242 #endif
1243         } else printf("does not exist");
1244     }
1245     printf("\n");
1246     return 0;
1247 }
1248
1249 int
1250 afs_vop_islocked(ap)
1251         struct vop_islocked_args /* {
1252                 struct vnode *a_vp;
1253         } */ *ap;
1254 {
1255     struct vcache *vc = VTOAFS(ap->a_vp);
1256     return lockstatus(&vc->rwlock);
1257 }
1258
1259 /*
1260  * Return POSIX pathconf information applicable to ufs filesystems.
1261  */
1262 afs_vop_pathconf(ap)
1263         struct vop_pathconf_args /* {
1264                 struct vnode *a_vp;
1265                 int a_name;
1266                 int *a_retval;
1267         } */ *ap;
1268 {
1269     AFS_STATCNT(afs_cntl);
1270     switch (ap->a_name) {
1271       case _PC_LINK_MAX:
1272         *ap->a_retval = LINK_MAX;
1273         break;
1274       case _PC_NAME_MAX:
1275         *ap->a_retval = NAME_MAX;
1276         break;
1277       case _PC_PATH_MAX:
1278         *ap->a_retval = PATH_MAX;
1279         break;
1280       case _PC_CHOWN_RESTRICTED:
1281         *ap->a_retval = 1;
1282         break;
1283       case _PC_NO_TRUNC:
1284         *ap->a_retval = 1;
1285         break;
1286       case _PC_PIPE_BUF:
1287         return EINVAL;
1288         break;
1289       default:
1290         return EINVAL;
1291     }
1292     return 0;
1293 }
1294
1295 /*
1296  * Advisory record locking support (fcntl() POSIX style)
1297  */
1298 int
1299 afs_vop_advlock(ap)
1300         struct vop_advlock_args /* {
1301                 struct vnode *a_vp;
1302                 caddr_t  a_id;
1303                 int  a_op;
1304                 struct flock *a_fl;
1305                 int  a_flags;
1306         } */ *ap;
1307 {
1308     int error;
1309     struct proc *p=current_proc();
1310     struct ucred cr;
1311     pcred_readlock(p);
1312     cr=*p->p_cred->pc_ucred;
1313     pcred_unlock(p);
1314     AFS_GLOCK();
1315     error= afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr,
1316                        (int) ap->a_id);
1317     AFS_GUNLOCK();
1318     return error;
1319 }
1320
1321 int
1322 afs_vop_truncate(ap)
1323         struct vop_truncate_args /* {
1324                 struct vnode *a_vp;
1325                 off_t a_length;
1326                 int a_flags;
1327                 struct ucred *a_cred;
1328                 struct proc *a_p;
1329         } */ *ap;
1330 {
1331     printf("stray afs_vop_truncate\n");
1332     return EOPNOTSUPP;
1333 }
1334
1335 int
1336 afs_vop_update(ap)
1337         struct vop_update_args /* {
1338                 struct vnode *a_vp;
1339                 struct timeval *a_access;
1340                 struct timeval *a_modify;
1341                 int a_waitfor;
1342         } */ *ap;
1343 {
1344     printf("stray afs_vop_update\n");
1345     return EOPNOTSUPP;
1346 }
1347
1348 int afs_vop_blktooff(ap)
1349         struct vop_blktooff_args /* {
1350                 struct vnode *a_vp;
1351                 daddr_t a_lblkno;
1352                 off_t *a_offset;    
1353         } */ *ap;
1354 {
1355         *ap->a_offset = (off_t)(ap->a_lblkno *  DEV_BSIZE);
1356         return 0;
1357 }
1358
1359 int afs_vop_offtoblk(ap)
1360         struct vop_offtoblk_args /* {
1361                 struct vnode *a_vp;
1362                 off_t a_offset;    
1363                 daddr_t *a_lblkno;
1364         } */ *ap;
1365 {
1366         *ap->a_lblkno = (daddr_t)(ap->a_offset /  DEV_BSIZE);
1367
1368         return (0);
1369 }
1370
1371 int afs_vop_cmap(ap)
1372         struct vop_cmap_args /* {
1373                 struct vnode *a_vp;
1374                 off_t a_foffset;    
1375                 size_t a_size;
1376                 daddr_t *a_bpn;
1377                 size_t *a_run;
1378                 void *a_poff;
1379         } */ *ap;
1380 {
1381         *ap->a_bpn = (daddr_t)(ap->a_foffset /  DEV_BSIZE);     
1382         *ap->a_run= MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
1383         return 0;
1384 }
1385