/*
- * Copyright 2000, International Business Machines Corporation and others.
- * All Rights Reserved.
- *
- * This software has been released under the terms of the IBM Public
- * License. For details, see the LICENSE file in the top-level source
- * directory or online at http://www.openafs.org/dl/license10.html
+ * OpenBSD specific vnodeops + other misc interface glue
+ * Original NetBSD version for Transarc afs by John Kohl <jtk@MIT.EDU>
+ * OpenBSD version by Jim Rees <rees@umich.edu>
+ *
+ * $Id: osi_vnodeops.c,v 1.20 2006/03/09 15:27:17 rees Exp $
*/
/*
- * vnodeops structure and Digital Unix specific ops and support routines.
+copyright 2002
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
+
+/*
+Copyright 1995 Massachusetts Institute of Technology. All Rights
+Reserved.
+
+You are hereby granted a worldwide, irrevocable, paid-up, right and
+license to use, execute, display, modify, copy and distribute MIT's
+Modifications, provided that (i) you abide by the terms and conditions
+of your OpenAFS License Agreement, and (ii) you do not use the name
+of MIT in any advertising or publicity without the prior written consent
+of MIT. MIT disclaims all liability for your use of MIT's
+Modifications. MIT's Modifications are provided "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
+ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT.
+*/
+
+/*
+ * A bunch of code cribbed from NetBSD ufs_vnops.c, ffs_vnops.c, and
+ * nfs_vnops.c which carry this copyright:
+ */
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
*/
#include <afsconfig.h>
#include "afs/param.h"
-RCSID
- ("$Header$");
#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
+#include "afs/afsincludes.h" /* Afs-based standard headers */
#include "afs/afs_stats.h" /* statistics */
-#include <vm/vm.h>
-#include <vm/vnode_pager.h>
-#include <vm/vm_map.h>
-/* #include <vm/vm_ubc.h> */
+
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#include <sys/pool.h>
+#include <miscfs/genfs/genfs.h>
+
+
#include "afs/afs_cbqueue.h"
#include "afs/nfsclient.h"
#include "afs/afs_osidnlc.h"
+#define M_AFSNODE (M_TEMP-1) /* XXX */
+
+int afs_nbsd_lookup(void *);
+int afs_nbsd_create(void *);
+int afs_nbsd_mknod(void *);
+int afs_nbsd_open(void *);
+int afs_nbsd_close(void *);
+int afs_nbsd_access(void *);
+int afs_nbsd_getattr(void *);
+int afs_nbsd_setattr(void *);
+int afs_nbsd_read(void *);
+int afs_nbsd_write(void *);
+int afs_nbsd_ioctl(void *);
+int afs_nbsd_select(void *);
+int afs_nbsd_fsync(void *);
+int afs_nbsd_remove(void *);
+int afs_nbsd_link(void *);
+int afs_nbsd_rename(void *);
+int afs_nbsd_mkdir(void *);
+int afs_nbsd_rmdir(void *);
+int afs_nbsd_symlink(void *);
+int afs_nbsd_readdir(void *);
+int afs_nbsd_readlink(void *);
+int afs_nbsd_inactive(void *);
+int afs_nbsd_reclaim(void *);
+int afs_nbsd_lock(void *);
+int afs_nbsd_unlock(void *);
+int afs_nbsd_bmap(void *);
+int afs_nbsd_strategy(void *);
+int afs_nbsd_print(void *);
+int afs_nbsd_islocked(void *);
+int afs_nbsd_pathconf(void *);
+int afs_nbsd_advlock(void *);
+
+#if LATER
+int afs_nbsd_getpages(void*);
+#endif
-extern int afs_lookup(), afs_create(), afs_noop(), afs_open(), afs_close();
-extern int afs_access(), afs_getattr(), afs_setattr(), afs_badop();
-extern int afs_fsync(), afs_seek(), afs_remove(), afs_link(), afs_rename();
-extern int afs_mkdir(), afs_rmdir(), afs_symlink(), afs_readdir();
-extern int afs_readlink(), afs_lockctl();
-extern int vn_pathconf_default(), seltrue();
-
-int mp_afs_lookup(), mp_afs_create(), mp_afs_open();
-int mp_afs_access(), mp_afs_getattr(), mp_afs_setattr(), mp_afs_ubcrdwr();
-int mp_afs_ubcrdwr(), mp_afs_mmap();
-int mp_afs_fsync(), mp_afs_seek(), mp_afs_remove(), mp_afs_link();
-int mp_afs_rename(), mp_afs_mkdir(), mp_afs_rmdir(), mp_afs_symlink();
-int mp_afs_readdir(), mp_afs_readlink(), mp_afs_abortop(), mp_afs_inactive();
-int mp_afs_reclaim(), mp_afs_bmap(), mp_afs_strategy(), mp_afs_print();
-int mp_afs_page_read(), mp_afs_page_write(), mp_afs_swap(), mp_afs_bread();
-int mp_afs_brelse(), mp_afs_lockctl(), mp_afs_syncdata(), mp_afs_close();
-int mp_afs_closex();
+/*
+ * Implement:
+ * vop_getpages (VM)
+ * vop_putpages (VM)
+ *
+ * Someday:
+ * vop_mmap_desc (mmap'd IO)
+ *
+ * Skip:
+ * vop_*xtattr
+ *
+ * Unknown:
+ * vop_fcntl
+ *
+ */
+#define afs_nbsd_opnotsupp \
+ ((int (*) __P((void *)))eopnotsupp)
+#define afs_nbsd_reallocblks afs_nbsd_opnotsupp
+
+/* Global vfs data structures for AFS. */
+int (**afs_vnodeop_p) __P((void *));
+struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
+ {&vop_default_desc, vn_default_error},
+ {&vop_lookup_desc, afs_nbsd_lookup}, /* lookup */
+ {&vop_create_desc, afs_nbsd_create}, /* create */
+ {&vop_mknod_desc, afs_nbsd_mknod}, /* mknod */
+ {&vop_open_desc, afs_nbsd_open}, /* open */
+ {&vop_close_desc, afs_nbsd_close}, /* close */
+ {&vop_access_desc, afs_nbsd_access}, /* access */
+ {&vop_getattr_desc, afs_nbsd_getattr}, /* getattr */
+ {&vop_setattr_desc, afs_nbsd_setattr}, /* setattr */
+ {&vop_read_desc, afs_nbsd_read}, /* read */
+ {&vop_write_desc, afs_nbsd_write}, /* write */
+ {&vop_ioctl_desc, afs_nbsd_ioctl}, /* XXX ioctl */
+ {&vop_poll_desc, afs_nbsd_select}, /* select */
+ {&vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */
+ {&vop_fsync_desc, afs_nbsd_fsync}, /* fsync */
+ {&vop_remove_desc, afs_nbsd_remove}, /* remove */
+ {&vop_link_desc, afs_nbsd_link}, /* link */
+ {&vop_rename_desc, afs_nbsd_rename}, /* rename */
+ {&vop_mkdir_desc, afs_nbsd_mkdir}, /* mkdir */
+ {&vop_rmdir_desc, afs_nbsd_rmdir}, /* rmdir */
+ {&vop_symlink_desc, afs_nbsd_symlink}, /* symlink */
+ {&vop_readdir_desc, afs_nbsd_readdir}, /* readdir */
+ {&vop_readlink_desc, afs_nbsd_readlink}, /* readlink */
+ {&vop_abortop_desc, genfs_abortop}, /* abortop */
+ {&vop_inactive_desc, afs_nbsd_inactive}, /* inactive */
+ {&vop_reclaim_desc, afs_nbsd_reclaim}, /* reclaim */
+ {&vop_lock_desc, afs_nbsd_lock}, /* lock */
+ {&vop_unlock_desc, afs_nbsd_unlock}, /* unlock */
+ {&vop_bmap_desc, afs_nbsd_bmap}, /* bmap */
+ {&vop_strategy_desc, afs_nbsd_strategy}, /* strategy */
+ {&vop_print_desc, afs_nbsd_print}, /* print */
+ {&vop_islocked_desc, afs_nbsd_islocked}, /* islocked */
+ {&vop_pathconf_desc, afs_nbsd_pathconf}, /* pathconf */
+ {&vop_advlock_desc, afs_nbsd_advlock}, /* advlock */
#if 0
-/* AFS vnodeops */
-struct vnodeops Afs_vnodeops = {
- mp_afs_lookup,
- mp_afs_create,
- afs_noop, /* vn_mknod */
- mp_afs_open,
- mp_afs_close,
- mp_afs_access,
- mp_afs_getattr,
- mp_afs_setattr,
- mp_afs_ubcrdwr,
- mp_afs_ubcrdwr,
- afs_badop, /* vn_ioctl */
- seltrue, /* vn_select */
- mp_afs_mmap,
- mp_afs_fsync,
- mp_afs_seek,
- mp_afs_remove,
- mp_afs_link,
- mp_afs_rename,
- mp_afs_mkdir,
- mp_afs_rmdir,
- mp_afs_symlink,
- mp_afs_readdir,
- mp_afs_readlink,
- mp_afs_abortop,
- mp_afs_inactive,
- mp_afs_reclaim,
- mp_afs_bmap,
- mp_afs_strategy,
- mp_afs_print,
- mp_afs_page_read,
- mp_afs_page_write,
- mp_afs_swap,
- mp_afs_bread,
- mp_afs_brelse,
- mp_afs_lockctl,
- mp_afs_syncdata,
- afs_noop, /* Lock */
- afs_noop, /* unLock */
- afs_noop, /* get ext attrs */
- afs_noop, /* set ext attrs */
- afs_noop, /* del ext attrs */
- vn_pathconf_default,
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-#endif /* 0 */
-
-/* vnode file operations, and our own */
-extern int vn_read();
-extern int vn_write();
-extern int vn_ioctl();
-extern int vn_select();
-extern int afs_closex();
-
-struct fileops afs_fileops = {
- vn_read,
- vn_write,
- vn_ioctl,
- vn_select,
- mp_afs_closex,
+ {&vop_reallocblks_desc, afs_nbsd_reallocblks}, /* reallocblks */
+#endif
+ {&vop_bwrite_desc, vn_bwrite}, /* bwrite */
+#if LATER
+ { &vop_getpages_desc, ffs_getpages }, /* getpages */
+ { &vop_putpages_desc, genfs_putpages }, /* putpages */
+#endif
+ {(struct vnodeop_desc *)NULL, (int (*)__P((void *)))NULL}
};
-
-#if 0
-mp_afs_lookup(adp, ndp)
- struct vcache *adp;
- struct nameidata *ndp;
+struct vnodeopv_desc afs_vnodeop_opv_desc =
+ { &afs_vnodeop_p, afs_vnodeop_entries };
+
+#define GETNAME() \
+ struct componentname *cnp = ap->a_cnp; \
+ char *name; \
+ name = PNBUF_GET(); \
+ bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
+ name[cnp->cn_namelen] = '\0'
+
+#define DROPNAME() PNBUF_PUT(name)
+#define DROPCNP PNBUF_PUT
+
+/* toss "stale" pages by shrinking the vnode uobj to a 0-length
+ * region (see uvm_vnp_setsize in uvm_vnode.c) */
+#define VNP_UNCACHE(vp) \
+ do { \
+ struct uvm_object *uobj = &vp->v_uobj; \
+ simple_lock(&uobj->vmobjlock); \
+ VOP_PUTPAGES( (struct vnode *) uobj, 0 /* offlo */, 0 /* offhi */, PGO_FREE | PGO_SYNCIO); \
+ simple_unlock(&uobj->vmobjlock); \
+ } while(0);
+
+/* psuedo-vnop, wherein we learn that obsd and nbsd disagree
+ * about vnode refcounting */
+void
+afs_nbsd_getnewvnode(struct vcache *tvc)
{
- int code;
- AFS_GLOCK();
- code = afs_lookup(adp, ndp);
- AFS_GUNLOCK();
- return code;
+ while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
+ /* no vnodes available, force an alloc (limits be damned)! */
+ desiredvnodes++;
+ }
+ afs_warn("afs_nbsd_getnewvnode: vp %lx refs %d (soon to be 1)\n", tvc->v,
+ tvc->v->v_usecount);
+ simple_lock(&tvc->v->v_interlock);
+ tvc->v->v_data = (void *)tvc;
+ tvc->v->v_usecount = 1; /* !locked, and vref w/v_usecount < 1 panics */
+ simple_unlock(&tvc->v->v_interlock);
}
-mp_afs_create(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs;
-{
- int code;
- AFS_GLOCK();
- code = afs_create(ndp, attrs);
- AFS_GUNLOCK();
- return code;
-}
+int afs_debug;
-mp_afs_open(avcp, aflags, acred)
- struct vcache **avcp;
- afs_int32 aflags;
- struct AFS_UCRED *acred;
+int
+afs_nbsd_lookup(void *v)
{
+ struct vop_lookup_args /* {
+ * struct vnodeop_desc * a_desc;
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * } */ *ap = v;
int code;
+ struct vcache *vcp;
+ struct vnode *vp, *dvp;
+ int flags = ap->a_cnp->cn_flags;
+ int lockparent; /* 1 => lockparent flag is set */
+
+ afs_warn("afs_nbsd_lookup enter\n");
+
+ GETNAME();
+ lockparent = flags & LOCKPARENT;
+ if (ap->a_dvp->v_type != VDIR) {
+ *ap->a_vpp = NULL;
+ DROPNAME();
+ return ENOTDIR;
+ }
+ dvp = ap->a_dvp;
+ if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
+ printf("nbsd_lookup dvp %p flags %x name %s cnt %d\n", dvp, flags,
+ name, dvp->v_usecount);
AFS_GLOCK();
- code = afs_open(avcp, aflags, acred);
+ code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
AFS_GUNLOCK();
+ if (code) {
+ if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
+ && (flags & ISLASTCN) && code == ENOENT)
+ code = EJUSTRETURN;
+ if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
+ cnp->cn_flags |= SAVENAME;
+ DROPNAME();
+ *ap->a_vpp = NULL;
+ return (code);
+ }
+ vp = AFSTOV(vcp); /* always get a node if no error */
+
+ /*
+ * The parent directory comes in locked. We unlock it on return
+ * unless the caller wants it left locked.
+ * we also always return the vnode locked.
+ */
+
+ if (vp == dvp) {
+ /* they're the same; afs_lookup() already ref'ed the leaf.
+ * It came in locked, so we don't need to ref OR lock it */
+ if (afs_debug & AFSDEB_VNLAYER)
+ printf("ref'ed %p as .\n", dvp);
+ } else {
+ if (!lockparent || !(flags & ISLASTCN)) {
+ VOP_UNLOCK(dvp, 0); /* done with parent. */
+ }
+
+ simple_lock(&vp->v_interlock);
+ vp->v_usecount = (vp->v_usecount < 1) ? 1 : (vp->v_usecount+1);
+ simple_unlock(&vp->v_interlock);
+ if (!VOP_ISLOCKED(vp)) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ afs_warn("h2\n");
+ /* vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); *//* always return the child locked */
+ } else {
+ afs_warn("lookup: vp %lx is locked\n", vp);
+ }
+ afs_warn("lookup: after islocked\n");
+ if (afs_debug & AFSDEB_VNLAYER)
+ printf("locked ret %p from lookup\n", vp);
+ }
+ *ap->a_vpp = vp;
+
+ if (((cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
+ || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
+ cnp->cn_flags |= SAVENAME;
+
+ DROPNAME();
+ if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
+ printf("nbsd_lookup done dvp %p cnt %d\n", dvp, dvp->v_usecount);
return code;
}
-mp_afs_access(avc, amode, acred)
- struct vcache *avc;
- afs_int32 amode;
- struct AFS_UCRED *acred;
+int
+afs_nbsd_create(void *v)
{
- int code;
+ struct vop_create_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap = v;
+ int code = 0;
+ struct vcache *vcp;
+ struct vnode *dvp = ap->a_dvp;
+ GETNAME();
+
+ if (afs_debug & AFSDEB_VNLAYER)
+ printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
+
+ /* vnode layer handles excl/nonexcl */
+
AFS_GLOCK();
- code = afs_access(avc, amode, acred);
+ code =
+ afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
+ &vcp, cnp->cn_cred);
AFS_GUNLOCK();
+ if (code) {
+ VOP_ABORTOP(dvp, cnp);
+ vput(dvp);
+ DROPNAME();
+ return (code);
+ }
+
+ if (vcp) {
+ *ap->a_vpp = AFSTOV(vcp);
+ vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
+ } else
+ *ap->a_vpp = 0;
+
+ if ((cnp->cn_flags & SAVESTART) == 0)
+ DROPCNP(cnp);
+ vput(dvp);
+ DROPNAME();
+ if (afs_debug & AFSDEB_VNLAYER)
+ printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
return code;
}
-mp_afs_close(avc, flags, cred)
- struct vnode *avc;
- int flags;
- struct ucred *cred;
+int
+afs_nbsd_mknod(void *v)
{
- int code;
- AFS_GLOCK();
- code = afs_close(avc, flags, cred);
- AFS_GUNLOCK();
- return code;
+ struct vop_mknod_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap = v;
+ DROPCNP(ap->a_cnp);
+ vput(ap->a_dvp);
+ return (ENODEV);
}
-mp_afs_getattr(avc, attrs, acred)
- struct vcache *avc;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
+int
+afs_nbsd_open(void *v)
{
+ struct vop_open_args /* {
+ * struct vnode *a_vp;
+ * int a_mode;
+ * struct ucred *a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+ struct vcache *vc = VTOAFS(ap->a_vp);
+
AFS_GLOCK();
- code = afs_getattr(avc, attrs, acred);
+ code = afs_open(&vc, ap->a_mode, ap->a_cred);
+#ifdef DIAGNOSTIC
+ if (AFSTOV(vc) != ap->a_vp)
+ panic("AFS open changed vnode!");
+#endif
AFS_GUNLOCK();
return code;
}
-mp_afs_setattr(avc, attrs, acred)
- struct vcache *avc;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
+int
+afs_nbsd_close(void *v)
{
+ struct vop_close_args /* {
+ * struct vnode *a_vp;
+ * int a_fflag;
+ * kauth_cred_t a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+
AFS_GLOCK();
- code = afs_setattr(avc, attrs, acred);
+ code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred);
AFS_GUNLOCK();
return code;
}
-mp_afs_fsync(avc, fflags, acred, waitfor)
- struct vcache *avc;
- int fflags;
- struct AFS_UCRED *acred;
- int waitfor;
+int
+afs_nbsd_access(void *v)
{
+ struct vop_access_args /* {
+ * struct vnode *a_vp;
+ * int a_mode;
+ * kauth_cred_t a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+
AFS_GLOCK();
- code = afs_fsync(avc, fflags, acred, waitfor);
+ code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
AFS_GUNLOCK();
return code;
}
-mp_afs_remove(ndp)
- struct nameidata *ndp;
+int
+afs_nbsd_getattr(void *v)
{
+ struct vop_getattr_args /* {
+ * struct vnode *a_vp;
+ * struct vattr *a_vap;
+ * kauth_cred_t a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+
AFS_GLOCK();
- code = afs_remove(ndp);
+ code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
AFS_GUNLOCK();
return code;
}
-mp_afs_link(avc, ndp)
- struct vcache *avc;
- struct nameidata *ndp;
+int
+afs_nbsd_setattr(void *v)
{
+ struct vop_setattr_args /* {
+ * struct vnode *a_vp;
+ * struct vattr *a_vap;
+ * kauth_cred_t a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+
AFS_GLOCK();
- code = afs_link(avc, ndp);
+ code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
AFS_GUNLOCK();
return code;
}
-mp_afs_rename(fndp, tndp)
- struct nameidata *fndp, *tndp;
+int
+afs_nbsd_read(void *v)
{
+ struct vop_read_args /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * int a_ioflag;
+ * kauth_cred_t a_cred;
+ * } */ *ap = v;
int code;
+
AFS_GLOCK();
- code = afs_rename(fndp, tndp);
+ code =
+ afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, (daddr_t) 0, NULL,
+ 0);
AFS_GUNLOCK();
return code;
}
-mp_afs_mkdir(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs;
+int
+afs_nbsd_write(void *v)
{
+ struct vop_write_args /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * int a_ioflag;
+ * kauth_cred_t a_cred;
+ * } */ *ap = v;
int code;
+
+#if 1
+ /* all pages are really "stale?" */
+ VNP_UNCACHE(ap->a_vp);
+#else
+ (void)uvm_vnp_uncache(ap->a_vp); /* toss stale pages */
+#endif
AFS_GLOCK();
- code = afs_mkdir(ndp, attrs);
+ code =
+ afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
AFS_GUNLOCK();
return code;
}
-mp_afs_rmdir(ndp)
- struct nameidata *ndp;
+int
+afs_nbsd_ioctl(void *v)
{
+ struct vop_ioctl_args /* {
+ * struct vnode *a_vp;
+ * int a_command;
+ * caddr_t a_data;
+ * int a_fflag;
+ * kauth_cred_t a_cred;
+ * struct lwp *a_l;
+ * } */ *ap = v;
int code;
+
+ /* in case we ever get in here... */
+
+ AFS_STATCNT(afs_ioctl);
AFS_GLOCK();
- code = afs_rmdir(ndp);
+ if (((ap->a_command >> 8) & 0xff) == 'V')
+ /* This is a VICEIOCTL call */
+ code =
+ HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
+ (struct afs_ioctl *)ap->a_data);
+ else
+ /* No-op call; just return. */
+ code = ENOTTY;
AFS_GUNLOCK();
return code;
}
-mp_afs_symlink(ndp, attrs, atargetName)
- struct nameidata *ndp;
- struct vattr *attrs;
- register char *atargetName;
+int
+afs_nbsd_select(void *v)
{
- int code;
- AFS_GLOCK();
- code = afs_symlink(ndp, attrs, atargetName);
- AFS_GUNLOCK();
- return code;
+ return 1;
}
-mp_afs_readdir(avc, auio, acred, eofp)
- struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
- int *eofp;
+int
+afs_nbsd_fsync(void *v)
{
- int code;
+ struct vop_fsync_args /* {
+ * struct vnode *a_vp;
+ * kauth_cred_t a_cred;
+ * int a_waitfor;
+ * struct lwp *a_l;
+ * } */ *ap = v;
+ struct vnode *vp = ap->a_vp;
+ int code, wait;
+
+ wait = (ap->a_flags & FSYNC_WAIT) != 0;
+
AFS_GLOCK();
- code = afs_readdir(avc, auio, acred, eofp);
+ vflushbuf(vp, wait);
+ code = afs_fsync(VTOAFS(vp), ap->a_cred);
AFS_GUNLOCK();
+
return code;
}
-mp_afs_readlink(avc, auio, acred)
- struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
+int
+afs_nbsd_remove(void *v)
{
+ struct vop_remove_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode *a_vp;
+ * struct componentname *a_cnp;
+ * } */ *ap = v;
int code;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+
+ GETNAME();
AFS_GLOCK();
- code = afs_readlink(avc, auio, acred);
+ code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
AFS_GUNLOCK();
+ if (dvp == vp)
+ vrele(vp);
+ else
+ vput(vp);
+ vput(dvp);
+ DROPCNP(cnp);
+ DROPNAME();
return code;
}
-mp_afs_lockctl(avc, af, flag, acred, clid, offset)
- struct vcache *avc;
- struct eflock *af;
- struct AFS_UCRED *acred;
- int flag;
- pid_t clid;
- off_t offset;
+int
+afs_nbsd_link(void *v)
{
+ struct vop_link_args /* {
+ * struct vnode *a_vp;
+ * struct vnode *a_tdvp;
+ * struct componentname *a_cnp;
+ * } */ *ap = v;
int code;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+
+ GETNAME();
+ if (dvp->v_mount != vp->v_mount) {
+ VOP_ABORTOP(vp, cnp);
+ code = EXDEV;
+ goto out;
+ }
+ if (vp->v_type == VDIR) {
+ VOP_ABORTOP(vp, cnp);
+ code = EISDIR;
+ goto out;
+ }
+ if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))) {
+ VOP_ABORTOP(dvp, cnp);
+ goto out;
+ }
+
AFS_GLOCK();
- code = afs_lockctl(avc, af, flag, acred, clid, offset);
+ code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
AFS_GUNLOCK();
+ DROPCNP(cnp);
+ if (dvp != vp)
+ VOP_UNLOCK(vp, 0);
+
+ out:
+ vput(dvp);
+ DROPNAME();
return code;
}
-mp_afs_closex(afd)
- struct file *afd;
+int
+afs_nbsd_rename(void *v)
{
- int code;
+ struct vop_rename_args /* {
+ * struct vnode *a_fdvp;
+ * struct vnode *a_fvp;
+ * struct componentname *a_fcnp;
+ * struct vnode *a_tdvp;
+ * struct vnode *a_tvp;
+ * struct componentname *a_tcnp;
+ * } */ *ap = v;
+ int code = 0;
+ struct componentname *fcnp = ap->a_fcnp;
+ char *fname;
+ struct componentname *tcnp = ap->a_tcnp;
+ char *tname;
+ struct vnode *tvp = ap->a_tvp;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *fvp = ap->a_fvp;
+ struct vnode *fdvp = ap->a_fdvp;
+
+ /*
+ * Check for cross-device rename.
+ */
+ if ((fvp->v_mount != tdvp->v_mount)
+ || (tvp && (fvp->v_mount != tvp->v_mount))) {
+ code = EXDEV;
+ abortit:
+ VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
+ if (tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ if (tvp)
+ vput(tvp);
+ VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
+ vrele(fdvp);
+ vrele(fvp);
+ return (code);
+ }
+ /*
+ * if fvp == tvp, we're just removing one name of a pair of
+ * directory entries for the same element. convert call into rename.
+ ( (pinched from NetBSD 1.0's ufs_rename())
+ */
+ if (fvp == tvp) {
+ if (fvp->v_type == VDIR) {
+ code = EINVAL;
+ goto abortit;
+ }
+
+ /* Release destination completely. */
+ VOP_ABORTOP(tdvp, tcnp);
+ vput(tdvp);
+ vput(tvp);
+
+ /* Delete source. */
+ vrele(fdvp);
+ vrele(fvp);
+ fcnp->cn_flags &= ~MODMASK;
+ fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
+ if ((fcnp->cn_flags & SAVESTART) == 0)
+ panic("afs_rename: lost from startdir");
+ fcnp->cn_nameiop = DELETE;
+ (void)relookup(fdvp, &fvp, fcnp);
+ return (VOP_REMOVE(fdvp, fvp, fcnp));
+ }
+
+ if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)))
+ goto abortit;
+
+ /* XXX GETNAME() ? */
+ MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
+ bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
+ fname[fcnp->cn_namelen] = '\0';
+ MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
+ bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
+ tname[tcnp->cn_namelen] = '\0';
+
+
AFS_GLOCK();
- code = afs_closex(afd);
+ /* XXX use "from" or "to" creds? NFS uses "to" creds */
+ code =
+ afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname,
+ tcnp->cn_cred);
AFS_GUNLOCK();
- return code;
-}
-mp_afs_seek(avc, oldoff, newoff, cred)
- struct vcache *avc;
- off_t oldoff, newoff;
- struct ucred *cred;
-{
- if ((int)newoff < 0)
- return (EINVAL);
+ VOP_UNLOCK(fvp, 0);
+ FREE(fname, M_TEMP);
+ FREE(tname, M_TEMP);
+ if (code)
+ goto abortit; /* XXX */
+ if (tdvp == tvp)
+ vrele(tdvp);
else
- return (0);
+ vput(tdvp);
+ if (tvp)
+ vput(tvp);
+ vrele(fdvp);
+ vrele(fvp);
+ return code;
}
-mp_afs_abortop(ndp)
- struct nameidata *ndp;
+int
+afs_nbsd_mkdir(void *v)
{
- return (0);
-}
+ struct vop_mkdir_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ int code;
+ struct vcache *vcp;
-mp_afs_inactive(avc, acred)
- register struct vcache *avc;
- struct AFS_UCRED *acred;
-{
+ GETNAME();
+#ifdef DIAGNOSTIC
+ if ((cnp->cn_flags & HASBUF) == 0)
+ panic("afs_nbsd_mkdir: no name");
+#endif
AFS_GLOCK();
- afs_InactiveVCache(avc, acred);
+ code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
AFS_GUNLOCK();
+ if (code) {
+ VOP_ABORTOP(dvp, cnp);
+ vput(dvp);
+ DROPNAME();
+ return (code);
+ }
+ if (vcp) {
+ *ap->a_vpp = AFSTOV(vcp);
+ vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY);
+ } else
+ *ap->a_vpp = 0;
+ DROPCNP(cnp);
+ DROPNAME();
+ vput(dvp);
+ return code;
}
-
-mp_afs_reclaim(avc)
- struct vcache *avc;
-{
- return (0);
-}
-
-mp_afs_print(avc)
- struct vcache *avc;
-{
- return (0);
-}
-
-mp_afs_page_read(avc, uio, acred)
- struct vcache *avc;
- struct uio *uio;
- struct ucred *acred;
+int
+afs_nbsd_rmdir(void *v)
{
- int error;
- struct vrequest treq;
+ struct vop_rmdir_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode *a_vp;
+ * struct componentname *a_cnp;
+ * } */ *ap = v;
+ int code;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+
+ GETNAME();
+ if (dvp == vp) {
+ vrele(dvp);
+ vput(vp);
+ DROPCNP(cnp);
+ DROPNAME();
+ return (EINVAL);
+ }
AFS_GLOCK();
- error = afs_rdwr(avc, uio, UIO_READ, 0, acred);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_READ, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, error, ICL_TYPE_INT32, avc->f.states);
- if (error) {
- error = EIO;
- } else if ((avc->f.states) == 0) {
- afs_InitReq(&treq, acred);
- ObtainWriteLock(&avc->lock, 161);
- afs_Wire(avc, &treq);
- ReleaseWriteLock(&avc->lock);
- }
+ code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
AFS_GUNLOCK();
- return (error);
+ DROPNAME();
+ vput(dvp);
+ vput(vp);
+ return code;
}
-
-mp_afs_page_write(avc, uio, acred, pager, offset)
- struct vcache *avc;
- struct uio *uio;
- struct ucred *acred;
- memory_object_t pager;
- vm_offset_t offset;
+int
+afs_nbsd_symlink(void *v)
{
- int error;
+ struct vop_symlink_args /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * char *a_target;
+ * } */ *ap = v;
+ struct vnode *dvp = ap->a_dvp;
+ int code;
+ /* NFS ignores a_vpp; so do we. */
+ GETNAME();
AFS_GLOCK();
- error = afs_rdwr(avc, uio, UIO_WRITE, 0, acred);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_WRITE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, error, ICL_TYPE_INT32, avc->f.states);
- if (error) {
- error = EIO;
- }
+ code =
+ afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
+ cnp->cn_cred);
AFS_GUNLOCK();
- return (error);
+ DROPCNP(cnp);
+ DROPNAME();
+ vput(dvp);
+ return code;
}
-
-int DO_FLUSH = 1;
-mp_afs_ubcrdwr(avc, uio, ioflag, cred)
- struct vcache *avc;
- struct uio *uio;
- int ioflag;
- struct ucred *cred;
+int
+afs_nbsd_readdir(void *v)
{
- register afs_int32 code;
- register char *data;
- afs_int32 fileBase, size, cnt = 0;
- afs_int32 pageBase;
- register afs_int32 tsize;
- register afs_int32 pageOffset;
- int eof;
- struct vrequest treq;
- int rw = uio->uio_rw;
- int rv, flags;
- int newpage = 0;
- vm_page_t page;
- afs_int32 save_resid;
- struct dcache *tdc;
- int didFakeOpen = 0;
- int counter = 0;
+ struct vop_readdir_args /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * kauth_cred_t a_cred;
+ * int *a_eofflag;
+ * int *a_ncookies;
+ * u_long **a_cookies;
+ * } */ *ap = v;
+ int code;
AFS_GLOCK();
- afs_InitReq(&treq, cred);
- if (AFS_NFSXLATORREQ(cred) && rw == UIO_READ) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- AFS_GUNLOCK();
- return EACCES;
- }
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, (rw == UIO_WRITE ? 1 : 0), ICL_TYPE_LONG,
- uio->uio_offset, ICL_TYPE_LONG, uio->uio_resid);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 35);
- AFS_GUNLOCK();
- return code;
- }
- if (vType(avc) != VREG) {
- AFS_GUNLOCK();
- return EISDIR; /* can't read or write other things */
- }
- osi_FlushPages(avc); /* hold bozon lock, but not basic vnode lock */
- ObtainWriteLock(&avc->lock, 162);
- /* adjust parameters when appending files */
- if ((ioflag & IO_APPEND) && uio->uio_rw == UIO_WRITE)
- uio->uio_offset = avc->f.m.Length; /* write at EOF position */
- if (uio->uio_rw == UIO_WRITE) {
- avc->f.states |= CDirty;
- afs_FakeOpen(avc);
- didFakeOpen = 1;
- /*
- * before starting any I/O, we must ensure that the file is big enough
- * to hold the results (since afs_putpage will be called to force
- * the I/O.
- */
- size = uio->afsio_resid + uio->afsio_offset; /* new file size */
- if (size > avc->f.m.Length)
- avc->f.m.Length = size; /* file grew */
- avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
- if (uio->afsio_resid > PAGE_SIZE)
- cnt = uio->afsio_resid / PAGE_SIZE;
- save_resid = uio->afsio_resid;
- }
-
- while (1) {
- /*
- * compute the amount of data to move into this block,
- * based on uio->afsio_resid.
- */
- size = uio->afsio_resid; /* transfer size */
- fileBase = uio->afsio_offset; /* start file position */
- pageBase = fileBase & ~(PAGE_SIZE - 1); /* file position of the page */
- pageOffset = fileBase & (PAGE_SIZE - 1); /* start offset within page */
- tsize = PAGE_SIZE - pageOffset; /* amount left in this page */
- /*
- * we'll read tsize bytes,
- * but first must make sure tsize isn't too big
- */
- if (tsize > size)
- tsize = size; /* don't read past end of request */
- eof = 0; /* flag telling us if we hit the EOF on the read */
- if (uio->uio_rw == UIO_READ) { /* we're doing a read operation */
- /* don't read past EOF */
- if (tsize + fileBase > avc->f.m.Length) {
- tsize = avc->f.m.Length - fileBase;
- eof = 1; /* we did hit the EOF */
- if (tsize < 0)
- tsize = 0; /* better safe than sorry */
- }
- }
- if (tsize <= 0)
- break; /* nothing to transfer, we're done */
-
- /* Purge dirty chunks of file if there are too many dirty chunks.
- * Inside the write loop, we only do this at a chunk boundary.
- * Clean up partial chunk if necessary at end of loop.
- */
- if (uio->uio_rw == UIO_WRITE && counter > 0
- && AFS_CHUNKOFFSET(fileBase) == 0) {
- code = afs_DoPartialWrite(avc, &treq);
- avc->f.states |= CDirty;
- }
-
- if (code) {
- break;
- }
-
- flags = 0;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- code =
- ubc_lookup(((struct vnode *)avc)->v_object, pageBase, PAGE_SIZE,
- PAGE_SIZE, &page, &flags);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 163);
-
- if (code) {
- break;
- }
- if (flags & B_NOCACHE) {
- /*
- * No page found. We should not read the page in if
- * 1. the write starts on a page edge (ie, pageoffset == 0)
- * and either
- * 1. we will fill the page (ie, size == PAGESIZE), or
- * 2. we are writing past eof
- */
- if ((uio->uio_rw == UIO_WRITE)
- &&
- ((pageOffset == 0
- && (size == PAGE_SIZE || fileBase >= avc->f.m.Length)))) {
- struct vnode *vp = (struct vnode *)avc;
- /* we're doing a write operation past eof; no need to read it */
- newpage = 1;
- AFS_GUNLOCK();
- ubc_page_zero(page, 0, PAGE_SIZE);
- ubc_page_release(page, B_DONE);
- AFS_GLOCK();
- } else {
- /* page wasn't cached, read it in. */
- struct buf *bp;
-
- AFS_GUNLOCK();
- bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_READ);
- AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(pageBase);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 164);
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- AFS_GUNLOCK();
- ubc_page_release(page, 0);
- AFS_GLOCK();
- break;
- }
- }
- }
- AFS_GUNLOCK();
- ubc_page_wait(page);
- data = (char *)page->pg_addr; /* DUX 4.0D */
- if (data == 0)
- data = (char *)PHYS_TO_KSEG(page->pg_phys_addr); /* DUX 4.0E */
- AFS_GLOCK();
- ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
- AFS_GUNLOCK();
- code = uiomove(data + pageOffset, tsize, uio);
- ubc_unload(page, pageOffset, page_size);
- if (uio->uio_rw == UIO_WRITE) {
- vm_offset_t toffset;
-
- /* Mark the page dirty and release it to avoid a deadlock
- * in ubc_dirty_kluster when more than one process writes
- * this page at the same time. */
- toffset = page->pg_offset;
- flags |= B_DIRTY;
- ubc_page_release(page, flags);
-
- if (cnt > 10) {
- vm_page_t pl;
- int kpcnt;
- struct buf *bp;
-
- /* We released the page, so we can get a null page
- * list if another thread calls the strategy routine.
- */
- pl = ubc_dirty_kluster(((struct vnode *)avc)->v_object, NULL,
- toffset, 0, B_WANTED, FALSE, &kpcnt);
- if (pl) {
- bp = ubc_bufalloc(pl, 1, PAGE_SIZE, 1, B_WRITE);
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(pageBase);
- AFS_GLOCK();
- code = afs_ustrategy(bp, cred); /* do the I/O */
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- if (code) {
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 415);
- break;
- }
- }
- }
- } else {
- ubc_page_release(page, flags);
- }
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 165);
- /*
- * If reading at a chunk boundary, start prefetch of next chunk.
- */
- if (uio->uio_rw == UIO_READ
- && (counter == 0 || AFS_CHUNKOFFSET(fileBase) == 0)) {
- tdc = afs_FindDCache(avc, fileBase);
- if (tdc) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, cred, &treq);
- afs_PutDCache(tdc);
- }
- }
- counter++;
- if (code)
- break;
- }
- if (didFakeOpen)
- afs_FakeClose(avc, cred);
- if (uio->uio_rw == UIO_WRITE && code == 0 && (avc->f.states & CDirty)) {
- code = afs_DoPartialWrite(avc, &treq);
- }
- ReleaseWriteLock(&avc->lock);
- if (DO_FLUSH || (!newpage && (cnt < 10))) {
- AFS_GUNLOCK();
- ubc_flush_dirty(((struct vnode *)avc)->v_object, flags);
- AFS_GLOCK();
- }
-
- ObtainSharedLock(&avc->lock, 409);
- if (!code) {
- if (avc->vc_error) {
- code = avc->vc_error;
- }
- }
- /* This is required since we may still have dirty pages after the write.
- * I could just let close do the right thing, but stat's before the close
- * return the wrong length.
- */
- if (code == EDQUOT || code == ENOSPC) {
- uio->uio_resid = save_resid;
- UpgradeSToWLock(&avc->lock, 410);
- osi_ReleaseVM(avc, cred);
- ConvertWToSLock(&avc->lock);
- }
- ReleaseSharedLock(&avc->lock);
-
- if (!code && (ioflag & IO_SYNC) && (uio->uio_rw == UIO_WRITE)
- && !AFS_NFSXLATORREQ(cred)) {
- code = afs_fsync(avc, 0, cred, 0);
- }
- out:
- code = afs_CheckCode(code, &treq, 36);
+#ifdef AFS_HAVE_COOKIES
+ printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
+ ap->a_ncookies);
+ code =
+ afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag,
+ ap->a_ncookies, ap->a_cookies);
+#else
+ code =
+ afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
+#endif
AFS_GUNLOCK();
return code;
}
-
-/*
- * Now for some bad news. Since we artificially hold on to vnodes by doing
- * and extra VNHOLD in afs_NewVCache(), there is no way for us to know
- * when we need to flush the pages when a program exits. Particularly
- * if it closes the file after mapping it R/W.
- *
- */
-
-mp_afs_mmap(avc, offset, map, addrp, len, prot, maxprot, flags, cred)
- register struct vcache *avc;
- vm_offset_t offset;
- vm_map_t map;
- vm_offset_t *addrp;
- vm_size_t len;
- vm_prot_t prot;
- vm_prot_t maxprot;
- int flags;
- struct ucred *cred;
+int
+afs_nbsd_readlink(void *v)
{
- struct vp_mmap_args args;
- register struct vp_mmap_args *ap = &args;
- struct vnode *vp = (struct vnode *)avc;
+ struct vop_readlink_args /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * kauth_cred_t a_cred;
+ * } */ *ap = v;
int code;
- struct vrequest treq;
-#if !defined(DYNEL)
- extern kern_return_t u_vp_create();
-#endif
AFS_GLOCK();
- afs_InitReq(&treq, cred);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 37);
- AFS_GUNLOCK();
- return code;
- }
- osi_FlushPages(avc); /* ensure old pages are gone */
- ObtainWriteLock(&avc->lock, 166);
- avc->f.states |= CMAPPED;
- ReleaseWriteLock(&avc->lock);
- ap->a_offset = offset;
- ap->a_vaddr = addrp;
- ap->a_size = len;
- ap->a_prot = prot, ap->a_maxprot = maxprot;
- ap->a_flags = flags;
- AFS_GUNLOCK();
- code = u_vp_create(map, vp->v_object, (vm_offset_t) ap);
- AFS_GLOCK();
- code = afs_CheckCode(code, &treq, 38);
+ code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
AFS_GUNLOCK();
return code;
}
+extern int prtactive;
int
-mp_afs_getpage(vop, offset, len, protp, pl, plsz, mape, addr, rw, cred)
- vm_ubc_object_t vop;
- vm_offset_t offset;
- vm_size_t len;
- vm_prot_t *protp;
- vm_page_t *pl;
- int plsz;
- vm_map_entry_t mape;
- vm_offset_t addr;
- int rw;
- struct ucred *cred;
+afs_nbsd_inactive(void *v)
{
- register afs_int32 code;
- struct vrequest treq;
- int flags = 0;
- int i, pages = (len + PAGE_SIZE - 1) >> page_shift;
- vm_page_t *pagep;
- vm_offset_t off;
+ struct vop_inactive_args /* {
+ * struct vnode *a_vp;
+ * } */ *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vcache *vc = VTOAFS(vp);
+ int haveGlock = ISAFS_GLOCK();
- struct vcache *avc = VTOAFS(vop->vu_vp);
+ AFS_STATCNT(afs_inactive);
- /* first, obtain the proper lock for the VM system */
+ if (prtactive && vp->v_usecount != 0)
+ vprint("afs_nbsd_inactive(): pushing active", vp);
- AFS_GLOCK();
- afs_InitReq(&treq, cred);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- *pl = VM_PAGE_NULL;
- code = afs_CheckCode(code, &treq, 39); /* failed to get it */
+ if (!haveGlock)
+ AFS_GLOCK();
+ afs_InactiveVCache(vc, 0); /* decrs ref counts */
+ if (!haveGlock)
AFS_GUNLOCK();
- return code;
- }
- /* clean all dirty pages for this vnode */
- AFS_GUNLOCK();
- ubc_flush_dirty(vop, 0);
- AFS_GLOCK();
-
- ObtainWriteLock(&avc->lock, 167);
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, avc,
- ICL_TYPE_LONG, offset, ICL_TYPE_LONG, len, ICL_TYPE_INT32,
- (int)rw);
- for (i = 0; i < pages; i++) {
- pagep = &pl[i];
- off = offset + PAGE_SIZE * i;
- if (protp)
- protp[i] = 0;
- flags = 0;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- code =
- ubc_lookup(((struct vnode *)avc)->v_object, off, PAGE_SIZE,
- PAGE_SIZE, pagep, &flags);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 168);
- if (code) {
- goto out;
- }
- if (flags & B_NOCACHE) { /* if (page) */
- if ((rw & B_WRITE) && (offset + len >= avc->f.m.Length)) {
- struct vnode *vp = (struct vnode *)avc;
- /* we're doing a write operation past eof; no need to read it */
- AFS_GUNLOCK();
- ubc_page_zero(*pagep, 0, PAGE_SIZE);
- ubc_page_release(*pagep, B_DONE);
- AFS_GLOCK();
- } else {
- /* page wasn't cached, read it in. */
- struct buf *bp;
-
- AFS_GUNLOCK();
- bp = ubc_bufalloc(*pagep, 1, PAGE_SIZE, 1, B_READ);
- AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(off);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 169);
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- AFS_GUNLOCK();
- ubc_page_release(pl[i], 0);
- AFS_GLOCK();
- goto out;
- }
- }
- }
- if ((rw & B_READ) == 0) {
- AFS_GUNLOCK();
- ubc_page_dirty(pl[i]);
- AFS_GLOCK();
- } else {
- if (protp && (flags & B_DIRTY) == 0) {
- protp[i] = VM_PROT_WRITE;
- }
- }
- }
- out:
- pl[i] = VM_PAGE_NULL;
- ReleaseWriteLock(&avc->lock);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_INT32, code,
- ICL_TYPE_POINTER, *pagep, ICL_TYPE_INT32, flags);
- code = afs_CheckCode(code, &treq, 40);
- AFS_GUNLOCK();
- return code;
+ lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
+ return 0;
}
-
int
-mp_afs_putpage(vop, pl, pcnt, flags, cred)
- vm_ubc_object_t vop;
- vm_page_t *pl;
- int pcnt;
- int flags;
- struct ucred *cred;
+afs_nbsd_reclaim(void *v)
{
- register afs_int32 code = 0;
- struct vcache *avc = VTOAFS(vop->vu_vp);
- struct vnode *vp = (struct vnode *)avc;
- int i;
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, pcnt, ICL_TYPE_INT32, vp->v_flag,
- ICL_TYPE_INT32, flags);
- if (flags & B_UBC) {
- AFS_GUNLOCK();
- VN_LOCK(vp);
- if (vp->v_flag & VXLOCK) {
- VN_UNLOCK(vp);
- for (i = 0; i < pcnt; i++) {
- ubc_page_release(pl[i], B_DONE | B_DIRTY);
- pl[i] = VM_PAGE_NULL;
- }
- return (0);
- } else {
- VN_UNLOCK(vp);
- }
- AFS_GLOCK();
- }
-
- /* first, obtain the proper lock for the VM system */
- ObtainWriteLock(&avc->lock, 170);
- for (i = 0; i < pcnt; i++) {
- vm_page_t page = pl[i];
- struct buf *bp;
+ struct vop_reclaim_args /* {
+ * struct vnode *a_vp;
+ * } */ *ap = v;
+ int code, slept;
+ struct vnode *vp = ap->a_vp;
+ struct vcache *avc = VTOAFS(vp);
+ int haveGlock = ISAFS_GLOCK();
+ int haveVlock = CheckLock(&afs_xvcache);
- /* write it out */
- AFS_GUNLOCK();
- bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_WRITE);
+#if 0
+ printf("reclaim usecount %d\n", vp->v_usecount);
+ /* OK, there are no internal vrefCounts, so there shouldn't
+ * be any more refs here. */
+ vp->v_data = NULL; /* remove from vnode */
+ avc->v = NULL; /* also drop the ptr to vnode */
+ return 0;
+#else
+ if (!haveGlock)
AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(page->pg_offset);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 171);
+ if (!haveVlock)
+ ObtainWriteLock(&afs_xvcache, 901);
+ /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
+ code = afs_FlushVCache(avc, &slept);
+ if (!haveVlock)
+ ReleaseWriteLock(&afs_xvcache);
+ if (!haveGlock)
AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- goto done;
- } else {
- pl[i] = VM_PAGE_NULL;
- }
- }
- done:
- ReleaseWriteLock(&avc->lock);
- afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_INT32, code,
- ICL_TYPE_INT32, avc->f.m.Length);
- AFS_GUNLOCK();
return code;
+#endif
}
-
int
-mp_afs_swap(avc, swapop, argp)
- struct vcache *avc;
- vp_swap_op_t swapop;
- vm_offset_t argp;
+afs_nbsd_lock(void *v)
{
- return EIO;
+ struct vop_lock_args /* {
+ * struct vnode *a_vp;
+ * int a_flags;
+ * struct lwp *a_l;
+ * } */ *ap = v;
+
+ return (genfs_lock(v));
}
int
-mp_afs_syncdata(avc, flag, offset, length, cred)
- struct vcache *avc;
- int flag;
- vm_offset_t offset;
- vm_size_t length;
- struct ucred *cred;
+afs_nbsd_unlock(void *v)
{
- /* NFS V3 makes this call, ignore it. We'll sync the data in afs_fsync. */
- if (AFS_NFSXLATORREQ(cred))
- return 0;
- else
- return EINVAL;
-}
+ struct vop_unlock_args /* {
+ * struct vnode *a_vp;
+ * int a_flags;
+ * struct lwp *a_l;
+ * } */ *ap = v;
-/* a freelist of one */
-struct buf *afs_bread_freebp = 0;
+ return (genfs_unlock(v));
+}
-/*
- * Only rfs_read calls this, and it only looks at bp->b_un.b_addr.
- * Thus we can use fake bufs (ie not from the real buffer pool).
- */
-mp_afs_bread(vp, lbn, bpp, cred)
- struct ucred *cred;
- struct vnode *vp;
- daddr_t lbn;
- struct buf **bpp;
+int
+afs_nbsd_bmap(void *v)
{
- int offset, fsbsize, error;
- struct buf *bp;
- struct iovec iov;
- struct uio uio;
+ struct vop_bmap_args /* {
+ * struct vnode *a_vp;
+ * daddr_t a_bn;
+ * struct vnode **a_vpp;
+ * daddr_t *a_bnp;
+ * int *a_runp;
+ * } */ *ap = v;
+ struct vcache *vcp = VTOAFS(ap->a_vp);
- AFS_GLOCK();
- AFS_STATCNT(afs_bread);
- fsbsize = vp->v_vfsp->vfs_bsize;
- offset = lbn * fsbsize;
- if (afs_bread_freebp) {
- bp = afs_bread_freebp;
- afs_bread_freebp = 0;
- } else {
- bp = (struct buf *)AFS_KALLOC(sizeof(*bp));
- bp->b_un.b_addr = (caddr_t) AFS_KALLOC(fsbsize);
- }
+ AFS_STATCNT(afs_bmap);
- iov.iov_base = bp->b_un.b_addr;
- iov.iov_len = fsbsize;
- uio.afsio_iov = &iov;
- uio.afsio_iovcnt = 1;
- uio.afsio_seg = AFS_UIOSYS;
- uio.afsio_offset = offset;
- uio.afsio_resid = fsbsize;
- *bpp = 0;
- error = afs_read(VTOAFS(vp), &uio, cred, lbn, bpp, 0);
- if (error) {
- afs_bread_freebp = bp;
- AFS_GUNLOCK();
- return error;
+ /* borrowed from DARWIN--why notyet? */
+ if (ap->a_bnp) {
+ *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
}
- if (*bpp) {
- afs_bread_freebp = bp;
- } else {
- *(struct buf **)&bp->b_vp = bp; /* mark as fake */
- *bpp = bp;
+ if (ap->a_vpp) {
+ *ap->a_vpp = ap->a_vp;
}
- AFS_GUNLOCK();
- return 0;
-}
-
+ if (ap->a_runp != NULL)
+ *ap->a_runp = 0;
+#ifdef notyet
+ if (ap->a_runb != NULL)
+ *ap->a_runb = 0;
+#endif
-mp_afs_brelse(vp, bp)
- struct vnode *vp;
- struct buf *bp;
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_brelse);
- if ((struct buf *)bp->b_vp != bp) { /* not fake */
- brelse(bp);
- } else if (afs_bread_freebp) {
- AFS_KFREE(bp->b_un.b_addr, vp->v_vfsp->vfs_bsize);
- AFS_KFREE(bp, sizeof(*bp));
- } else {
- afs_bread_freebp = bp;
- }
- AFS_GUNLOCK();
+ return 0;
}
-
-mp_afs_bmap(avc, abn, anvp, anbn)
- register struct vcache *avc;
- afs_int32 abn, *anbn;
- struct vcache **anvp;
+int
+afs_nbsd_strategy(void *v)
{
- AFS_GLOCK();
- AFS_STATCNT(afs_bmap);
- if (anvp)
- *anvp = avc;
- if (anbn)
- *anbn = abn * (8192 / DEV_BSIZE); /* in 512 byte units */
- AFS_GUNLOCK();
- return 0;
-}
+ struct vop_strategy_args /* {
+ * struct buf *a_bp;
+ * } */ *ap = v;
+ struct buf *abp = ap->a_bp;
+ struct uio tuio;
+ struct iovec tiovec[1];
+ struct vcache *tvc = VTOAFS(abp->b_vp);
+ afs_ucred_t credp = osi_curcred();
+ long len = abp->b_bcount;
+ int code;
+ AFS_STATCNT(afs_strategy);
-/* real strategy */
-mp_afs_strategy(abp)
- register struct buf *abp;
-{
- register afs_int32 code;
+ tuio.afsio_iov = tiovec;
+ tuio.afsio_iovcnt = 1;
+ tuio.afsio_resid = len;
+ tiovec[0].iov_base = abp->b_un.b_addr;
+ tiovec[0].iov_len = len;
+ UIO_SETUP_SYSSPACE(&tuio);
AFS_GLOCK();
- AFS_STATCNT(afs_strategy);
- code = afs_osi_MapStrategy(afs_ustrategy, abp);
+ if ((abp->b_flags & B_READ) == B_READ) {
+ code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
+ if (code == 0 && tuio.afsio_resid > 0)
+ bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
+ tuio.afsio_resid);
+ } else
+ code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
AFS_GUNLOCK();
+
+ ReleaseWriteLock(&tvc->lock);
+ AFS_RELE(AFSTOV(tvc));
return code;
}
-
-mp_afs_refer(vm_ubc_object_t vop)
+int
+afs_nbsd_print(void *v)
{
- VREF(vop->vu_vp);
+ struct vop_print_args /* {
+ * struct vnode *a_vp;
+ * } */ *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct vcache *vc = VTOAFS(ap->a_vp);
+
+ printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell,
+ (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode,
+ (int)vc->f.fid.Fid.Unique);
+ lockmgr_printinfo(&vc->rwlock);
+ printf("\n");
+ return 0;
}
-
-mp_afs_release(vm_ubc_object_t vop)
+int
+afs_nbsd_islocked(void *v)
{
- vrele(vop->vu_vp);
+ struct vop_islocked_args /* {
+ * struct vnode *a_vp;
+ * } */ *ap = v;
+ return (genfs_islocked(v));
}
-
-mp_afs_write_check(vm_ubc_object_t vop, vm_page_t pp)
+/*
+ * Return POSIX pathconf information applicable to ufs filesystems.
+ */
+int
+afs_nbsd_pathconf(void *v)
{
- return TRUE;
+ struct vop_pathconf_args /* {
+ * struct vnode *a_vp;
+ * int a_name;
+ * int *a_retval;
+ * } */ *ap = v;
+ AFS_STATCNT(afs_cntl);
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = LINK_MAX;
+ break;
+ case _PC_NAME_MAX:
+ *ap->a_retval = NAME_MAX;
+ break;
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ break;
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ break;
+ case _PC_PIPE_BUF:
+ return EINVAL;
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
}
-
-
-struct vfs_ubcops afs_ubcops = {
- mp_afs_refer, /* refer vnode */
- mp_afs_release, /* release vnode */
- mp_afs_getpage, /* get page */
- mp_afs_putpage, /* put page */
- mp_afs_write_check, /* check writablity */
-};
-#endif /* 0 */
+extern int
+ afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
+ afs_ucred_t *acred, pid_t clid);
/*
- * Cover function for lookup name using OSF equivalent, namei()
- *
- * Note, the result vnode (ni_vp) in the namei data structure is remains
- * locked after return.
+ * Advisory record locking support (fcntl() POSIX style)
*/
-lookupname(namep, seg, follow, dvpp, cvpp)
- char *namep; /* path name */
- int seg; /* address space containing name */
- int follow; /* follow symbolic links */
- struct vnode **dvpp; /* result, containing parent vnode */
- struct vnode **cvpp; /* result, containing final component vnode */
+int
+afs_nbsd_advlock(void *v)
{
- /* Should I use free-bee in u-area? */
- struct nameidata *ndp = &u.u_nd;
- int error;
-
- ndp->ni_nameiop = ((follow) ? (LOOKUP | FOLLOW) : (LOOKUP));
- ndp->ni_segflg = seg;
- ndp->ni_dirp = namep;
- error = namei(ndp);
- if (dvpp != NULL)
- *dvpp = ndp->ni_dvp;
- if (cvpp != NULL)
- *cvpp = ndp->ni_vp;
- return (error);
+ struct vop_advlock_args /* {
+ * struct vnode *a_vp;
+ * caddr_t a_id;
+ * int a_op;
+ * struct flock *a_fl;
+ * int a_flags;
+ * } */ *ap = v;
+ int code;
+
+ AFS_GLOCK();
+ code =
+ afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
+ (int)ap->a_id);
+ AFS_GUNLOCK();
+ return code;
}