56c42a3272b7c85c3293aec6097098edeed9a309
[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
102
103 #include "afs/sysincludes.h"    /* Standard vendor system headers */
104 #include "afs/afsincludes.h"    /* Afs-based standard headers */
105 #include "afs/afs_stats.h"      /* statistics */
106
107 #include <sys/malloc.h>
108 #include <sys/namei.h>
109 #include <sys/pool.h>
110 #include <miscfs/genfs/genfs.h>
111
112
113 #include "afs/afs_cbqueue.h"
114 #include "afs/nfsclient.h"
115 #include "afs/afs_osidnlc.h"
116
117 #define M_AFSNODE (M_TEMP-1)    /* XXX */
118
119 int afs_nbsd_lookup(void *);
120 int afs_nbsd_create(void *);
121 int afs_nbsd_mknod(void *);
122 int afs_nbsd_open(void *);
123 int afs_nbsd_close(void *);
124 int afs_nbsd_access(void *);
125 int afs_nbsd_getattr(void *);
126 int afs_nbsd_setattr(void *);
127 int afs_nbsd_read(void *);
128 int afs_nbsd_write(void *);
129 int afs_nbsd_ioctl(void *);
130 int afs_nbsd_select(void *);
131 int afs_nbsd_fsync(void *);
132 int afs_nbsd_remove(void *);
133 int afs_nbsd_link(void *);
134 int afs_nbsd_rename(void *);
135 int afs_nbsd_mkdir(void *);
136 int afs_nbsd_rmdir(void *);
137 int afs_nbsd_symlink(void *);
138 int afs_nbsd_readdir(void *);
139 int afs_nbsd_readlink(void *);
140 int afs_nbsd_inactive(void *);
141 int afs_nbsd_reclaim(void *);
142 int afs_nbsd_lock(void *);
143 int afs_nbsd_unlock(void *);
144 int afs_nbsd_bmap(void *);
145 int afs_nbsd_strategy(void *);
146 int afs_nbsd_print(void *);
147 int afs_nbsd_islocked(void *);
148 int afs_nbsd_pathconf(void *);
149 int afs_nbsd_advlock(void *);
150
151 #if LATER
152 int afs_nbsd_getpages(void*);
153 #endif
154
155 /*
156  * Implement:
157  *   vop_getpages (VM)
158  *   vop_putpages (VM)
159  *
160  * Someday:
161  *   vop_mmap_desc (mmap'd IO)
162  *
163  * Skip:
164  *   vop_*xtattr
165  *
166  * Unknown:
167  *   vop_fcntl
168  *
169  */
170
171 #define afs_nbsd_opnotsupp \
172         ((int (*) __P((void *)))eopnotsupp)
173 #define afs_nbsd_reallocblks afs_nbsd_opnotsupp
174
175 /* Global vfs data structures for AFS. */
176 int (**afs_vnodeop_p) __P((void *));
177 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
178     {&vop_default_desc, vn_default_error},
179     {&vop_lookup_desc, afs_nbsd_lookup},        /* lookup */
180     {&vop_create_desc, afs_nbsd_create},        /* create */
181     {&vop_mknod_desc, afs_nbsd_mknod},          /* mknod */
182     {&vop_open_desc, afs_nbsd_open},            /* open */
183     {&vop_close_desc, afs_nbsd_close},          /* close */
184     {&vop_access_desc, afs_nbsd_access},        /* access */
185     {&vop_getattr_desc, afs_nbsd_getattr},      /* getattr */
186     {&vop_setattr_desc, afs_nbsd_setattr},      /* setattr */
187     {&vop_read_desc, afs_nbsd_read},            /* read */
188     {&vop_write_desc, afs_nbsd_write},          /* write */
189     {&vop_ioctl_desc, afs_nbsd_ioctl},          /* XXX ioctl */
190     {&vop_poll_desc, afs_nbsd_select},          /* select */
191     {&vop_kqfilter_desc, genfs_kqfilter },      /* kqfilter */
192     {&vop_fsync_desc, afs_nbsd_fsync},          /* fsync */
193     {&vop_remove_desc, afs_nbsd_remove},        /* remove */
194     {&vop_link_desc, afs_nbsd_link},            /* link */
195     {&vop_rename_desc, afs_nbsd_rename},        /* rename */
196     {&vop_mkdir_desc, afs_nbsd_mkdir},          /* mkdir */
197     {&vop_rmdir_desc, afs_nbsd_rmdir},          /* rmdir */
198     {&vop_symlink_desc, afs_nbsd_symlink},      /* symlink */
199     {&vop_readdir_desc, afs_nbsd_readdir},      /* readdir */
200     {&vop_readlink_desc, afs_nbsd_readlink},    /* readlink */
201     {&vop_abortop_desc, genfs_abortop},         /* abortop */
202     {&vop_inactive_desc, afs_nbsd_inactive},    /* inactive */
203     {&vop_reclaim_desc, afs_nbsd_reclaim},      /* reclaim */
204     {&vop_lock_desc, afs_nbsd_lock},            /* lock */
205     {&vop_unlock_desc, afs_nbsd_unlock},        /* unlock */
206     {&vop_bmap_desc, afs_nbsd_bmap},            /* bmap */
207     {&vop_strategy_desc, afs_nbsd_strategy},    /* strategy */
208     {&vop_print_desc, afs_nbsd_print},          /* print */
209     {&vop_islocked_desc, afs_nbsd_islocked},    /* islocked */
210     {&vop_pathconf_desc, afs_nbsd_pathconf},    /* pathconf */
211     {&vop_advlock_desc, afs_nbsd_advlock},      /* advlock */
212 #if 0
213     {&vop_reallocblks_desc, afs_nbsd_reallocblks},      /* reallocblks */
214 #endif
215     {&vop_bwrite_desc, vn_bwrite},      /* bwrite */
216 #if LATER
217     { &vop_getpages_desc, ffs_getpages },       /* getpages */
218     { &vop_putpages_desc, genfs_putpages },     /* putpages */
219 #endif
220     {(struct vnodeop_desc *)NULL, (int (*)__P((void *)))NULL}
221 };
222 struct vnodeopv_desc afs_vnodeop_opv_desc =
223     { &afs_vnodeop_p, afs_vnodeop_entries };
224
225 #define GETNAME() \
226     struct componentname *cnp = ap->a_cnp; \
227     char *name; \
228     name = PNBUF_GET(); \
229     bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
230     name[cnp->cn_namelen] = '\0'
231
232 #define DROPNAME() PNBUF_PUT(name)
233 #define DROPCNP PNBUF_PUT
234
235 /* toss "stale" pages by shrinking the vnode uobj to a 0-length
236  * region (see uvm_vnp_setsize in uvm_vnode.c) */
237 #define VNP_UNCACHE(vp) \
238     do {                \
239         struct uvm_object *uobj = &vp->v_uobj; \
240         simple_lock(&uobj->vmobjlock); \
241         VOP_PUTPAGES( (struct vnode *) uobj, 0 /* offlo */, 0 /* offhi */, PGO_FREE | PGO_SYNCIO); \
242         simple_unlock(&uobj->vmobjlock); \
243     } while(0);
244
245 /* psuedo-vnop, wherein we learn that obsd and nbsd disagree
246  * about vnode refcounting */
247 void
248 afs_nbsd_getnewvnode(struct vcache *tvc)
249 {
250     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
251         /* no vnodes available, force an alloc (limits be damned)! */
252         desiredvnodes++;
253     }
254     afs_warn("afs_nbsd_getnewvnode: vp %lx refs %d (soon to be 1)\n", tvc->v,
255              tvc->v->v_usecount);
256     simple_lock(&tvc->v->v_interlock);
257     tvc->v->v_data = (void *)tvc;
258     tvc->v->v_usecount = 1; /* !locked, and vref w/v_usecount < 1 panics */
259     simple_unlock(&tvc->v->v_interlock);
260 }
261
262 int afs_debug;
263
264 int
265 afs_nbsd_lookup(void *v)
266 {
267     struct vop_lookup_args      /* {
268                                  * struct vnodeop_desc * a_desc;
269                                  * struct vnode *a_dvp;
270                                  * struct vnode **a_vpp;
271                                  * struct componentname *a_cnp;
272                                  * } */ *ap = v;
273     int code;
274     struct vcache *vcp;
275     struct vnode *vp, *dvp;
276     int flags = ap->a_cnp->cn_flags;
277     int lockparent;             /* 1 => lockparent flag is set */
278
279     afs_warn("afs_nbsd_lookup enter\n");
280
281     GETNAME();
282     lockparent = flags & LOCKPARENT;
283     if (ap->a_dvp->v_type != VDIR) {
284         *ap->a_vpp = NULL;
285         DROPNAME();
286         return ENOTDIR;
287     }
288     dvp = ap->a_dvp;
289     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
290         printf("nbsd_lookup dvp %p flags %x name %s cnt %d\n", dvp, flags,
291                name, dvp->v_usecount);
292     AFS_GLOCK();
293     code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
294     AFS_GUNLOCK();
295     if (code) {
296         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
297             && (flags & ISLASTCN) && code == ENOENT)
298             code = EJUSTRETURN;
299         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
300             cnp->cn_flags |= SAVENAME;
301         DROPNAME();
302         *ap->a_vpp = NULL;
303         return (code);
304     }
305     vp = AFSTOV(vcp);           /* always get a node if no error */
306
307     /*
308      * The parent directory comes in locked.  We unlock it on return
309      * unless the caller wants it left locked.
310      * we also always return the vnode locked.
311      */
312
313     if (vp == dvp) {
314         /* they're the same; afs_lookup() already ref'ed the leaf.
315          * It came in locked, so we don't need to ref OR lock it */
316         if (afs_debug & AFSDEB_VNLAYER)
317             printf("ref'ed %p as .\n", dvp);
318     } else {
319         if (!lockparent || !(flags & ISLASTCN)) {
320             VOP_UNLOCK(dvp, 0); /* done with parent. */
321         }
322
323         simple_lock(&vp->v_interlock);
324         vp->v_usecount = (vp->v_usecount < 1) ? 1 : (vp->v_usecount+1);
325         simple_unlock(&vp->v_interlock);
326         if (!VOP_ISLOCKED(vp)) {
327             vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
328             afs_warn("h2\n");
329             /* vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); *//* always return the child locked */
330         } else {
331             afs_warn("lookup: vp %lx is locked\n", vp);
332         }
333         afs_warn("lookup: after islocked\n");
334         if (afs_debug & AFSDEB_VNLAYER)
335             printf("locked ret %p from lookup\n", vp);
336     }
337     *ap->a_vpp = vp;
338
339     if (((cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
340          || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
341         cnp->cn_flags |= SAVENAME;
342
343     DROPNAME();
344     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
345         printf("nbsd_lookup done dvp %p cnt %d\n", dvp, dvp->v_usecount);
346     return code;
347 }
348
349 int
350 afs_nbsd_create(void *v)
351 {
352     struct vop_create_args      /* {
353                                  * struct vnode *a_dvp;
354                                  * struct vnode **a_vpp;
355                                  * struct componentname *a_cnp;
356                                  * struct vattr *a_vap;
357                                  * } */ *ap = v;
358     int code = 0;
359     struct vcache *vcp;
360     struct vnode *dvp = ap->a_dvp;
361     GETNAME();
362
363     if (afs_debug & AFSDEB_VNLAYER)
364         printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
365
366     /* vnode layer handles excl/nonexcl */
367
368     AFS_GLOCK();
369     code =
370         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
371                    &vcp, cnp->cn_cred);
372     AFS_GUNLOCK();
373     if (code) {
374         VOP_ABORTOP(dvp, cnp);
375         vput(dvp);
376         DROPNAME();
377         return (code);
378     }
379
380     if (vcp) {
381         *ap->a_vpp = AFSTOV(vcp);
382         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
383     } else
384         *ap->a_vpp = 0;
385
386     if ((cnp->cn_flags & SAVESTART) == 0)
387         DROPCNP(cnp);
388     vput(dvp);
389     DROPNAME();
390     if (afs_debug & AFSDEB_VNLAYER)
391         printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
392     return code;
393 }
394
395 int
396 afs_nbsd_mknod(void *v)
397 {
398     struct vop_mknod_args       /* {
399                                  * struct vnode *a_dvp;
400                                  * struct vnode **a_vpp;
401                                  * struct componentname *a_cnp;
402                                  * struct vattr *a_vap;
403                                  * } */ *ap = v;
404     DROPCNP(ap->a_cnp);
405     vput(ap->a_dvp);
406     return (ENODEV);
407 }
408
409 int
410 afs_nbsd_open(void *v)
411 {
412     struct vop_open_args        /* {
413                                  * struct vnode *a_vp;
414                                  * int  a_mode;
415                                  * struct ucred *a_cred;
416                                  * struct lwp *a_l;
417                                  * } */ *ap = v;
418     int code;
419     struct vcache *vc = VTOAFS(ap->a_vp);
420
421     AFS_GLOCK();
422     code = afs_open(&vc, ap->a_mode, ap->a_cred);
423 #ifdef DIAGNOSTIC
424     if (AFSTOV(vc) != ap->a_vp)
425         panic("AFS open changed vnode!");
426 #endif
427     AFS_GUNLOCK();
428     return code;
429 }
430
431 int
432 afs_nbsd_close(void *v)
433 {
434     struct vop_close_args       /* {
435                                  * struct vnode *a_vp;
436                                  * int  a_fflag;
437                                  * kauth_cred_t a_cred;
438                                  * struct lwp *a_l;
439                                  * } */ *ap = v;
440     int code;
441
442     AFS_GLOCK();
443     code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred);
444     AFS_GUNLOCK();
445     return code;
446 }
447
448 int
449 afs_nbsd_access(void *v)
450 {
451     struct vop_access_args      /* {
452                                  * struct vnode *a_vp;
453                                  * int  a_mode;
454                                  * kauth_cred_t a_cred;
455                                  * struct lwp *a_l;
456                                  * } */ *ap = v;
457     int code;
458
459     AFS_GLOCK();
460     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
461     AFS_GUNLOCK();
462     return code;
463 }
464
465 int
466 afs_nbsd_getattr(void *v)
467 {
468     struct vop_getattr_args     /* {
469                                  * struct vnode *a_vp;
470                                  * struct vattr *a_vap;
471                                  * kauth_cred_t a_cred;
472                                  * struct lwp *a_l;
473                                  * } */ *ap = v;
474     int code;
475
476     AFS_GLOCK();
477     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
478     AFS_GUNLOCK();
479     return code;
480 }
481
482 int
483 afs_nbsd_setattr(void *v)
484 {
485     struct vop_setattr_args     /* {
486                                  * struct vnode *a_vp;
487                                  * struct vattr *a_vap;
488                                  * kauth_cred_t a_cred;
489                                  * struct lwp *a_l;
490                                  * } */ *ap = v;
491     int code;
492
493     AFS_GLOCK();
494     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
495     AFS_GUNLOCK();
496     return code;
497 }
498
499 int
500 afs_nbsd_read(void *v)
501 {
502     struct vop_read_args        /* {
503                                  * struct vnode *a_vp;
504                                  * struct uio *a_uio;
505                                  * int a_ioflag;
506                                  * kauth_cred_t a_cred;
507                                  * } */ *ap = v;
508     int code;
509
510     AFS_GLOCK();
511     code =
512         afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, (daddr_t) 0, NULL,
513                  0);
514     AFS_GUNLOCK();
515     return code;
516 }
517
518 int
519 afs_nbsd_write(void *v)
520 {
521     struct vop_write_args       /* {
522                                  * struct vnode *a_vp;
523                                  * struct uio *a_uio;
524                                  * int a_ioflag;
525                                  * kauth_cred_t a_cred;
526                                  * } */ *ap = v;
527     int code;
528
529 #if 1
530     /* all pages are really "stale?" */
531     VNP_UNCACHE(ap->a_vp);
532 #else
533     (void)uvm_vnp_uncache(ap->a_vp);    /* toss stale pages */
534 #endif
535     AFS_GLOCK();
536     code =
537         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
538     AFS_GUNLOCK();
539     return code;
540 }
541
542 int
543 afs_nbsd_ioctl(void *v)
544 {
545     struct vop_ioctl_args       /* {
546                                  * struct vnode *a_vp;
547                                  * int  a_command;
548                                  * caddr_t  a_data;
549                                  * int  a_fflag;
550                                  * kauth_cred_t a_cred;
551                                  * struct lwp *a_l;
552                                  * } */ *ap = v;
553     int code;
554
555     /* in case we ever get in here... */
556
557     AFS_STATCNT(afs_ioctl);
558     AFS_GLOCK();
559     if (((ap->a_command >> 8) & 0xff) == 'V')
560         /* This is a VICEIOCTL call */
561         code =
562             HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
563                         (struct afs_ioctl *)ap->a_data);
564     else
565         /* No-op call; just return. */
566         code = ENOTTY;
567     AFS_GUNLOCK();
568     return code;
569 }
570
571 int
572 afs_nbsd_select(void *v)
573 {
574     return 1;
575 }
576
577 int
578 afs_nbsd_fsync(void *v)
579 {
580     struct vop_fsync_args       /* {
581                                  * struct vnode *a_vp;
582                                  * kauth_cred_t a_cred;
583                                  * int a_waitfor;
584                                  * struct lwp *a_l;
585                                  * } */ *ap = v;
586     struct vnode *vp = ap->a_vp;
587     int code, wait;
588
589     wait = (ap->a_flags & FSYNC_WAIT) != 0;
590
591     AFS_GLOCK();
592     vflushbuf(vp, wait);
593     code = afs_fsync(VTOAFS(vp), ap->a_cred);
594     AFS_GUNLOCK();
595
596     return code;
597 }
598
599 int
600 afs_nbsd_remove(void *v)
601 {
602     struct vop_remove_args      /* {
603                                  * struct vnode *a_dvp;
604                                  * struct vnode *a_vp;
605                                  * struct componentname *a_cnp;
606                                  * } */ *ap = v;
607     int code;
608     struct vnode *vp = ap->a_vp;
609     struct vnode *dvp = ap->a_dvp;
610
611     GETNAME();
612     AFS_GLOCK();
613     code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
614     AFS_GUNLOCK();
615     if (dvp == vp)
616         vrele(vp);
617     else
618         vput(vp);
619     vput(dvp);
620     DROPCNP(cnp);
621     DROPNAME();
622     return code;
623 }
624
625 int
626 afs_nbsd_link(void *v)
627 {
628     struct vop_link_args        /* {
629                                  * struct vnode *a_vp;
630                                  * struct vnode *a_tdvp;
631                                  * struct componentname *a_cnp;
632                                  * } */ *ap = v;
633     int code;
634     struct vnode *dvp = ap->a_dvp;
635     struct vnode *vp = ap->a_vp;
636
637     GETNAME();
638     if (dvp->v_mount != vp->v_mount) {
639         VOP_ABORTOP(vp, cnp);
640         code = EXDEV;
641         goto out;
642     }
643     if (vp->v_type == VDIR) {
644         VOP_ABORTOP(vp, cnp);
645         code = EISDIR;
646         goto out;
647     }
648     if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))) {
649         VOP_ABORTOP(dvp, cnp);
650         goto out;
651     }
652
653     AFS_GLOCK();
654     code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
655     AFS_GUNLOCK();
656     DROPCNP(cnp);
657     if (dvp != vp)
658         VOP_UNLOCK(vp, 0);
659
660   out:
661     vput(dvp);
662     DROPNAME();
663     return code;
664 }
665
666 int
667 afs_nbsd_rename(void *v)
668 {
669     struct vop_rename_args      /* {
670                                  * struct vnode *a_fdvp;
671                                  * struct vnode *a_fvp;
672                                  * struct componentname *a_fcnp;
673                                  * struct vnode *a_tdvp;
674                                  * struct vnode *a_tvp;
675                                  * struct componentname *a_tcnp;
676                                  * } */ *ap = v;
677     int code = 0;
678     struct componentname *fcnp = ap->a_fcnp;
679     char *fname;
680     struct componentname *tcnp = ap->a_tcnp;
681     char *tname;
682     struct vnode *tvp = ap->a_tvp;
683     struct vnode *tdvp = ap->a_tdvp;
684     struct vnode *fvp = ap->a_fvp;
685     struct vnode *fdvp = ap->a_fdvp;
686
687     /*
688      * Check for cross-device rename.
689      */
690     if ((fvp->v_mount != tdvp->v_mount)
691         || (tvp && (fvp->v_mount != tvp->v_mount))) {
692         code = EXDEV;
693       abortit:
694         VOP_ABORTOP(tdvp, tcnp);        /* XXX, why not in NFS? */
695         if (tdvp == tvp)
696             vrele(tdvp);
697         else
698             vput(tdvp);
699         if (tvp)
700             vput(tvp);
701         VOP_ABORTOP(fdvp, fcnp);        /* XXX, why not in NFS? */
702         vrele(fdvp);
703         vrele(fvp);
704         return (code);
705     }
706     /*
707      * if fvp == tvp, we're just removing one name of a pair of
708      * directory entries for the same element.  convert call into rename.
709      ( (pinched from NetBSD 1.0's ufs_rename())
710      */
711     if (fvp == tvp) {
712         if (fvp->v_type == VDIR) {
713             code = EINVAL;
714             goto abortit;
715         }
716
717         /* Release destination completely. */
718         VOP_ABORTOP(tdvp, tcnp);
719         vput(tdvp);
720         vput(tvp);
721
722         /* Delete source. */
723         vrele(fdvp);
724         vrele(fvp);
725         fcnp->cn_flags &= ~MODMASK;
726         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
727         if ((fcnp->cn_flags & SAVESTART) == 0)
728             panic("afs_rename: lost from startdir");
729         fcnp->cn_nameiop = DELETE;
730         (void)relookup(fdvp, &fvp, fcnp);
731         return (VOP_REMOVE(fdvp, fvp, fcnp));
732     }
733
734     if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)))
735         goto abortit;
736
737     /* XXX GETNAME() ? */
738     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
739     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
740     fname[fcnp->cn_namelen] = '\0';
741     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
742     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
743     tname[tcnp->cn_namelen] = '\0';
744
745
746     AFS_GLOCK();
747     /* XXX use "from" or "to" creds? NFS uses "to" creds */
748     code =
749         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname,
750                    tcnp->cn_cred);
751     AFS_GUNLOCK();
752
753     VOP_UNLOCK(fvp, 0);
754     FREE(fname, M_TEMP);
755     FREE(tname, M_TEMP);
756     if (code)
757         goto abortit;           /* XXX */
758     if (tdvp == tvp)
759         vrele(tdvp);
760     else
761         vput(tdvp);
762     if (tvp)
763         vput(tvp);
764     vrele(fdvp);
765     vrele(fvp);
766     return code;
767 }
768
769 int
770 afs_nbsd_mkdir(void *v)
771 {
772     struct vop_mkdir_args       /* {
773                                  * struct vnode *a_dvp;
774                                  * struct vnode **a_vpp;
775                                  * struct componentname *a_cnp;
776                                  * struct vattr *a_vap;
777                                  * } */ *ap = v;
778     struct vnode *dvp = ap->a_dvp;
779     struct vattr *vap = ap->a_vap;
780     int code;
781     struct vcache *vcp;
782
783     GETNAME();
784 #ifdef DIAGNOSTIC
785     if ((cnp->cn_flags & HASBUF) == 0)
786         panic("afs_nbsd_mkdir: no name");
787 #endif
788     AFS_GLOCK();
789     code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
790     AFS_GUNLOCK();
791     if (code) {
792         VOP_ABORTOP(dvp, cnp);
793         vput(dvp);
794         DROPNAME();
795         return (code);
796     }
797     if (vcp) {
798         *ap->a_vpp = AFSTOV(vcp);
799         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
800     } else
801         *ap->a_vpp = 0;
802     DROPCNP(cnp);
803     DROPNAME();
804     vput(dvp);
805     return code;
806 }
807
808 int
809 afs_nbsd_rmdir(void *v)
810 {
811     struct vop_rmdir_args       /* {
812                                  * struct vnode *a_dvp;
813                                  * struct vnode *a_vp;
814                                  * struct componentname *a_cnp;
815                                  * } */ *ap = v;
816     int code;
817     struct vnode *vp = ap->a_vp;
818     struct vnode *dvp = ap->a_dvp;
819
820     GETNAME();
821     if (dvp == vp) {
822         vrele(dvp);
823         vput(vp);
824         DROPCNP(cnp);
825         DROPNAME();
826         return (EINVAL);
827     }
828
829     AFS_GLOCK();
830     code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
831     AFS_GUNLOCK();
832     DROPNAME();
833     vput(dvp);
834     vput(vp);
835     return code;
836 }
837
838 int
839 afs_nbsd_symlink(void *v)
840 {
841     struct vop_symlink_args     /* {
842                                  * struct vnode *a_dvp;
843                                  * struct vnode **a_vpp;
844                                  * struct componentname *a_cnp;
845                                  * struct vattr *a_vap;
846                                  * char *a_target;
847                                  * } */ *ap = v;
848     struct vnode *dvp = ap->a_dvp;
849     int code;
850     /* NFS ignores a_vpp; so do we. */
851
852     GETNAME();
853     AFS_GLOCK();
854     code =
855         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
856                     cnp->cn_cred);
857     AFS_GUNLOCK();
858     DROPCNP(cnp);
859     DROPNAME();
860     vput(dvp);
861     return code;
862 }
863
864 int
865 afs_nbsd_readdir(void *v)
866 {
867     struct vop_readdir_args     /* {
868                                  * struct vnode *a_vp;
869                                  * struct uio *a_uio;
870                                  * kauth_cred_t a_cred;
871                                  * int *a_eofflag;
872                                  * int *a_ncookies;
873                                  * u_long **a_cookies;
874                                  * } */ *ap = v;
875     int code;
876
877     AFS_GLOCK();
878 #ifdef AFS_HAVE_COOKIES
879     printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
880            ap->a_ncookies);
881     code =
882         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag,
883                     ap->a_ncookies, ap->a_cookies);
884 #else
885     code =
886         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
887 #endif
888     AFS_GUNLOCK();
889     return code;
890 }
891
892 int
893 afs_nbsd_readlink(void *v)
894 {
895     struct vop_readlink_args    /* {
896                                  * struct vnode *a_vp;
897                                  * struct uio *a_uio;
898                                  * kauth_cred_t a_cred;
899                                  * } */ *ap = v;
900     int code;
901
902     AFS_GLOCK();
903     code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
904     AFS_GUNLOCK();
905     return code;
906 }
907
908 extern int prtactive;
909
910 int
911 afs_nbsd_inactive(void *v)
912 {
913     struct vop_inactive_args    /* {
914                                  * struct vnode *a_vp;
915                                  * } */ *ap = v;
916     struct vnode *vp = ap->a_vp;
917     struct vcache *vc = VTOAFS(vp);
918     int haveGlock = ISAFS_GLOCK();
919
920     AFS_STATCNT(afs_inactive);
921
922     if (prtactive && vp->v_usecount != 0)
923         vprint("afs_nbsd_inactive(): pushing active", vp);
924
925     if (!haveGlock)
926         AFS_GLOCK();
927     afs_InactiveVCache(vc, 0);  /* decrs ref counts */
928     if (!haveGlock)
929         AFS_GUNLOCK();
930
931     lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
932     return 0;
933 }
934
935 int
936 afs_nbsd_reclaim(void *v)
937 {
938     struct vop_reclaim_args     /* {
939                                  * struct vnode *a_vp;
940                                  * } */ *ap = v;
941     int code, slept;
942     struct vnode *vp = ap->a_vp;
943     struct vcache *avc = VTOAFS(vp);
944     int haveGlock = ISAFS_GLOCK();
945     int haveVlock = CheckLock(&afs_xvcache);
946
947 #if 0
948     printf("reclaim usecount %d\n", vp->v_usecount);
949     /* OK, there are no internal vrefCounts, so there shouldn't
950      * be any more refs here. */
951     vp->v_data = NULL;          /* remove from vnode */
952     avc->v = NULL;              /* also drop the ptr to vnode */
953     return 0;
954 #else
955     if (!haveGlock)
956         AFS_GLOCK();
957     if (!haveVlock)
958         ObtainWriteLock(&afs_xvcache, 901);
959     /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
960     code = afs_FlushVCache(avc, &slept);
961     if (!haveVlock)
962         ReleaseWriteLock(&afs_xvcache);
963     if (!haveGlock)
964         AFS_GUNLOCK();
965     return code;
966 #endif
967 }
968
969 int
970 afs_nbsd_lock(void *v)
971 {
972     struct vop_lock_args        /* {
973                                  * struct vnode *a_vp;
974                                  * int a_flags;
975                                  * struct lwp *a_l;
976                                  * } */ *ap = v;
977
978     return (genfs_lock(v));
979 }
980
981 int
982 afs_nbsd_unlock(void *v)
983 {
984     struct vop_unlock_args      /* {
985                                  * struct vnode *a_vp;
986                                  * int a_flags;
987                                  * struct lwp *a_l;
988                                  * } */ *ap = v;
989
990     return (genfs_unlock(v));
991 }
992
993 int
994 afs_nbsd_bmap(void *v)
995 {
996     struct vop_bmap_args        /* {
997                                  * struct vnode *a_vp;
998                                  * daddr_t  a_bn;
999                                  * struct vnode **a_vpp;
1000                                  * daddr_t *a_bnp;
1001                                  * int *a_runp;
1002                                  * } */ *ap = v;
1003     struct vcache *vcp = VTOAFS(ap->a_vp);
1004
1005     AFS_STATCNT(afs_bmap);
1006
1007     /* borrowed from DARWIN--why notyet? */
1008     if (ap->a_bnp) {
1009         *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1010     }
1011     if (ap->a_vpp) {
1012         *ap->a_vpp = ap->a_vp;
1013     }
1014     if (ap->a_runp != NULL)
1015         *ap->a_runp = 0;
1016 #ifdef notyet
1017     if (ap->a_runb != NULL)
1018         *ap->a_runb = 0;
1019 #endif
1020
1021     return 0;
1022 }
1023
1024 int
1025 afs_nbsd_strategy(void *v)
1026 {
1027     struct vop_strategy_args    /* {
1028                                  * struct buf *a_bp;
1029                                  * } */ *ap = v;
1030     struct buf *abp = ap->a_bp;
1031     struct uio tuio;
1032     struct iovec tiovec[1];
1033     struct vcache *tvc = VTOAFS(abp->b_vp);
1034     afs_ucred_t credp = osi_curcred();
1035     long len = abp->b_bcount;
1036     int code;
1037
1038     AFS_STATCNT(afs_strategy);
1039
1040     tuio.afsio_iov = tiovec;
1041     tuio.afsio_iovcnt = 1;
1042     tuio.afsio_resid = len;
1043     tiovec[0].iov_base = abp->b_un.b_addr;
1044     tiovec[0].iov_len = len;
1045     UIO_SETUP_SYSSPACE(&tuio);
1046
1047     AFS_GLOCK();
1048     if ((abp->b_flags & B_READ) == B_READ) {
1049         code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
1050         if (code == 0 && tuio.afsio_resid > 0)
1051             bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
1052                   tuio.afsio_resid);
1053     } else
1054         code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1055     AFS_GUNLOCK();
1056
1057     ReleaseWriteLock(&tvc->lock);
1058     AFS_RELE(AFSTOV(tvc));
1059     return code;
1060 }
1061
1062 int
1063 afs_nbsd_print(void *v)
1064 {
1065     struct vop_print_args       /* {
1066                                  * struct vnode *a_vp;
1067                                  * } */ *ap = v;
1068     struct vnode *vp = ap->a_vp;
1069     struct vcache *vc = VTOAFS(ap->a_vp);
1070
1071     printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell,
1072            (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode,
1073            (int)vc->f.fid.Fid.Unique);
1074     lockmgr_printinfo(&vc->rwlock);
1075     printf("\n");
1076     return 0;
1077 }
1078
1079 int
1080 afs_nbsd_islocked(void *v)
1081 {
1082     struct vop_islocked_args    /* {
1083                                  * struct vnode *a_vp;
1084                                  * } */ *ap = v;
1085     return (genfs_islocked(v));
1086 }
1087
1088 /*
1089  * Return POSIX pathconf information applicable to ufs filesystems.
1090  */
1091 int
1092 afs_nbsd_pathconf(void *v)
1093 {
1094     struct vop_pathconf_args    /* {
1095                                  * struct vnode *a_vp;
1096                                  * int a_name;
1097                                  * int *a_retval;
1098                                  * } */ *ap = v;
1099     AFS_STATCNT(afs_cntl);
1100     switch (ap->a_name) {
1101     case _PC_LINK_MAX:
1102         *ap->a_retval = LINK_MAX;
1103         break;
1104     case _PC_NAME_MAX:
1105         *ap->a_retval = NAME_MAX;
1106         break;
1107     case _PC_PATH_MAX:
1108         *ap->a_retval = PATH_MAX;
1109         break;
1110     case _PC_CHOWN_RESTRICTED:
1111         *ap->a_retval = 1;
1112         break;
1113     case _PC_NO_TRUNC:
1114         *ap->a_retval = 1;
1115         break;
1116     case _PC_PIPE_BUF:
1117         return EINVAL;
1118         break;
1119     default:
1120         return EINVAL;
1121     }
1122     return 0;
1123 }
1124
1125 extern int
1126   afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1127               afs_ucred_t *acred, pid_t clid);
1128
1129 /*
1130  * Advisory record locking support (fcntl() POSIX style)
1131  */
1132 int
1133 afs_nbsd_advlock(void *v)
1134 {
1135     struct vop_advlock_args     /* {
1136                                  * struct vnode *a_vp;
1137                                  * caddr_t  a_id;
1138                                  * int  a_op;
1139                                  * struct flock *a_fl;
1140                                  * int  a_flags;
1141                                  * } */ *ap = v;
1142     int code;
1143
1144     AFS_GLOCK();
1145     code =
1146         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1147                     (int)ap->a_id);
1148     AFS_GUNLOCK();
1149     return code;
1150 }