c8a0edf39fd3fb6672aac9dd7a95cefa9a4f5c36
[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 =
606         afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, (daddr_t) 0, NULL,
607                  0);
608     AFS_GUNLOCK();
609
610     if (afs_debug & AFSDEB_VNLAYER)
611         printf("nbsd_read exit %p", ap);
612
613     return (code);
614 }
615
616 int
617 afs_nbsd_write(void *v)
618 {
619     struct vop_write_args       /* {
620                                  * struct vnode *a_vp;
621                                  * struct uio *a_uio;
622                                  * int a_ioflag;
623                                  * kauth_cred_t a_cred;
624                                  * } */ *ap = v;
625     int code;
626
627     if (afs_debug & AFSDEB_VNLAYER)
628         printf("nbsd_write enter %p", ap);
629
630 #if 1
631     /* all pages are really "stale?" */
632     VNP_UNCACHE(ap->a_vp);
633 #else
634     (void)uvm_vnp_uncache(ap->a_vp);    /* toss stale pages */
635 #endif
636     AFS_GLOCK();
637     code =
638         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
639     AFS_GUNLOCK();
640
641     if (afs_debug & AFSDEB_VNLAYER)
642         printf("nbsd_write exit %p", ap);
643
644     return (code);
645 }
646
647 int
648 afs_nbsd_ioctl(void *v)
649 {
650     struct vop_ioctl_args       /* {
651                                  * struct vnode *a_vp;
652                                  * int  a_command;
653                                  * caddr_t  a_data;
654                                  * int  a_fflag;
655                                  * kauth_cred_t a_cred;
656                                  * struct lwp *a_l;
657                                  * } */ *ap = v;
658     int code;
659
660     if (afs_debug & AFSDEB_VNLAYER)
661         printf("nbsd_ioctl: enter %p\n", ap);
662
663     /* in case we ever get in here... */
664
665     AFS_STATCNT(afs_ioctl);
666     AFS_GLOCK();
667     if (((ap->a_command >> 8) & 0xff) == 'V')
668         /* This is a VICEIOCTL call */
669         code =
670             HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
671                         (struct afs_ioctl *)ap->a_data);
672     else
673         /* No-op call; just return. */
674         code = ENOTTY;
675     AFS_GUNLOCK();
676
677     if (afs_debug & AFSDEB_VNLAYER)
678         printf("nbsd_ioctl: exit %p\n", ap);
679
680     return (code);
681 }
682
683 int
684 afs_nbsd_select(void *v)
685 {
686     return 1;
687 }
688
689 int
690 afs_nbsd_fsync(void *v)
691 {
692     struct vop_fsync_args       /* {
693                                  * struct vnode *a_vp;
694                                  * kauth_cred_t a_cred;
695                                  * int a_waitfor;
696                                  * struct lwp *a_l;
697                                  * } */ *ap = v;
698     struct vnode *vp = ap->a_vp;
699     int code, wait;
700
701     if (afs_debug & AFSDEB_VNLAYER)
702         printf("nbsd_fsync: enter %p\n", ap);
703
704     wait = (ap->a_flags & FSYNC_WAIT) != 0;
705
706     AFS_GLOCK();
707     vflushbuf(vp, wait);
708     code = afs_fsync(VTOAFS(vp), ap->a_cred);
709     AFS_GUNLOCK();
710
711     if (afs_debug & AFSDEB_VNLAYER)
712         printf("nbsd_fsync: exit %p\n", ap);
713
714     return (code);
715 }
716
717 int
718 afs_nbsd_remove(void *v)
719 {
720     struct vop_remove_args      /* {
721                                  * struct vnode *a_dvp;
722                                  * struct vnode *a_vp;
723                                  * struct componentname *a_cnp;
724                                  * } */ *ap = v;
725     int code;
726     struct vnode *vp = ap->a_vp;
727     struct vnode *dvp = ap->a_dvp;
728
729     if (afs_debug & AFSDEB_VNLAYER)
730         printf("nbsd_remove: enter %p\n", ap);
731
732     GETNAME();
733     AFS_GLOCK();
734     code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
735     AFS_GUNLOCK();
736     if (dvp == vp)
737         vrele(vp);
738     else
739         vput(vp);
740     vput(dvp);
741     DROPCNP(cnp);
742     DROPNAME();
743
744     if (afs_debug & AFSDEB_VNLAYER)
745         printf("nbsd_remove: exit %p\n", ap);
746
747     return (code);
748 }
749
750 int
751 afs_nbsd_link(void *v)
752 {
753     struct vop_link_args        /* {
754                                  * struct vnode *a_vp;
755                                  * struct vnode *a_tdvp;
756                                  * struct componentname *a_cnp;
757                                  * } */ *ap = v;
758     int code;
759     struct vnode *dvp = ap->a_dvp;
760     struct vnode *vp = ap->a_vp;
761
762     if (afs_debug & AFSDEB_VNLAYER)
763         printf("nbsd_link: enter %p\n", ap);
764
765     GETNAME();
766     if (dvp->v_mount != vp->v_mount) {
767         VOP_ABORTOP(vp, cnp);
768         code = EXDEV;
769         goto out;
770     }
771     if (vp->v_type == VDIR) {
772         VOP_ABORTOP(vp, cnp);
773         code = EISDIR;
774         goto out;
775     }
776     if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))) {
777         VOP_ABORTOP(dvp, cnp);
778         goto out;
779     }
780
781     AFS_GLOCK();
782     code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
783     AFS_GUNLOCK();
784     DROPCNP(cnp);
785     if (dvp != vp)
786         VOP_UNLOCK(vp, 0);
787
788   out:
789     vput(dvp);
790     DROPNAME();
791
792     if (afs_debug & AFSDEB_VNLAYER)
793         printf("nbsd_link: exit %p\n", ap);
794
795     return (code);
796 }
797
798 int
799 afs_nbsd_rename(void *v)
800 {
801     struct vop_rename_args      /* {
802                                  * struct vnode *a_fdvp;
803                                  * struct vnode *a_fvp;
804                                  * struct componentname *a_fcnp;
805                                  * struct vnode *a_tdvp;
806                                  * struct vnode *a_tvp;
807                                  * struct componentname *a_tcnp;
808                                  * } */ *ap = v;
809     int code = 0;
810     struct componentname *fcnp = ap->a_fcnp;
811     char *fname;
812     struct componentname *tcnp = ap->a_tcnp;
813     char *tname;
814     struct vnode *tvp = ap->a_tvp;
815     struct vnode *tdvp = ap->a_tdvp;
816     struct vnode *fvp = ap->a_fvp;
817     struct vnode *fdvp = ap->a_fdvp;
818
819     if (afs_debug & AFSDEB_VNLAYER)
820         printf("nbsd_rename: enter %p\n", ap);
821
822     /*
823      * Check for cross-device rename.
824      */
825     if ((fvp->v_mount != tdvp->v_mount)
826         || (tvp && (fvp->v_mount != tvp->v_mount))) {
827         code = EXDEV;
828     abortit:
829         VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
830         if (tdvp == tvp)
831             vrele(tdvp);
832         else
833             vput(tdvp);
834         if (tvp)
835             vput(tvp);
836         VOP_ABORTOP(fdvp, fcnp);    /* XXX, why not in NFS? */
837         vrele(fdvp);
838         vrele(fvp);
839         goto out;
840     }
841     /*
842      * if fvp == tvp, we're just removing one name of a pair of
843      * directory entries for the same element.  convert call into rename.
844      ( (pinched from NetBSD 1.0's ufs_rename())
845      */
846     if (fvp == tvp) {
847         if (fvp->v_type == VDIR) {
848             code = EINVAL;
849             goto abortit;
850         }
851
852         /* Release destination completely. */
853         VOP_ABORTOP(tdvp, tcnp);
854         vput(tdvp);
855         vput(tvp);
856
857         /* Delete source. */
858         vrele(fdvp);
859         vrele(fvp);
860         fcnp->cn_flags &= ~MODMASK;
861         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
862         if ((fcnp->cn_flags & SAVESTART) == 0)
863             panic("afs_rename: lost from startdir");
864         fcnp->cn_nameiop = DELETE;
865         (void)relookup(fdvp, &fvp, fcnp);
866         code = VOP_REMOVE(fdvp, fvp, fcnp);
867         goto out;
868     }
869
870     if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)))
871         goto abortit;
872
873     /* XXX GETNAME() ? */
874     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
875     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
876     fname[fcnp->cn_namelen] = '\0';
877     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
878     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
879     tname[tcnp->cn_namelen] = '\0';
880
881     AFS_GLOCK();
882     /* XXX use "from" or "to" creds? NFS uses "to" creds */
883     code =
884         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname,
885                    tcnp->cn_cred);
886     AFS_GUNLOCK();
887
888     VOP_UNLOCK(fvp, 0);
889     FREE(fname, M_TEMP);
890     FREE(tname, M_TEMP);
891     if (code)
892         goto abortit;        /* XXX */
893     if (tdvp == tvp)
894         vrele(tdvp);
895     else
896         vput(tdvp);
897     if (tvp)
898         vput(tvp);
899     vrele(fdvp);
900     vrele(fvp);
901
902  out:
903     if (afs_debug & AFSDEB_VNLAYER)
904         printf("nbsd_rename: exit %p\n", ap);
905
906     return (code);
907 }
908
909 int
910 afs_nbsd_mkdir(void *v)
911 {
912     struct vop_mkdir_args       /* {
913                                  * struct vnode *a_dvp;
914                                  * struct vnode **a_vpp;
915                                  * struct componentname *a_cnp;
916                                  * struct vattr *a_vap;
917                                  * } */ *ap = v;
918     struct vnode *dvp = ap->a_dvp;
919     struct vattr *vap = ap->a_vap;
920     int code;
921     struct vcache *vcp;
922
923     if (afs_debug & AFSDEB_VNLAYER)
924         printf("nbsd_mkdir: enter %p\n", ap);
925
926     GETNAME();
927 #ifdef DIAGNOSTIC
928     if ((cnp->cn_flags & HASBUF) == 0)
929         panic("afs_nbsd_mkdir: no name");
930 #endif
931     AFS_GLOCK();
932     code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
933     AFS_GUNLOCK();
934     if (code) {
935         VOP_ABORTOP(dvp, cnp);
936         vput(dvp);
937         DROPNAME();
938         goto out;
939     }
940     if (vcp) {
941         *ap->a_vpp = AFSTOV(vcp);
942         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
943     } else
944         *ap->a_vpp = 0;
945     DROPCNP(cnp);
946     DROPNAME();
947     vput(dvp);
948
949  out:
950     if (afs_debug & AFSDEB_VNLAYER)
951         printf("nbsd_mkdir: exit %p\n", ap);
952
953     return (code);
954 }
955
956 int
957 afs_nbsd_rmdir(void *v)
958 {
959     struct vop_rmdir_args       /* {
960                                  * struct vnode *a_dvp;
961                                  * struct vnode *a_vp;
962                                  * struct componentname *a_cnp;
963                                  * } */ *ap = v;
964     int code;
965     struct vnode *vp = ap->a_vp;
966     struct vnode *dvp = ap->a_dvp;
967
968     if (afs_debug & AFSDEB_VNLAYER)
969         printf("nbsd_rmdir: enter %p", ap);
970
971     GETNAME();
972     if (dvp == vp) {
973         vrele(dvp);
974         vput(vp);
975         DROPCNP(cnp);
976         DROPNAME();
977         code = EINVAL;
978         goto out;
979     }
980
981     AFS_GLOCK();
982     code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
983     AFS_GUNLOCK();
984     DROPNAME();
985     vput(dvp);
986     vput(vp);
987
988  out:
989     if (afs_debug & AFSDEB_VNLAYER)
990         printf("nbsd_rmdir: exit %p\n", ap);
991
992     return (code);
993 }
994
995 int
996 afs_nbsd_symlink(void *v)
997 {
998     struct vop_symlink_args     /* {
999                                  * struct vnode *a_dvp;
1000                                  * struct vnode **a_vpp;
1001                                  * struct componentname *a_cnp;
1002                                  * struct vattr *a_vap;
1003                                  * char *a_target;
1004                                  * } */ *ap = v;
1005     struct vnode *dvp = ap->a_dvp;
1006     int code;
1007     /* NFS ignores a_vpp; so do we. */
1008
1009     if (afs_debug & AFSDEB_VNLAYER)
1010         printf("nbsd_symlink: enter %p\n", ap);
1011
1012     GETNAME();
1013     AFS_GLOCK();
1014     code =
1015         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
1016                     cnp->cn_cred);
1017     AFS_GUNLOCK();
1018     DROPCNP(cnp);
1019     DROPNAME();
1020     vput(dvp);
1021
1022     if (afs_debug & AFSDEB_VNLAYER)
1023         printf("nbsd_symlink: exit %p\n", ap);
1024
1025     return (code);
1026 }
1027
1028 int
1029 nbsd_fake_readdir(struct vnode *vp, struct vcache *vc, struct uio *auio,
1030                   kauth_cred_t acred, int *a_eofflag, int *a_ncookies,
1031                   u_long **a_cookies)
1032 {
1033     static int ino = 2;
1034     afs_int32 code, maxb;
1035     struct dirent *dp;
1036     maxb = auio->uio_resid;
1037
1038     if (afs_debug & AFSDEB_VNLAYER)
1039         printf("nbsd_fake_readdir: enter vp %p vc %p acred %p auio %p "
1040                "uio_offset %d uio_resid %d\n",
1041                vp, vc, acred, auio, (int) auio->uio_offset,
1042                (int) auio->uio_resid);
1043
1044     /* 1. simply returning 0 had good behavior (/afs is empty) */
1045
1046 /*
1047 (gdb) p *auio
1048 $5 = {uio_iov = 0xcbd0ec90, uio_iovcnt = 1, uio_offset = 0, uio_resid = 4096,
1049   uio_rw = UIO_READ, uio_vmspace = 0xcbe8beec}
1050 */
1051     /* ok.  we don't know about cookies, so since auio->uio_resid is 4096,
1052      * what we can legitimately do is move as many appropriately aligned
1053      * NetBSD dirent records into uio_iov[0] as will fit in the total size
1054      * of 4KB.  We do not need to zero-fill anything.  This does not
1055      * terminate the directly listing. If we return 0, VFS will re-enter
1056      * nbsd_readdir to continue reading--to termiate the iteration, we must
1057      * return a non-zero value from nbsd_readdir.  VOP_READDIR(9) appears to
1058      * suggest that enumeration is terminated by setting a_eofflag = 1,
1059      * but as noted there this -can- only be done if VFS passed a value for
1060      * a_eofflag--apparently, this is to do with NFS.  Setting the eof is
1061      * correct but insufficient. */
1062
1063     /* 2. next, let's move ONE entry in by hand--due to termination
1064      * rules, this will actually create file_1 .. file_99 and many
1065      * unecessary nbsd_readdir invocations.  The solution to this is to
1066      * make proper use of auio->uio_offset and auio->uio_resid, together
1067      * when accounting bytes moved each invocation, allowing VFS to
1068      * invoke nbsd_readdir at successive offsets until we have consumed
1069      * all entries in all chunks of the vnode being read--setting a_eofflag
1070      * when this is done.
1071      */
1072
1073     /* this isn't thread safe--we would in fact use incoming offset
1074      * to select the offset of the next AFS dirent, read it, then take
1075      * its values for (modulo volume) inode number and name */
1076     if (auio->uio_offset == 0)
1077         ino = 2;
1078
1079     dp = (struct dirent *) kmem_zalloc(sizeof(struct dirent), KM_SLEEP);
1080     dp->d_ino =  ino;
1081     dp->d_type = DT_REG;
1082     sprintf(dp->d_name, "file_%d", ino);
1083     dp->d_namlen = strlen(dp->d_name);
1084     dp->d_reclen = _DIRENT_SIZE(dp); /* comp reclen from d_namlen and align */
1085     printf("nbsd_fake_readdir: add dirent %s\n", dp->d_name);
1086     code = uiomove(dp, dp->d_reclen, auio);
1087     if (code)
1088         printf("nbsd_fake_readdir: uiomove FAILED\n");
1089     kmem_free(dp, sizeof(struct dirent));
1090     ++ino;
1091
1092     /* terminate enumeration */
1093     if (!code)
1094         if (ino > 100) {
1095             code = EINVAL;
1096             if(a_eofflag)
1097                 *a_eofflag = 1;
1098         }
1099
1100     return (code);
1101 }
1102
1103 int
1104 afs_nbsd_readdir(void *v)
1105 {
1106     struct vop_readdir_args     /* {
1107                                  * struct vnode *a_vp;
1108                                  * struct uio *a_uio;
1109                                  * kauth_cred_t a_cred;
1110                                  * int *a_eofflag;
1111                                  * int *a_ncookies;
1112                                  * u_long **a_cookies;
1113                                  * } */ *ap = v;
1114     int code;
1115     struct vnode *vp = ap->a_vp;
1116     struct vcache *vc = VTOAFS(vp);
1117
1118     if (afs_debug & AFSDEB_VNLAYER)
1119         printf("nbsd_readdir: enter vp %p vc %p acred %p auio %p\n", vp, vc,
1120                ap->a_cred, ap->a_uio);
1121
1122     AFS_GLOCK();
1123 #ifdef AFS_HAVE_COOKIES
1124     printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
1125            ap->a_ncookies);
1126     code =
1127         afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag,
1128                     ap->a_ncookies, ap->a_cookies);
1129 #else
1130     code =
1131         afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag);
1132 #endif
1133     AFS_GUNLOCK();
1134
1135     if (afs_debug & AFSDEB_VNLAYER)
1136         printf("nbsd_readdir: exit %p eofflag %d\n", ap, *ap->a_eofflag);
1137
1138     return (code);
1139 }
1140
1141 int
1142 afs_nbsd_readlink(void *v)
1143 {
1144     struct vop_readlink_args    /* {
1145                                  * struct vnode *a_vp;
1146                                  * struct uio *a_uio;
1147                                  * kauth_cred_t a_cred;
1148                                  * } */ *ap = v;
1149     int code;
1150
1151     if (afs_debug & AFSDEB_VNLAYER)
1152         printf("nbsd_readlink: enter %p\n", ap);
1153
1154     AFS_GLOCK();
1155     code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1156     AFS_GUNLOCK();
1157
1158     if (afs_debug & AFSDEB_VNLAYER)
1159         printf("nbsd_readlink: exit %p\n", ap);
1160
1161     return (code);
1162 }
1163
1164 extern int prtactive;
1165
1166 int
1167 afs_nbsd_inactive(void *v)
1168 {
1169     struct vop_inactive_args    /* {
1170                                  * struct vnode *a_vp;
1171                                  * } */ *ap = v;
1172     struct vnode *vp = ap->a_vp;
1173     struct vcache *vc = VTOAFS(vp);
1174     int haveGlock = ISAFS_GLOCK();
1175
1176     AFS_STATCNT(afs_inactive);
1177
1178     if (afs_debug & AFSDEB_VNLAYER)
1179         printf("nbsd_inactive: enter %p\n", ap);
1180
1181     if (prtactive && vp->v_usecount != 0)
1182         vprint("afs_nbsd_inactive: pushing active", vp);
1183
1184     if (!haveGlock)
1185         AFS_GLOCK();
1186     afs_InactiveVCache(vc, 0);  /* decrs ref counts */
1187     if (!haveGlock)
1188         AFS_GUNLOCK();
1189
1190 #ifdef AFS_NBSD50_ENV
1191     mutex_init(&vc->rwlock, MUTEX_DEFAULT, IPL_NONE);
1192 #else
1193     lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
1194 #endif
1195
1196     if (afs_debug & AFSDEB_VNLAYER)
1197         printf("nbsd_inactive: exit %p\n", ap);
1198
1199     return (0);
1200 }
1201
1202 int
1203 afs_nbsd_reclaim(void *v)
1204 {
1205     struct vop_reclaim_args     /* {
1206                                  * struct vnode *a_vp;
1207                                  * } */ *ap = v;
1208     int code, slept;
1209     struct vnode *vp = ap->a_vp;
1210     struct vcache *avc = VTOAFS(vp);
1211     int haveGlock = ISAFS_GLOCK();
1212     int haveVlock = CheckLock(&afs_xvcache);
1213
1214         if (afs_debug & AFSDEB_VNLAYER)
1215                 printf("nbsd_reclaim: enter %p\n", ap);
1216
1217 #if 0
1218     printf("reclaim usecount %d\n", vp->v_usecount);
1219     /* OK, there are no internal vrefCounts, so there shouldn't
1220      * be any more refs here. */
1221     vp->v_data = NULL;          /* remove from vnode */
1222     avc->v = NULL;              /* also drop the ptr to vnode */
1223
1224         if (afs_debug & AFSDEB_VNLAYER)
1225                 printf("nbsd_reclaim: exit %p\n", ap);
1226
1227     return (0);
1228 #else
1229     if (!haveGlock)
1230                 AFS_GLOCK();
1231     if (!haveVlock)
1232                 ObtainWriteLock(&afs_xvcache, 901);
1233 #ifndef AFS_DISCON_ENV
1234         code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
1235 #else
1236     /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
1237     code = afs_FlushVCache(avc, &slept);
1238 #endif
1239     if (!haveVlock)
1240                 ReleaseWriteLock(&afs_xvcache);
1241     if (!haveGlock)
1242                 AFS_GUNLOCK();
1243
1244         if (afs_debug & AFSDEB_VNLAYER)
1245                 printf("nbsd_reclaim: exit %p\n", ap);
1246
1247     return code;
1248 #endif /* 0 */
1249 }
1250
1251 int
1252 afs_nbsd_lock(void *v)
1253 {
1254     struct vop_lock_args        /* {
1255                                  * struct vnode *a_vp;
1256                                  * int a_flags;
1257                                  * struct lwp *a_l;
1258                                  * } */ *ap = v;
1259     int code;
1260     struct vnode *vp = ap->a_vp;
1261     int flags = ap->a_flags;
1262
1263     if (afs_debug & AFSDEB_VNLAYER)
1264         printf("nbsd_lock: enter vp %p flags %d\n", vp, flags);
1265
1266     code = genfs_lock(v);
1267
1268     if (afs_debug & AFSDEB_VNLAYER)
1269         printf("nbsd_lock: exit vp %p flags %d\n\n", vp, flags);
1270
1271     return (code);
1272 }
1273
1274 int
1275 afs_nbsd_unlock(void *v)
1276 {
1277     struct vop_unlock_args      /* {
1278                                  * struct vnode *a_vp;
1279                                  * int a_flags;
1280                                  * struct lwp *a_l;
1281                                  * } */ *ap = v;
1282     int code;
1283     struct vnode *vp = ap->a_vp;
1284     int flags = ap->a_flags;
1285
1286     if (afs_debug & AFSDEB_VNLAYER)
1287         printf("nbsd_unlock: enter vp %p flags %d\n", vp, flags);
1288
1289     code = genfs_unlock(v);
1290
1291     if (afs_debug & AFSDEB_VNLAYER)
1292         printf("nbsd_unlock: exit vp %p flags %d\n", vp, flags);
1293
1294     return (code);
1295 }
1296
1297 int
1298 afs_nbsd_islocked(void *v)
1299 {
1300     struct vop_islocked_args    /* {
1301                                  * struct vnode *a_vp;
1302                                  * } */ *ap = v;
1303
1304     int code;
1305     struct vnode *vp = ap->a_vp;
1306
1307     if (afs_debug & AFSDEB_VNLAYER)
1308         printf("nbsd_islocked: enter vp %p flags %d\n", vp);
1309
1310     code = genfs_islocked(v);
1311
1312     if (afs_debug & AFSDEB_VNLAYER)
1313         printf("nbsd_islocked: exit vp %p flags %d\n", vp);
1314
1315     return (code);
1316 }
1317
1318
1319 int
1320 afs_nbsd_bmap(void *v)
1321 {
1322     struct vop_bmap_args        /* {
1323                                  * struct vnode *a_vp;
1324                                  * daddr_t  a_bn;
1325                                  * struct vnode **a_vpp;
1326                                  * daddr_t *a_bnp;
1327                                  * int *a_runp;
1328                                  * } */ *ap = v;
1329     struct vcache *vcp = VTOAFS(ap->a_vp);
1330
1331     AFS_STATCNT(afs_bmap);
1332
1333     if (afs_debug & AFSDEB_VNLAYER)
1334         printf("nbsd_bmap: enter %p\n", ap);
1335
1336     /* borrowed from DARWIN--why notyet? */
1337     if (ap->a_bnp)
1338         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1339     if (ap->a_vpp)
1340         *ap->a_vpp = ap->a_vp;
1341     if (ap->a_runp != NULL)
1342         *ap->a_runp = 0;
1343 #ifdef notyet
1344     if (ap->a_runb != NULL)
1345         *ap->a_runb = 0;
1346 #endif
1347
1348     if (afs_debug & AFSDEB_VNLAYER)
1349         printf("nbsd_bmap: exit %p\n", ap);
1350
1351     return (0);
1352 }
1353
1354 int
1355 afs_nbsd_strategy(void *v)
1356 {
1357     struct vop_strategy_args    /* {
1358                                  * struct buf *a_bp;
1359                                  * } */ *ap = v;
1360     struct buf *abp = ap->a_bp;
1361     struct uio tuio;
1362     struct iovec tiovec[1];
1363     struct vcache *tvc = VTOAFS(abp->b_vp);
1364     afs_ucred_t credp = osi_curcred();
1365     long len = abp->b_bcount;
1366     int code;
1367
1368     AFS_STATCNT(afs_strategy);
1369
1370     if (afs_debug & AFSDEB_VNLAYER)
1371         printf("nbsd_strategy: enter %p\n", ap);
1372
1373     tuio.afsio_iov = tiovec;
1374     tuio.afsio_iovcnt = 1;
1375     tuio.afsio_resid = len;
1376 /*
1377  * b_un was removed in NBSD50...there's no true substitute for the
1378  * b_addr that was in it, but b_blkno is the closest.
1379  *      mattjsm
1380  */
1381 #ifdef AFS_NBSD50_ENV
1382     tiovec[0].iov_base = abp->b_blkno;
1383 #else
1384     tiovec[0].iov_base = abp->b_un.b_addr;
1385 #endif
1386     tiovec[0].iov_len = len;
1387     UIO_SETUP_SYSSPACE(&tuio);
1388
1389     AFS_GLOCK();
1390     if ((abp->b_flags & B_READ) == B_READ) {
1391         code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
1392         if (code == 0 && tuio.afsio_resid > 0)
1393 #ifdef AFS_NBSD50_ENV
1394             bzero(abp->b_blkno + len - tuio.afsio_resid,
1395 #else
1396             bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
1397 #endif
1398                   tuio.afsio_resid);
1399         } else
1400             code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1401     AFS_GUNLOCK();
1402
1403     ReleaseWriteLock(&tvc->lock);
1404     AFS_RELE(AFSTOV(tvc));
1405
1406     if (afs_debug & AFSDEB_VNLAYER)
1407         printf("nbsd_strategy: exit %p\n", ap);
1408
1409     return (code);
1410 }
1411
1412 int
1413 afs_nbsd_print(void *v)
1414 {
1415     struct vop_print_args       /* {
1416                                  * struct vnode *a_vp;
1417                                  * } */ *ap = v;
1418     struct vnode *vp = ap->a_vp;
1419     struct vcache *vc = VTOAFS(ap->a_vp);
1420
1421     printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell,
1422            (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode,
1423            (int)vc->f.fid.Fid.Unique);
1424 #ifdef AFS_NBSD50_ENV
1425         mutex_owned(&vc->rwlock);
1426 #else
1427     lockmgr_printinfo(&vc->rwlock);
1428 #endif
1429     printf("\n");
1430     return (0);
1431 }
1432
1433 /*
1434  * Return POSIX pathconf information applicable to ufs filesystems.
1435  */
1436 int
1437 afs_nbsd_pathconf(void *v)
1438 {
1439     struct vop_pathconf_args    /* {
1440                                  * struct vnode *a_vp;
1441                                  * int a_name;
1442                                  * int *a_retval;
1443                                  * } */ *ap = v;
1444     int code = 0;
1445
1446     AFS_STATCNT(afs_cntl);
1447
1448     if (afs_debug & AFSDEB_VNLAYER)
1449         printf("nbsd_pathconf: enter %p\n", ap);
1450
1451     switch (ap->a_name) {
1452     case _PC_LINK_MAX:
1453         *ap->a_retval = LINK_MAX;
1454         break;
1455     case _PC_NAME_MAX:
1456         *ap->a_retval = NAME_MAX;
1457         break;
1458     case _PC_PATH_MAX:
1459         *ap->a_retval = PATH_MAX;
1460         break;
1461     case _PC_CHOWN_RESTRICTED:
1462         *ap->a_retval = 1;
1463         break;
1464     case _PC_NO_TRUNC:
1465         *ap->a_retval = 1;
1466         break;
1467     case _PC_PIPE_BUF:
1468         code = EINVAL;
1469         goto out;
1470         break;
1471     default:
1472         code = EINVAL;
1473         goto out;
1474     }
1475
1476 out:
1477     if (afs_debug & AFSDEB_VNLAYER)
1478         printf("nbsd_pathconf: exit %p\n", ap);
1479
1480     return (0);
1481 }
1482
1483 extern int
1484   afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1485               afs_ucred_t *acred, pid_t clid);
1486
1487 /*
1488  * Advisory record locking support (fcntl() POSIX style)
1489  */
1490 int
1491 afs_nbsd_advlock(void *v)
1492 {
1493     struct vop_advlock_args     /* {
1494                                  * struct vnode *a_vp;
1495                                  * caddr_t  a_id;
1496                                  * int  a_op;
1497                                  * struct flock *a_fl;
1498                                  * int  a_flags;
1499                                  * } */ *ap = v;
1500     int code;
1501
1502     if (afs_debug & AFSDEB_VNLAYER)
1503         printf("nbsd_pathconf: enter %p\n", ap);
1504
1505     AFS_GLOCK();
1506     code =
1507         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1508                     (int)ap->a_id);
1509     AFS_GUNLOCK();
1510
1511     if (afs_debug & AFSDEB_VNLAYER)
1512         printf("nbsd_pathconf: exit %p\n", ap);
1513
1514     return (code);
1515 }