openbsd-20021028
authorJim Rees <rees@umich.edu>
Mon, 28 Oct 2002 21:28:25 +0000 (21:28 +0000)
committerJim Rees <rees@umich.edu>
Mon, 28 Oct 2002 21:28:25 +0000 (21:28 +0000)
Add OBSD subdirs to afs and rx
some other minor tweaks

14 files changed:
src/afs/OBSD/osi_file.c [new file with mode: 0644]
src/afs/OBSD/osi_groups.c [new file with mode: 0644]
src/afs/OBSD/osi_machdep.h [new file with mode: 0644]
src/afs/OBSD/osi_misc.c [new file with mode: 0644]
src/afs/OBSD/osi_sleep.c [new file with mode: 0644]
src/afs/OBSD/osi_vfsops.c [new file with mode: 0644]
src/afs/OBSD/osi_vm.c [new file with mode: 0644]
src/afs/OBSD/osi_vnodeops.c [new file with mode: 0644]
src/afs/afs_pioctl.c
src/libafs/MakefileProto.OBSD.in
src/rx/OBSD/rx_kmutex.c [new file with mode: 0644]
src/rx/OBSD/rx_kmutex.h [new file with mode: 0644]
src/rx/OBSD/rx_knet.c [new file with mode: 0644]
src/rx/rx_packet.c

diff --git a/src/afs/OBSD/osi_file.c b/src/afs/OBSD/osi_file.c
new file mode 100644 (file)
index 0000000..58ba584
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * 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
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afs/afsincludes.h"   /* Afs-based standard headers */
+#include "afs/afs_stats.h"  /* afs statistics */
+
+
+int afs_osicred_initialized=0;
+struct  AFS_UCRED afs_osi_cred;
+afs_lock_t afs_xosi;           /* lock is for tvattr */
+extern struct osi_dev cacheDev;
+extern struct mount *afs_cacheVfsp;
+
+
+void *osi_UFSOpen(afs_int32 ainode)
+{
+    struct osi_file *afile = NULL;
+    struct vnode *vp;
+    extern int cacheDiskType;
+    afs_int32 code = 0;
+
+    AFS_STATCNT(osi_UFSOpen);
+    if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
+       osi_Panic("UFSOpen called for non-UFS cache\n");
+    if (!afs_osicred_initialized) {
+       /* valid for alpha_osf, SunOS, Ultrix */
+       memset(&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
+       crhold(&afs_osi_cred);
+       afs_osicred_initialized = 1;
+    }
+    afile = (struct osi_file *) osi_AllocSmallSpace(sizeof(struct osi_file));
+    code = VFS_VGET(cacheDev.mp, (ino_t) ainode, &vp);
+    if (code) {
+       osi_FreeSmallSpace(afile);
+       osi_Panic("UFSOpen: igetinode failed");
+    }
+    afile->vnode = vp;
+    afile->size = 0;
+    afile->offset = 0;
+    afile->proc = (int (*)()) NULL;
+    afile->inum = ainode;      /* for hint validity checking */
+    VOP_UNLOCK(vp, 0, curproc);
+    return (void *)afile;
+}
+
+int afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
+{
+    afs_int32 code;
+    struct vattr tvattr;
+
+    AFS_STATCNT(osi_Stat);
+    MObtainWriteLock(&afs_xosi, 320);
+    AFS_GUNLOCK();
+    code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, curproc);
+    AFS_GLOCK();
+    if (code == 0) {
+       astat->size = tvattr.va_size;
+       astat->blksize = tvattr.va_blocksize;
+       astat->mtime = tvattr.va_mtime.tv_sec;
+       astat->atime = tvattr.va_atime.tv_sec;
+    }
+    MReleaseWriteLock(&afs_xosi);
+    return code;
+}
+
+int osi_UFSClose(struct osi_file *afile)
+{
+    AFS_STATCNT(osi_Close);
+
+    if (afile->vnode)
+       AFS_RELE(afile->vnode);
+
+    osi_FreeSmallSpace(afile);
+    return 0;
+}
+
+int osi_UFSTruncate(struct osi_file *afile, afs_int32 asize)
+{
+    struct vattr tvattr;
+    afs_int32 code;
+    struct osi_stat tstat;
+
+    AFS_STATCNT(osi_Truncate);
+
+    /* This routine only shrinks files, and most systems
+     * have very slow truncates, even when the file is already
+     * small enough.  Check now and save some time.
+     */
+    code = afs_osi_Stat(afile, &tstat);
+    if (code || tstat.size <= asize)
+       return code;
+
+    MObtainWriteLock(&afs_xosi,321);
+    VATTR_NULL(&tvattr);
+    tvattr.va_size = asize;
+    AFS_GUNLOCK();
+    VOP_LOCK(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curproc);
+    code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, curproc);
+    VOP_UNLOCK(afile->vnode, 0, curproc);
+    AFS_GLOCK();
+    MReleaseWriteLock(&afs_xosi);
+    return code;
+}
+
+void osi_DisableAtimes(struct vnode *avp)
+{
+    struct inode *ip = VTOI(avp);
+    ip->i_flag &= ~IACC;
+}
+
+
+/* Generic read interface */
+int afs_osi_Read(struct osi_file *afile, int offset, void *aptr, afs_int32 asize)
+{
+    unsigned int resid;
+    afs_int32 code;
+
+    AFS_STATCNT(osi_Read);
+
+    /**
+     * If the osi_file passed in is NULL, panic only if AFS is not shutting
+     * down. No point in crashing when we are already shutting down
+     */
+    if ( !afile ) {
+       if ( !afs_shuttingdown )
+           osi_Panic("osi_Read called with null param");
+       else
+           return EIO;
+    }
+
+    if (offset != -1) afile->offset = offset;
+    AFS_GUNLOCK();
+    code = gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
+                   AFS_UIOSYS, IO_UNIT, &afs_osi_cred, &resid);
+    AFS_GLOCK();
+    if (code == 0) {
+       code = asize - resid;
+       afile->offset += code;
+       osi_DisableAtimes(afile->vnode);
+    }
+    else {
+       afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
+                  ICL_TYPE_INT32, code);
+       code = -1;
+    }
+    return code;
+}
+
+/* Generic write interface */
+int afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr, afs_int32 asize)
+{
+    unsigned int resid;
+    afs_int32 code;
+
+    AFS_STATCNT(osi_Write);
+    if (!afile)
+        osi_Panic("afs_osi_Write called with null afile");
+    if (offset != -1)
+       afile->offset = offset;
+
+    AFS_GUNLOCK();
+    VOP_LOCK(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curproc);
+    code = gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize, afile->offset,
+                   AFS_UIOSYS, IO_UNIT, &afs_osi_cred, &resid);
+    VOP_UNLOCK(afile->vnode, 0, curproc);
+    AFS_GLOCK();
+
+    if (code == 0) {
+       code = asize - resid;
+       afile->offset += code;
+    } else
+       code = -1;
+
+    if (afile->proc)
+       (*afile->proc)(afile, code);
+
+    return code;
+}
+
+
+/*  This work should be handled by physstrat in ca/machdep.c.
+    This routine written from the RT NFS port strategy routine.
+    It has been generalized a bit, but should still be pretty clear. */
+int afs_osi_MapStrategy(int (*aproc)(), struct buf *bp)
+{
+    afs_int32 returnCode;
+
+    AFS_STATCNT(osi_MapStrategy);
+    returnCode = (*aproc)(bp);
+
+    return returnCode;
+}
+
+
+
+void shutdown_osifile(void)
+{
+    AFS_STATCNT(shutdown_osifile);
+    if (afs_cold_shutdown)
+       afs_osicred_initialized = 0;
+}
diff --git a/src/afs/OBSD/osi_groups.c b/src/afs/OBSD/osi_groups.c
new file mode 100644 (file)
index 0000000..0ab2fe2
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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
+ */
+
+/*
+ * osi_groups.c
+ *
+ * Implements:
+ * Afs_xsetgroups (syscall)
+ * setpag
+ *
+ */
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"
+#include "afs/afsincludes.h"
+#include "afs/afs_stats.h"  /* statistics */
+#include "sys/syscallargs.h"
+
+#define NOUID   ((uid_t) -1)
+#define NOGID   ((gid_t) -1)
+
+
+static int
+afs_getgroups(
+    struct ucred *cred,
+    int ngroups,
+    gid_t *gidset);
+
+static int
+afs_setgroups(
+    struct proc *proc,
+    struct ucred **cred,
+    int ngroups,
+    gid_t *gidset,
+    int change_parent);
+
+int
+Afs_xsetgroups(p, args, retval)
+    struct proc *p;
+    void *args;
+    int *retval;
+{
+    int code = 0;
+    struct vrequest treq;
+
+    AFS_STATCNT(afs_xsetgroups);
+    AFS_GLOCK();
+
+    code = afs_InitReq(&treq, osi_curcred());
+    AFS_GUNLOCK();
+    if (code) return code;
+
+    code = setgroups(p, args, retval);
+    /* Note that if there is a pag already in the new groups we don't
+     * overwrite it with the old pag.
+     */
+    if (PagInCred(osi_curcred()) == NOPAG) {
+       if (((treq.uid >> 24) & 0xff) == 'A') {
+           AFS_GLOCK();
+           /* we've already done a setpag, so now we redo it */
+           AddPag(p, treq.uid, &p->p_rcred);
+           AFS_GUNLOCK();
+       }
+    }
+    return code;
+}
+
+
+int
+setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
+       afs_uint32 *newpag, int change_parent)
+{
+    gid_t gidset[NGROUPS];
+    int ngroups, code;
+    int j;
+
+    AFS_STATCNT(setpag);
+    ngroups = afs_getgroups(*cred, NGROUPS, gidset);
+    if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
+       /* We will have to shift grouplist to make room for pag */
+       if (ngroups + 2 > NGROUPS) {
+           return (E2BIG);
+       }
+       for (j = ngroups -1; j >= 0; j--) {
+           gidset[j+2] = gidset[j];
+       }
+       ngroups += 2;
+    }
+    *newpag = (pagvalue == -1 ? genpag(): pagvalue);
+    afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
+    code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
+    return code;
+}
+
+
+static int
+afs_getgroups(
+    struct ucred *cred,
+    int ngroups,
+    gid_t *gidset)
+{
+    int ngrps, savengrps;
+    gid_t *gp;
+
+    AFS_STATCNT(afs_getgroups);
+    savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
+    gp = cred->cr_groups;
+    while (ngrps--)
+       *gidset++ = *gp++;
+    return savengrps;
+}
+
+
+
+static int
+afs_setgroups(
+    struct proc *proc,
+    struct ucred **cred,
+    int ngroups,
+    gid_t *gidset,
+    int change_parent)
+{
+    gid_t *gp;
+    struct ucred *newcr, *cr;
+
+    AFS_STATCNT(afs_setgroups);
+    /*
+     * The real setgroups() call does this, so maybe we should too.
+     *
+     */
+    if (ngroups > NGROUPS)
+       return EINVAL;
+    cr = *cred;
+    if (!change_parent) {
+       crhold(cr);
+       newcr = crcopy(cr);
+    } else
+       newcr = cr;
+    newcr->cr_ngroups = ngroups;
+    gp = newcr->cr_groups;
+    while (ngroups--)
+       *gp++ = *gidset++;
+    for ( ; gp < &(*cred)->cr_groups[NGROUPS]; gp++)
+       *gp = NOGROUP;
+    *cred = newcr;
+    return(0);
+}
diff --git a/src/afs/OBSD/osi_machdep.h b/src/afs/OBSD/osi_machdep.h
new file mode 100644 (file)
index 0000000..59d2f74
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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 OSI header file. Extends afs_osi.h.
+ *
+ * afs_osi.h includes this file, which is the only way this file should
+ * be included in a source file. This file can redefine macros declared in
+ * afs_osi.h.
+ */
+
+#ifndef _OSI_MACHDEP_H_
+#define _OSI_MACHDEP_H_
+
+#include <sys/lock.h>
+
+#define getpid()               curproc
+extern struct simplelock afs_rxglobal_lock;
+
+/* 
+ * Time related macros
+ */
+extern struct timeval time;
+#define osi_Time() (time.tv_sec)
+#define        afs_hz      hz
+
+#define M_AFSFID       (M_TEMP-1)
+#define M_AFSBUFHDR    (M_TEMP-2)
+#define M_AFSBUFFER    (M_TEMP-3)
+#define M_AFSGENERIC   (M_TEMP-4)
+
+#define PAGESIZE 8192
+
+#define        AFS_UCRED       ucred
+#define        AFS_PROC        struct proc
+
+#define afs_bufferpages bufpages
+
+#define osi_vnhold(avc,r)  do { \
+       if ((avc)->vrefCount) { VN_HOLD((struct vnode *)(avc)); } \
+       else osi_Panic("refcnt==0");  } while(0)
+
+#define        gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
+  vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(aresid), curproc)
+
+#define afs_suser() afs_osi_suser(osi_curcred()) 
+
+extern int (**afs_vnodeop_p)();
+#define SetAfsVnode(vn) /* nothing; done in getnewvnode() */
+#define        IsAfsVnode(vn)      ((vn)->v_op == afs_vnodeop_p)
+
+#define AFS_HOLD(vp) afs_nbsd_ref(vp)
+#define AFS_RELE(vp) afs_nbsd_rele(vp)
+extern void afs_nbsd_ref(struct vnode *);
+extern void afs_nbsd_rele(struct vnode *);
+
+#define va_nodeid va_fileid
+#define v_vfsp v_mount
+#define vfs_vnodecovered mnt_vnodecovered
+#define vfs_bsize mnt_stat.f_bsize
+typedef void (*osi_timeout_t)(void *);
+#define osi_timeout_t_done
+#define osi_curproc()          (curproc)
+#define osi_curcred()          (curproc->p_cred->pc_ucred)
+#define osi_vfs        mount
+#define osi_vfs_bsize mnt_stat.f_bsize
+#define osi_vfs_fsid mnt_stat.f_fsid
+#define afs_osi_alloc osi_Alloc
+#define afs_osi_free osi_Free
+#define printk printf                  /* for RX version of xdr_* */
+#define        vType(vc)               (vc)->v->v_type
+#define vSetType(vc, type)     AFSTOV(vc)->v_type = (type)
+#define        vSetVfsp(vc, vfsp)      AFSTOV(vc)->v_mount = (vfsp)
+#define osi_sleep(chan, pri)   tsleep((chan), pri, "afs", 0)
+#define afs_osi_Sleep(chan)    tsleep((chan), PVFS, "afs", 0)
+#define afs_osi_Wakeup(chan)   (wakeup(chan), 1)
+#define FTRUNC O_TRUNC
+#define FEXLOCK O_EXLOCK
+#define FSHLOCK O_SHLOCK
+#define UVM
+
+/* no protoytpe 'cuz our includers don't always have uio_rw in scope first */
+extern int afs_nbsd_rdwr();
+extern int afs_nbsd_lookupname();
+extern void afs_nbsd_getnewvnode();
+
+#define VOP_RDWR afs_nbsd_rdwr
+#define        gop_lookupname(fnamep, segflg, followlink, dirvpp, compvpp) \
+       afs_nbsd_lookupname((fnamep), (segflg), (followlink), (dirvpp), (compvpp))
+
+#ifdef KERNEL
+extern struct simplelock afs_global_lock;
+
+#ifndef AFS_GLOBAL_SUNLOCK
+#define AFS_ASSERT_GLOCK()
+#endif
+#define AFS_GLOCK()
+#define AFS_GUNLOCK()
+#define AFS_RXGLOCK()
+#define AFS_RXGUNLOCK()
+#define ISAFS_RXGLOCK() 1
+#define ISAFS_GLOCK() 1
+
+#undef SPLVAR
+#define SPLVAR
+#undef NETPRI
+#define NETPRI
+#undef USERPRI
+#define USERPRI
+#endif /* KERNEL */
+
+#endif /* _OSI_MACHDEP_H_ */
diff --git a/src/afs/OBSD/osi_misc.c b/src/afs/OBSD/osi_misc.c
new file mode 100644 (file)
index 0000000..fa568bc
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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
+ */
+
+/* 
+ * osi_misc.c
+ *
+ * OpenBSD version of afs_osi_suser() by Jim Rees.
+ * See osi_machdep.h for afs_suser macro. It simply calls afs_osi_suser()
+ * with the creds of the current process.
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afs/afsincludes.h"   /* Afs-based standard headers */
+
+/*
+ * afs_suser() returns true if the caller is superuser, false otherwise.
+ *
+ * Note that it must NOT set errno.
+ */
+
+int
+afs_osi_suser(void *credp)
+{
+    return (suser((struct ucred *) credp, &curproc->p_acflag) ? 0 : 1);
+}
+
+int
+afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
+     long *retval;
+     long dev, near_inode, param1, param2, param3, param4;
+{
+    return EINVAL;
+}
+
+int
+afs_syscall_iopen(dev, inode, usrmod, retval)
+     long *retval;
+     int dev, inode, usrmod;
+{
+    return EINVAL;
+}
+
+int
+afs_syscall_iincdec(dev, inode, inode_p1, amount)
+     int dev, inode, inode_p1, amount;
+{
+    return EINVAL;
+}
diff --git a/src/afs/OBSD/osi_sleep.c b/src/afs/OBSD/osi_sleep.c
new file mode 100644 (file)
index 0000000..f47ea90
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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
+ */
+
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afs/afsincludes.h"   /* Afs-based standard headers */
+#include "afs/afs_stats.h"   /* afs statistics */
+
+static char waitV;
+
+
+void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
+{
+    AFS_STATCNT(osi_InitWaitHandle);
+    achandle->proc = NULL;
+}
+
+/* cancel osi_Wait */
+void afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
+{
+    caddr_t proc;
+
+    AFS_STATCNT(osi_CancelWait);
+    proc = achandle->proc;
+    if (proc == 0)
+       return;
+    achandle->proc = NULL;
+    wakeup(&waitV);
+}
+
+/* afs_osi_Wait
+ * Waits for data on ahandle, or ams ms later.  ahandle may be null.
+ * Returns 0 if timeout and EINTR if signalled.
+ */
+int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
+{
+    int code = 0;
+    afs_int32 endTime;
+    int timo = (ams * afs_hz) / 1000 + 1;
+
+    AFS_STATCNT(osi_Wait);
+    endTime = osi_Time() + (ams / 1000);
+    if (ahandle)
+       ahandle->proc = (caddr_t) curproc;
+    do {
+       if (aintok) {
+           code = tsleep(&waitV, PCATCH | (PZERO+8), "afs_osi_Wait", timo);
+           if (code)   /* if interrupted, return EINTR */
+               code = EINTR;
+       } else
+           tsleep(&waitV, (PZERO-3), "afs_osi_Wait", timo);
+
+       /* if we were cancelled, quit now */
+       if (ahandle && (ahandle->proc == NULL)) {
+           /* we've been signalled */
+           break;
+       }
+    } while (osi_Time() < endTime);
+    return code;
+}
+
+int afs_osi_SleepSig(void *event)
+{
+    afs_osi_Sleep(event);
+    return 0;
+}
diff --git a/src/afs/OBSD/osi_vfsops.c b/src/afs/OBSD/osi_vfsops.c
new file mode 100644 (file)
index 0000000..e2a5b93
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+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 Transarc AFS 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.
+*/
+
+/*
+ * OpenBSD specific assistance routines & VFS ops
+ * Original NetBSD version for Transarc afs by John Kohl <jtk@MIT.EDU>
+ * OpenBSD version by Jim Rees <rees@umich.edu>
+ *
+ * $Id$
+ */
+
+/*
+ * Some code cribbed from ffs_vfsops and other NetBSD sources, which
+ * are marked:
+ */
+/*
+ * Copyright (c) 1989, 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * 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 "afs/afsincludes.h"   /* Afs-based standard headers */
+#include "afs/afs_stats.h" /* statistics */
+
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/lkm.h>
+#include <sys/namei.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+#define NBSD_DONTFOLLOW_LINK 0
+#define NBSD_FOLLOW_LINK 1
+static int lkmid = -1;
+static int afs_badcall(struct proc *p, void *xx, register_t *yy);
+
+char afs_NetBSD_osname[] = "OpenBSD";
+struct osi_vfs *afs_globalVFS;
+struct vcache *afs_globalVp;
+
+int afs_quotactl();
+int afs_fhtovp();
+int afs_vptofh();
+int afsinit();
+int afs_start();
+int afs_mount();
+int afs_unmount();
+int afs_root();
+int afs_statfs();
+int afs_sync();
+int afs_vget();
+int afs_sysctl();
+int afs_checkexp();
+
+struct vfsops afs_vfsops = {
+    afs_mount,
+    afs_start,
+    afs_unmount,
+    afs_root,
+    afs_quotactl,
+    afs_statfs,
+    afs_sync,
+    afs_vget,
+    afs_fhtovp,
+    afs_vptofh,
+    afsinit,
+    afs_sysctl,
+    afs_checkexp,
+};
+
+int
+afs_nbsd_lookupname(char *fnamep,
+                   enum uio_seg segflg,
+                   int followlink,
+                   struct vnode **dirvpp,
+                   struct vnode **compvpp)
+{
+    struct nameidata nd;
+    int niflag;
+    int error;
+
+    /*
+     * Lookup pathname "fnamep", returning parent directory in
+     * *dirvpp (if non-null) and leaf in *compvpp.  segflg says whether the
+     * pathname is user or system space.
+     */
+    /* XXX LOCKLEAF ? */
+    niflag =  (followlink == NBSD_FOLLOW_LINK) ? FOLLOW : NOFOLLOW;
+    if (dirvpp)
+       niflag |= WANTPARENT;           /* XXX LOCKPARENT? */
+    NDINIT(&nd, LOOKUP,
+          niflag,
+          segflg,
+          fnamep, osi_curproc());
+    if ((error = namei(&nd)))
+       return error;
+    *compvpp = nd.ni_vp;
+    if (dirvpp)
+       *dirvpp = nd.ni_dvp;
+    return error;
+}
+
+#if 0
+int
+afs_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw op,
+             int flags, struct AFS_UCRED *cred)
+{
+    uiop->uio_rw = op;
+    if (op == UIO_READ)
+       return VOP_READ(vp, uiop, flags, cred);
+    if (op == UIO_WRITE)
+       return VOP_WRITE(vp, uiop, flags, cred);
+#ifdef DIAGNOSTIC
+    panic("afs_rdwr mode");
+#endif
+    return EINVAL;
+}
+#endif
+
+int
+afs_quotactl()
+{
+    return EOPNOTSUPP;
+}
+
+int
+afs_sysctl()
+{
+    return EOPNOTSUPP;
+}
+
+int
+afs_checkexp()
+{
+       return EOPNOTSUPP;
+}
+
+int
+afs_fhtovp(mp, fhp, vpp)
+struct mount *mp;
+struct fid *fhp;
+struct vnode **vpp;
+{
+
+    return (EINVAL);
+}
+
+int
+afs_vptofh(vp, fhp)
+struct vnode *vp;
+struct fid *fhp;
+{
+
+    return (EINVAL);
+}
+
+int
+afs_start(mp, flags, p)
+struct mount *mp;
+int flags;
+struct proc *p;
+{
+    return (0);                                /* nothing to do. ? */
+}
+
+int
+afs_mount(mp, path, data, ndp, p)
+register struct mount *mp;
+char *path;
+caddr_t data;
+struct nameidata *ndp;
+struct proc *p;
+{
+    /* ndp contains the mounted-from device.  Just ignore it.
+       we also don't care about our proc struct. */
+    int size;
+
+    if (mp->mnt_flag & MNT_UPDATE)
+       return EINVAL;
+
+    if (afs_globalVFS) {
+       /* Don't allow remounts */
+       return EBUSY;
+    }
+
+    AFS_GLOCK();
+    AFS_STATCNT(afs_mount);
+
+#ifdef DISCONN
+    /* initialize the vcache entries before we start using them */
+
+    /* XXX find a better place for this if possible  */
+    init_vcache_entries();
+#endif
+    afs_globalVFS = mp;
+    mp->osi_vfs_bsize = 8192;
+    mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
+    mp->osi_vfs_fsid.val[1] = (int) AFS_VFSFSID; 
+
+    AFS_GUNLOCK();
+
+    (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN-1, &size);
+    bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
+    bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
+    strcpy(mp->mnt_stat.f_mntfromname, "AFS");
+    /* null terminated string "AFS" will fit, just leave it be. */
+    strcpy(mp->mnt_stat.f_fstypename, MOUNT_AFS);
+    (void) afs_statfs(mp, &mp->mnt_stat);
+
+    return 0;
+}
+
+int
+afs_unmount(afsp, flags, p)
+struct mount *afsp;
+int flags;
+struct proc *p;
+{
+    int err;
+    extern int sys_ioctl(), sys_setgroups();
+
+    err = afs_unmount(afsp, flags);
+    if (err == 0) {
+       /* give up syscall entries for ioctl & setgroups, which we've stolen */
+       sysent[SYS_ioctl].sy_call = sys_ioctl;
+       sysent[SYS_setgroups].sy_call = sys_setgroups;
+       /* give up the stolen syscall entry */
+       sysent[AFS_SYSCALL].sy_narg = 0;
+       sysent[AFS_SYSCALL].sy_argsize = 0;
+       sysent[AFS_SYSCALL].sy_call = afs_badcall;
+       printf("AFS unmounted--use `/sbin/modunload -i %d' to unload before restarting AFS\n", lkmid);
+    }
+    return err;
+}
+
+static int
+afs_badcall(struct proc *p, void *xx, register_t *yy)
+{
+    return ENOSYS;
+}
+
+void
+afs_nbsd_getnewvnode(struct vcache *tvc)
+{
+    while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
+       /* no vnodes available, force an alloc (limits be damned)! */
+       desiredvnodes++;
+    }
+    tvc->v->v_data = (void *)tvc;
+}
+
+int
+afs_root(struct mount *mp,
+             struct vnode **vpp)
+{
+    int error;
+    error = afs_root(mp, vpp);
+    if (!error)
+       vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curproc);                /* return it locked */
+    return error;
+}
+
+int
+afs_statfs(struct osi_vfs *afsp, struct statfs *abp)
+{
+    AFS_STATCNT(afs_statfs);
+#ifdef  AFS_GLOBAL_SUNLOCK
+    mutex_enter(&afs_global_lock);
+#endif
+    abp->f_bsize = afsp->osi_vfs_bsize;
+    /* Fake a high number below to satisfy programs that use the ustat (for AIX), or statfs (for the rest) call to make sure that there's enough space in the device partition before storing something there (like ed(1)) */
+    abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files = abp->f_ffree  = 9000000; /* XXX */
+    abp->f_fsid.val[0] = AFS_VFSMAGIC; /* magic */
+    abp->f_fsid.val[1] = (int) AFS_VFSFSID;
+#ifdef  AFS_GLOBAL_SUNLOCK
+    mutex_exit(&afs_global_lock);
+#endif
+    return 0;
+}
+
+int
+afs_sync(struct osi_vfs *afsp)
+{
+    AFS_STATCNT(afs_sync);
+#if defined(DISCONN) && !defined(AFS_OBSD_ENV)
+    /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
+    store_dirty_vcaches();
+#endif
+    return 0;
+}
+
+void
+afs_nbsd_ref(struct vnode *vp)
+{
+    if (vp->v_usecount == 0) {
+       vprint("holding unheld node", vp);
+       panic("afs_ref");
+    }
+    VREF(vp);
+}
+
+void
+afs_nbsd_rele(struct vnode *vp)
+{
+    if (vp->v_usecount <= 0) {
+       vprint("rele'ing unheld node", vp);
+       panic("afs_rele");
+    }
+    vrele(vp);
+}
+
+int
+afs_vget(vp, lfl)
+struct vnode *vp;
+int lfl;
+{
+    int error;
+
+    if (vp->v_usecount < 0) {
+       vprint("bad usecount", vp);
+       panic("afs_vget");
+    }
+    error = vget(vp, lfl, curproc);
+    if (!error)
+       insmntque(vp, afs_globalVFS);   /* take off free list */
+    return error;
+}
+
+extern struct vfsops afs_vfsops;
+extern struct vnodeopv_desc afs_vnodeop_opv_desc;
+
+static struct vfsconf afs_vfsconf = {
+    &afs_vfsops,
+    "afs",
+    0,
+    0,
+    0,
+    NULL,
+    NULL,
+};
+
+MOD_VFS("afs", 0, &afs_vfsconf);
+
+static char afsgenmem[] = "afsgenmem";
+static char afsfidmem[] = "afsfidmem";
+static char afsbhdrmem[] = "afsbhdrmem";
+static char afsbfrmem[] = "afsbfrmem";
+
+int
+afsinit()
+{
+    extern int afs3_syscall(), afs_xioctl(), Afs_xsetgroups(), afs_xflock();
+
+    sysent[AFS_SYSCALL].sy_call = afs3_syscall;
+    sysent[AFS_SYSCALL].sy_narg = 6;
+    sysent[AFS_SYSCALL].sy_argsize = 6*sizeof(long);
+    sysent[54].sy_call = afs_xioctl;
+    sysent[80].sy_call = Afs_xsetgroups;
+
+    return 0;
+}
+
+int
+afs_vfs_load(struct lkm_table *lkmtp,
+            int cmd)
+{
+    extern char *memname[];
+
+    vfs_opv_init_explicit(&afs_vnodeop_opv_desc);
+    vfs_opv_init_default(&afs_vnodeop_opv_desc);
+    if (memname[M_AFSGENERIC] == NULL)
+       memname[M_AFSGENERIC] = afsgenmem;
+    if (memname[M_AFSFID] == NULL)
+       memname[M_AFSFID] = afsfidmem;
+    if (memname[M_AFSBUFHDR] == NULL)
+       memname[M_AFSBUFHDR] = afsbhdrmem;
+    if (memname[M_AFSBUFFER] == NULL)
+       memname[M_AFSBUFFER] = afsbfrmem;
+    lkmid = lkmtp->id;
+    printf("OpenAFS ($Revision$) lkm loaded\n");
+    return 0;
+}
+
+int
+afs_vfs_unload(struct lkm_table *lktmp,
+            int cmd)
+{
+    extern char *memname[];
+    extern int sys_lkmnosys();
+
+    if (afs_globalVp)
+       return EBUSY;
+    if (sysent[SYS_ioctl].sy_call != sys_ioctl)
+       return EBUSY;
+
+    if (memname[M_AFSGENERIC] == afsgenmem)
+       memname[M_AFSGENERIC] = NULL;
+    if (memname[M_AFSFID] == afsfidmem)
+       memname[M_AFSFID] = NULL;
+    if (memname[M_AFSBUFHDR] == afsbhdrmem)
+       memname[M_AFSBUFHDR] = NULL;
+    if (memname[M_AFSBUFFER] == afsbfrmem)
+       memname[M_AFSBUFFER] = NULL;
+
+    sysent[AFS_SYSCALL].sy_call = sys_lkmnosys;
+    printf("OpenAFS unloaded\n");
+    return 0;
+}
+
+
+
+int
+afsmodload(struct lkm_table *lkmtp,
+          int cmd,
+          int ver)
+{
+    extern int sys_lkmnosys();
+
+    if (cmd == LKM_E_LOAD) {
+       if (strcmp(ostype,afs_NetBSD_osname)) {
+           printf("This is %s version %s\n", ostype, osrelease);
+           printf("This version of AFS is only for %s\n",
+                  afs_NetBSD_osname);
+/*         return EPROGMISMATCH;*/
+       }
+       if (sysent[AFS_SYSCALL].sy_call != sys_lkmnosys) {
+           printf("AFS must be loaded with syscall %d assigned to sys_lkmnosys\nIs AFS already loaded?\n",
+                  AFS_SYSCALL);
+           return EINVAL;
+       }
+    }
+    DISPATCH(lkmtp,cmd,ver,afs_vfs_load,afs_vfs_unload,lkm_nofunc);
+}
diff --git a/src/afs/OBSD/osi_vm.c b/src/afs/OBSD/osi_vm.c
new file mode 100644 (file)
index 0000000..ff9cf24
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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
+ */
+
+
+/* osi_vm.c implements:
+ *
+ * osi_VM_FlushVCache(avc, slept)
+ * osi_ubc_flush_dirty_and_wait(vp, flags)
+ * osi_VM_StoreAllSegments(avc)
+ * osi_VM_TryToSmush(avc, acred, sync)
+ * osi_VM_FlushPages(avc, credp)
+ * osi_VM_Truncate(avc, alen, acred)
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afs/afsincludes.h"   /* Afs-based standard headers */
+#include "afs/afs_stats.h"  /* statistics */
+/* #include <vm/vm_ubc.h> */
+#include <limits.h>
+#include <float.h>
+
+/* Try to discard pages, in order to recycle a vcache entry.
+ *
+ * We also make some sanity checks:  ref count, open count, held locks.
+ *
+ * We also do some non-VM-related chores, such as releasing the cred pointer
+ * (for AIX and Solaris) and releasing the gnode (for AIX).
+ *
+ * Locking:  afs_xvcache lock is held.  If it is dropped and re-acquired,
+ *   *slept should be set to warn the caller.
+ *
+ * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
+ * is not dropped and re-acquired for any platform.  It may be that *slept is
+ * therefore obsolescent.
+ *
+ * OSF/1 Locking:  VN_LOCK has been called.
+ */
+int osi_VM_FlushVCache(struct vcache *avc, int *slept)
+{
+    return 0;
+}
+
+/* Try to store pages to cache, in order to store a file back to the server.
+ *
+ * Locking:  the vcache entry's lock is held.  It will usually be dropped and
+ * re-obtained.
+ */
+void osi_VM_StoreAllSegments(struct vcache *avc)
+{
+}
+
+/* Try to invalidate pages, for "fs flush" or "fs flushv"; or
+ * try to free pages, when deleting a file.
+ *
+ * Locking:  the vcache entry's lock is held.  It may be dropped and
+ * re-obtained.
+ *
+ * Since we drop and re-obtain the lock, we can't guarantee that there won't
+ * be some pages around when we return, newly created by concurrent activity.
+ */
+void osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
+{
+}
+
+/* Purge VM for a file when its callback is revoked.
+ *
+ * Locking:  No lock is held, not even the global lock.
+ */
+void osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
+{
+}
+
+/* Purge pages beyond end-of-file, when truncating a file.
+ *
+ * Locking:  no lock is held, not even the global lock.
+ * activeV is raised.  This is supposed to block pageins, but at present
+ * it only works on Solaris.
+ */
+void osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
+{
+}
diff --git a/src/afs/OBSD/osi_vnodeops.c b/src/afs/OBSD/osi_vnodeops.c
new file mode 100644 (file)
index 0000000..3ea68b3
--- /dev/null
@@ -0,0 +1,999 @@
+/*
+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 Transarc AFS 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.
+*/
+
+/*
+ * 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$
+ */
+
+/*
+ * 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 "afs/afsincludes.h"   /* Afs-based standard headers */
+#include "afs/afs_stats.h" /* statistics */
+
+#include <sys/malloc.h>
+#include <sys/namei.h>
+
+#include "afs/afs_cbqueue.h"
+#include "afs/nfsclient.h"
+#include "afs/afs_osidnlc.h"
+
+#ifdef DISCONN
+extern int afs_FlushVS(struct vcache *tvc);
+#endif
+
+#define M_AFSNODE (M_TEMP-1)           /* XXX */
+
+int afs_nbsd_lookup(struct vop_lookup_args *);
+int afs_nbsd_create(struct vop_create_args *);
+int afs_nbsd_mknod(struct vop_mknod_args *);
+int afs_nbsd_open(struct vop_open_args *);
+int afs_nbsd_close(struct vop_close_args *);
+int afs_nbsd_access(struct vop_access_args *);
+int afs_nbsd_getattr(struct vop_getattr_args *);
+int afs_nbsd_setattr(struct vop_setattr_args *);
+int afs_nbsd_read(struct vop_read_args *);
+int afs_nbsd_write(struct vop_write_args *);
+int afs_nbsd_ioctl(struct vop_ioctl_args *);
+int afs_nbsd_select(struct vop_select_args *);
+int afs_nbsd_fsync(struct vop_fsync_args *);
+int afs_nbsd_remove(struct vop_remove_args *);
+int afs_nbsd_link(struct vop_link_args *);
+int afs_nbsd_rename(struct vop_rename_args *);
+int afs_nbsd_mkdir(struct vop_mkdir_args *);
+int afs_nbsd_rmdir(struct vop_rmdir_args *);
+int afs_nbsd_symlink(struct vop_symlink_args *);
+int afs_nbsd_readdir(struct vop_readdir_args *);
+int afs_nbsd_readlink(struct vop_readlink_args *);
+extern int ufs_abortop(struct vop_abortop_args *);
+int afs_nbsd_inactive(struct vop_inactive_args *);
+int afs_nbsd_reclaim(struct vop_reclaim_args *);
+int afs_nbsd_lock(struct vop_lock_args *);
+int afs_nbsd_unlock(struct vop_unlock_args *);
+int afs_nbsd_bmap(struct vop_bmap_args *);
+int afs_nbsd_strategy(struct vop_strategy_args *);
+int afs_nbsd_print(struct vop_print_args *);
+int afs_nbsd_islocked(struct vop_islocked_args *);
+int afs_nbsd_pathconf(struct vop_pathconf_args *);
+int afs_nbsd_advlock(struct vop_advlock_args *);
+
+#define afs_nbsd_opnotsupp \
+       ((int (*) __P((struct  vop_reallocblks_args *)))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_select_desc, afs_nbsd_select },          /* select */
+       { &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, vop_generic_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 */
+       { &vop_reallocblks_desc, afs_nbsd_reallocblks }, /* reallocblks */
+       { &vop_bwrite_desc, vop_generic_bwrite },
+       { (struct vnodeop_desc *) NULL, (int (*) __P((void *))) NULL}
+};
+struct vnodeopv_desc afs_vnodeop_opv_desc =
+       { &afs_vnodeop_p, afs_vnodeop_entries };
+
+#define GETNAME()      \
+    struct componentname *cnp = ap->a_cnp; \
+    char *name; \
+    MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
+    bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
+    name[cnp->cn_namelen] = '\0'
+
+#define DROPNAME() FREE(name, M_TEMP)
+
+int afs_debug;
+
+#define NBSD_WRITES_ALLOWED
+#ifndef NBSD_WRITES_ALLOWED
+int nbsd_writes_allowed = 0;
+#endif
+
+#undef vrele
+#define vrele afs_nbsd_rele
+#undef VREF
+#define VREF afs_nbsd_ref
+
+int
+afs_nbsd_lookup(ap)
+struct vop_lookup_args /* {
+                         struct vnodeop_desc * a_desc;
+                         struct vnode *a_dvp;
+                         struct vnode **a_vpp;
+                         struct componentname *a_cnp;
+                         } */ *ap;
+{
+    int error;
+    struct vcache *vcp;
+    struct vnode *vp, *dvp;
+    int flags = ap->a_cnp->cn_flags;
+    int lockparent;                    /* 1 => lockparent flag is set */
+    int wantparent;                    /* 1 => wantparent or lockparent flag */
+
+    GETNAME();
+    lockparent = flags & LOCKPARENT;
+    wantparent = flags & (LOCKPARENT|WANTPARENT);
+
+    if (ap->a_dvp->v_type != VDIR) {
+       *ap->a_vpp = 0;
+       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);
+    error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
+    if (error) {
+       if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
+           (flags & ISLASTCN) && error == ENOENT)
+           error = EJUSTRETURN;
+       if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
+           cnp->cn_flags |= SAVENAME;
+       DROPNAME();
+       *ap->a_vpp = 0;
+       return (error);
+    }
+    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, curproc);                /* done with parent. */
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);                  /* always return the child locked */
+       if (afs_debug & AFSDEB_VNLAYER)
+           printf("locked ret %p from lookup\n", vp);
+    }
+    *ap->a_vpp = vp;
+
+    if (((cnp->cn_nameiop == RENAME && wantparent && (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 error;
+}
+
+int
+afs_nbsd_create(ap)
+       struct vop_create_args /* {
+               struct vnode *a_dvp;
+               struct vnode **a_vpp;
+               struct componentname *a_cnp;
+               struct vattr *a_vap;
+       } */ *ap;
+{
+    int error = 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 */
+
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error = afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL,
+                      ap->a_vap->va_mode, &vcp,
+                      cnp->cn_cred);
+    if (error) {
+       VOP_ABORTOP(dvp, cnp);
+       vput(dvp);
+       DROPNAME();
+       return(error);
+    }
+
+    if (vcp) {
+       *ap->a_vpp = AFSTOV(vcp);
+       vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
+    }
+    else *ap->a_vpp = 0;
+
+    if ((cnp->cn_flags & SAVESTART) == 0)
+       FREE(cnp->cn_pnbuf, M_NAMEI);
+    vput(dvp);
+    DROPNAME();
+    if (afs_debug & AFSDEB_VNLAYER)
+       printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
+    return error;
+}
+
+int
+afs_nbsd_mknod(ap)
+       struct vop_mknod_args /* {
+               struct vnode *a_dvp;
+               struct vnode **a_vpp;
+               struct componentname *a_cnp;
+               struct vattr *a_vap;
+       } */ *ap;
+{
+    free(ap->a_cnp->cn_pnbuf, M_NAMEI);
+    vput(ap->a_dvp);
+    return(ENODEV);
+}
+
+int
+afs_nbsd_open(ap)
+       struct vop_open_args /* {
+               struct vnode *a_vp;
+               int  a_mode;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    int error;
+    struct vcache *vc = VTOAFS(ap->a_vp);
+    error = afs_open(&vc, ap->a_mode, ap->a_cred);
+#ifdef DIAGNOSTIC
+    if (AFSTOV(vc) != ap->a_vp)
+       panic("AFS open changed vnode!");
+#endif
+    return error;
+}
+
+int
+afs_nbsd_close(ap)
+       struct vop_close_args /* {
+               struct vnode *a_vp;
+               int  a_fflag;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    return afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred, ap->a_p);
+}
+
+int
+afs_nbsd_access(ap)
+       struct vop_access_args /* {
+               struct vnode *a_vp;
+               int  a_mode;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    return afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
+}
+int
+afs_nbsd_getattr(ap)
+       struct vop_getattr_args /* {
+               struct vnode *a_vp;
+               struct vattr *a_vap;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    return afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
+}
+int
+afs_nbsd_setattr(ap)
+       struct vop_setattr_args /* {
+               struct vnode *a_vp;
+               struct vattr *a_vap;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    return afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
+}
+int
+afs_nbsd_read(ap)
+       struct vop_read_args /* {
+               struct vnode *a_vp;
+               struct uio *a_uio;
+               int a_ioflag;
+               struct ucred *a_cred;
+       } */ *ap;
+{
+    return afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, 0, 0, 0);
+}
+int
+afs_nbsd_write(ap)
+       struct vop_write_args /* {
+               struct vnode *a_vp;
+               struct uio *a_uio;
+               int a_ioflag;
+               struct ucred *a_cred;
+       } */ *ap;
+{
+#ifdef UVM
+    (void) uvm_vnp_uncache(ap->a_vp);  /* toss stale pages */
+#else
+    vnode_pager_uncache(ap->a_vp);
+#endif
+    return afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
+}
+int
+afs_nbsd_ioctl(ap)
+       struct vop_ioctl_args /* {
+               struct vnode *a_vp;
+               int  a_command;
+               caddr_t  a_data;
+               int  a_fflag;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+    struct vcache *tvc = VTOAFS(ap->a_vp);
+    int error = 0;
+
+    /* in case we ever get in here... */
+
+    AFS_STATCNT(afs_ioctl);
+    if (((ap->a_command >> 8) & 0xff) == 'V') {
+       /* This is a VICEIOCTL call */
+       error = HandleIoctl(tvc, (struct file *)0/*Not used*/,
+                           ap->a_command, ap->a_data);
+       return(error);
+    } else {
+       /* No-op call; just return. */
+       return(ENOTTY);
+    }
+}
+
+/* ARGSUSED */
+int
+afs_nbsd_select(ap)
+       struct vop_select_args /* {
+               struct vnode *a_vp;
+               int  a_which;
+               int  a_fflags;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+       /*
+        * We should really check to see if I/O is possible.
+        */
+       return (1);
+}
+
+int
+afs_nbsd_fsync(ap)
+       struct vop_fsync_args /* {
+               struct vnode *a_vp;
+               struct ucred *a_cred;
+               int a_waitfor;
+               struct proc *a_p;
+       } */ *ap;
+{
+    int wait = ap->a_waitfor == MNT_WAIT;
+    struct vnode *vp = ap->a_vp;
+    vflushbuf(vp, wait);
+    return afs_fsync(VTOAFS(vp), ap->a_cred);
+}
+
+int
+afs_nbsd_remove(ap)
+       struct vop_remove_args /* {
+               struct vnode *a_dvp;
+               struct vnode *a_vp;
+               struct componentname *a_cnp;
+       } */ *ap;
+{
+    int error = 0;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+
+    GETNAME();
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error =  afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
+    if (dvp == vp)
+       vrele(vp);
+    else
+       vput(vp);
+    vput(dvp);
+    FREE(cnp->cn_pnbuf, M_NAMEI);
+    DROPNAME();
+    return error;
+}
+
+int
+afs_nbsd_link(ap)
+       struct vop_link_args /* {
+               struct vnode *a_vp;
+               struct vnode *a_tdvp;
+               struct componentname *a_cnp;
+       } */ *ap;
+{
+    int error = 0;
+    struct vnode *dvp = ap->a_dvp;
+    struct vnode *vp = ap->a_vp;
+
+    GETNAME();
+    if (dvp->v_mount != vp->v_mount) {
+       VOP_ABORTOP(vp, cnp);
+       error = EXDEV;
+       goto out;
+    }
+    if (vp->v_type == VDIR) {
+       VOP_ABORTOP(vp, cnp);
+       error = EISDIR;
+       goto out;
+    }
+    if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
+       VOP_ABORTOP(dvp, cnp);
+       goto out;
+    }
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
+    FREE(cnp->cn_pnbuf, M_NAMEI);
+    if (dvp != vp)
+       VOP_UNLOCK(vp, 0, curproc);
+out:
+    vput(dvp);
+    DROPNAME();
+    return error;
+}
+
+int
+afs_nbsd_rename(ap)
+       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;
+{
+    int error = 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))) {
+       error = 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 (error);
+    }
+    /*
+     * 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) {
+           error = 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 ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curproc)))
+       goto abortit;
+
+    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';
+
+
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    /* XXX use "from" or "to" creds? NFS uses "to" creds */
+    error = afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
+
+    VOP_UNLOCK(fvp, 0, curproc);
+    FREE(fname, M_TEMP);
+    FREE(tname, M_TEMP);
+    if (error)
+       goto abortit;                   /* XXX */
+    if (tdvp == tvp)
+       vrele(tdvp);
+    else
+       vput(tdvp);
+    if (tvp)
+       vput(tvp);
+    vrele(fdvp);
+    vrele(fvp);
+    return error;
+}
+
+int
+afs_nbsd_mkdir(ap)
+       struct vop_mkdir_args /* {
+               struct vnode *a_dvp;
+               struct vnode **a_vpp;
+               struct componentname *a_cnp;
+               struct vattr *a_vap;
+       } */ *ap;
+{
+    struct vnode *dvp = ap->a_dvp;
+    struct vattr *vap = ap->a_vap;
+    int error = 0;
+    struct vcache *vcp;
+
+    GETNAME();
+#ifdef DIAGNOSTIC
+    if ((cnp->cn_flags & HASBUF) == 0)
+       panic("afs_nbsd_mkdir: no name");
+#endif
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
+    if (error) {
+       VOP_ABORTOP(dvp, cnp);
+       vput(dvp);
+       DROPNAME();
+       return(error);
+    }
+    if (vcp) {
+       *ap->a_vpp = AFSTOV(vcp);
+       vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
+    } else
+       *ap->a_vpp = 0;
+    DROPNAME();
+    FREE(cnp->cn_pnbuf, M_NAMEI);
+    vput(dvp);
+    return error;
+}
+
+int
+afs_nbsd_rmdir(ap)
+       struct vop_rmdir_args /* {
+               struct vnode *a_dvp;
+               struct vnode *a_vp;
+               struct componentname *a_cnp;
+       } */ *ap;
+{
+    int error = 0;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+
+    GETNAME();
+    if (dvp == vp) {
+       vrele(dvp);
+       vput(vp);
+       FREE(cnp->cn_pnbuf, M_NAMEI);
+       DROPNAME();
+       return (EINVAL);
+    }
+
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
+    DROPNAME();
+    vput(dvp);
+    vput(vp);
+    return error;
+}
+
+int
+afs_nbsd_symlink(ap)
+       struct vop_symlink_args /* {
+               struct vnode *a_dvp;
+               struct vnode **a_vpp;
+               struct componentname *a_cnp;
+               struct vattr *a_vap;
+               char *a_target;
+       } */ *ap;
+{
+    struct vnode *dvp = ap->a_dvp;
+    int error = 0;
+    /* NFS ignores a_vpp; so do we. */
+
+    GETNAME();
+#ifndef NBSD_WRITES_ALLOWED
+    if (!nbsd_writes_allowed)
+       error = EROFS;
+    if (!error)
+#endif
+    error = afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
+                       cnp->cn_cred);
+    DROPNAME();
+    FREE(cnp->cn_pnbuf, M_NAMEI);
+    vput(dvp);
+    return error;
+}
+
+int
+afs_nbsd_readdir(ap)
+       struct vop_readdir_args /* {
+               struct vnode *a_vp;
+               struct uio *a_uio;
+               struct ucred *a_cred;
+               int *a_eofflag;
+               int *a_ncookies;
+               u_long **a_cookies;
+       } */ *ap;
+{
+/*    printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
+          ap->a_ncookies); */
+    return afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred,
+                      ap->a_eofflag, ap->a_ncookies, ap->a_cookies);
+}
+
+int
+afs_nbsd_readlink(ap)
+       struct vop_readlink_args /* {
+               struct vnode *a_vp;
+               struct uio *a_uio;
+               struct ucred *a_cred;
+       } */ *ap;
+{
+/*    printf("readlink %p\n", ap->a_vp);*/
+    return afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
+}
+
+extern int prtactive;
+
+int
+afs_nbsd_inactive(ap)
+       struct vop_inactive_args /* {
+               struct vnode *a_vp;
+       } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *vc = VTOAFS(vp);
+
+    AFS_STATCNT(afs_inactive);
+
+    if (prtactive && vp->v_usecount != 0)
+       vprint("afs_nbsd_inactive(): pushing active", vp);
+
+    vc->states &= ~CMAPPED;
+    vc->states &= ~CDirty;
+
+    lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
+    return 0;
+}
+
+int
+afs_nbsd_reclaim(ap)
+       struct vop_reclaim_args /* {
+               struct vnode *a_vp;
+       } */ *ap;
+{
+    int error, slept;
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+
+    cache_purge(vp);                   /* just in case... */
+#ifdef UVM
+    uvm_vnp_uncache(vp);
+#else
+    vnode_pager_uncache(vp);
+#endif
+
+#ifndef DISCONN
+    error = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
+#else
+    /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
+    error = afs_FlushVS(avc);
+#endif
+    if (!error && vp->v_data)
+       panic("afs_reclaim: vnode not cleaned");
+    return error;
+}
+
+int
+afs_nbsd_lock(ap)
+       struct vop_lock_args /* {
+               struct vnode *a_vp;
+               int a_flags;
+               sturct proc *a_p;
+       } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *vc = VTOAFS(vp);
+
+#ifdef DIAGNOSTIC
+    if (!vc)
+       panic("afs_nbsd_lock: null vcache");
+#endif
+    return lockmgr(&vc->rwlock, ap->a_flags | LK_CANRECURSE, &vp->v_interlock, ap->a_p);
+}
+
+int
+afs_nbsd_unlock(ap)
+       struct vop_unlock_args /* {
+               struct vnode *a_vp;
+               int a_flags;
+               struct proc *a_p;
+       } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *vc = VTOAFS(vp);
+
+#ifdef DIAGNOSTIC
+    if (!vc)
+       panic("afs_nbsd_unlock: null vcache");
+#endif
+    return lockmgr(&vc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock, ap->a_p);
+}
+
+int
+afs_nbsd_bmap(ap)
+       struct vop_bmap_args /* {
+               struct vnode *a_vp;
+               daddr_t  a_bn;
+               struct vnode **a_vpp;
+               daddr_t *a_bnp;
+               int *a_runp;
+       } */ *ap;
+{
+    struct vcache *vcp = VTOAFS(ap->a_vp);
+
+    AFS_STATCNT(afs_bmap);
+    if (ap->a_bnp)
+       ap->a_bnp = ap->a_bn * (8192 / DEV_BSIZE);
+    if (ap->a_vpp)
+       *ap->a_vpp = (vcp) ? AFSTOV(vcp) : NULL;
+    return 0;
+}
+
+int
+afs_nbsd_strategy(ap)
+    struct vop_strategy_args /* {
+       struct buf *a_bp;
+    } */ *ap;
+{
+    struct buf *abp = ap->a_bp;
+    struct uio tuio;
+    struct iovec tiovec[1];
+    struct vcache *tvc = VTOAFS(abp->b_vp);
+    struct ucred *credp = osi_curcred();
+    long len = abp->b_bcount;
+    int code;
+
+    AFS_STATCNT(afs_strategy);
+
+    tuio.afsio_iov = tiovec;
+    tuio.afsio_iovcnt = 1;
+    tuio.afsio_seg = AFS_UIOSYS;
+    tuio.afsio_resid = len;
+    tiovec[0].iov_base = abp->b_un.b_addr;
+    tiovec[0].iov_len = len;
+
+    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);
+
+    ReleaseWriteLock(&tvc->lock);
+    AFS_RELE(AFSTOV(tvc));
+    return code;
+}
+
+int
+afs_nbsd_print(ap)
+       struct vop_print_args /* {
+               struct vnode *a_vp;
+       } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *vc = VTOAFS(ap->a_vp);
+
+    printf("tag %d, fid: %ld.%x.%x.%x, ", vp->v_tag, vc->fid.Cell,
+          (int) vc->fid.Fid.Volume, (int) vc->fid.Fid.Vnode, (int) vc->fid.Fid.Unique);
+    lockmgr_printinfo(&vc->rwlock);
+    printf("\n");
+    return 0;
+}
+
+int
+afs_nbsd_islocked(ap)
+       struct vop_islocked_args /* {
+               struct vnode *a_vp;
+       } */ *ap;
+{
+    return lockstatus(&VTOAFS(ap->a_vp)->rwlock);
+}
+
+/*
+ * Return POSIX pathconf information applicable to ufs filesystems.
+ */
+int
+afs_nbsd_pathconf(ap)
+       struct vop_pathconf_args /* {
+               struct vnode *a_vp;
+               int a_name;
+               int *a_retval;
+       } */ *ap;
+{
+    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;
+}
+
+/*
+ * Advisory record locking support (fcntl() POSIX style)
+ */
+int
+afs_nbsd_advlock(ap)
+       struct vop_advlock_args /* {
+               struct vnode *a_vp;
+               caddr_t  a_id;
+               int  a_op;
+               struct flock *a_fl;
+               int  a_flags;
+       } */ *ap;
+{
+    return afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
+                      (int) ap->a_id);
+}
index 852d195..5710722 100644 (file)
@@ -532,6 +532,9 @@ int afs_xioctl (void)
        /* good, this is a vnode; next see if it is an AFS vnode */
 #if    defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
        tvc = VTOAFS(fd->f_vnode);      /* valid, given a vnode */
+#elif defined(AFS_OBSD_ENV)
+       tvc = IsAfsVnode((struct vnode *) fd->f_data) ?
+           VTOAFS((struct vnode *) fd->f_data) : NULL;
 #else
        tvc = VTOAFS((struct vnode*)fd->f_data);        /* valid, given a vnode */
 #endif
index 898d748..3efd407 100644 (file)
@@ -17,7 +17,7 @@ OPTF2= ${OPT2}
 CFLAGS= ${FSINCLUDES} $(DEFINES) $(KDEFS) $(KOPTS) ${DBUG}
 
 # Name of directory to hold object files and libraries.
-KOBJ = COMMON
+KOBJ = MODLOAD
 
 # OS specific object files:
 AFS_OS_OBJS = \
@@ -81,6 +81,7 @@ DEST_LIBAFSNONFS = ${DEST}/root.client/bin/${LIBAFSNONFS}
 
 # libafs:      $(LIBAFS) $(LIBAFSNONFS)
 libafs:        $(LIBAFSNONFS)
+       touch libafs
 # install_libafs:      $(INST_LIBAFS) $(INST_LIBAFSNONFS)
 install_libafs:        $(INST_LIBAFSNONFS)
 # dest_libafs: $(DEST_LIBAFS) $(DEST_LIBAFSNONFS)
diff --git a/src/rx/OBSD/rx_kmutex.c b/src/rx/OBSD/rx_kmutex.c
new file mode 100644 (file)
index 0000000..c4b5782
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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
+ */
+
+/*
+ * rx_kmutex.c - mutex and condition variable macros for kernel environment.
+ *
+ * NetBSD implementation.
+ */
+
+/*
+ * Currently everything is implemented in rx_kmutex.h
+ */
diff --git a/src/rx/OBSD/rx_kmutex.h b/src/rx/OBSD/rx_kmutex.h
new file mode 100644 (file)
index 0000000..b8ab7c5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+/*
+ * rx_kmutex.h - mutex and condition variable macros for kernel environment.
+ *
+ * OpenBSD implementation by Jim Rees.
+ */
+
+#ifndef _RX_KMUTEX_H_
+#define _RX_KMUTEX_H_
+
+#include <sys/lock.h>
+
+/* Remind me to fix this later... */
+
+#define MUTEX_ISMINE(a)
+#define osirx_AssertMine(addr, msg)
+
+#define MUTEX_DESTROY(a)
+#define MUTEX_ENTER(a)
+#define MUTEX_TRYENTER(a) 1
+#define MUTEX_EXIT(a)  
+#define MUTEX_INIT(a,b,c,d) 
+#define CV_INIT(a,b,c,d)
+#define CV_DESTROY(a)
+#define AFS_ASSERT_RXGLOCK()
+
+#endif /* _RX_KMUTEX_H_ */
diff --git a/src/rx/OBSD/rx_knet.c b/src/rx/OBSD/rx_knet.c
new file mode 100644 (file)
index 0000000..65fef1e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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
+ */
+
+#include <afsconfig.h>
+#include "../afs/param.h"
+
+RCSID("$Header$");
+
+#include "../rx/rx_kcommon.h"
+
+int osi_NetReceive(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
+                  int nvecs, int *alength)
+{
+    struct uio u;
+    int i, code;
+    struct iovec iov[RX_MAXIOVECS];
+    struct sockaddr *sa;
+
+    int haveGlock = ISAFS_GLOCK();
+
+    if (nvecs > RX_MAXIOVECS)
+        osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
+
+    for (i = 0 ; i < nvecs ; i++) {
+        iov[i].iov_base = dvec[i].iov_base;
+        iov[i].iov_len = dvec[i].iov_len;
+    }
+
+    u.uio_iov = &iov[0];
+    u.uio_iovcnt = nvecs;
+    u.uio_offset = 0;
+    u.uio_resid = *alength;
+    u.uio_segflg = UIO_SYSSPACE;
+    u.uio_rw = UIO_READ;
+    u.uio_procp = NULL;
+
+    if (haveGlock)
+        AFS_GUNLOCK();
+    code = soreceive(asocket, (struct sockaddr_in *) &sa, &u, NULL, NULL, NULL);
+    if (haveGlock)
+        AFS_GLOCK();
+
+    *alength = *alength - u.uio_resid;
+    if (sa != NULL && sa->sa_family == AF_INET && addr != NULL)
+       *addr = *(struct sockaddr_in *)sa;
+
+    return code;
+}
+
+extern int rxk_ListenerPid;
+void osi_StopListener(void)
+{
+   struct proc *p;
+
+   soclose(rx_socket);
+   p = pfind(rxk_ListenerPid);
+   if (p)
+       psignal(p, SIGUSR1);
+}
+
+/* rx_NetSend - send asize bytes at adata from asocket to host at addr.
+ *
+ * Now, why do we allocate a new buffer when we could theoretically use the one
+ * pointed to by adata?  Because PRU_SEND returns after queueing the message,
+ * not after sending it.  If the sender changes the data after queueing it,
+ * we'd see the already-queued data change.  One attempt to fix this without
+ * adding a copy would be to have this function wait until the datagram is
+ * sent; however this doesn't work well.  In particular, if a host is down, and
+ * an ARP fails to that host, this packet will be queued until the ARP request
+ * comes back, which could be hours later.  We can't block in this routine that
+ * long, since it prevents RPC timeouts from happening.
+ */
+/* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
+ * and just queue those.  XXX
+ */
+
+
+int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
+               struct iovec *dvec, int nvecs, afs_int32 alength, int istack)
+{
+    int i, code;
+    struct iovec iov[RX_MAXIOVECS];
+    struct uio u;
+    struct mbuf *nam;
+    int haveGlock = ISAFS_GLOCK();
+
+    AFS_STATCNT(osi_NetSend);
+    if (nvecs > RX_MAXIOVECS)
+        osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
+
+    for (i = 0; i < nvecs; i++) {
+        iov[i].iov_base = dvec[i].iov_base;
+        iov[i].iov_len = dvec[i].iov_len;
+    }
+
+    u.uio_iov = &iov[0];
+    u.uio_iovcnt = nvecs;
+    u.uio_offset = 0;
+    u.uio_resid = alength;
+    u.uio_segflg = UIO_SYSSPACE;
+    u.uio_rw = UIO_WRITE;
+    u.uio_procp = NULL;
+    if (haveGlock)
+       AFS_GUNLOCK();
+
+    nam = m_get(M_DONTWAIT, MT_SONAME);
+    if (nam == NULL) {
+        code = ENOBUFS;
+        goto bad;
+    }
+    nam->m_len = addr->sin_len = sizeof(struct sockaddr_in);
+    memcpy(mtod(nam, caddr_t), (caddr_t)addr, addr->sin_len);
+    code = sosend(asocket, mtod(nam, struct sockaddr_in *), &u, NULL, NULL, 0);
+    m_freem(nam);
+
+bad:
+    if (haveGlock)
+       AFS_GLOCK();
+
+    return code;
+}
index a2975a8..a8f00d5 100644 (file)
@@ -32,6 +32,9 @@ RCSID("$Header$");
 #if defined(AFS_SGI_ENV) || defined(AFS_HPUX110_ENV)
 #include "afs/sysincludes.h"
 #endif
+#if defined(AFS_OBSD_ENV)
+#include "h/proc.h"
+#endif
 #include "h/socket.h"
 #if !defined(AFS_SUN5_ENV) &&  !defined(AFS_LINUX20_ENV)
 #if    !defined(AFS_OSF_ENV) && !defined(AFS_AIX41_ENV)