c7c87294d416b2c2b23dceae03d3cd10b02be474
[openafs.git] / src / afs / NBSD / osi_vnodeops.c
1 /*
2  * OpenBSD specific vnodeops + other misc interface glue
3  * Original NetBSD version for Transarc afs by John Kohl <jtk@MIT.EDU>
4  * OpenBSD version by Jim Rees <rees@umich.edu>
5  *
6  * $Id: osi_vnodeops.c,v 1.20 2006/03/09 15:27:17 rees Exp $
7  */
8
9 /*
10 copyright 2002
11 the regents of the university of michigan
12 all rights reserved
13
14 permission is granted to use, copy, create derivative works
15 and redistribute this software and such derivative works
16 for any purpose, so long as the name of the university of
17 michigan is not used in any advertising or publicity
18 pertaining to the use or distribution of this software
19 without specific, written prior authorization.  if the
20 above copyright notice or any other identification of the
21 university of michigan is included in any copy of any
22 portion of this software, then the disclaimer below must
23 also be included.
24
25 this software is provided as is, without representation
26 from the university of michigan as to its fitness for any
27 purpose, and without warranty by the university of
28 michigan of any kind, either express or implied, including
29 without limitation the implied warranties of
30 merchantability and fitness for a particular purpose. the
31 regents of the university of michigan shall not be liable
32 for any damages, including special, indirect, incidental, or
33 consequential damages, with respect to any claim arising
34 out of or in connection with the use of the software, even
35 if it has been or is hereafter advised of the possibility of
36 such damages.
37 */
38
39 /*
40 Copyright 1995 Massachusetts Institute of Technology.  All Rights
41 Reserved.
42
43 You are hereby granted a worldwide, irrevocable, paid-up, right and
44 license to use, execute, display, modify, copy and distribute MIT's
45 Modifications, provided that (i) you abide by the terms and conditions
46 of your OpenAFS License Agreement, and (ii) you do not use the name
47 of MIT in any advertising or publicity without the prior written consent
48 of MIT.  MIT disclaims all liability for your use of MIT's
49 Modifications.  MIT's Modifications are provided "AS IS" WITHOUT
50 WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
51 ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
52 NONINFRINGEMENT.
53 */
54
55 /*
56  * A bunch of code cribbed from NetBSD ufs_vnops.c, ffs_vnops.c, and
57  * nfs_vnops.c which carry this copyright:
58  */
59 /*
60  * Copyright (c) 1982, 1986, 1989, 1993
61  *      The Regents of the University of California.  All rights reserved.
62  * (c) UNIX System Laboratories, Inc.
63  * All or some portions of this file are derived from material licensed
64  * to the University of California by American Telephone and Telegraph
65  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
66  * the permission of UNIX System Laboratories, Inc.
67  *
68  * Redistribution and use in source and binary forms, with or without
69  * modification, are permitted provided that the following conditions
70  * are met:
71  * 1. Redistributions of source code must retain the above copyright
72  *    notice, this list of conditions and the following disclaimer.
73  * 2. Redistributions in binary form must reproduce the above copyright
74  *    notice, this list of conditions and the following disclaimer in the
75  *    documentation and/or other materials provided with the distribution.
76  * 3. All advertising materials mentioning features or use of this software
77  *    must display the following acknowledgement:
78  *      This product includes software developed by the University of
79  *      California, Berkeley and its contributors.
80  * 4. Neither the name of the University nor the names of its contributors
81  *    may be used to endorse or promote products derived from this software
82  *    without specific prior written permission.
83  *
84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94  * SUCH DAMAGE.
95  *
96  */
97
98 #include <afsconfig.h>
99 #include "afs/param.h"
100
101 #include "afs/sysincludes.h"    /* Standard vendor system headers */
102 #include "afs/afsincludes.h"    /* Afs-based standard headers */
103 #include "afs/afs_stats.h"      /* statistics */
104
105 #include <sys/malloc.h>
106 #include <sys/namei.h>
107 #include <sys/pool.h>
108 #include <miscfs/genfs/genfs.h>
109
110
111 #include "afs/afs_cbqueue.h"
112 #include "afs/nfsclient.h"
113 #include "afs/afs_osidnlc.h"
114
115 #define M_AFSNODE (M_TEMP-1)    /* XXX */
116
117 int afs_nbsd_lookup(void *);
118 int afs_nbsd_create(void *);
119 int afs_nbsd_mknod(void *);
120 int afs_nbsd_open(void *);
121 int afs_nbsd_close(void *);
122 int afs_nbsd_access(void *);
123 int afs_nbsd_getattr(void *);
124 int afs_nbsd_setattr(void *);
125 int afs_nbsd_read(void *);
126 int afs_nbsd_write(void *);
127 int afs_nbsd_ioctl(void *);
128 int afs_nbsd_select(void *);
129 int afs_nbsd_fsync(void *);
130 int afs_nbsd_remove(void *);
131 int afs_nbsd_link(void *);
132 int afs_nbsd_rename(void *);
133 int afs_nbsd_mkdir(void *);
134 int afs_nbsd_rmdir(void *);
135 int afs_nbsd_symlink(void *);
136 int afs_nbsd_readdir(void *);
137 int afs_nbsd_readlink(void *);
138 int afs_nbsd_inactive(void *);
139 int afs_nbsd_reclaim(void *);
140 int afs_nbsd_lock(void *);
141 int afs_nbsd_unlock(void *);
142 int afs_nbsd_bmap(void *);
143 int afs_nbsd_strategy(void *);
144 int afs_nbsd_print(void *);
145 int afs_nbsd_islocked(void *);
146 int afs_nbsd_pathconf(void *);
147 int afs_nbsd_advlock(void *);
148
149 #if LATER
150 int afs_nbsd_getpages(void*);
151 #endif
152
153 /*
154  * Implement:
155  *   vop_getpages (VM)
156  *   vop_putpages (VM)
157  *
158  * Someday:
159  *   vop_mmap_desc (mmap'd IO)
160  *
161  * Skip:
162  *   vop_*xtattr
163  *
164  * Unknown:
165  *   vop_fcntl
166  *
167  */
168
169 #define afs_nbsd_opnotsupp \
170         ((int (*) __P((void *)))eopnotsupp)
171 #define afs_nbsd_reallocblks afs_nbsd_opnotsupp
172
173 /* Global vfs data structures for AFS. */
174 int (**afs_vnodeop_p) __P((void *));
175 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
176     {&vop_default_desc, vn_default_error},
177     {&vop_lookup_desc, afs_nbsd_lookup},        /* lookup */
178     {&vop_create_desc, afs_nbsd_create},        /* create */
179     {&vop_mknod_desc, afs_nbsd_mknod},          /* mknod */
180     {&vop_open_desc, afs_nbsd_open},            /* open */
181     {&vop_close_desc, afs_nbsd_close},          /* close */
182     {&vop_access_desc, afs_nbsd_access},        /* access */
183     {&vop_getattr_desc, afs_nbsd_getattr},      /* getattr */
184     {&vop_setattr_desc, afs_nbsd_setattr},      /* setattr */
185     {&vop_read_desc, afs_nbsd_read},            /* read */
186     {&vop_write_desc, afs_nbsd_write},          /* write */
187     {&vop_ioctl_desc, afs_nbsd_ioctl},          /* XXX ioctl */
188     {&vop_poll_desc, afs_nbsd_select},          /* select */
189     {&vop_kqfilter_desc, genfs_kqfilter },      /* kqfilter */
190     {&vop_fsync_desc, afs_nbsd_fsync},          /* fsync */
191     {&vop_remove_desc, afs_nbsd_remove},        /* remove */
192     {&vop_link_desc, afs_nbsd_link},            /* link */
193     {&vop_rename_desc, afs_nbsd_rename},        /* rename */
194     {&vop_mkdir_desc, afs_nbsd_mkdir},          /* mkdir */
195     {&vop_rmdir_desc, afs_nbsd_rmdir},          /* rmdir */
196     {&vop_symlink_desc, afs_nbsd_symlink},      /* symlink */
197     {&vop_readdir_desc, afs_nbsd_readdir},      /* readdir */
198     {&vop_readlink_desc, afs_nbsd_readlink},    /* readlink */
199     {&vop_abortop_desc, genfs_abortop},         /* abortop */
200     {&vop_inactive_desc, afs_nbsd_inactive},    /* inactive */
201     {&vop_reclaim_desc, afs_nbsd_reclaim},      /* reclaim */
202     {&vop_lock_desc, afs_nbsd_lock},            /* lock */
203     {&vop_unlock_desc, afs_nbsd_unlock},        /* unlock */
204     {&vop_bmap_desc, afs_nbsd_bmap},            /* bmap */
205     {&vop_strategy_desc, afs_nbsd_strategy},    /* strategy */
206     {&vop_print_desc, afs_nbsd_print},          /* print */
207     {&vop_islocked_desc, afs_nbsd_islocked},    /* islocked */
208     {&vop_pathconf_desc, afs_nbsd_pathconf},    /* pathconf */
209     {&vop_advlock_desc, afs_nbsd_advlock},      /* advlock */
210 #if 0
211     {&vop_reallocblks_desc, afs_nbsd_reallocblks},      /* reallocblks */
212 #endif
213     {&vop_bwrite_desc, vn_bwrite},      /* bwrite */
214 #if LATER
215     { &vop_getpages_desc, ffs_getpages },       /* getpages */
216     { &vop_putpages_desc, genfs_putpages },     /* putpages */
217 #endif
218     {(struct vnodeop_desc *)NULL, (int (*)__P((void *)))NULL}
219 };
220 struct vnodeopv_desc afs_vnodeop_opv_desc =
221     { &afs_vnodeop_p, afs_vnodeop_entries };
222
223 #define GETNAME() \
224     struct componentname *cnp = ap->a_cnp; \
225     char *name; \
226     name = PNBUF_GET(); \
227     bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
228     name[cnp->cn_namelen] = '\0'
229
230 #define DROPNAME() PNBUF_PUT(name)
231 #define DROPCNP PNBUF_PUT
232
233 /* toss "stale" pages by shrinking the vnode uobj to a 0-length
234  * region (see uvm_vnp_setsize in uvm_vnode.c) */
235 #ifdef AFS_NBSD50_ENV
236 #define VNP_UNCACHE(vp) \
237     do {                \
238         struct uvm_object *uobj = &vp->v_uobj; \
239         mutex_enter(&uobj->vmobjlock); \
240         VOP_PUTPAGES( (struct vnode *) uobj, 0 /* offlo */, 0 /* offhi */, PGO_FREE | PGO_SYNCIO); \
241         mutex_exit(&uobj->vmobjlock); \
242     } while(0);
243 #else
244 #define VNP_UNCACHE(vp) \
245     do {                \
246         struct uvm_object *uobj = &vp->v_uobj; \
247         simple_lock(&uobj->vmobjlock); \
248         VOP_PUTPAGES( (struct vnode *) uobj, 0 /* offlo */, 0 /* offhi */, PGO_FREE | PGO_SYNCIO); \
249         simple_unlock(&uobj->vmobjlock); \
250     } while(0);
251 #endif
252
253 /* psuedo-vnop, wherein we learn that obsd and nbsd disagree
254  * about vnode refcounting */
255 void
256 afs_nbsd_getnewvnode(struct vcache *tvc)
257 {
258     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
259         /* no vnodes available, force an alloc (limits be damned)! */
260         desiredvnodes++;
261     }
262     printf("afs_nbsd_getnewvnode: vp %p refs %d\n", tvc->v,
263           tvc->v->v_usecount);
264 #ifdef AFS_NBSD50_ENV
265     mutex_enter(&tvc->v->v_interlock);
266 #else
267     simple_lock(&tvc->v->v_interlock);
268 #endif
269     tvc->v->v_data = (void *)tvc;
270 #if 0
271     tvc->v->v_usecount = 1; /* !locked, and vref w/v_usecount < 1 panics */
272 #endif
273 #ifdef AFS_NBSD50_ENV
274     mutex_exit(&tvc->v->v_interlock);
275 #else
276     simple_unlock(&tvc->v->v_interlock);
277 #endif
278 }
279
280 unsigned long long afs_debug;
281
282 int
283 afs_nbsd_lookup(void *v)
284 {
285     struct vop_lookup_args      /* {
286                                  * struct vnodeop_desc * a_desc;
287                                  * struct vnode *a_dvp;
288                                  * struct vnode **a_vpp;
289                                  * struct componentname *a_cnp;
290                                  * } */ *ap = v;
291     int code;
292     struct vcache *vcp;
293     struct vnode *vp, *dvp;
294     int flags = ap->a_cnp->cn_flags;
295     int lockparent;             /* 1 => lockparent flag is set */
296
297     if (afs_debug & AFSDEB_VNLAYER)
298         printf("nbsd_lookup enter ap %p\n", ap);
299
300     GETNAME();
301     lockparent = flags & LOCKPARENT;
302     if (ap->a_dvp->v_type != VDIR) {
303         *ap->a_vpp = NULL;
304         DROPNAME();
305         return ENOTDIR;
306     }
307     dvp = ap->a_dvp;
308 /*
309 *       v_flag was broke up into 3 separate flags. v_vflag is the
310 *       substitute when referencing V_ROOT (which was also renamed)
311 *
312 *       mattjsm
313 */
314 #ifdef AFS_NBSD50_ENV
315     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_vflag & VV_ROOT))
316 #else
317     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
318 #endif
319         printf("nbsd_lookup dvp %p flags %x name %s v_usecnt %d\n", dvp, flags,
320                name, dvp->v_usecount);
321     AFS_GLOCK();
322     code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
323     AFS_GUNLOCK();
324     if (code) {
325         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
326             && (flags & ISLASTCN) && code == ENOENT)
327             code = EJUSTRETURN;
328         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
329             cnp->cn_flags |= SAVENAME;
330         DROPNAME();
331         *ap->a_vpp = NULL;
332         return (code);
333     }
334     vp = AFSTOV(vcp); /* always get a node if no error */
335
336     /*
337      * The parent directory comes in locked.  We unlock it on return
338      * unless the caller wants it left locked.
339      * we also always return the vnode locked.
340      */
341
342     if (vp == dvp) {
343         /* they're the same; afs_lookup() already ref'ed the leaf.
344          * It came in locked, so we don't need to ref OR lock it */
345         if (afs_debug & AFSDEB_VNLAYER)
346             printf("nbsd_lookup: ref'ed %p as .\n", dvp);
347     } else {
348         if (!lockparent || !(flags & ISLASTCN)) {
349             VOP_UNLOCK(dvp, 0); /* done with parent. */
350         }
351
352         if (afs_debug & AFSDEB_VNLAYER)
353             printf("nbsd_lookup dvp %p flags %x name %s v_usecnt %d\n",
354                    dvp, flags, name, dvp->v_usecount);
355
356         /* XXXX hacked here, recheck OBSD and bundled--NBSD has
357          * removed PDIRUNLOCK, so we must at least accommodate that
358          * change. M.*/
359         if (!VOP_ISLOCKED(vp)) {
360             vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
361             if (afs_debug & AFSDEB_VNLAYER)
362                 printf("nbsd_lookup: omitting to always return child locked\n");
363             /* vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); *//* always return the child locked */
364         } else {
365             if (afs_debug & AFSDEB_VNLAYER)
366                 printf("lookup: vp %p is locked\n", vp);
367         }
368         if (afs_debug & AFSDEB_VNLAYER)
369             printf("locked ret %p from lookup\n", vp);
370     }
371     *ap->a_vpp = vp;
372
373     if (((cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
374      || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
375     cnp->cn_flags |= SAVENAME;
376
377     DROPNAME();
378 #ifdef AFS_NBSD50_ENV
379     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_vflag & VV_ROOT))
380 #else
381     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
382 #endif
383         if (afs_debug & AFSDEB_VNLAYER)
384             printf("nbsd_lookup done ap %p dvp %p cnt %d\n", ap, dvp,
385                    dvp->v_usecount);
386     return (code);
387 }
388
389 int
390 afs_nbsd_create(void *v)
391 {
392     struct vop_create_args      /* {
393                                  * struct vnode *a_dvp;
394                                  * struct vnode **a_vpp;
395                                  * struct componentname *a_cnp;
396                                  * struct vattr *a_vap;
397                                  * } */ *ap = v;
398     int code = 0;
399     struct vcache *vcp;
400     struct vnode *dvp = ap->a_dvp;
401     GETNAME();
402
403     if (afs_debug & AFSDEB_VNLAYER)
404         printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
405
406     /* vnode layer handles excl/nonexcl */
407
408     AFS_GLOCK();
409     code =
410         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
411                    &vcp, cnp->cn_cred);
412     AFS_GUNLOCK();
413     if (code) {
414         VOP_ABORTOP(dvp, cnp);
415         vput(dvp);
416         DROPNAME();
417         return (code);
418     }
419
420     if (vcp) {
421         *ap->a_vpp = AFSTOV(vcp);
422         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
423     } else
424         *ap->a_vpp = 0;
425
426     if ((cnp->cn_flags & SAVESTART) == 0)
427         DROPCNP(cnp);
428     vput(dvp);
429     DROPNAME();
430     if (afs_debug & AFSDEB_VNLAYER)
431         printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
432     return code;
433 }
434
435 int
436 afs_nbsd_mknod(void *v)
437 {
438     struct vop_mknod_args       /* {
439                                  * struct vnode *a_dvp;
440                                  * struct vnode **a_vpp;
441                                  * struct componentname *a_cnp;
442                                  * struct vattr *a_vap;
443                                  * } */ *ap = v;
444
445     if (afs_debug & AFSDEB_VNLAYER)
446         printf("nbsd_mknod: enter ap %p\n", ap);
447
448     DROPCNP(ap->a_cnp);
449     vput(ap->a_dvp);
450     return (ENODEV);
451
452     if (afs_debug & AFSDEB_VNLAYER)
453         printf("nbsd_mknod: exit ap %p\n", ap);
454 }
455
456 int
457 afs_nbsd_open(void *v)
458 {
459     struct vop_open_args        /* {
460                                  * struct vnode *a_vp;
461                                  * int  a_mode;
462                                  * struct ucred *a_cred;
463                                  * struct lwp *a_l;
464                                  * } */ *ap = v;
465     int code;
466     struct vnode *vp = ap->a_vp;
467     struct vcache *vc = VTOAFS(vp);
468
469     if (afs_debug & AFSDEB_VNLAYER)
470         printf("nbsd_open: enter vp %p vc %p\n", vp, vc);
471
472     AFS_GLOCK();
473     code = afs_open(&vc, ap->a_mode, ap->a_cred);
474 #ifdef DIAGNOSTIC
475     if (AFSTOV(vc) != ap->a_vp)
476         panic("nbsd_open: AFS open changed vnode!");
477 #endif
478     AFS_GUNLOCK();
479
480     if (afs_debug & AFSDEB_VNLAYER)
481         printf("nbsd_open: exit vp %p vc %p\n", vp, vc);
482
483     return (code);
484 }
485
486 int
487 afs_nbsd_close(void *v)
488 {
489     struct vop_close_args       /* {
490                                  * struct vnode *a_vp;
491                                  * int  a_fflag;
492                                  * kauth_cred_t a_cred;
493                                  * struct lwp *a_l;
494                                  * } */ *ap = v;
495     int code;
496     struct vnode *vp = ap->a_vp;
497     struct vcache *vc = VTOAFS(vp);
498
499     if (afs_debug & AFSDEB_VNLAYER)
500         printf("nbsd_close: enter vp %p vc %p\n", vp, vc);
501
502     AFS_GLOCK();
503     code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred);
504     AFS_GUNLOCK();
505
506     if (afs_debug & AFSDEB_VNLAYER)
507         printf("nbsd_close: exit vp %p vc %p\n", vp, vc);
508
509     return (code);
510 }
511
512 int
513 afs_nbsd_access(void *v)
514 {
515     struct vop_access_args      /* {
516                                  * struct vnode *a_vp;
517                                  * int  a_mode;
518                                  * kauth_cred_t a_cred;
519                                  * struct lwp *a_l;
520                                  * } */ *ap = v;
521     int code;
522     struct vnode *vp = ap->a_vp;
523     struct vcache *vc = VTOAFS(vp);
524
525     if (afs_debug & AFSDEB_VNLAYER)
526         printf("nbsd_access: enter vp %p vc %p mode %d\n", vp, vc, ap->a_mode);
527
528     AFS_GLOCK();
529     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
530     AFS_GUNLOCK();
531
532     if (afs_debug & AFSDEB_VNLAYER)
533         printf("nbsd_access: exit vp %p vc %p mode %d\n", vp, vc, ap->a_mode);
534
535     return (code);
536 }
537
538 int
539 afs_nbsd_getattr(void *v)
540 {
541     struct vop_getattr_args     /* {
542                                  * struct vnode *a_vp;
543                                  * struct vattr *a_vap;
544                                  * kauth_cred_t a_cred;
545                                  * struct lwp *a_l;
546                                  * } */ *ap = v;
547     int code;
548     struct vnode *vp = ap->a_vp;
549     struct vcache *vc = VTOAFS(vp);
550
551     if (afs_debug & AFSDEB_VNLAYER)
552         printf("nbsd_getattr: enter vp %p vc %p acred %p\n", vp, vc,
553                ap->a_cred);
554
555     AFS_GLOCK();
556     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
557     AFS_GUNLOCK();
558
559     if (afs_debug & AFSDEB_VNLAYER)
560         printf("nbsd_getattr: exit vp %p vc %p acred %p\n", vp, vc,
561                ap->a_cred);
562
563     return (code);
564 }
565
566 int
567 afs_nbsd_setattr(void *v)
568 {
569     struct vop_setattr_args     /* {
570                                  * struct vnode *a_vp;
571                                  * struct vattr *a_vap;
572                                  * kauth_cred_t a_cred;
573                                  * struct lwp *a_l;
574                                  * } */ *ap = v;
575     int code;
576
577     if (afs_debug & AFSDEB_VNLAYER)
578         printf("nbsd_setattr: enter %p\n", ap);
579
580     AFS_GLOCK();
581     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
582     AFS_GUNLOCK();
583
584     if (afs_debug & AFSDEB_VNLAYER)
585         printf("nbsd_setattr: exit %p\n", ap);
586
587     return (code);
588 }
589
590 int
591 afs_nbsd_read(void *v)
592 {
593     struct vop_read_args        /* {
594                                  * struct vnode *a_vp;
595                                  * struct uio *a_uio;
596                                  * int a_ioflag;
597                                  * kauth_cred_t a_cred;
598                                  * } */ *ap = v;
599     int code;
600
601     if (afs_debug & AFSDEB_VNLAYER)
602         printf("nbsd_read enter %p", ap);
603
604     AFS_GLOCK();
605     code = afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, 0);
606     AFS_GUNLOCK();
607
608     if (afs_debug & AFSDEB_VNLAYER)
609         printf("nbsd_read exit %p", ap);
610
611     return (code);
612 }
613
614 int
615 afs_nbsd_write(void *v)
616 {
617     struct vop_write_args       /* {
618                                  * struct vnode *a_vp;
619                                  * struct uio *a_uio;
620                                  * int a_ioflag;
621                                  * kauth_cred_t a_cred;
622                                  * } */ *ap = v;
623     int code;
624
625     if (afs_debug & AFSDEB_VNLAYER)
626         printf("nbsd_write enter %p", ap);
627
628 #if 1
629     /* all pages are really "stale?" */
630     VNP_UNCACHE(ap->a_vp);
631 #else
632     (void)uvm_vnp_uncache(ap->a_vp);    /* toss stale pages */
633 #endif
634     AFS_GLOCK();
635     code =
636         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
637     AFS_GUNLOCK();
638
639     if (afs_debug & AFSDEB_VNLAYER)
640         printf("nbsd_write exit %p", ap);
641
642     return (code);
643 }
644
645 int
646 afs_nbsd_ioctl(void *v)
647 {
648     struct vop_ioctl_args       /* {
649                                  * struct vnode *a_vp;
650                                  * int  a_command;
651                                  * caddr_t  a_data;
652                                  * int  a_fflag;
653                                  * kauth_cred_t a_cred;
654                                  * struct lwp *a_l;
655                                  * } */ *ap = v;
656     int code;
657
658     if (afs_debug & AFSDEB_VNLAYER)
659         printf("nbsd_ioctl: enter %p\n", ap);
660
661     /* in case we ever get in here... */
662
663     AFS_STATCNT(afs_ioctl);
664     AFS_GLOCK();
665     if (((ap->a_command >> 8) & 0xff) == 'V')
666         /* This is a VICEIOCTL call */
667         code =
668             HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
669                         (struct afs_ioctl *)ap->a_data);
670     else
671         /* No-op call; just return. */
672         code = ENOTTY;
673     AFS_GUNLOCK();
674
675     if (afs_debug & AFSDEB_VNLAYER)
676         printf("nbsd_ioctl: exit %p\n", ap);
677
678     return (code);
679 }
680
681 int
682 afs_nbsd_select(void *v)
683 {
684     return 1;
685 }
686
687 int
688 afs_nbsd_fsync(void *v)
689 {
690     struct vop_fsync_args       /* {
691                                  * struct vnode *a_vp;
692                                  * kauth_cred_t a_cred;
693                                  * int a_waitfor;
694                                  * struct lwp *a_l;
695                                  * } */ *ap = v;
696     struct vnode *vp = ap->a_vp;
697     int code, wait;
698
699     if (afs_debug & AFSDEB_VNLAYER)
700         printf("nbsd_fsync: enter %p\n", ap);
701
702     wait = (ap->a_flags & FSYNC_WAIT) != 0;
703
704     AFS_GLOCK();
705     vflushbuf(vp, wait);
706     code = afs_fsync(VTOAFS(vp), ap->a_cred);
707     AFS_GUNLOCK();
708
709     if (afs_debug & AFSDEB_VNLAYER)
710         printf("nbsd_fsync: exit %p\n", ap);
711
712     return (code);
713 }
714
715 int
716 afs_nbsd_remove(void *v)
717 {
718     struct vop_remove_args      /* {
719                                  * struct vnode *a_dvp;
720                                  * struct vnode *a_vp;
721                                  * struct componentname *a_cnp;
722                                  * } */ *ap = v;
723     int code;
724     struct vnode *vp = ap->a_vp;
725     struct vnode *dvp = ap->a_dvp;
726
727     if (afs_debug & AFSDEB_VNLAYER)
728         printf("nbsd_remove: enter %p\n", ap);
729
730     GETNAME();
731     AFS_GLOCK();
732     code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
733     AFS_GUNLOCK();
734     if (dvp == vp)
735         vrele(vp);
736     else
737         vput(vp);
738     vput(dvp);
739     DROPCNP(cnp);
740     DROPNAME();
741
742     if (afs_debug & AFSDEB_VNLAYER)
743         printf("nbsd_remove: exit %p\n", ap);
744
745     return (code);
746 }
747
748 int
749 afs_nbsd_link(void *v)
750 {
751     struct vop_link_args        /* {
752                                  * struct vnode *a_vp;
753                                  * struct vnode *a_tdvp;
754                                  * struct componentname *a_cnp;
755                                  * } */ *ap = v;
756     int code;
757     struct vnode *dvp = ap->a_dvp;
758     struct vnode *vp = ap->a_vp;
759
760     if (afs_debug & AFSDEB_VNLAYER)
761         printf("nbsd_link: enter %p\n", ap);
762
763     GETNAME();
764     if (dvp->v_mount != vp->v_mount) {
765         VOP_ABORTOP(vp, cnp);
766         code = EXDEV;
767         goto out;
768     }
769     if (vp->v_type == VDIR) {
770         VOP_ABORTOP(vp, cnp);
771         code = EISDIR;
772         goto out;
773     }
774     if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))) {
775         VOP_ABORTOP(dvp, cnp);
776         goto out;
777     }
778
779     AFS_GLOCK();
780     code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
781     AFS_GUNLOCK();
782     DROPCNP(cnp);
783     if (dvp != vp)
784         VOP_UNLOCK(vp, 0);
785
786   out:
787     vput(dvp);
788     DROPNAME();
789
790     if (afs_debug & AFSDEB_VNLAYER)
791         printf("nbsd_link: exit %p\n", ap);
792
793     return (code);
794 }
795
796 int
797 afs_nbsd_rename(void *v)
798 {
799     struct vop_rename_args      /* {
800                                  * struct vnode *a_fdvp;
801                                  * struct vnode *a_fvp;
802                                  * struct componentname *a_fcnp;
803                                  * struct vnode *a_tdvp;
804                                  * struct vnode *a_tvp;
805                                  * struct componentname *a_tcnp;
806                                  * } */ *ap = v;
807     int code = 0;
808     struct componentname *fcnp = ap->a_fcnp;
809     char *fname;
810     struct componentname *tcnp = ap->a_tcnp;
811     char *tname;
812     struct vnode *tvp = ap->a_tvp;
813     struct vnode *tdvp = ap->a_tdvp;
814     struct vnode *fvp = ap->a_fvp;
815     struct vnode *fdvp = ap->a_fdvp;
816
817     if (afs_debug & AFSDEB_VNLAYER)
818         printf("nbsd_rename: enter %p\n", ap);
819
820     /*
821      * Check for cross-device rename.
822      */
823     if ((fvp->v_mount != tdvp->v_mount)
824         || (tvp && (fvp->v_mount != tvp->v_mount))) {
825         code = EXDEV;
826     abortit:
827         VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
828         if (tdvp == tvp)
829             vrele(tdvp);
830         else
831             vput(tdvp);
832         if (tvp)
833             vput(tvp);
834         VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
835         vrele(fdvp);
836         vrele(fvp);
837         goto out;
838     }
839     /*
840      * if fvp == tvp, we're just removing one name of a pair of
841      * directory entries for the same element.  convert call into rename.
842      ( (pinched from NetBSD 1.0's ufs_rename())
843      */
844     if (fvp == tvp) {
845         if (fvp->v_type == VDIR) {
846             code = EINVAL;
847             goto abortit;
848         }
849
850         /* Release destination completely. */
851         VOP_ABORTOP(tdvp, tcnp);
852         vput(tdvp);
853         vput(tvp);
854
855         /* Delete source. */
856         vrele(fdvp);
857         vrele(fvp);
858         fcnp->cn_flags &= ~MODMASK;
859         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
860         if ((fcnp->cn_flags & SAVESTART) == 0)
861             panic("afs_rename: lost from startdir");
862         fcnp->cn_nameiop = DELETE;
863         (void)relookup(fdvp, &fvp, fcnp);
864         code = VOP_REMOVE(fdvp, fvp, fcnp);
865         goto out;
866     }
867
868     if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)))
869         goto abortit;
870
871     /* XXX GETNAME() ? */
872     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
873     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
874     fname[fcnp->cn_namelen] = '\0';
875     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
876     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
877     tname[tcnp->cn_namelen] = '\0';
878
879     AFS_GLOCK();
880     /* XXX use "from" or "to" creds? NFS uses "to" creds */
881     code =
882         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname,
883                    tcnp->cn_cred);
884     AFS_GUNLOCK();
885
886     VOP_UNLOCK(fvp, 0);
887     FREE(fname, M_TEMP);
888     FREE(tname, M_TEMP);
889     if (code)
890         goto abortit;        /* XXX */
891     if (tdvp == tvp)
892         vrele(tdvp);
893     else
894         vput(tdvp);
895     if (tvp)
896         vput(tvp);
897     vrele(fdvp);
898     vrele(fvp);
899
900  out:
901     if (afs_debug & AFSDEB_VNLAYER)
902         printf("nbsd_rename: exit %p\n", ap);
903
904     return (code);
905 }
906
907 int
908 afs_nbsd_mkdir(void *v)
909 {
910     struct vop_mkdir_args       /* {
911                                  * struct vnode *a_dvp;
912                                  * struct vnode **a_vpp;
913                                  * struct componentname *a_cnp;
914                                  * struct vattr *a_vap;
915                                  * } */ *ap = v;
916     struct vnode *dvp = ap->a_dvp;
917     struct vattr *vap = ap->a_vap;
918     int code;
919     struct vcache *vcp;
920
921     if (afs_debug & AFSDEB_VNLAYER)
922         printf("nbsd_mkdir: enter %p\n", ap);
923
924     GETNAME();
925 #ifdef DIAGNOSTIC
926     if ((cnp->cn_flags & HASBUF) == 0)
927         panic("afs_nbsd_mkdir: no name");
928 #endif
929     AFS_GLOCK();
930     code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
931     AFS_GUNLOCK();
932     if (code) {
933         VOP_ABORTOP(dvp, cnp);
934         vput(dvp);
935         DROPNAME();
936         goto out;
937     }
938     if (vcp) {
939         *ap->a_vpp = AFSTOV(vcp);
940         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
941     } else
942         *ap->a_vpp = 0;
943     DROPCNP(cnp);
944     DROPNAME();
945     vput(dvp);
946
947  out:
948     if (afs_debug & AFSDEB_VNLAYER)
949         printf("nbsd_mkdir: exit %p\n", ap);
950
951     return (code);
952 }
953
954 int
955 afs_nbsd_rmdir(void *v)
956 {
957     struct vop_rmdir_args       /* {
958                                  * struct vnode *a_dvp;
959                                  * struct vnode *a_vp;
960                                  * struct componentname *a_cnp;
961                                  * } */ *ap = v;
962     int code;
963     struct vnode *vp = ap->a_vp;
964     struct vnode *dvp = ap->a_dvp;
965
966     if (afs_debug & AFSDEB_VNLAYER)
967         printf("nbsd_rmdir: enter %p", ap);
968
969     GETNAME();
970     if (dvp == vp) {
971         vrele(dvp);
972         vput(vp);
973         DROPCNP(cnp);
974         DROPNAME();
975         code = EINVAL;
976         goto out;
977     }
978
979     AFS_GLOCK();
980     code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
981     AFS_GUNLOCK();
982     DROPNAME();
983     vput(dvp);
984     vput(vp);
985
986  out:
987     if (afs_debug & AFSDEB_VNLAYER)
988         printf("nbsd_rmdir: exit %p\n", ap);
989
990     return (code);
991 }
992
993 int
994 afs_nbsd_symlink(void *v)
995 {
996     struct vop_symlink_args     /* {
997                                  * struct vnode *a_dvp;
998                                  * struct vnode **a_vpp;
999                                  * struct componentname *a_cnp;
1000                                  * struct vattr *a_vap;
1001                                  * char *a_target;
1002                                  * } */ *ap = v;
1003     struct vnode *dvp = ap->a_dvp;
1004     int code;
1005     /* NFS ignores a_vpp; so do we. */
1006
1007     if (afs_debug & AFSDEB_VNLAYER)
1008         printf("nbsd_symlink: enter %p\n", ap);
1009
1010     GETNAME();
1011     AFS_GLOCK();
1012     code =
1013         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
1014                     cnp->cn_cred);
1015     AFS_GUNLOCK();
1016     DROPCNP(cnp);
1017     DROPNAME();
1018     vput(dvp);
1019
1020     if (afs_debug & AFSDEB_VNLAYER)
1021         printf("nbsd_symlink: exit %p\n", ap);
1022
1023     return (code);
1024 }
1025
1026 int
1027 nbsd_fake_readdir(struct vnode *vp, struct vcache *vc, struct uio *auio,
1028                   kauth_cred_t acred, int *a_eofflag, int *a_ncookies,
1029                   u_long **a_cookies)
1030 {
1031     static int ino = 2;
1032     afs_int32 code, maxb;
1033     struct dirent *dp;
1034     maxb = auio->uio_resid;
1035
1036     if (afs_debug & AFSDEB_VNLAYER)
1037         printf("nbsd_fake_readdir: enter vp %p vc %p acred %p auio %p "
1038                "uio_offset %d uio_resid %d\n",
1039                vp, vc, acred, auio, (int) auio->uio_offset,
1040                (int) auio->uio_resid);
1041
1042     /* 1. simply returning 0 had good behavior (/afs is empty) */
1043
1044 /*
1045 (gdb) p *auio
1046 $5 = {uio_iov = 0xcbd0ec90, uio_iovcnt = 1, uio_offset = 0, uio_resid = 4096,
1047   uio_rw = UIO_READ, uio_vmspace = 0xcbe8beec}
1048 */
1049     /* ok.  we don't know about cookies, so since auio->uio_resid is 4096,
1050      * what we can legitimately do is move as many appropriately aligned
1051      * NetBSD dirent records into uio_iov[0] as will fit in the total size
1052      * of 4KB.  We do not need to zero-fill anything.  This does not
1053      * terminate the directly listing. If we return 0, VFS will re-enter
1054      * nbsd_readdir to continue reading--to termiate the iteration, we must
1055      * return a non-zero value from nbsd_readdir.  VOP_READDIR(9) appears to
1056      * suggest that enumeration is terminated by setting a_eofflag = 1,
1057      * but as noted there this -can- only be done if VFS passed a value for
1058      * a_eofflag--apparently, this is to do with NFS.  Setting the eof is
1059      * correct but insufficient. */
1060
1061     /* 2. next, let's move ONE entry in by hand--due to termination
1062      * rules, this will actually create file_1 .. file_99 and many
1063      * unecessary nbsd_readdir invocations.  The solution to this is to
1064      * make proper use of auio->uio_offset and auio->uio_resid, together
1065      * when accounting bytes moved each invocation, allowing VFS to
1066      * invoke nbsd_readdir at successive offsets until we have consumed
1067      * all entries in all chunks of the vnode being read--setting a_eofflag
1068      * when this is done.
1069      */
1070
1071     /* this isn't thread safe--we would in fact use incoming offset
1072      * to select the offset of the next AFS dirent, read it, then take
1073      * its values for (modulo volume) inode number and name */
1074     if (auio->uio_offset == 0)
1075         ino = 2;
1076
1077     dp = (struct dirent *) kmem_zalloc(sizeof(struct dirent), KM_SLEEP);
1078     dp->d_ino =  ino;
1079     dp->d_type = DT_REG;
1080     sprintf(dp->d_name, "file_%d", ino);
1081     dp->d_namlen = strlen(dp->d_name);
1082     dp->d_reclen = _DIRENT_SIZE(dp); /* comp reclen from d_namlen and align */
1083     printf("nbsd_fake_readdir: add dirent %s\n", dp->d_name);
1084     code = uiomove(dp, dp->d_reclen, auio);
1085     if (code)
1086         printf("nbsd_fake_readdir: uiomove FAILED\n");
1087     kmem_free(dp, sizeof(struct dirent));
1088     ++ino;
1089
1090     /* terminate enumeration */
1091     if (!code)
1092         if (ino > 100) {
1093             code = EINVAL;
1094             if(a_eofflag)
1095                 *a_eofflag = 1;
1096         }
1097
1098     return (code);
1099 }
1100
1101 int
1102 afs_nbsd_readdir(void *v)
1103 {
1104     struct vop_readdir_args     /* {
1105                                  * struct vnode *a_vp;
1106                                  * struct uio *a_uio;
1107                                  * kauth_cred_t a_cred;
1108                                  * int *a_eofflag;
1109                                  * int *a_ncookies;
1110                                  * u_long **a_cookies;
1111                                  * } */ *ap = v;
1112     int code;
1113     struct vnode *vp = ap->a_vp;
1114     struct vcache *vc = VTOAFS(vp);
1115
1116     if (afs_debug & AFSDEB_VNLAYER)
1117         printf("nbsd_readdir: enter vp %p vc %p acred %p auio %p\n", vp, vc,
1118                ap->a_cred, ap->a_uio);
1119
1120     AFS_GLOCK();
1121 #ifdef AFS_HAVE_COOKIES
1122     printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
1123            ap->a_ncookies);
1124     code =
1125         afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag,
1126                     ap->a_ncookies, ap->a_cookies);
1127 #else
1128     code =
1129         afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag);
1130 #endif
1131     AFS_GUNLOCK();
1132
1133     if (afs_debug & AFSDEB_VNLAYER)
1134         printf("nbsd_readdir: exit %p eofflag %d\n", ap, *ap->a_eofflag);
1135
1136     return (code);
1137 }
1138
1139 int
1140 afs_nbsd_readlink(void *v)
1141 {
1142     struct vop_readlink_args    /* {
1143                                  * struct vnode *a_vp;
1144                                  * struct uio *a_uio;
1145                                  * kauth_cred_t a_cred;
1146                                  * } */ *ap = v;
1147     int code;
1148
1149     if (afs_debug & AFSDEB_VNLAYER)
1150         printf("nbsd_readlink: enter %p\n", ap);
1151
1152     AFS_GLOCK();
1153     code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1154     AFS_GUNLOCK();
1155
1156     if (afs_debug & AFSDEB_VNLAYER)
1157         printf("nbsd_readlink: exit %p\n", ap);
1158
1159     return (code);
1160 }
1161
1162 extern int prtactive;
1163
1164 int
1165 afs_nbsd_inactive(void *v)
1166 {
1167     struct vop_inactive_args    /* {
1168                                  * struct vnode *a_vp;
1169                                  * } */ *ap = v;
1170     struct vnode *vp = ap->a_vp;
1171     struct vcache *vc = VTOAFS(vp);
1172     int haveGlock = ISAFS_GLOCK();
1173
1174     AFS_STATCNT(afs_inactive);
1175
1176     if (afs_debug & AFSDEB_VNLAYER)
1177         printf("nbsd_inactive: enter %p\n", ap);
1178
1179     if (prtactive && vp->v_usecount != 0)
1180         vprint("afs_nbsd_inactive: pushing active", vp);
1181
1182     if (!haveGlock)
1183         AFS_GLOCK();
1184     afs_InactiveVCache(vc, 0);  /* decrs ref counts */
1185     if (!haveGlock)
1186         AFS_GUNLOCK();
1187
1188 #ifdef AFS_NBSD50_ENV
1189     mutex_init(&vc->rwlock, MUTEX_DEFAULT, IPL_NONE);
1190 #else
1191     lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
1192 #endif
1193
1194     if (afs_debug & AFSDEB_VNLAYER)
1195         printf("nbsd_inactive: exit %p\n", ap);
1196
1197     return (0);
1198 }
1199
1200 int
1201 afs_nbsd_reclaim(void *v)
1202 {
1203     struct vop_reclaim_args     /* {
1204                                  * struct vnode *a_vp;
1205                                  * } */ *ap = v;
1206     int code, slept;
1207     struct vnode *vp = ap->a_vp;
1208     struct vcache *avc = VTOAFS(vp);
1209     int haveGlock = ISAFS_GLOCK();
1210     int haveVlock = CheckLock(&afs_xvcache);
1211
1212         if (afs_debug & AFSDEB_VNLAYER)
1213                 printf("nbsd_reclaim: enter %p\n", ap);
1214
1215 #if 0
1216     printf("reclaim usecount %d\n", vp->v_usecount);
1217     /* OK, there are no internal vrefCounts, so there shouldn't
1218      * be any more refs here. */
1219     vp->v_data = NULL;          /* remove from vnode */
1220     avc->v = NULL;              /* also drop the ptr to vnode */
1221
1222         if (afs_debug & AFSDEB_VNLAYER)
1223                 printf("nbsd_reclaim: exit %p\n", ap);
1224
1225     return (0);
1226 #else
1227     if (!haveGlock)
1228                 AFS_GLOCK();
1229     if (!haveVlock)
1230                 ObtainWriteLock(&afs_xvcache, 901);
1231 #ifndef AFS_DISCON_ENV
1232         code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
1233 #else
1234     /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
1235     code = afs_FlushVCache(avc, &slept);
1236 #endif
1237     if (!haveVlock)
1238                 ReleaseWriteLock(&afs_xvcache);
1239     if (!haveGlock)
1240                 AFS_GUNLOCK();
1241
1242         if (afs_debug & AFSDEB_VNLAYER)
1243                 printf("nbsd_reclaim: exit %p\n", ap);
1244
1245     return code;
1246 #endif /* 0 */
1247 }
1248
1249 int
1250 afs_nbsd_lock(void *v)
1251 {
1252     struct vop_lock_args        /* {
1253                                  * struct vnode *a_vp;
1254                                  * int a_flags;
1255                                  * struct lwp *a_l;
1256                                  * } */ *ap = v;
1257     int code;
1258     struct vnode *vp = ap->a_vp;
1259     int flags = ap->a_flags;
1260
1261     if (afs_debug & AFSDEB_VNLAYER)
1262         printf("nbsd_lock: enter vp %p flags %d\n", vp, flags);
1263
1264     code = genfs_lock(v);
1265
1266     if (afs_debug & AFSDEB_VNLAYER)
1267         printf("nbsd_lock: exit vp %p flags %d\n\n", vp, flags);
1268
1269     return (code);
1270 }
1271
1272 int
1273 afs_nbsd_unlock(void *v)
1274 {
1275     struct vop_unlock_args      /* {
1276                                  * struct vnode *a_vp;
1277                                  * int a_flags;
1278                                  * struct lwp *a_l;
1279                                  * } */ *ap = v;
1280     int code;
1281     struct vnode *vp = ap->a_vp;
1282     int flags = ap->a_flags;
1283
1284     if (afs_debug & AFSDEB_VNLAYER)
1285         printf("nbsd_unlock: enter vp %p flags %d\n", vp, flags);
1286
1287     code = genfs_unlock(v);
1288
1289     if (afs_debug & AFSDEB_VNLAYER)
1290         printf("nbsd_unlock: exit vp %p flags %d\n", vp, flags);
1291
1292     return (code);
1293 }
1294
1295 int
1296 afs_nbsd_islocked(void *v)
1297 {
1298     struct vop_islocked_args    /* {
1299                                  * struct vnode *a_vp;
1300                                  * } */ *ap = v;
1301
1302     int code;
1303     struct vnode *vp = ap->a_vp;
1304
1305     if (afs_debug & AFSDEB_VNLAYER)
1306         printf("nbsd_islocked: enter vp %p flags %d\n", vp);
1307
1308     code = genfs_islocked(v);
1309
1310     if (afs_debug & AFSDEB_VNLAYER)
1311         printf("nbsd_islocked: exit vp %p flags %d\n", vp);
1312
1313     return (code);
1314 }
1315
1316
1317 int
1318 afs_nbsd_bmap(void *v)
1319 {
1320     struct vop_bmap_args        /* {
1321                                  * struct vnode *a_vp;
1322                                  * daddr_t  a_bn;
1323                                  * struct vnode **a_vpp;
1324                                  * daddr_t *a_bnp;
1325                                  * int *a_runp;
1326                                  * } */ *ap = v;
1327     struct vcache *vcp = VTOAFS(ap->a_vp);
1328
1329     AFS_STATCNT(afs_bmap);
1330
1331     if (afs_debug & AFSDEB_VNLAYER)
1332         printf("nbsd_bmap: enter %p\n", ap);
1333
1334     /* borrowed from DARWIN--why notyet? */
1335     if (ap->a_bnp)
1336         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1337     if (ap->a_vpp)
1338         *ap->a_vpp = ap->a_vp;
1339     if (ap->a_runp != NULL)
1340         *ap->a_runp = 0;
1341 #ifdef notyet
1342     if (ap->a_runb != NULL)
1343         *ap->a_runb = 0;
1344 #endif
1345
1346     if (afs_debug & AFSDEB_VNLAYER)
1347         printf("nbsd_bmap: exit %p\n", ap);
1348
1349     return (0);
1350 }
1351
1352 int
1353 afs_nbsd_strategy(void *v)
1354 {
1355     struct vop_strategy_args    /* {
1356                                  * struct buf *a_bp;
1357                                  * } */ *ap = v;
1358     struct buf *abp = ap->a_bp;
1359     struct uio tuio;
1360     struct iovec tiovec[1];
1361     struct vcache *tvc = VTOAFS(abp->b_vp);
1362     afs_ucred_t credp = osi_curcred();
1363     long len = abp->b_bcount;
1364     int code;
1365
1366     AFS_STATCNT(afs_strategy);
1367
1368     if (afs_debug & AFSDEB_VNLAYER)
1369         printf("nbsd_strategy: enter %p\n", ap);
1370
1371     tuio.afsio_iov = tiovec;
1372     tuio.afsio_iovcnt = 1;
1373     tuio.afsio_resid = len;
1374 /*
1375  * b_un was removed in NBSD50...there's no true substitute for the
1376  * b_addr that was in it, but b_blkno is the closest.
1377  *      mattjsm
1378  */
1379 #ifdef AFS_NBSD50_ENV
1380     tiovec[0].iov_base = abp->b_blkno;
1381 #else
1382     tiovec[0].iov_base = abp->b_un.b_addr;
1383 #endif
1384     tiovec[0].iov_len = len;
1385     UIO_SETUP_SYSSPACE(&tuio);
1386
1387     AFS_GLOCK();
1388     if ((abp->b_flags & B_READ) == B_READ) {
1389         code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
1390         if (code == 0 && tuio.afsio_resid > 0)
1391 #ifdef AFS_NBSD50_ENV
1392             bzero(abp->b_blkno + len - tuio.afsio_resid,
1393 #else
1394             bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
1395 #endif
1396                   tuio.afsio_resid);
1397         } else
1398             code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1399     AFS_GUNLOCK();
1400
1401     ReleaseWriteLock(&tvc->lock);
1402     AFS_RELE(AFSTOV(tvc));
1403
1404     if (afs_debug & AFSDEB_VNLAYER)
1405         printf("nbsd_strategy: exit %p\n", ap);
1406
1407     return (code);
1408 }
1409
1410 int
1411 afs_nbsd_print(void *v)
1412 {
1413     struct vop_print_args       /* {
1414                                  * struct vnode *a_vp;
1415                                  * } */ *ap = v;
1416     struct vnode *vp = ap->a_vp;
1417     struct vcache *vc = VTOAFS(ap->a_vp);
1418
1419     printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell,
1420            (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode,
1421            (int)vc->f.fid.Fid.Unique);
1422 #ifdef AFS_NBSD50_ENV
1423         mutex_owned(&vc->rwlock);
1424 #else
1425     lockmgr_printinfo(&vc->rwlock);
1426 #endif
1427     printf("\n");
1428     return (0);
1429 }
1430
1431 /*
1432  * Return POSIX pathconf information applicable to ufs filesystems.
1433  */
1434 int
1435 afs_nbsd_pathconf(void *v)
1436 {
1437     struct vop_pathconf_args    /* {
1438                                  * struct vnode *a_vp;
1439                                  * int a_name;
1440                                  * int *a_retval;
1441                                  * } */ *ap = v;
1442     int code = 0;
1443
1444     AFS_STATCNT(afs_cntl);
1445
1446     if (afs_debug & AFSDEB_VNLAYER)
1447         printf("nbsd_pathconf: enter %p\n", ap);
1448
1449     switch (ap->a_name) {
1450     case _PC_LINK_MAX:
1451         *ap->a_retval = LINK_MAX;
1452         break;
1453     case _PC_NAME_MAX:
1454         *ap->a_retval = NAME_MAX;
1455         break;
1456     case _PC_PATH_MAX:
1457         *ap->a_retval = PATH_MAX;
1458         break;
1459     case _PC_CHOWN_RESTRICTED:
1460         *ap->a_retval = 1;
1461         break;
1462     case _PC_NO_TRUNC:
1463         *ap->a_retval = 1;
1464         break;
1465     case _PC_PIPE_BUF:
1466         code = EINVAL;
1467         goto out;
1468         break;
1469     default:
1470         code = EINVAL;
1471         goto out;
1472     }
1473
1474 out:
1475     if (afs_debug & AFSDEB_VNLAYER)
1476         printf("nbsd_pathconf: exit %p\n", ap);
1477
1478     return (0);
1479 }
1480
1481 extern int
1482   afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1483               afs_ucred_t *acred, pid_t clid);
1484
1485 /*
1486  * Advisory record locking support (fcntl() POSIX style)
1487  */
1488 int
1489 afs_nbsd_advlock(void *v)
1490 {
1491     struct vop_advlock_args     /* {
1492                                  * struct vnode *a_vp;
1493                                  * caddr_t  a_id;
1494                                  * int  a_op;
1495                                  * struct flock *a_fl;
1496                                  * int  a_flags;
1497                                  * } */ *ap = v;
1498     int code;
1499
1500     if (afs_debug & AFSDEB_VNLAYER)
1501         printf("nbsd_pathconf: enter %p\n", ap);
1502
1503     AFS_GLOCK();
1504     code =
1505         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1506                     (int)ap->a_id);
1507     AFS_GUNLOCK();
1508
1509     if (afs_debug & AFSDEB_VNLAYER)
1510         printf("nbsd_pathconf: exit %p\n", ap);
1511
1512     return (code);
1513 }