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>
6 * $Id: osi_vnodeops.c,v 1.20 2006/03/09 15:27:17 rees Exp $
11 the regents of the university of michigan
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
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
40 Copyright 1995 Massachusetts Institute of Technology. All Rights
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
56 * A bunch of code cribbed from NetBSD ufs_vnops.c, ffs_vnops.c, and
57 * nfs_vnops.c which carry this copyright:
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.
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
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.
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
98 #include <afsconfig.h>
99 #include "afs/param.h"
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 */
105 #include <sys/malloc.h>
106 #include <sys/namei.h>
107 #include <sys/pool.h>
108 #include <miscfs/genfs/genfs.h>
111 #include "afs/afs_cbqueue.h"
112 #include "afs/nfsclient.h"
113 #include "afs/afs_osidnlc.h"
115 #define M_AFSNODE (M_TEMP-1) /* XXX */
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 *);
150 int afs_nbsd_getpages(void*);
159 * vop_mmap_desc (mmap'd IO)
169 #define afs_nbsd_opnotsupp \
170 ((int (*) __P((void *)))eopnotsupp)
171 #define afs_nbsd_reallocblks afs_nbsd_opnotsupp
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 */
211 {&vop_reallocblks_desc, afs_nbsd_reallocblks}, /* reallocblks */
213 {&vop_bwrite_desc, vn_bwrite}, /* bwrite */
215 { &vop_getpages_desc, ffs_getpages }, /* getpages */
216 { &vop_putpages_desc, genfs_putpages }, /* putpages */
218 {(struct vnodeop_desc *)NULL, (int (*)__P((void *)))NULL}
220 struct vnodeopv_desc afs_vnodeop_opv_desc =
221 { &afs_vnodeop_p, afs_vnodeop_entries };
224 struct componentname *cnp = ap->a_cnp; \
226 name = PNBUF_GET(); \
227 bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
228 name[cnp->cn_namelen] = '\0'
230 #define DROPNAME() PNBUF_PUT(name)
231 #define DROPCNP PNBUF_PUT
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) \
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); \
244 #define VNP_UNCACHE(vp) \
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); \
253 /* psuedo-vnop, wherein we learn that obsd and nbsd disagree
254 * about vnode refcounting */
256 afs_nbsd_getnewvnode(struct vcache *tvc)
258 while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
259 /* no vnodes available, force an alloc (limits be damned)! */
262 printf("afs_nbsd_getnewvnode: vp %p refs %d\n", tvc->v,
264 #ifdef AFS_NBSD50_ENV
265 mutex_enter(&tvc->v->v_interlock);
267 simple_lock(&tvc->v->v_interlock);
269 tvc->v->v_data = (void *)tvc;
271 tvc->v->v_usecount = 1; /* !locked, and vref w/v_usecount < 1 panics */
273 #ifdef AFS_NBSD50_ENV
274 mutex_exit(&tvc->v->v_interlock);
276 simple_unlock(&tvc->v->v_interlock);
280 unsigned long long afs_debug;
283 afs_nbsd_lookup(void *v)
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;
293 struct vnode *vp, *dvp;
294 int flags = ap->a_cnp->cn_flags;
295 int lockparent; /* 1 => lockparent flag is set */
297 if (afs_debug & AFSDEB_VNLAYER)
298 printf("nbsd_lookup enter ap %p\n", ap);
301 lockparent = flags & LOCKPARENT;
302 if (ap->a_dvp->v_type != VDIR) {
309 * v_flag was broke up into 3 separate flags. v_vflag is the
310 * substitute when referencing V_ROOT (which was also renamed)
314 #ifdef AFS_NBSD50_ENV
315 if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_vflag & VV_ROOT))
317 if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
319 printf("nbsd_lookup dvp %p flags %x name %s v_usecnt %d\n", dvp, flags,
320 name, dvp->v_usecount);
322 code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
325 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
326 && (flags & ISLASTCN) && code == ENOENT)
328 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
329 cnp->cn_flags |= SAVENAME;
334 vp = AFSTOV(vcp); /* always get a node if no error */
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.
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);
348 if (!lockparent || !(flags & ISLASTCN)) {
349 VOP_UNLOCK(dvp, 0); /* done with parent. */
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);
356 /* XXXX hacked here, recheck OBSD and bundled--NBSD has
357 * removed PDIRUNLOCK, so we must at least accommodate that
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 */
365 if (afs_debug & AFSDEB_VNLAYER)
366 printf("lookup: vp %p is locked\n", vp);
368 if (afs_debug & AFSDEB_VNLAYER)
369 printf("locked ret %p from lookup\n", vp);
373 if (((cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
374 || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
375 cnp->cn_flags |= SAVENAME;
378 #ifdef AFS_NBSD50_ENV
379 if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_vflag & VV_ROOT))
381 if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
383 if (afs_debug & AFSDEB_VNLAYER)
384 printf("nbsd_lookup done ap %p dvp %p cnt %d\n", ap, dvp,
390 afs_nbsd_create(void *v)
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;
400 struct vnode *dvp = ap->a_dvp;
403 if (afs_debug & AFSDEB_VNLAYER)
404 printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
406 /* vnode layer handles excl/nonexcl */
410 afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
414 VOP_ABORTOP(dvp, cnp);
421 *ap->a_vpp = AFSTOV(vcp);
422 vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
426 if ((cnp->cn_flags & SAVESTART) == 0)
430 if (afs_debug & AFSDEB_VNLAYER)
431 printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
436 afs_nbsd_mknod(void *v)
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;
445 if (afs_debug & AFSDEB_VNLAYER)
446 printf("nbsd_mknod: enter ap %p\n", ap);
452 if (afs_debug & AFSDEB_VNLAYER)
453 printf("nbsd_mknod: exit ap %p\n", ap);
457 afs_nbsd_open(void *v)
459 struct vop_open_args /* {
460 * struct vnode *a_vp;
462 * struct ucred *a_cred;
466 struct vnode *vp = ap->a_vp;
467 struct vcache *vc = VTOAFS(vp);
469 if (afs_debug & AFSDEB_VNLAYER)
470 printf("nbsd_open: enter vp %p vc %p\n", vp, vc);
473 code = afs_open(&vc, ap->a_mode, ap->a_cred);
475 if (AFSTOV(vc) != ap->a_vp)
476 panic("nbsd_open: AFS open changed vnode!");
480 if (afs_debug & AFSDEB_VNLAYER)
481 printf("nbsd_open: exit vp %p vc %p\n", vp, vc);
487 afs_nbsd_close(void *v)
489 struct vop_close_args /* {
490 * struct vnode *a_vp;
492 * kauth_cred_t a_cred;
496 struct vnode *vp = ap->a_vp;
497 struct vcache *vc = VTOAFS(vp);
499 if (afs_debug & AFSDEB_VNLAYER)
500 printf("nbsd_close: enter vp %p vc %p\n", vp, vc);
503 code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred);
506 if (afs_debug & AFSDEB_VNLAYER)
507 printf("nbsd_close: exit vp %p vc %p\n", vp, vc);
513 afs_nbsd_access(void *v)
515 struct vop_access_args /* {
516 * struct vnode *a_vp;
518 * kauth_cred_t a_cred;
522 struct vnode *vp = ap->a_vp;
523 struct vcache *vc = VTOAFS(vp);
525 if (afs_debug & AFSDEB_VNLAYER)
526 printf("nbsd_access: enter vp %p vc %p mode %d\n", vp, vc, ap->a_mode);
529 code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
532 if (afs_debug & AFSDEB_VNLAYER)
533 printf("nbsd_access: exit vp %p vc %p mode %d\n", vp, vc, ap->a_mode);
539 afs_nbsd_getattr(void *v)
541 struct vop_getattr_args /* {
542 * struct vnode *a_vp;
543 * struct vattr *a_vap;
544 * kauth_cred_t a_cred;
548 struct vnode *vp = ap->a_vp;
549 struct vcache *vc = VTOAFS(vp);
551 if (afs_debug & AFSDEB_VNLAYER)
552 printf("nbsd_getattr: enter vp %p vc %p acred %p\n", vp, vc,
556 code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
559 if (afs_debug & AFSDEB_VNLAYER)
560 printf("nbsd_getattr: exit vp %p vc %p acred %p\n", vp, vc,
567 afs_nbsd_setattr(void *v)
569 struct vop_setattr_args /* {
570 * struct vnode *a_vp;
571 * struct vattr *a_vap;
572 * kauth_cred_t a_cred;
577 if (afs_debug & AFSDEB_VNLAYER)
578 printf("nbsd_setattr: enter %p\n", ap);
581 code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
584 if (afs_debug & AFSDEB_VNLAYER)
585 printf("nbsd_setattr: exit %p\n", ap);
591 afs_nbsd_read(void *v)
593 struct vop_read_args /* {
594 * struct vnode *a_vp;
597 * kauth_cred_t a_cred;
601 if (afs_debug & AFSDEB_VNLAYER)
602 printf("nbsd_read enter %p", ap);
606 afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, (daddr_t) 0, NULL,
610 if (afs_debug & AFSDEB_VNLAYER)
611 printf("nbsd_read exit %p", ap);
617 afs_nbsd_write(void *v)
619 struct vop_write_args /* {
620 * struct vnode *a_vp;
623 * kauth_cred_t a_cred;
627 if (afs_debug & AFSDEB_VNLAYER)
628 printf("nbsd_write enter %p", ap);
631 /* all pages are really "stale?" */
632 VNP_UNCACHE(ap->a_vp);
634 (void)uvm_vnp_uncache(ap->a_vp); /* toss stale pages */
638 afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
641 if (afs_debug & AFSDEB_VNLAYER)
642 printf("nbsd_write exit %p", ap);
648 afs_nbsd_ioctl(void *v)
650 struct vop_ioctl_args /* {
651 * struct vnode *a_vp;
655 * kauth_cred_t a_cred;
660 if (afs_debug & AFSDEB_VNLAYER)
661 printf("nbsd_ioctl: enter %p\n", ap);
663 /* in case we ever get in here... */
665 AFS_STATCNT(afs_ioctl);
667 if (((ap->a_command >> 8) & 0xff) == 'V')
668 /* This is a VICEIOCTL call */
670 HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
671 (struct afs_ioctl *)ap->a_data);
673 /* No-op call; just return. */
677 if (afs_debug & AFSDEB_VNLAYER)
678 printf("nbsd_ioctl: exit %p\n", ap);
684 afs_nbsd_select(void *v)
690 afs_nbsd_fsync(void *v)
692 struct vop_fsync_args /* {
693 * struct vnode *a_vp;
694 * kauth_cred_t a_cred;
698 struct vnode *vp = ap->a_vp;
701 if (afs_debug & AFSDEB_VNLAYER)
702 printf("nbsd_fsync: enter %p\n", ap);
704 wait = (ap->a_flags & FSYNC_WAIT) != 0;
708 code = afs_fsync(VTOAFS(vp), ap->a_cred);
711 if (afs_debug & AFSDEB_VNLAYER)
712 printf("nbsd_fsync: exit %p\n", ap);
718 afs_nbsd_remove(void *v)
720 struct vop_remove_args /* {
721 * struct vnode *a_dvp;
722 * struct vnode *a_vp;
723 * struct componentname *a_cnp;
726 struct vnode *vp = ap->a_vp;
727 struct vnode *dvp = ap->a_dvp;
729 if (afs_debug & AFSDEB_VNLAYER)
730 printf("nbsd_remove: enter %p\n", ap);
734 code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
744 if (afs_debug & AFSDEB_VNLAYER)
745 printf("nbsd_remove: exit %p\n", ap);
751 afs_nbsd_link(void *v)
753 struct vop_link_args /* {
754 * struct vnode *a_vp;
755 * struct vnode *a_tdvp;
756 * struct componentname *a_cnp;
759 struct vnode *dvp = ap->a_dvp;
760 struct vnode *vp = ap->a_vp;
762 if (afs_debug & AFSDEB_VNLAYER)
763 printf("nbsd_link: enter %p\n", ap);
766 if (dvp->v_mount != vp->v_mount) {
767 VOP_ABORTOP(vp, cnp);
771 if (vp->v_type == VDIR) {
772 VOP_ABORTOP(vp, cnp);
776 if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))) {
777 VOP_ABORTOP(dvp, cnp);
782 code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
792 if (afs_debug & AFSDEB_VNLAYER)
793 printf("nbsd_link: exit %p\n", ap);
799 afs_nbsd_rename(void *v)
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;
810 struct componentname *fcnp = ap->a_fcnp;
812 struct componentname *tcnp = ap->a_tcnp;
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;
819 if (afs_debug & AFSDEB_VNLAYER)
820 printf("nbsd_rename: enter %p\n", ap);
823 * Check for cross-device rename.
825 if ((fvp->v_mount != tdvp->v_mount)
826 || (tvp && (fvp->v_mount != tvp->v_mount))) {
829 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
836 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
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())
847 if (fvp->v_type == VDIR) {
852 /* Release destination completely. */
853 VOP_ABORTOP(tdvp, tcnp);
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);
870 if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)))
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';
882 /* XXX use "from" or "to" creds? NFS uses "to" creds */
884 afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname,
892 goto abortit; /* XXX */
903 if (afs_debug & AFSDEB_VNLAYER)
904 printf("nbsd_rename: exit %p\n", ap);
910 afs_nbsd_mkdir(void *v)
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;
918 struct vnode *dvp = ap->a_dvp;
919 struct vattr *vap = ap->a_vap;
923 if (afs_debug & AFSDEB_VNLAYER)
924 printf("nbsd_mkdir: enter %p\n", ap);
928 if ((cnp->cn_flags & HASBUF) == 0)
929 panic("afs_nbsd_mkdir: no name");
932 code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
935 VOP_ABORTOP(dvp, cnp);
941 *ap->a_vpp = AFSTOV(vcp);
942 vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
950 if (afs_debug & AFSDEB_VNLAYER)
951 printf("nbsd_mkdir: exit %p\n", ap);
957 afs_nbsd_rmdir(void *v)
959 struct vop_rmdir_args /* {
960 * struct vnode *a_dvp;
961 * struct vnode *a_vp;
962 * struct componentname *a_cnp;
965 struct vnode *vp = ap->a_vp;
966 struct vnode *dvp = ap->a_dvp;
968 if (afs_debug & AFSDEB_VNLAYER)
969 printf("nbsd_rmdir: enter %p", ap);
982 code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
989 if (afs_debug & AFSDEB_VNLAYER)
990 printf("nbsd_rmdir: exit %p\n", ap);
996 afs_nbsd_symlink(void *v)
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;
1005 struct vnode *dvp = ap->a_dvp;
1007 /* NFS ignores a_vpp; so do we. */
1009 if (afs_debug & AFSDEB_VNLAYER)
1010 printf("nbsd_symlink: enter %p\n", ap);
1015 afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
1022 if (afs_debug & AFSDEB_VNLAYER)
1023 printf("nbsd_symlink: exit %p\n", ap);
1029 nbsd_fake_readdir(struct vnode *vp, struct vcache *vc, struct uio *auio,
1030 kauth_cred_t acred, int *a_eofflag, int *a_ncookies,
1034 afs_int32 code, maxb;
1036 maxb = auio->uio_resid;
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);
1044 /* 1. simply returning 0 had good behavior (/afs is empty) */
1048 $5 = {uio_iov = 0xcbd0ec90, uio_iovcnt = 1, uio_offset = 0, uio_resid = 4096,
1049 uio_rw = UIO_READ, uio_vmspace = 0xcbe8beec}
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. */
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.
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)
1079 dp = (struct dirent *) kmem_zalloc(sizeof(struct dirent), KM_SLEEP);
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);
1088 printf("nbsd_fake_readdir: uiomove FAILED\n");
1089 kmem_free(dp, sizeof(struct dirent));
1092 /* terminate enumeration */
1104 afs_nbsd_readdir(void *v)
1106 struct vop_readdir_args /* {
1107 * struct vnode *a_vp;
1108 * struct uio *a_uio;
1109 * kauth_cred_t a_cred;
1112 * u_long **a_cookies;
1115 struct vnode *vp = ap->a_vp;
1116 struct vcache *vc = VTOAFS(vp);
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);
1123 #ifdef AFS_HAVE_COOKIES
1124 printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
1127 afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag,
1128 ap->a_ncookies, ap->a_cookies);
1131 afs_readdir(vc, ap->a_uio, ap->a_cred, ap->a_eofflag);
1135 if (afs_debug & AFSDEB_VNLAYER)
1136 printf("nbsd_readdir: exit %p eofflag %d\n", ap, *ap->a_eofflag);
1142 afs_nbsd_readlink(void *v)
1144 struct vop_readlink_args /* {
1145 * struct vnode *a_vp;
1146 * struct uio *a_uio;
1147 * kauth_cred_t a_cred;
1151 if (afs_debug & AFSDEB_VNLAYER)
1152 printf("nbsd_readlink: enter %p\n", ap);
1155 code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1158 if (afs_debug & AFSDEB_VNLAYER)
1159 printf("nbsd_readlink: exit %p\n", ap);
1164 extern int prtactive;
1167 afs_nbsd_inactive(void *v)
1169 struct vop_inactive_args /* {
1170 * struct vnode *a_vp;
1172 struct vnode *vp = ap->a_vp;
1173 struct vcache *vc = VTOAFS(vp);
1174 int haveGlock = ISAFS_GLOCK();
1176 AFS_STATCNT(afs_inactive);
1178 if (afs_debug & AFSDEB_VNLAYER)
1179 printf("nbsd_inactive: enter %p\n", ap);
1181 if (prtactive && vp->v_usecount != 0)
1182 vprint("afs_nbsd_inactive: pushing active", vp);
1186 afs_InactiveVCache(vc, 0); /* decrs ref counts */
1190 #ifdef AFS_NBSD50_ENV
1191 mutex_init(&vc->rwlock, MUTEX_DEFAULT, IPL_NONE);
1193 lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
1196 if (afs_debug & AFSDEB_VNLAYER)
1197 printf("nbsd_inactive: exit %p\n", ap);
1203 afs_nbsd_reclaim(void *v)
1205 struct vop_reclaim_args /* {
1206 * struct vnode *a_vp;
1209 struct vnode *vp = ap->a_vp;
1210 struct vcache *avc = VTOAFS(vp);
1211 int haveGlock = ISAFS_GLOCK();
1212 int haveVlock = CheckLock(&afs_xvcache);
1214 if (afs_debug & AFSDEB_VNLAYER)
1215 printf("nbsd_reclaim: enter %p\n", ap);
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 */
1224 if (afs_debug & AFSDEB_VNLAYER)
1225 printf("nbsd_reclaim: exit %p\n", ap);
1232 ObtainWriteLock(&afs_xvcache, 901);
1233 #ifndef AFS_DISCON_ENV
1234 code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
1236 /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
1237 code = afs_FlushVCache(avc, &slept);
1240 ReleaseWriteLock(&afs_xvcache);
1244 if (afs_debug & AFSDEB_VNLAYER)
1245 printf("nbsd_reclaim: exit %p\n", ap);
1252 afs_nbsd_lock(void *v)
1254 struct vop_lock_args /* {
1255 * struct vnode *a_vp;
1260 struct vnode *vp = ap->a_vp;
1261 int flags = ap->a_flags;
1263 if (afs_debug & AFSDEB_VNLAYER)
1264 printf("nbsd_lock: enter vp %p flags %d\n", vp, flags);
1266 code = genfs_lock(v);
1268 if (afs_debug & AFSDEB_VNLAYER)
1269 printf("nbsd_lock: exit vp %p flags %d\n\n", vp, flags);
1275 afs_nbsd_unlock(void *v)
1277 struct vop_unlock_args /* {
1278 * struct vnode *a_vp;
1283 struct vnode *vp = ap->a_vp;
1284 int flags = ap->a_flags;
1286 if (afs_debug & AFSDEB_VNLAYER)
1287 printf("nbsd_unlock: enter vp %p flags %d\n", vp, flags);
1289 code = genfs_unlock(v);
1291 if (afs_debug & AFSDEB_VNLAYER)
1292 printf("nbsd_unlock: exit vp %p flags %d\n", vp, flags);
1298 afs_nbsd_islocked(void *v)
1300 struct vop_islocked_args /* {
1301 * struct vnode *a_vp;
1305 struct vnode *vp = ap->a_vp;
1307 if (afs_debug & AFSDEB_VNLAYER)
1308 printf("nbsd_islocked: enter vp %p flags %d\n", vp);
1310 code = genfs_islocked(v);
1312 if (afs_debug & AFSDEB_VNLAYER)
1313 printf("nbsd_islocked: exit vp %p flags %d\n", vp);
1320 afs_nbsd_bmap(void *v)
1322 struct vop_bmap_args /* {
1323 * struct vnode *a_vp;
1325 * struct vnode **a_vpp;
1329 struct vcache *vcp = VTOAFS(ap->a_vp);
1331 AFS_STATCNT(afs_bmap);
1333 if (afs_debug & AFSDEB_VNLAYER)
1334 printf("nbsd_bmap: enter %p\n", ap);
1336 /* borrowed from DARWIN--why notyet? */
1338 *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1340 *ap->a_vpp = ap->a_vp;
1341 if (ap->a_runp != NULL)
1344 if (ap->a_runb != NULL)
1348 if (afs_debug & AFSDEB_VNLAYER)
1349 printf("nbsd_bmap: exit %p\n", ap);
1355 afs_nbsd_strategy(void *v)
1357 struct vop_strategy_args /* {
1360 struct buf *abp = ap->a_bp;
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;
1368 AFS_STATCNT(afs_strategy);
1370 if (afs_debug & AFSDEB_VNLAYER)
1371 printf("nbsd_strategy: enter %p\n", ap);
1373 tuio.afsio_iov = tiovec;
1374 tuio.afsio_iovcnt = 1;
1375 tuio.afsio_resid = len;
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.
1381 #ifdef AFS_NBSD50_ENV
1382 tiovec[0].iov_base = abp->b_blkno;
1384 tiovec[0].iov_base = abp->b_un.b_addr;
1386 tiovec[0].iov_len = len;
1387 UIO_SETUP_SYSSPACE(&tuio);
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,
1396 bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
1400 code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1403 ReleaseWriteLock(&tvc->lock);
1404 AFS_RELE(AFSTOV(tvc));
1406 if (afs_debug & AFSDEB_VNLAYER)
1407 printf("nbsd_strategy: exit %p\n", ap);
1413 afs_nbsd_print(void *v)
1415 struct vop_print_args /* {
1416 * struct vnode *a_vp;
1418 struct vnode *vp = ap->a_vp;
1419 struct vcache *vc = VTOAFS(ap->a_vp);
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);
1427 lockmgr_printinfo(&vc->rwlock);
1434 * Return POSIX pathconf information applicable to ufs filesystems.
1437 afs_nbsd_pathconf(void *v)
1439 struct vop_pathconf_args /* {
1440 * struct vnode *a_vp;
1446 AFS_STATCNT(afs_cntl);
1448 if (afs_debug & AFSDEB_VNLAYER)
1449 printf("nbsd_pathconf: enter %p\n", ap);
1451 switch (ap->a_name) {
1453 *ap->a_retval = LINK_MAX;
1456 *ap->a_retval = NAME_MAX;
1459 *ap->a_retval = PATH_MAX;
1461 case _PC_CHOWN_RESTRICTED:
1477 if (afs_debug & AFSDEB_VNLAYER)
1478 printf("nbsd_pathconf: exit %p\n", ap);
1484 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1485 afs_ucred_t *acred, pid_t clid);
1488 * Advisory record locking support (fcntl() POSIX style)
1491 afs_nbsd_advlock(void *v)
1493 struct vop_advlock_args /* {
1494 * struct vnode *a_vp;
1497 * struct flock *a_fl;
1502 if (afs_debug & AFSDEB_VNLAYER)
1503 printf("nbsd_pathconf: enter %p\n", ap);
1507 afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1511 if (afs_debug & AFSDEB_VNLAYER)
1512 printf("nbsd_pathconf: exit %p\n", ap);