Index: src/afs/afs.h
===================================================================
RCS file: /cvs/openafs/src/afs/afs.h,v
retrieving revision 1.43
diff -u -r1.43 afs.h
--- src/afs/afs.h	27 Nov 2003 01:17:39 -0000	1.43
+++ src/afs/afs.h	9 Mar 2004 22:08:27 -0000
@@ -545,15 +545,11 @@
 #define VPageCleaning 0x2	/* Solaris - Cache Trunc Daemon sez keep out */
 
 #define	CPSIZE	    2
-#if defined(AFS_FBSD_ENV)
-#define vrefCount   v.v_usecount
-#else
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
 #define vrefCount   v->v_usecount
 #else
 #define vrefCount   v.v_count
-#endif /* AFS_OBSD_ENV */
-#endif /* AFS_FBSD_ENV */
+#endif /* AFS_XBSD_ENV */
 
 #ifdef AFS_LINUX24_ENV
 #define VREFCOUNT(v)		atomic_read(&((vnode_t *) v)->v_count)
@@ -598,7 +594,7 @@
 extern afs_uint32 afs_stampValue;	/* stamp for pair's usage */
 #define	MakeStamp()	(++afs_stampValue)
 
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
 #define VTOAFS(v) ((struct vcache *)(v)->v_data)
 #define AFSTOV(vc) ((vc)->v)
 #else
@@ -616,7 +612,7 @@
  * !(avc->nextfree) && !avc->vlruq.next => (FreeVCList == avc->nextfree)
  */
 struct vcache {
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
     struct vnode *v;
 #else
     struct vnode v;		/* Has reference count in v.v_count */
Index: src/afs/afs_call.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_call.c,v
retrieving revision 1.64
diff -u -r1.64 afs_call.c
--- src/afs/afs_call.c	3 Feb 2004 06:23:34 -0000	1.64
+++ src/afs/afs_call.c	9 Mar 2004 22:08:27 -0000
@@ -64,13 +64,12 @@
 struct lock__bsd__ afs_global_lock;
 #endif
 
-#if defined(AFS_XBSD_ENV)
+#if defined(AFS_XBSD_ENV) && !defined(AFS_FBSD50_ENV)
 struct lock afs_global_lock;
-#ifdef AFS_FBSD50_ENV
-struct thread *afs_global_owner;
-#else
 struct proc *afs_global_owner;
 #endif
+#ifdef AFS_FBSD50_ENV
+struct mtx afs_global_mtx;
 #endif
 
 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
Index: src/afs/afs_init.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_init.c,v
retrieving revision 1.26
diff -u -r1.26 afs_init.c
--- src/afs/afs_init.c	15 Jul 2003 23:14:12 -0000	1.26
+++ src/afs/afs_init.c	9 Mar 2004 22:08:28 -0000
@@ -41,7 +41,7 @@
 int afs_sysnamecount = 0;
 struct volume *Initialafs_freeVolList;
 int afs_memvolumes = 0;
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_XBSD_ENV)
 static struct vnode *volumeVnode;
 #endif
 
@@ -295,9 +295,9 @@
     struct osi_file *tfile;
 
     AFS_STATCNT(afs_InitVolumeInfo);
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
     /*
-     * On Open/NetBSD, we can get into big trouble if we don't hold the volume file
+     * On Open/Free/NetBSD, we can get into big trouble if we don't hold the volume file
      * vnode.  SetupVolume holds afs_xvolume lock exclusive.
      * SetupVolume->GetVolSlot->UFSGetVolSlot->{GetVolCache or WriteVolCache}
      * ->osi_UFSOpen->VFS_VGET()->ffs_vget->getnewvnode->vgone on some vnode.
@@ -368,20 +368,14 @@
     {
 #if	defined(AFS_SUN56_ENV)
 	struct statvfs64 st;
-#else
-#if	defined(AFS_HPUX102_ENV)
+#elif	defined(AFS_HPUX102_ENV)
 	struct k_statvfs st;
-#else
-#if	defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) ||defined(AFS_HPUX100_ENV)
+#elif	defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) ||defined(AFS_HPUX100_ENV)
 	struct statvfs st;
-#else
-#if defined(AFS_DUX40_ENV)
+#elif defined(AFS_DUX40_ENV)
 	struct nstatfs st;
 #else
 	struct statfs st;
-#endif /* DUX40 */
-#endif /* SUN5 SGI */
-#endif /* HP 10.20 */
 #endif /* SUN56 */
 
 #if	defined(AFS_SGI_ENV)
@@ -424,15 +418,17 @@
 	    afs_fsfragsize = st.f_bsize - 1;
 #endif
     }
-#ifdef AFS_LINUX20_ENV
+#if defined(AFS_LINUX20_ENV)
     cacheInode = filevp->i_ino;
     afs_cacheSBp = filevp->i_sb;
-#else
-#ifdef AFS_OBSD_ENV
+#elif defined(AFS_XBSD_ENV)
     cacheInode = VTOI(filevp)->i_number;
     cacheDev.mp = filevp->v_mount;
     cacheDev.held_vnode = filevp;
-    AFS_HOLD(filevp);		/* Make sure mount point stays busy. XXX */
+    vref(filevp);		/* Make sure mount point stays busy. XXX */
+#if !defined(AFS_OBSD_ENV)
+    afs_cacheVfsp = filevp->v_vfsp;
+#endif
 #else
 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
     afs_InitDualFSCacheOps(filevp);
@@ -440,7 +436,6 @@
     cacheInode = afs_vnodeToInumber(filevp);
     cacheDev.dev = afs_vnodeToDev(filevp);
     afs_cacheVfsp = filevp->v_vfsp;
-#endif /* AFS_OBSD_ENV */
 #endif /* AFS_LINUX20_ENV */
     AFS_RELE(filevp);
 #endif /* AFS_LINUX22_ENV */
@@ -494,10 +489,12 @@
     RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
     RWLOCK_INIT(&afs_xinterface, "afs_xinterface");
     LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
+#ifndef AFS_FBSD_ENV
 #ifndef	AFS_AIX32_ENV
     LOCK_INIT(&osi_fsplock, "osi_fsplock");
 #endif
     LOCK_INIT(&osi_flplock, "osi_flplock");
+#endif
     RWLOCK_INIT(&afs_xconn, "afs_xconn");
 
     afs_CellInit();
@@ -669,11 +666,11 @@
 	afs_cacheFiles = afs_cacheBlocks = 0;
 	pag_epoch = maxIHint = nihints = usedihint = 0;
 	pagCounter = 0;
-#ifdef AFS_OBSD_ENV
-	AFS_RELE(volumeVnode);	/* let it go, finally. */
+#if defined(AFS_XBSD_ENV)
+	vrele(volumeVnode);	/* let it go, finally. */
 	volumeVnode = NULL;
 	if (cacheDev.held_vnode) {
-	    AFS_RELE(cacheDev.held_vnode);
+	    vrele(cacheDev.held_vnode);
 	    cacheDev.held_vnode = NULL;
 	}
 #endif
Index: src/afs/afs_osi.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_osi.c,v
retrieving revision 1.39
diff -u -r1.39 afs_osi.c
--- src/afs/afs_osi.c	27 Nov 2003 01:17:39 -0000	1.39
+++ src/afs/afs_osi.c	9 Mar 2004 22:08:28 -0000
@@ -57,6 +57,8 @@
 #elif defined(AFS_OSF_ENV)
     usimple_lock_init(&afs_global_lock);
     afs_global_owner = (thread_t) 0;
+#elif defined(AFS_FBSD50_ENV)
+    mtx_init(&afs_global_mtx, "AFS global lock", NULL, MTX_DEF);
 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     lockinit(&afs_global_lock, PLOCK, "afs global lock", 0, 0);
     afs_global_owner = 0;
@@ -433,6 +435,8 @@
     AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
 #ifdef AFS_LINUX20_ENV
     return osi_linux_alloc(x, 1);
+#elif defined(AFS_FBSD_ENV)
+    return osi_fbsd_alloc(x, 1);
 #else
     size = x;
     tm = (struct osimem *)AFS_KALLOC(size);
@@ -479,6 +483,8 @@
     AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
 #if defined(AFS_LINUX20_ENV)
     osi_linux_free(x);
+#elif defined(AFS_FBSD_ENV)
+    osi_fbsd_free(x);
 #else
     AFS_KFREE((struct osimem *)x, asize);
 #endif
Index: src/afs/afs_osi.h
===================================================================
RCS file: /cvs/openafs/src/afs/afs_osi.h,v
retrieving revision 1.19
diff -u -r1.19 afs_osi.h
--- src/afs/afs_osi.h	29 Aug 2003 22:00:04 -0000	1.19
+++ src/afs/afs_osi.h	9 Mar 2004 22:08:28 -0000
@@ -13,6 +13,10 @@
 #include "h/types.h"
 #include "h/param.h"
 
+#ifdef AFS_FBSD50_ENV
+#include <sys/condvar.h>
+#endif
+
 #ifdef AFS_LINUX20_ENV
 #ifndef _LINUX_CODA_FS_I
 #define _LINUX_CODA_FS_I
@@ -68,11 +72,9 @@
 };
 
 struct osi_dev {
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_XBSD_ENV)
     struct mount *mp;
     struct vnode *held_vnode;
-#elif defined(AFS_FBSD50_ENV)
-    struct cdev *dev;
 #elif defined(AFS_AIX42_ENV)
     dev_t dev;
 #else
@@ -81,7 +83,12 @@
 };
 
 struct afs_osi_WaitHandle {
+#ifdef AFS_FBSD50_ENV
+    struct cv wh_condvar;
+    int wh_inited;		/* XXX */
+#else
     caddr_t proc;		/* process waiting */
+#endif
 };
 
 #define	osi_SetFileProc(x,p)	((x)->proc=(p))
Index: src/afs/afs_osi_alloc.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_osi_alloc.c,v
retrieving revision 1.9
diff -u -r1.9 afs_osi_alloc.c
--- src/afs/afs_osi_alloc.c	15 Jul 2003 23:14:12 -0000	1.9
+++ src/afs/afs_osi_alloc.c	9 Mar 2004 22:08:28 -0000
@@ -19,6 +19,7 @@
 #include "afsincludes.h"	/* Afs-based standard headers */
 #include "afs/afs_stats.h"	/* afs statistics */
 
+#ifndef AFS_FBSD_ENV
 #ifdef AFS_AIX41_ENV
 #include "sys/lockl.h"
 #include "sys/sleep.h"
@@ -368,3 +369,4 @@
 	LOCK_INIT(&osi_flplock, "osi_flplock");
     }
 }
+#endif
Index: src/afs/afs_prototypes.h
===================================================================
RCS file: /cvs/openafs/src/afs/afs_prototypes.h,v
retrieving revision 1.45
diff -u -r1.45 afs_prototypes.h
--- src/afs/afs_prototypes.h	23 Jan 2004 16:53:35 -0000	1.45
+++ src/afs/afs_prototypes.h	9 Mar 2004 22:08:28 -0000
@@ -465,8 +465,12 @@
 extern void afs_osi_MaskSignals(void);
 extern void afs_osi_UnmaskRxkSignals(void);
 extern void *afs_osi_Alloc(size_t x);
+#ifndef afs_osi_Alloc_NoSleep
 extern void *afs_osi_Alloc_NoSleep(size_t x);
+#endif
+#ifndef afs_osi_Free
 extern void afs_osi_Free(void *x, size_t asize);
+#endif
 extern void afs_osi_FreeStr(char *x);
 extern void osi_Init(void);
 extern int osi_Active(register struct vcache *avc);
@@ -503,9 +507,11 @@
 extern afs_int32 PagInCred(const struct AFS_UCRED *cred);
 
 /* afs_osi_alloc.c */
+#ifndef AFS_FBSD_ENV
 extern afs_int32 afs_preallocs;
 extern afs_lock_t osi_fsplock;
 extern afs_lock_t osi_flplock;
+#endif
 extern void osi_FreeLargeSpace(void *adata);
 extern void osi_FreeMediumSpace(void *adata);
 extern void osi_FreeSmallSpace(void *adata);
Index: src/afs/afs_vcache.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_vcache.c,v
retrieving revision 1.56
diff -u -r1.56 afs_vcache.c
--- src/afs/afs_vcache.c	10 Oct 2003 20:01:56 -0000	1.56
+++ src/afs/afs_vcache.c	9 Mar 2004 22:08:28 -0000
@@ -153,7 +153,7 @@
 	afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
 	avc->linkData = NULL;
     }
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
     /* OK, there are no internal vrefCounts, so there shouldn't
      * be any more refs here. */
     if (avc->v) {
@@ -801,36 +801,6 @@
 		    continue;	/* start over - may have raced. */
 		}
 	    }
-#elif defined(AFS_FBSD50_ENV)
-	    if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
-		&& (tvc->states & CUnlinkedDel) == 0) {
-		if (!(VOP_LOCK(&tvc->v, LK_EXCLUSIVE, curthread))) {
-		    if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
-			&& (tvc->states & CUnlinkedDel) == 0) {
-			VREFCOUNT_DEC(tvc);
-			AFS_GUNLOCK();	/* perhaps inline inactive for locking */
-			VOP_INACTIVE(&tvc->v, curthread);
-			AFS_GLOCK();
-		    } else {
-			VOP_UNLOCK(&tvc->v, 0, curthread);
-		    }
-		}
-	    }
-#elif defined(AFS_FBSD_ENV) && !defined(AFS_FBSD50_ENV)
-	    if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
-		&& (tvc->states & CUnlinkedDel) == 0) {
-		if (!(VOP_LOCK(&tvc->v, LK_EXCLUSIVE, curproc))) {
-		    if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
-			&& (tvc->states & CUnlinkedDel) == 0) {
-			VREFCOUNT_DEC(tvc);
-			AFS_GUNLOCK();	/* perhaps inline inactive for locking */
-			VOP_INACTIVE(&tvc->v, curproc);
-			AFS_GLOCK();
-		    } else {
-			VOP_UNLOCK(&tvc->v, 0, curproc);
-		    }
-		}
-	    }
 #elif defined(AFS_LINUX22_ENV)
 	    if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0)
 		afs_TryFlushDcacheChildren(tvc);
@@ -838,12 +808,13 @@
 
 	    if (VREFCOUNT(tvc) == 0 && tvc->opens == 0
 		&& (tvc->states & CUnlinkedDel) == 0) {
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_XBSD_ENV)
 		/*
 		 * vgone() reclaims the vnode, which calls afs_FlushVCache(),
 		 * then it puts the vnode on the free list.
 		 * If we don't do this we end up with a cleaned vnode that's
 		 * not on the free list.
+		 * XXX assume FreeBSD is the same for now.
 		 */
 		vgone(AFSTOV(tvc));
 		code = fv_slept = 0;
@@ -907,7 +878,7 @@
     vm_info_ptr = tvc->v.v_vm_info;
 #endif /* AFS_MACH_ENV */
 
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_XBSD_ENV)
     if (tvc->v)
 	panic("afs_NewVCache(): free vcache with vnode attached");
 #endif
@@ -933,6 +904,36 @@
     AFS_GLOCK();
     lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0);
 #endif
+#ifdef AFS_FBSD_ENV
+    {
+	struct vnode *vp;
+
+	AFS_GUNLOCK();
+#ifdef AFS_FBSD50_ENV
+	if (getnewvnode(MOUNT_AFS, afs_globalVFS, afs_vnodeop_p, &vp))
+#else
+	if (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &vp))
+#endif
+	    panic("afs getnewvnode");	/* can't happen */
+	AFS_GLOCK();
+	if (tvc->v != NULL) {
+	    /* I'd like to know if this ever happens...
+	       We don't drop global for the rest of this function,
+	       so if we do lose the race, the other thread should
+	       have found the same vnode and finished initializing
+	       the vcache entry.  Is it conceivable that this vcache
+	       entry could be recycled during this interval?  If so,
+	       then there probably needs to be some sort of additional
+	       mutual exclusion (an Embryonic flag would suffice).
+		-GAW */
+	    printf("afs_NewVCache: lost the race\n");
+	    return (tvc);
+	}
+	tvc->v = vp;
+	tvc->v->v_data = tvc;
+	lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0);
+    }
+#endif
     tvc->parentVnode = 0;
     tvc->mvid = NULL;
     tvc->linkData = NULL;
@@ -957,9 +958,9 @@
     /* Hold it for the LRU (should make count 2) */
     VN_HOLD(AFSTOV(tvc));
 #else /* AFS_OSF_ENV */
-#ifndef AFS_OBSD_ENV
+#if !defined(AFS_XBSD_ENV)
     VREFCOUNT_SET(tvc, 1);	/* us */
-#endif /* AFS_OBSD_ENV */
+#endif /* AFS_XBSD_ENV */
 #endif /* AFS_OSF_ENV */
 #ifdef	AFS_AIX32_ENV
     LOCK_INIT(&tvc->pvmlock, "vcache pvmlock");
@@ -1040,14 +1041,6 @@
     tvc->v.v_freelist.tqe_prev = (struct vnode **)0xdeadb;
     /*tvc->vrefCount++; */
 #endif
-#ifdef AFS_FBSD_ENV
-    lockinit(&tvc->rwlock, PINOD, "vcache rwlock", 0, 0);
-    cache_purge(AFSTOV(tvc));
-    tvc->v.v_data = tvc;
-    tvc->v.v_tag = VT_AFS;
-    tvc->v.v_usecount++;	/* steal an extra ref for now so vfree never happens */
-    /* This extra ref is dealt with above... */
-#endif
     /*
      * The proper value for mvstat (for root fids) is setup by the caller.
      */
@@ -1800,6 +1793,40 @@
     VOP_LOCK(AFSTOV(tvc), LK_EXCLUSIVE | LK_RETRY, curproc);
     uvm_vnp_uncache(AFSTOV(tvc));
     VOP_UNLOCK(AFSTOV(tvc), 0, curproc);
+#endif
+#ifdef AFS_FBSD_ENV
+    /*
+     * XXX - I really don't like this.  Should try to understand better.
+     * It seems that sometimes, when we get called, we already hold the
+     * lock on the vnode (e.g., from afs_getattr via afs_VerifyVCache).
+     * We can't drop the vnode lock, because that could result in a race.
+     * Sometimes, though, we get here and don't hold the vnode lock.
+     * I hate code paths that sometimes hold locks and sometimes don't.
+     * In any event, the dodge we use here is to check whether the vnode
+     * is locked, and if it isn't, then we gain and drop it around the call
+     * to vinvalbuf; otherwise, we leave it alone.
+     */
+    {
+	struct vnode *vp;
+	int iheldthelock;
+
+	vp = AFSTOV(tvc);
+#ifdef AFS_FBSD50_ENV
+	iheldthelock = VOP_ISLOCKED(vp, curthread);
+	if (!iheldthelock)
+	    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+	vinvalbuf(vp, V_SAVE, osi_curcred(), curthread, PINOD, 0);
+	if (!iheldthelock)
+	    VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
+#else
+	iheldthelock = VOP_ISLOCKED(vp, curproc);
+	if (!iheldthelock)
+	    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
+	vinvalbuf(vp, V_SAVE, osi_curcred(), curproc, PINOD, 0);
+	if (!iheldthelock)
+	    VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
+#endif
+    }
 #endif
 
     ObtainWriteLock(&afs_xcbhash, 464);
Index: src/afs/FBSD/osi_file.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_file.c,v
retrieving revision 1.12
diff -u -r1.12 osi_file.c
--- src/afs/FBSD/osi_file.c	9 Sep 2003 21:14:34 -0000	1.12
+++ src/afs/FBSD/osi_file.c	9 Mar 2004 22:08:28 -0000
@@ -28,11 +28,10 @@
 void *
 osi_UFSOpen(afs_int32 ainode)
 {
-    struct inode *ip;
-    register struct osi_file *afile = NULL;
+    struct osi_file *afile;
+    struct vnode *vp;
     extern int cacheDiskType;
-    afs_int32 code = 0;
-    int dummy;
+    afs_int32 code;
 
     AFS_STATCNT(osi_UFSOpen);
     if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
@@ -40,24 +39,24 @@
     afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
     AFS_GUNLOCK();
 #if defined(AFS_FBSD50_ENV)
-    code = VFS_VGET(afs_cacheVfsp, (ino_t) ainode, LK_EXCLUSIVE, &afile->vnode);
+    code = VFS_VGET(afs_cacheVfsp, (ino_t) ainode, LK_EXCLUSIVE, &vp);
 #else
-    code =
-	igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t) ainode, &ip,
-		  &dummy);
+    code = VFS_VGET(afs_cacheVfsp, (ino_t) ainode, &vp);
 #endif
     AFS_GLOCK();
+    if (code == 0 && vp->v_type == VNON)
+	code = ENOENT;
     if (code) {
 	osi_FreeSmallSpace(afile);
 	osi_Panic("UFSOpen: igetinode failed");
     }
 #if defined(AFS_FBSD50_ENV)
-    VOP_UNLOCK(afile->vnode, 0, curthread);
+    VOP_UNLOCK(vp, 0, curthread);
 #else
-    afile->vnode = ITOV(ip);
-    VOP_UNLOCK(afile->vnode, 0, curproc);
+    VOP_UNLOCK(vp, 0, curproc);
 #endif
-    afile->size = VTOI(afile->vnode)->i_size;
+    afile->vnode = vp;
+    afile->size = VTOI(vp)->i_size;
     afile->offset = 0;
     afile->proc = NULL;
     afile->inum = ainode;	/* for hint validity checking */
@@ -73,7 +72,9 @@
     MObtainWriteLock(&afs_xosi, 320);
     AFS_GUNLOCK();
 #if defined(AFS_FBSD50_ENV)
+    vn_lock(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
     code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
+    VOP_UNLOCK(afile->vnode, LK_EXCLUSIVE, curthread);
 #else
     code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc);
 #endif
@@ -104,25 +105,41 @@
 osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
 {
     struct vattr tvattr;
+    struct vnode *vp;
     register afs_int32 code;
-    struct osi_stat tstat;
     AFS_STATCNT(osi_Truncate);
 
-    /* This routine only shrinks files, and most systems
+    MObtainWriteLock(&afs_xosi, 321);
+    vp = afile->vnode;
+    /*
+     * 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);
+    AFS_GUNLOCK();
+#if defined(AFS_FBSD50_ENV)
+    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+    code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
+#else
+    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
+    code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc);
+#endif
+    if (code != 0 || tvattr.va_size <= asize)
+	goto out;
+
     VATTR_NULL(&tvattr);
     tvattr.va_size = asize;
-    AFS_GUNLOCK();
 #if defined(AFS_FBSD50_ENV)
-    code = VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
+    code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curthread);
+#else
+    code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curproc);
+#endif
+
+out:
+#if defined(AFS_FBSD50_ENV)
+    VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
 #else
-    code = VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc);
+    VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
 #endif
     AFS_GLOCK();
     MReleaseWriteLock(&afs_xosi);
Index: src/afs/FBSD/osi_inode.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_inode.c,v
retrieving revision 1.8
diff -u -r1.8 osi_inode.c
--- src/afs/FBSD/osi_inode.c	15 Jul 2003 23:14:19 -0000	1.8
+++ src/afs/FBSD/osi_inode.c	9 Mar 2004 22:08:28 -0000
@@ -53,14 +53,14 @@
 #else
 	simple_lock(&mountlist_slock);
 #endif
-	if (mp = TAILQ_FIRST(&mountlist))
+	if ((mp = TAILQ_FIRST(&mountlist)) != NULL)
 	    do {
 		/*
 		 * XXX Also do the test for MFS
 		 */
 #undef m_data
 #undef m_next
-		if (mp->mnt_stat.f_type == MOUNT_UFS) {
+		if (!strcmp(mp->mnt_stat.f_fstypename, MOUNT_UFS)) {
 		    ump = VFSTOUFS(mp);
 		    if (ump->um_fs == NULL)
 			break;
Index: src/afs/FBSD/osi_machdep.h
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_machdep.h,v
retrieving revision 1.7
diff -u -r1.7 osi_machdep.h
--- src/afs/FBSD/osi_machdep.h	15 Jul 2003 23:14:19 -0000	1.7
+++ src/afs/FBSD/osi_machdep.h	9 Mar 2004 22:08:28 -0000
@@ -21,8 +21,9 @@
 
 #include <sys/lock.h>
 #include <sys/time.h>
-/* #include <kern/sched_prim.h> */
-/* #include <sys/unix_defs.h> */
+#if defined(AFS_FBSD50_ENV)
+#include <sys/mutex.h>
+#endif
 
 extern struct simplelock afs_rxglobal_lock;
 
@@ -42,7 +43,13 @@
 #define iodone biodone
 #endif
 
-#define osi_vnhold(avc,r) do { VN_HOLD((struct vnode *)(avc)); } while (0)
+#define osi_vnhold(avc,r)	vref(AFSTOV(avc))
+#undef vSetVfsp
+#define vSetVfsp(vc, vfsp)	AFSTOV(vc)->v_mount = (vfsp)
+#undef vSetType
+#define vSetType(vc, type)	AFSTOV(vc)->v_type = (type)
+#undef vType
+#define	vType(vc)		AFSTOV(vc)->v_type
 
 #undef gop_lookupname
 #define gop_lookupname osi_lookupname
@@ -52,7 +59,12 @@
 #define afs_strcat(s1, s2)	strcat((s1), (s2))
 
 #ifdef KERNEL
-extern struct lock afs_global_lock;
+
+#undef afs_osi_Alloc_NoSleep
+#define afs_osi_Alloc_NoSleep(size) osi_fbsd_alloc((size), 0)
+
+#define VN_RELE(vp)		vrele(vp)
+#define VN_HOLD(vp)		VREF(vp)
 
 #if defined(AFS_FBSD50_ENV)
 #define VT_AFS		"afs"
@@ -64,26 +76,16 @@
 #define simple_unlock(x) mtx_unlock(x)
 #define        gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
   vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(cred),(aresid), curthread)
-extern struct thread *afs_global_owner;
-#define AFS_GLOCK() \
-    do { \
-        osi_Assert(curthread); \
- 	lockmgr(&afs_global_lock, LK_EXCLUSIVE, 0, curthread); \
-        osi_Assert(afs_global_owner == 0); \
-   	afs_global_owner = curthread; \
-    } while (0)
-#define AFS_GUNLOCK() \
-    do { \
-        osi_Assert(curthread); \
- 	osi_Assert(afs_global_owner == curthread); \
-        afs_global_owner = 0; \
-        lockmgr(&afs_global_lock, LK_RELEASE, 0, curthread); \
-    } while(0)
-#define ISAFS_GLOCK() (afs_global_owner == curthread && curthread)
+extern struct mtx afs_global_mtx;
+#define AFS_GLOCK() mtx_lock(&afs_global_mtx)
+#define AFS_GUNLOCK() mtx_unlock(&afs_global_mtx)
+#define ISAFS_GLOCK() (mtx_owned(&afs_global_mtx))
 
 #else /* FBSD50 */
+extern struct lock afs_global_lock;
 
 #define osi_curcred()	(curproc->p_cred->pc_ucred)
+#define afs_suser()	(!suser(curproc))
 #define getpid()	curproc
 #define        gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
   vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(aresid), curproc)
Index: src/afs/FBSD/osi_misc.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_misc.c,v
retrieving revision 1.8
diff -u -r1.8 osi_misc.c
--- src/afs/FBSD/osi_misc.c	15 Jul 2003 23:14:19 -0000	1.8
+++ src/afs/FBSD/osi_misc.c	9 Mar 2004 22:08:28 -0000
@@ -30,30 +30,19 @@
 #define curproc curthread
 #endif
 
-#ifndef AFS_FBSD50_ENV
-/*
- * afs_suser() returns true if the caller is superuser, false otherwise.
- *
- * Note that it must NOT set errno.
- */
-
-afs_suser()
-{
-    int error;
-
-    if (suser(curproc) == 0) {
-	return (1);
-    }
-    return (0);
-}
-#endif
-
 int
 osi_lookupname(char *aname, enum uio_seg seg, int followlink,
 	       struct vnode **dirvpp, struct vnode **vpp)
 {
     struct nameidata n;
-    int flags, error;
+    int flags, error, wasowned;
+
+#ifdef AFS_FBSD50_ENV
+    wasowned = mtx_owned(&afs_global_mtx);
+    if (wasowned)
+	mtx_unlock(&afs_global_mtx);
+#endif
+
     flags = 0;
     flags = LOCKLEAF;
     if (followlink)
@@ -62,8 +51,13 @@
 	flags |= NOFOLLOW;
     /*   if (dirvpp) flags|=WANTPARENT; *//* XXX LOCKPARENT? */
     NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
-    if (error = namei(&n))
+    if ((error = namei(&n)) != 0) {
+#ifdef AFS_FBSD50_ENV
+	if (wasowned)
+	    mtx_lock(&afs_global_mtx);
+#endif
 	return error;
+    }
     *vpp = n.ni_vp;
 /*
    if (dirvpp)
@@ -72,6 +66,10 @@
     /* should we do this? */
     VOP_UNLOCK(n.ni_vp, 0, curproc);
     NDFREE(&n, NDF_ONLY_PNBUF);
+#ifdef AFS_FBSD50_ENV
+    if (wasowned)
+	mtx_lock(&afs_global_mtx);
+#endif
     return 0;
 }
 
@@ -102,4 +100,75 @@
     resettodr();
     AFS_GLOCK();
 #endif
+}
+
+/*
+ * Replace all of the bogus special-purpose memory allocators...
+ */
+void *
+osi_fbsd_alloc(size_t size, int dropglobal)
+{
+	void *rv;
+#ifdef AFS_FBSD50_ENV
+	int wasowned;
+
+	if (dropglobal) {
+		wasowned = mtx_owned(&afs_global_mtx);
+		if (wasowned)
+			mtx_unlock(&afs_global_mtx);
+		rv = malloc(size, M_AFS, M_WAITOK);
+		if (wasowned)
+			mtx_lock(&afs_global_mtx);
+	} else
+#endif
+		rv = malloc(size, M_AFS, M_NOWAIT);
+
+	return (rv);
+}
+
+void
+osi_fbsd_free(void *p)
+{
+
+	free(p, M_AFS);
+}
+
+void
+osi_AllocMoreSSpace(afs_int32 preallocs)
+{
+	;
+}
+
+void
+osi_FreeLargeSpace(void *p)
+{
+	osi_fbsd_free(p);
+}
+
+void
+osi_FreeSmallSpace(void *p)
+{
+	osi_fbsd_free(p);
+}
+
+void *
+osi_AllocLargeSpace(size_t size)
+{
+	AFS_ASSERT_GLOCK();
+	AFS_STATCNT(osi_AllocLargeSpace);
+	return (osi_fbsd_alloc(size, 1));
+}
+
+void *
+osi_AllocSmallSpace(size_t size)
+{
+	AFS_ASSERT_GLOCK();
+	AFS_STATCNT(osi_AllocSmallSpace);
+	return (osi_fbsd_alloc(size, 1));
+}
+
+void
+shutdown_osinet(void)
+{
+	;
 }
Index: src/afs/FBSD/osi_module.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_module.c,v
retrieving revision 1.4
diff -u -r1.4 osi_module.c
--- src/afs/FBSD/osi_module.c	15 Jul 2003 23:14:20 -0000	1.4
+++ src/afs/FBSD/osi_module.c	9 Mar 2004 22:08:28 -0000
@@ -60,8 +60,10 @@
 	vfs_register(&afs_vfsconf);	/* doesn't fail */
 	vfs_add_vnodeops(&afs_vnodeop_opv_desc);
 	osi_Init();
+#ifndef AFS_FBSD50_ENV
 	sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
 	sysent[SYS_ioctl].sy_call = afs_xioctl;
+#endif
 	old_handler = sysent[AFS_SYSCALL].sy_call;
 	sysent[AFS_SYSCALL].sy_call = afs3_syscall;
 	sysent[AFS_SYSCALL].sy_narg = 5;
Index: src/afs/FBSD/osi_prototypes.h
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_prototypes.h,v
retrieving revision 1.4
diff -u -r1.4 osi_prototypes.h
--- src/afs/FBSD/osi_prototypes.h	15 Jul 2003 23:14:20 -0000	1.4
+++ src/afs/FBSD/osi_prototypes.h	9 Mar 2004 22:08:28 -0000
@@ -20,8 +20,14 @@
 /* osi_misc.c */
 extern int osi_lookupname(char *aname, enum uio_seg seg, int followlink,
 			  struct vnode **dirvpp, struct vnode **vpp);
+extern void *osi_fbsd_alloc(size_t size, int dropglobal);
+extern void osi_fbsd_free(void *p);
 
 /* osi_vfsops.c */
+#ifdef AFS_FBSD50_ENV
+extern int afs_statfs(struct mount *mp, struct statfs *abp, struct thread *th);
+#else
 extern int afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p);
+#endif
 
 #endif /* _OSI_PROTO_H_ */
Index: src/afs/FBSD/osi_sleep.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_sleep.c,v
retrieving revision 1.10
diff -u -r1.10 osi_sleep.c
--- src/afs/FBSD/osi_sleep.c	15 Jul 2003 23:14:20 -0000	1.10
+++ src/afs/FBSD/osi_sleep.c	9 Mar 2004 22:08:28 -0000
@@ -18,32 +18,52 @@
 #include "afsincludes.h"	/* Afs-based standard headers */
 #include "afs/afs_stats.h"	/* afs statistics */
 
-
-
+#ifndef AFS_FBSD50_ENV
 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
 static char waitV;
+#endif
 
 
 void
 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
 {
     AFS_STATCNT(osi_InitWaitHandle);
-    achandle->proc = (caddr_t) 0;
+#ifdef AFS_FBSD50_ENV
+    cv_init(&achandle->wh_condvar, "afscondvar");
+    achandle->wh_inited = 1;
+#else
+    achandle->proc = NULL;
+#endif
 }
 
 /* cancel osi_Wait */
+/* XXX
+ * I can't tell -- is this supposed to be cv_signal() or cv_waitq_remove()?
+ * Or perhaps cv_broadcast()?
+ * Assuming cv_signal() is the desired meaning.  -GAW
+ */
 void
 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
 {
+#ifndef AFS_FBSD50_ENV
     caddr_t proc;
+#endif
 
     AFS_STATCNT(osi_CancelWait);
+
+#ifdef AFS_FBSD50_ENV
+    /* XXX should not be necessary */
+    if (!achandle->wh_inited)
+	return;
+    AFS_ASSERT_GLOCK();
+    cv_signal(&achandle->wh_condvar);
+#else
     proc = achandle->proc;
     if (proc == 0)
 	return;
-    achandle->proc = (caddr_t) 0;	/* so dude can figure out he was signalled */
+    achandle->proc = NULL;	/* so dude can figure out he was signalled */
     afs_osi_Wakeup(&waitV);
+#endif
 }
 
 /* afs_osi_Wait
@@ -54,31 +74,56 @@
 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
 {
     int code;
+#ifdef AFS_FBSD50_ENV
+    struct timeval tv;
+    int ticks;
+#else
     afs_int32 endTime;
+#endif
 
     AFS_STATCNT(osi_Wait);
+#ifdef AFS_FBSD50_ENV
+    tv.tv_sec = ams / 1000;
+    tv.tv_usec = (ams % 1000) * 1000;
+    ticks = tvtohz(&tv);
+
+    AFS_ASSERT_GLOCK();
+    if (ahandle == NULL) {
+	/* This is nasty and evil and rude. */
+	code = msleep(&tv, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS),
+	    "afswait", ticks);
+    } else {
+	if (!ahandle->wh_inited)
+	    afs_osi_InitWaitHandle(ahandle);	/* XXX should not be needed */
+
+	if (aintok)
+	    code = cv_timedwait_sig(&ahandle->wh_condvar, &afs_global_mtx,
+		ticks);
+	else
+	    code = cv_timedwait(&ahandle->wh_condvar, &afs_global_mtx, ticks);
+    }
+#else
     endTime = osi_Time() + (ams / 1000);
     if (ahandle)
 	ahandle->proc = (caddr_t) curproc;
     do {
 	AFS_ASSERT_GLOCK();
-	code = 0;
 	code = osi_TimedSleep(&waitV, ams, aintok);
-
 	if (code)
 	    break;		/* if something happened, quit now */
 	/* if we we're cancelled, quit now */
-	if (ahandle && (ahandle->proc == (caddr_t) 0)) {
+	if (ahandle && (ahandle->proc == NULL)) {
 	    /* we've been signalled */
 	    break;
 	}
     } while (osi_Time() < endTime);
+#endif
     return code;
 }
 
-
-
-
+/*
+ * All this gluck should probably also be replaced with CVs.
+ */
 typedef struct afs_event {
     struct afs_event *next;	/* next in hash chain */
     char *event;		/* lwp event: an address */
@@ -140,9 +185,13 @@
     seq = evp->seq;
     while (seq == evp->seq) {
 	AFS_ASSERT_GLOCK();
+#ifdef AFS_FBSD50_ENV
+	msleep(event, &afs_global_mtx, PVFS, "afsslp", 0);
+#else
 	AFS_GUNLOCK();
 	tsleep(event, PVFS, "afs_osi_Sleep", 0);
 	AFS_GLOCK();
+#endif
     }
     relevent(evp);
 }
@@ -154,6 +203,7 @@
     return 0;
 }
 
+#ifndef AFS_FBSD50_ENV
 /* osi_TimedSleep
  * 
  * Arguments:
@@ -188,7 +238,7 @@
     relevent(evp);
     return code;
 }
-
+#endif /* not AFS_FBSD50_ENV */
 
 int
 afs_osi_Wakeup(void *event)
Index: src/afs/FBSD/osi_vfsops.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_vfsops.c,v
retrieving revision 1.14
diff -u -r1.14 osi_vfsops.c
--- src/afs/FBSD/osi_vfsops.c	15 Jul 2003 23:14:20 -0000	1.14
+++ src/afs/FBSD/osi_vfsops.c	9 Mar 2004 22:08:28 -0000
@@ -16,48 +16,42 @@
 struct mount *afs_globalVFS = 0;
 int afs_pbuf_freecnt = -1;
 
+#ifdef AFS_FBSD50_ENV
+#define	THREAD_OR_PROC struct thread *p
+#else
+#define	THREAD_OR_PROC struct proc *p
+#endif
+
 int
-afs_quotactl()
+afs_quotactl(struct mount *mp, int c, uid_t u, caddr_t data, THREAD_OR_PROC)
 {
     return EOPNOTSUPP;
 }
 
 int
-afs_fhtovp(mp, fhp, vpp)
-     struct mount *mp;
-     struct fid *fhp;
-     struct vnode **vpp;
+afs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
 {
 
     return (EINVAL);
 }
 
 int
-afs_vptofh(vp, fhp)
-     struct vnode *vp;
-     struct fid *fhp;
+afs_vptofh(struct vnode *vp, struct fid *fhp)
 {
 
     return (EINVAL);
 }
 
 int
-afs_start(mp, flags, p)
-     struct mount *mp;
-     int flags;
-     struct proc *p;
+afs_start(struct mount *mp, int flags, THREAD_OR_PROC)
 {
     afs_pbuf_freecnt = nswbuf / 2 + 1;
     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;
+afs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
+	THREAD_OR_PROC)
 {
     /* ndp contains the mounted-from device.  Just ignore it.
      * we also don't care about our proc struct. */
@@ -91,12 +85,16 @@
 }
 
 int
-afs_unmount(mp, flags, p)
-     struct mount *mp;
-     int flags;
-     struct proc *p;
+afs_unmount(struct mount *mp, int flags, THREAD_OR_PROC)
 {
 
+    /*
+     * Release any remaining vnodes on this mount point.
+     * The `1' means that we hold one extra reference on
+     * the root vnode (this is just a guess right now).
+     * This has to be done outside the global lock.
+     */
+    vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
     AFS_GLOCK();
     AFS_STATCNT(afs_unmount);
     afs_globalVFS = 0;
@@ -114,24 +112,27 @@
     register struct vcache *tvp = 0;
 #ifdef AFS_FBSD50_ENV
     struct thread *td = curthread;
-    struct ucred cr = *td->td_ucred;
+    struct ucred *cr = td->td_ucred;
 #else
     struct proc *p = curproc;
-    struct ucred cr = *p->p_cred->pc_ucred;
+    struct ucred *cr = p->p_cred->pc_ucred;
 #endif
 
     AFS_GLOCK();
     AFS_STATCNT(afs_root);
+    crhold(cr);
     if (afs_globalVp && (afs_globalVp->states & CStatd)) {
 	tvp = afs_globalVp;
 	error = 0;
     } else {
+tryagain:
 	if (afs_globalVp) {
 	    afs_PutVCache(afs_globalVp);
+	    /* vrele() needed here or not? */
 	    afs_globalVp = NULL;
 	}
 
-	if (!(error = afs_InitReq(&treq, &cr)) && !(error = afs_CheckInit())) {
+	if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
 	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
 	    /* we really want this to stay around */
 	    if (tvp)
@@ -141,57 +142,45 @@
 	}
     }
     if (tvp) {
-	osi_vnhold(tvp, 0);
+	struct vnode *vp = AFSTOV(tvp);
+
+#ifdef AFS_FBSD50_ENV
+	ASSERT_VI_UNLOCKED(vp, "afs_root");
+#endif
 	AFS_GUNLOCK();
+	/*
+	 * I'm uncomfortable about this.  Shouldn't this happen at a
+	 * higher level, and shouldn't we busy the top-level directory
+	 * to prevent recycling?
+	 */
 #ifdef AFS_FBSD50_ENV
-	vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, td);
+	error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vp->v_vflag |= VV_ROOT;
 #else
-	vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
+	error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p);
+	vp->v_flag |= VROOT;
 #endif
 	AFS_GLOCK();
+	if (error != 0)
+		goto tryagain;
+
 	afs_globalVFS = mp;
-	*vpp = AFSTOV(tvp);
-	tvp->v.v_flag |= VROOT;
+	*vpp = vp;
     }
 
     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
 	       ICL_TYPE_INT32, error);
     AFS_GUNLOCK();
+    crfree(cr);
     return error;
 }
 
 int
-afs_vget(mp, lfl, vp)
-     struct mount *mp;
-     struct vnode *vp;
-     int lfl;
-{
-#ifdef AFS_FBSD50_ENV
-    return EOPNOTSUPP;
-#else
-    int error;
-
-    printf("vget called. help!\n");
-    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;
-#endif
-}
-
-int
-afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p)
+afs_statfs(struct mount *mp, struct statfs *abp, THREAD_OR_PROC)
 {
     AFS_GLOCK();
     AFS_STATCNT(afs_statfs);
 
-#if 0
-    abp->f_type = MOUNT_AFS;
-#endif
     abp->f_bsize = mp->vfs_bsize;
     abp->f_iosize = mp->vfs_bsize;
 
@@ -217,23 +206,12 @@
 }
 
 int
-afs_sync(mp, waitfor, cred, p)
-     struct mount *mp;
-     int waitfor;
-     struct ucred *cred;
-     struct prioc *p;
+afs_sync(struct mount *mp, int waitfor, struct ucred *cred, THREAD_OR_PROC)
 {
     return 0;
 }
 
 int
-afs_sysctl()
-{
-    return EOPNOTSUPP;
-}
-
-
-int
 afs_init(struct vfsconf *vfc)
 {
     return 0;
@@ -247,7 +225,7 @@
     afs_quotactl,
     afs_statfs,
     afs_sync,
-    afs_vget,
+    NULL,
     afs_fhtovp,
 #ifdef AFS_FBSD50_ENV
     vfs_stdcheckexp,
@@ -257,5 +235,4 @@
 #ifdef AFS_FBSD50_ENV
     vfs_stduninit,
 #endif
-    afs_sysctl
 };
Index: src/afs/FBSD/osi_vm.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_vm.c,v
retrieving revision 1.10
diff -u -r1.10 osi_vm.c
--- src/afs/FBSD/osi_vm.c	15 Jul 2003 23:14:20 -0000	1.10
+++ src/afs/FBSD/osi_vm.c	9 Mar 2004 22:08:28 -0000
@@ -32,6 +32,33 @@
 #include <limits.h>
 #include <float.h>
 
+/*
+ * FreeBSD implementation notes:
+ * Most of these operations require us to frob vm_objects.  Most
+ * functions require that the object be locked (with VM_OBJECT_LOCK)
+ * on entry and leave it locked on exit.  In order to get the
+ * vm_object itself we call VOP_GETVOBJECT on the vnode; the
+ * locking protocol requires that we do so with the heavy vnode lock
+ * held and the vnode interlock unlocked, and it returns the same
+ * way.
+ *
+ * The locking protocol for vnodes is defined in
+ * kern/vnode_if.src and sys/vnode.h; the locking is still a work in 
+ * progress, so some fields are (as of 5.1) still protected by Giant
+ * rather than an explicit lock.
+ */
+
+#ifdef AFS_FBSD50_ENV
+#define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curthread)
+#define unlock_vnode(v)	VOP_UNLOCK((v), 0, curthread)
+#else
+#define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curproc)
+#define unlock_vnode(v)	VOP_UNLOCK((v), 0, curproc)
+/* need splvm() protection? */
+#define	VM_OBJECT_LOCK(o)
+#define VM_OBJECT_UNLOCK(o)
+#endif
+
 /* Try to discard pages, in order to recycle a vcache entry.
  *
  * We also make some sanity checks:  ref count, open count, held locks.
@@ -47,6 +74,8 @@
  * therefore obsolescent.
  *
  * OSF/1 Locking:  VN_LOCK has been called.
+ * XXX - should FreeBSD have done this, too?  Certainly looks like it.
+ * Maybe better to just call vnode_pager_setsize()?
  */
 int
 osi_VM_FlushVCache(struct vcache *avc, int *slept)
@@ -65,8 +94,9 @@
 
     AFS_GUNLOCK();
     vp = AFSTOV(avc);
-    simple_lock(&vp->v_interlock);
+    lock_vnode(vp);
     if (VOP_GETVOBJECT(vp, &obj) == 0) {
+	VM_OBJECT_LOCK(obj);
 	vm_object_page_remove(obj, 0, 0, FALSE);
 #if 0
 	if (obj->ref_count == 0) {
@@ -76,8 +106,9 @@
 	    SetAfsVnode(vp);
 	}
 #endif
+	VM_OBJECT_UNLOCK(obj);
     }
-    simple_unlock(&vp->v_interlock);
+    unlock_vnode(vp);
     AFS_GLOCK();
 
     return 0;
@@ -99,25 +130,37 @@
     AFS_GUNLOCK();
     tries = 5;
     vp = AFSTOV(avc);
+
+    /*
+     * I don't understand this.  Why not just call vm_object_page_clean()
+     * and be done with it?  I particularly don't understand why we're calling
+     * vget() here.  Is there some reason to believe that the vnode might
+     * be being recycled at this point?  I don't think there's any need for
+     * this loop, either -- if we keep the vnode locked all the time,
+     * that and the object lock will prevent any new pages from appearing.
+     * The loop is what causes the race condition.  -GAW
+     */
     do {
 	anyio = 0;
-	simple_lock(&vp->v_interlock);
+	lock_vnode(vp);
 	if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
+	    /* XXX - obj locking? */
+	    unlock_vnode(vp);
 #ifdef AFS_FBSD50_ENV
-	    if (!vget(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY, curthread)) {
+	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
 #else
-	    if (!vget
-		(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ,
-		 curproc)) {
+	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
 #endif
 		if (VOP_GETVOBJECT(vp, &obj) == 0) {
+		    VM_OBJECT_LOCK(obj);
 		    vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
+		    VM_OBJECT_UNLOCK(obj);
 		    anyio = 1;
 		}
 		vput(vp);
 	    }
 	} else
-	    simple_unlock(&vp->v_interlock);
+	    unlock_vnode(vp);
     } while (anyio && (--tries > 0));
     AFS_GLOCK();
     ObtainWriteLock(&avc->lock, 94);
@@ -145,29 +188,41 @@
     vp = AFSTOV(avc);
     do {
 	anyio = 0;
-	simple_lock(&vp->v_interlock);
+	lock_vnode(vp);
+	/* See the comments above. */
 	if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
+	    /* XXX - obj locking */
+	    unlock_vnode(vp);
 #ifdef AFS_FBSD50_ENV
-	    if (!vget(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY, curthread)) {
+	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
 #else
-	    if (!vget
-		(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ,
-		 curproc)) {
+	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
 #endif
 		if (VOP_GETVOBJECT(vp, &obj) == 0) {
+		    VM_OBJECT_LOCK(obj);
+		    /*
+		     * Do we really want OBJPC_SYNC?  OBJPC_INVAL would be
+		     * faster, if invalidation is really what we are being
+		     * asked to do.  (It would make more sense, too, since
+		     * otherwise this function is practically identical to
+		     * osi_VM_StoreAllSegments().)  -GAW
+		     */
 		    vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
+		    VM_OBJECT_UNLOCK(obj);
 		    anyio = 1;
 		}
 		vput(vp);
 	    }
 	} else
-	    simple_unlock(&vp->v_interlock);
+	    unlock_vnode(vp);
     } while (anyio && (--tries > 0));
-    simple_lock(&vp->v_interlock);
+    lock_vnode(vp);
     if (VOP_GETVOBJECT(vp, &obj) == 0) {
+	VM_OBJECT_LOCK(obj);
 	vm_object_page_remove(obj, 0, 0, FALSE);
+	VM_OBJECT_UNLOCK(obj);
     }
-    simple_unlock(&vp->v_interlock);
+    unlock_vnode(vp);
     /*vinvalbuf(AFSTOV(avc),0, NOCRED, curproc, 0,0); */
     AFS_GLOCK();
     ObtainWriteLock(&avc->lock, 59);
@@ -184,11 +239,12 @@
     struct vm_object *obj;
 
     vp = AFSTOV(avc);
-    simple_lock(&vp->v_interlock);
+    ASSERT_VOP_LOCKED(vp, __func__);
     if (VOP_GETVOBJECT(vp, &obj) == 0) {
+	VM_OBJECT_LOCK(obj);
 	vm_object_page_remove(obj, 0, 0, FALSE);
+	VM_OBJECT_UNLOCK(obj);
     }
-    simple_unlock(&vp->v_interlock);
     /*vinvalbuf(AFSTOV(avc),0, NOCRED, curproc, 0,0); */
 }
 
Index: src/afs/FBSD/osi_vnodeops.c
===================================================================
RCS file: /cvs/openafs/src/afs/FBSD/osi_vnodeops.c,v
retrieving revision 1.16
diff -u -r1.16 osi_vnodeops.c
--- src/afs/FBSD/osi_vnodeops.c	27 Aug 2003 21:43:17 -0000	1.16
+++ src/afs/FBSD/osi_vnodeops.c	9 Mar 2004 22:08:28 -0000
@@ -1,3 +1,49 @@
+/*
+ * A large chunk of this file appears to be copied directly from
+ * sys/nfsclient/nfs_bio.c, which has the following license:
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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.
+ *
+ *	@(#)nfs_bio.c	8.9 (Berkeley) 3/30/95
+ */
+/*
+ * Pursuant to a statement of U.C. Berkeley dated 1999-07-22, this license
+ * is amended to drop clause (3) above.
+ */
+
 #include <afsconfig.h>
 #include <afs/param.h>
 
@@ -9,6 +55,7 @@
 #include <afs/afs_stats.h>	/* statistics */
 #include <sys/malloc.h>
 #include <sys/namei.h>
+#include <sys/unistd.h>
 #ifndef AFS_FBSD50_ENV
 #include <vm/vm_zone.h>
 #endif
@@ -31,6 +78,7 @@
 int afs_vop_getpages(struct vop_getpages_args *);
 int afs_vop_putpages(struct vop_putpages_args *);
 int afs_vop_ioctl(struct vop_ioctl_args *);
+static int afs_vop_pathconf(struct vop_pathconf_args *);
 int afs_vop_poll(struct vop_poll_args *);
 #ifndef AFS_FBSD50_ENV
 int afs_vop_mmap(struct vop_mmap_args *);
@@ -59,7 +107,7 @@
 /* Global vfs data structures for AFS. */
 vop_t **afs_vnodeop_p;
 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
-    {&vop_default_desc, (vop_t *) vop_eopnotsupp},
+    {&vop_default_desc, (vop_t *) vop_defaultop},
     {&vop_access_desc, (vop_t *) afs_vop_access},	/* access */
     {&vop_advlock_desc, (vop_t *) afs_vop_advlock},	/* advlock */
     {&vop_bmap_desc, (vop_t *) afs_vop_bmap},	/* bmap */
@@ -76,10 +124,8 @@
     {&vop_getvobject_desc, (vop_t *) vop_stdgetvobject},
     {&vop_putpages_desc, (vop_t *) afs_vop_putpages},	/* write */
     {&vop_inactive_desc, (vop_t *) afs_vop_inactive},	/* inactive */
-    {&vop_islocked_desc, (vop_t *) afs_vop_islocked},	/* islocked */
     {&vop_lease_desc, (vop_t *) vop_null},
     {&vop_link_desc, (vop_t *) afs_vop_link},	/* link */
-    {&vop_lock_desc, (vop_t *) afs_vop_lock},	/* lock */
     {&vop_lookup_desc, (vop_t *) afs_vop_lookup},	/* lookup */
     {&vop_mkdir_desc, (vop_t *) afs_vop_mkdir},	/* mkdir */
     {&vop_mknod_desc, (vop_t *) afs_vop_mknod},	/* mknod */
@@ -87,6 +133,7 @@
     {&vop_mmap_desc, (vop_t *) afs_vop_mmap},	/* mmap */
 #endif
     {&vop_open_desc, (vop_t *) afs_vop_open},	/* open */
+    {&vop_pathconf_desc, (vop_t *) afs_vop_pathconf},	/* pathconf */
     {&vop_poll_desc, (vop_t *) afs_vop_poll},	/* select */
     {&vop_print_desc, (vop_t *) afs_vop_print},	/* print */
     {&vop_read_desc, (vop_t *) afs_vop_read},	/* read */
@@ -99,7 +146,6 @@
     {&vop_setattr_desc, (vop_t *) afs_vop_setattr},	/* setattr */
     {&vop_strategy_desc, (vop_t *) afs_vop_strategy},	/* strategy */
     {&vop_symlink_desc, (vop_t *) afs_vop_symlink},	/* symlink */
-    {&vop_unlock_desc, (vop_t *) afs_vop_unlock},	/* unlock */
     {&vop_write_desc, (vop_t *) afs_vop_write},	/* write */
     {&vop_ioctl_desc, (vop_t *) afs_vop_ioctl},	/* XXX ioctl */
     /*{ &vop_seek_desc, afs_vop_seek }, *//* seek */
@@ -122,7 +168,98 @@
 #define a_p a_td
 #endif
 
+/*
+ * Mosty copied from sys/ufs/ufs/ufs_vnops.c:ufs_pathconf().
+ * We should know the correct answers to these questions with
+ * respect to the AFS protocol (which may differ from the UFS
+ * values) but for the moment this will do.
+ */
+static int
+afs_vop_pathconf(struct vop_pathconf_args *ap)
+{
+	int error;
 
+	error = 0;
+	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_PIPE_BUF:
+		*ap->a_retval = PIPE_BUF;
+		break;
+	case _PC_CHOWN_RESTRICTED:
+		*ap->a_retval = 1;
+		break;
+	case _PC_NO_TRUNC:
+		*ap->a_retval = 1;
+		break;
+#ifdef _PC_ACL_EXTENDED
+	case _PC_ACL_EXTENDED:
+		*ap->a_retval = 0;
+		break;
+	case _PC_ACL_PATH_MAX:
+		*ap->a_retval = 3;
+		break;
+#endif
+#ifdef _PC_MAC_PRESENT
+	case _PC_MAC_PRESENT:
+		*ap->a_retval = 0;
+		break;
+#endif
+#ifdef _PC_ASYNC_IO
+	case _PC_ASYNC_IO:
+		/* _PC_ASYNC_IO should have been handled by upper layers. */
+		KASSERT(0, ("_PC_ASYNC_IO should not get here"));
+		error = EINVAL;
+		break;
+	case _PC_PRIO_IO:
+		*ap->a_retval = 0;
+		break;
+	case _PC_SYNC_IO:
+		*ap->a_retval = 0;
+		break;
+#endif
+#ifdef _PC_ALLOC_SIZE_MIN
+	case _PC_ALLOC_SIZE_MIN:
+		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
+		break;
+#endif
+#ifdef _PC_FILESIZEBITS
+	case _PC_FILESIZEBITS:
+		*ap->a_retval = 32; /* XXX */
+		break;
+#endif
+#ifdef _PC_REC_INCR_XFER_SIZE
+	case _PC_REC_INCR_XFER_SIZE:
+		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
+		break;
+	case _PC_REC_MAX_XFER_SIZE:
+		*ap->a_retval = -1; /* means ``unlimited'' */
+		break;
+	case _PC_REC_MIN_XFER_SIZE:
+		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
+		break;
+	case _PC_REC_XFER_ALIGN:
+		*ap->a_retval = PAGE_SIZE;
+		break;
+#endif
+#ifdef _PC_SYMLINK_MAX
+	case _PC_SYMLINK_MAX:
+		*ap->a_retval = MAXPATHLEN;
+		break;
+#endif
+	default:
+		error = EINVAL;
+		break;
+	}
+	return (error);
+}
 
 int
 afs_vop_lookup(ap)
@@ -397,15 +534,16 @@
     return code;
 }
 
+/* struct vop_getpages_args {
+ *	struct vnode *a_vp;
+ *	vm_page_t *a_m;
+ *	int a_count;
+ *	int a_reqpage;
+ *	vm_oofset_t a_offset;
+ * };
+ */
 int
-afs_vop_getpages(ap)
-     struct vop_getpages_args	/* {
-				 * struct vnode *a_vp;
-				 * vm_page_t *a_m;
-				 * int a_count;
-				 * int a_reqpage;
-				 * vm_oofset_t a_offset;
-				 * } */ *ap;
+afs_vop_getpages(struct vop_getpages_args *ap)
 {
     int code;
     int i, nextoff, size, toff, npages;
@@ -413,9 +551,16 @@
     struct iovec iov;
     struct buf *bp;
     vm_offset_t kva;
-    struct vcache *avc = VTOAFS(ap->a_vp);
+    vm_object_t object;
+    struct vnode *vp;
+    struct vcache *avc;
 
-    if (avc->v.v_object == NULL) {
+#ifdef AFS_FBSD50_ENV
+    GIANT_REQUIRED;
+#endif
+    vp = ap->a_vp;
+    avc = VTOAFS(vp);
+    if ((object = vp->v_object) == NULL) {
 	printf("afs_getpages: called with non-merged cache vnode??\n");
 	return VM_PAGER_ERROR;
     }
@@ -429,6 +574,10 @@
     {
 	vm_page_t m = ap->a_m[ap->a_reqpage];
 
+#ifdef AFS_FBSD50_ENV
+	VM_OBJECT_LOCK(object);
+	vm_page_lock_queues();
+#endif
 	if (m->valid != 0) {
 	    /* handled by vm_fault now        */
 	    /* vm_page_zero_invalid(m, TRUE); */
@@ -436,12 +585,26 @@
 		if (i != ap->a_reqpage)
 		    vm_page_free(ap->a_m[i]);
 	    }
+#ifdef AFS_FBSD50_ENV
+	    vm_page_unlock_queues();
+	    VM_OBJECT_UNLOCK(object);
+#endif
 	    return (0);
 	}
+#ifdef AFS_FBSD50_ENV
+	vm_page_unlock_queues();
+	VM_OBJECT_UNLOCK(object);
+#endif
     }
     bp = getpbuf(&afs_pbuf_freecnt);
+
     kva = (vm_offset_t) bp->b_data;
     pmap_qenter(kva, ap->a_m, npages);
+#ifdef AFS_FBSD50_ENV
+    cnt.v_vnodein++;
+    cnt.v_vnodepgsin += npages;
+#endif
+
     iov.iov_base = (caddr_t) kva;
     iov.iov_len = ap->a_count;
     uio.uio_iov = &iov;
@@ -455,6 +618,7 @@
 #else
     uio.uio_procp = curproc;
 #endif
+
     AFS_GLOCK();
     afs_BozonLock(&avc->pvnLock, avc);
     osi_FlushPages(avc, osi_curcred());	/* hold bozon lock, but not basic vnode lock */
@@ -464,14 +628,28 @@
     pmap_qremove(kva, npages);
 
     relpbuf(bp, &afs_pbuf_freecnt);
+
     if (code && (uio.uio_resid == ap->a_count)) {
+#ifdef AFS_FBSD50_ENV
+	VM_OBJECT_LOCK(object);
+	vm_page_lock_queues();
+#endif
 	for (i = 0; i < npages; ++i) {
 	    if (i != ap->a_reqpage)
 		vm_page_free(ap->a_m[i]);
 	}
+#ifdef AFS_FBSD50_ENV
+	vm_page_unlock_queues();
+	VM_OBJECT_UNLOCK(object);
+#endif
 	return VM_PAGER_ERROR;
     }
+
     size = ap->a_count - uio.uio_resid;
+#ifdef AFS_FBSD50_ENV
+    VM_OBJECT_LOCK(object);
+    vm_page_lock_queues();
+#endif
     for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
 	vm_page_t m;
 	nextoff = toff + PAGE_SIZE;
@@ -519,6 +697,10 @@
 	    }
 	}
     }
+#ifdef AFS_FBSD50_ENV
+    vm_page_unlock_queues();
+    VM_OBJECT_UNLOCK(object);
+#endif
     return 0;
 }
 
@@ -543,16 +725,22 @@
     return code;
 }
 
+/*-
+ * struct vop_putpages_args {
+ *	struct vnode *a_vp;
+ *	vm_page_t *a_m;
+ *	int a_count;
+ *	int a_sync;
+ *	int *a_rtvals;
+ *	vm_oofset_t a_offset;
+ * };
+ */
+/*
+ * All of the pages passed to us in ap->a_m[] are already marked as busy,
+ * so there is no additional locking required to set their flags.  -GAW
+ */
 int
-afs_vop_putpages(ap)
-     struct vop_putpages_args	/* {
-				 * struct vnode *a_vp;
-				 * vm_page_t *a_m;
-				 * int a_count;
-				 * int a_sync;
-				 * int *a_rtvals;
-				 * vm_oofset_t a_offset;
-				 * } */ *ap;
+afs_vop_putpages(struct vop_putpages_args *ap)
 {
     int code;
     int i, size, npages, sync;
@@ -560,22 +748,36 @@
     struct iovec iov;
     struct buf *bp;
     vm_offset_t kva;
-    struct vcache *avc = VTOAFS(ap->a_vp);
+    struct vnode *vp;
+    struct vcache *avc;
 
-    if (avc->v.v_object == NULL) {
+#ifdef AFS_FBSD50_ENV
+    GIANT_REQUIRED;
+#endif
+
+    vp = ap->a_vp;
+    avc = VTOAFS(vp);
+    /* Perhaps these two checks should just be KASSERTs instead... */
+    if (vp->v_object == NULL) {
 	printf("afs_putpages: called with non-merged cache vnode??\n");
-	return VM_PAGER_ERROR;
+	return VM_PAGER_ERROR;	/* XXX I think this is insufficient */
     }
     if (vType(avc) != VREG) {
 	printf("afs_putpages: not VREG");
-	return VM_PAGER_ERROR;
+	return VM_PAGER_ERROR;	/* XXX I think this is insufficient */
     }
     npages = btoc(ap->a_count);
     for (i = 0; i < npages; i++)
 	ap->a_rtvals[i] = VM_PAGER_AGAIN;
     bp = getpbuf(&afs_pbuf_freecnt);
+
     kva = (vm_offset_t) bp->b_data;
     pmap_qenter(kva, ap->a_m, npages);
+#ifdef AFS_FBSD50_ENV
+    cnt.v_vnodeout++;
+    cnt.v_vnodepgsout += ap->a_count;
+#endif
+
     iov.iov_base = (caddr_t) kva;
     iov.iov_len = ap->a_count;
     uio.uio_iov = &iov;
@@ -600,16 +802,16 @@
     code = afs_write(avc, &uio, sync, osi_curcred(), 0);
     afs_BozonUnlock(&avc->pvnLock, avc);
     AFS_GUNLOCK();
-    pmap_qremove(kva, npages);
 
+    pmap_qremove(kva, npages);
     relpbuf(bp, &afs_pbuf_freecnt);
+
     if (!code) {
 	size = ap->a_count - uio.uio_resid;
 	for (i = 0; i < round_page(size) / PAGE_SIZE; i++) {
 	    ap->a_rtvals[i] = VM_PAGER_OK;
-	    ap->a_m[i]->dirty = 0;
+	    vm_page_undirty(ap->a_m[i]);
 	}
-	return VM_PAGER_ERROR;
     }
     return ap->a_rtvals[0];
 }
@@ -933,26 +1135,44 @@
     return error;
 }
 
+/* struct vop_symlink_args {
+ *	struct vnode *a_dvp;
+ *	struct vnode **a_vpp;
+ *	struct componentname *a_cnp;
+ *	struct vattr *a_vap;
+ *	char *a_target;
+ * };
+ */
 int
-afs_vop_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;
+afs_vop_symlink(struct vop_symlink_args *ap)
 {
-    register struct vnode *dvp = ap->a_dvp;
-    int error = 0;
-    /* NFS ignores a_vpp; so do we. */
+    struct vnode *dvp;
+    struct vnode *newvp;
+    struct vcache *vcp;
+    int error;
 
     GETNAME();
     AFS_GLOCK();
+
+    dvp = ap->a_dvp;
+    newvp = NULL;
+
     error =
 	afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
+    if (error == 0) {
+	error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
+	if (error == 0) {
+	    newvp = AFSTOV(vcp);
+#ifdef AFS_FBSD50_ENV
+	    vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_thread);
+#else
+	    vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_proc);
+#endif
+	}
+    }
     AFS_GUNLOCK();
     DROPNAME();
+    *(ap->a_vpp) = newvp;
     return error;
 }
 
@@ -1043,69 +1263,43 @@
     return 0;
 }
 
+/*
+ * struct vop_reclaim_args {
+ *	struct vnode *a_vp;
+ * };
+ */
 int
-afs_vop_reclaim(ap)
-     struct vop_reclaim_args	/* {
-				 * struct vnode *a_vp;
-				 * } */ *ap;
-{
-#ifdef AFS_DO_FLUSH_IN_RECLAIM
-    int error, sl;
-#endif
-    register struct vnode *vp = ap->a_vp;
-
-    cache_purge(vp);		/* just in case... */
-
-#ifdef AFS_DO_FLUSH_IN_RECLAIM
-    AFS_GLOCK();
-    error = afs_FlushVCache(VTOAFS(vp), &sl);	/* tosses our stuff from vnode */
-    AFS_GUNLOCK();
-    ubc_unlink(vp);
-    if (!error && vp->v_data)
-	panic("afs_reclaim: vnode not cleaned");
-    return error;
-#else
-    if (vp->v_usecount == 2) {
-	vprint("reclaim count==2", vp);
-    } else if (vp->v_usecount == 1) {
-	vprint("reclaim count==1", vp);
-    } else
-	vprint("reclaim bad count", vp);
-
-    return 0;
-#endif
-}
-
-int
-afs_vop_lock(ap)
-     struct vop_lock_args	/* {
-				 * struct vnode *a_vp;
-				 * } */ *ap;
+afs_vop_reclaim(struct vop_reclaim_args *ap)
 {
-    register struct vnode *vp = ap->a_vp;
-    register struct vcache *avc = VTOAFS(vp);
+    /* copied from ../OBSD/osi_vnodeops.c:afs_nbsd_reclaim() */
+    int code, slept;
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+    int haveGlock = ISAFS_GLOCK();
+    int haveVlock = CheckLock(&afs_xvcache);
 
-#ifdef AFS_FBSD50_ENV
-    if (!strcmp(vp->v_tag, "none"))
+    if (!haveGlock)
+	AFS_GLOCK();
+    if (!haveVlock)
+	ObtainWriteLock(&afs_xvcache, 901);
+#ifndef AFS_DISCON_ENV
+    code = afs_FlushVCache(avc, &slept);	/* tosses our stuff from vnode */
 #else
-    if (vp->v_tag == VT_NON)
+    /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
+    code = afs_FlushVS(avc);
 #endif
-	return (ENOENT);
-    return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
-}
-
-int
-afs_vop_unlock(ap)
-     struct vop_unlock_args	/* {
-				 * struct vnode *a_vp;
-				 * } */ *ap;
-{
-    struct vnode *vp = ap->a_vp;
-    struct vcache *avc = VTOAFS(vp);
-    return (lockmgr
-	    (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
-	     ap->a_p));
+    if (!haveVlock)
+	ReleaseWriteLock(&afs_xvcache);
+    if (!haveGlock)
+	AFS_GUNLOCK();
 
+    /*
+     * XXX Pretend it worked, to prevent panic on shutdown
+     * Garrett, please fix - Jim Rees
+     */
+    if (code)
+	printf("afs_vop_reclaim: afs_FlushVCache failed code %d\n", code);
+    return 0;
 }
 
 int
@@ -1173,16 +1367,6 @@
 	   (s & CVFlushed) ? " flush in progress" : "");
     printf("\n");
     return 0;
-}
-
-int
-afs_vop_islocked(ap)
-     struct vop_islocked_args	/* {
-				 * struct vnode *a_vp;
-				 * } */ *ap;
-{
-    struct vcache *vc = VTOAFS(ap->a_vp);
-    return lockstatus(&vc->rwlock, ap->a_p);
 }
 
 /*
Index: src/afs/OBSD/osi_file.c
===================================================================
RCS file: /cvs/openafs/src/afs/OBSD/osi_file.c,v
retrieving revision 1.9
diff -u -r1.9 osi_file.c
--- src/afs/OBSD/osi_file.c	8 Oct 2003 13:48:11 -0000	1.9
+++ src/afs/OBSD/osi_file.c	9 Mar 2004 22:08:28 -0000
@@ -37,19 +37,21 @@
     if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
 	osi_Panic("UFSOpen called for non-UFS cache\n");
     afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
+    AFS_GUNLOCK();
     code = VFS_VGET(cacheDev.mp, (ino_t) ainode, &vp);
-    if (vp->v_type == VNON)
+    AFS_GLOCK();
+    if (code == 0 && vp->v_type == VNON)
 	code = ENOENT;
     if (code) {
 	osi_FreeSmallSpace(afile);
 	osi_Panic("UFSOpen: igetinode failed");
     }
+    VOP_UNLOCK(vp, 0, curproc);
     afile->vnode = vp;
     afile->size = VTOI(vp)->i_ffs_size;
     afile->offset = 0;
     afile->proc = NULL;
     afile->inum = ainode;	/* for hint validity checking */
-    VOP_UNLOCK(vp, 0, curproc);
     return (void *)afile;
 }
 
Index: src/afs/OBSD/osi_vfsops.c
===================================================================
RCS file: /cvs/openafs/src/afs/OBSD/osi_vfsops.c,v
retrieving revision 1.14
diff -u -r1.14 osi_vfsops.c
--- src/afs/OBSD/osi_vfsops.c	15 Jul 2003 23:14:25 -0000	1.14
+++ src/afs/OBSD/osi_vfsops.c	9 Mar 2004 22:08:29 -0000
@@ -404,11 +404,13 @@
 void
 afs_nbsd_rele(struct vnode *vp)
 {
+    AFS_GUNLOCK();
     if (vp->v_usecount <= 0) {
 	vprint("rele'ing unheld node", vp);
 	panic("afs_rele");
     }
     vrele(vp);
+    AFS_GLOCK();
 }
 
 int
Index: src/config/param.i386_fbsd_42.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_42.h,v
retrieving revision 1.9
diff -u -r1.9 param.i386_fbsd_42.h
--- src/config/param.i386_fbsd_42.h	15 Jul 2003 23:14:55 -0000	1.9
+++ src/config/param.i386_fbsd_42.h	9 Mar 2004 22:08:30 -0000
@@ -79,8 +79,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define	AFS_KALLOC(x)	malloc(x, M_AFS, M_WAITOK)
-#define	AFS_KFREE(x,y)	free(x,M_AFS)
+#define	AFS_KALLOC(x)	osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x)	osi_fbsd_alloc((x), 0)
+#define	AFS_KFREE(x,y)	osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -99,9 +101,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_43.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_43.h,v
retrieving revision 1.6
diff -u -r1.6 param.i386_fbsd_43.h
--- src/config/param.i386_fbsd_43.h	15 Jul 2003 23:14:55 -0000	1.6
+++ src/config/param.i386_fbsd_43.h	9 Mar 2004 22:08:30 -0000
@@ -81,8 +81,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -101,9 +103,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_44.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_44.h,v
retrieving revision 1.6
diff -u -r1.6 param.i386_fbsd_44.h
--- src/config/param.i386_fbsd_44.h	15 Jul 2003 23:14:55 -0000	1.6
+++ src/config/param.i386_fbsd_44.h	9 Mar 2004 22:08:30 -0000
@@ -83,8 +83,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -103,9 +105,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_45.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_45.h,v
retrieving revision 1.7
diff -u -r1.7 param.i386_fbsd_45.h
--- src/config/param.i386_fbsd_45.h	15 Jul 2003 23:14:55 -0000	1.7
+++ src/config/param.i386_fbsd_45.h	9 Mar 2004 22:08:30 -0000
@@ -84,8 +84,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -104,9 +106,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_46.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_46.h,v
retrieving revision 1.6
diff -u -r1.6 param.i386_fbsd_46.h
--- src/config/param.i386_fbsd_46.h	15 Jul 2003 23:14:55 -0000	1.6
+++ src/config/param.i386_fbsd_46.h	9 Mar 2004 22:08:30 -0000
@@ -85,8 +85,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -105,9 +107,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_47.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_47.h,v
retrieving revision 1.4
diff -u -r1.4 param.i386_fbsd_47.h
--- src/config/param.i386_fbsd_47.h	15 Jul 2003 23:14:55 -0000	1.4
+++ src/config/param.i386_fbsd_47.h	9 Mar 2004 22:08:30 -0000
@@ -87,8 +87,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -107,9 +109,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_50.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_50.h,v
retrieving revision 1.6
diff -u -r1.6 param.i386_fbsd_50.h
--- src/config/param.i386_fbsd_50.h	15 Jul 2003 23:14:55 -0000	1.6
+++ src/config/param.i386_fbsd_50.h	9 Mar 2004 22:08:30 -0000
@@ -88,8 +88,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -108,9 +110,6 @@
 #endif /* SSYS */
 
 #define p_rcred         p_ucred
-
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
 
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
Index: src/config/param.i386_fbsd_51.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_51.h,v
retrieving revision 1.1
diff -u -r1.1 param.i386_fbsd_51.h
--- src/config/param.i386_fbsd_51.h	17 Jul 2003 16:00:56 -0000	1.1
+++ src/config/param.i386_fbsd_51.h	9 Mar 2004 22:08:30 -0000
@@ -79,7 +79,7 @@
 #ifdef _KERNEL
 #define AFS_GLOBAL_SUNLOCK        1
 #define	AFS_VFS34	1	/* What is VFS34??? */
-#define	AFS_SHORTGID	1	/* are group id's short? */
+#define	AFS_SHORTGID	0	/* are group id's short? */
 #define	afsio_iov	uio_iov
 #define	afsio_iovcnt	uio_iovcnt
 #define	afsio_offset	uio_offset
@@ -89,8 +89,10 @@
 #define	AFS_UIOUSER	UIO_USERSPACE
 #define	AFS_CLBYTES	CLBYTES
 #define	osi_GetTime(x)	microtime(x)
-#define AFS_KALLOC(x)   malloc(x, M_AFS, M_WAITOK)
-#define AFS_KFREE(x,y)  free(x,M_AFS)
+#define AFS_KALLOC(x)   osi_fbsd_alloc((x), 1)
+#undef	AFS_KALLOC_NOSLEEP
+#define	AFS_KALLOC_NOSLEEP(x) osi_fbsd_alloc((x), 0)
+#define AFS_KFREE(x,y)  osi_fbsd_free((x))
 #define	v_count		v_usecount
 #define v_vfsp		v_mount
 #define vfs_bsize	mnt_stat.f_bsize
@@ -110,9 +112,6 @@
 
 #define p_rcred         p_ucred
 
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
-
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
 
@@ -169,7 +168,7 @@
 #define SYS_NAME_ID	SYS_NAME_ID_i386_fbsd_51
 #define AFSLITTLE_ENDIAN    1
 #define AFS_HAVE_FFS        1	/* Use system's ffs. */
-#define AFS_HAVE_STATVFS    0	/* System doesn't support statvfs */
+#define AFS_HAVE_STATVFS    1	/* System doesn't support statvfs */
 #define AFS_VM_RDWR_ENV	    1	/* read/write implemented via VM */
 
 #define	afsio_iov	uio_iov
Index: src/config/param.i386_fbsd_52.h
===================================================================
RCS file: /cvs/openafs/src/config/param.i386_fbsd_52.h,v
retrieving revision 1.1
diff -u -r1.1 param.i386_fbsd_52.h
--- src/config/param.i386_fbsd_52.h	1 Oct 2003 14:04:34 -0000	1.1
+++ src/config/param.i386_fbsd_52.h	9 Mar 2004 22:08:30 -0000
@@ -113,9 +113,6 @@
 
 #define p_rcred         p_ucred
 
-#define	VN_RELE(vp)	vrele(((struct vnode *)(vp)))
-#define	VN_HOLD(vp)	VREF(((struct vnode *)(vp)))
-
 #if	!defined(ASSEMBLER) && !defined(__LANGUAGE_ASSEMBLY__)
 enum vcexcl { NONEXCL, EXCL };
 
Index: src/libafs/MakefileProto.FBSD.in
===================================================================
RCS file: /cvs/openafs/src/libafs/MakefileProto.FBSD.in,v
retrieving revision 1.23
diff -u -r1.23 MakefileProto.FBSD.in
--- src/libafs/MakefileProto.FBSD.in	15 Oct 2003 21:38:40 -0000	1.23
+++ src/libafs/MakefileProto.FBSD.in	9 Mar 2004 22:08:31 -0000
@@ -34,9 +34,12 @@
 <i386_fbsd_42 i386_fbsd_43 i386_fbsd_44 i386_fbsd_45 i386_fbsd_46 i386_fbsd_47>
 	-fformat-extensions
 <all -i386_fbsd_42 -i386_fbsd_43 -i386_fbsd_44 -i386_fbsd_45 -i386_fbsd_46 -i386_fbsd_47>
-	-mno-align-long-strings -fformat-extensions -fno-common -ffreestanding
+	-mno-align-long-strings -fformat-extensions -fno-common -ffreestanding \
+	-I${KSRC}/i386/compile/GENERIC -include opt_global.h -fno-strict-aliasing
 <all>
+
 DBUG = -O2
+#DBUG = -O -g
 DEFINES= -DAFSDEBUG -DKERNEL -DAFS -DVICE -DNFS -DUFS -DINET -DQUOTA -DGETMOUNT
 OPTF=${OPT} 
 OPTF2=${OPT2} 
@@ -140,5 +143,12 @@
 	$(CRULE_NOOPT)
 setdef1.o: setdef1.c
 	$(CRULE_NOOPT)
+
+# vnode_if.h build rules:
+<i386_fbsd_42 i386_fbsd_43 i386_fbsd_44 i386_fbsd_45 i386_fbsd_46 i386_fbsd_47>
+vnode_if.h:	${KSRC}/kern/vnode_if.src
+	perl5 ${KSRC}/kern/vnode_if.pl -h ${KSRC}/kern/vnode_if.src
+<all -i386_fbsd_42 -i386_fbsd_43 -i386_fbsd_44 -i386_fbsd_45 -i386_fbsd_46 -i386_fbsd_47>
 vnode_if.h:	${KSRC}/kern/vnode_if.src
 	awk -f ${KSRC}/tools/vnode_if.awk ${KSRC}/kern/vnode_if.src -h
+<all>
Index: src/libuafs/MakefileProto.FBSD.in
===================================================================
RCS file: /cvs/openafs/src/libuafs/MakefileProto.FBSD.in,v
retrieving revision 1.9
diff -u -r1.9 MakefileProto.FBSD.in
--- src/libuafs/MakefileProto.FBSD.in	10 Mar 2003 01:59:40 -0000	1.9
+++ src/libuafs/MakefileProto.FBSD.in	9 Mar 2004 22:08:31 -0000
@@ -10,16 +10,16 @@
 
 
 # System specific build commands and flags
-CC = gcc
+CC = @CC@
 DEFINES= -D_REENTRANT -DKERNEL -DUKERNEL
 KOPTS=
 CFLAGS=-I. -I.. -I${TOP_OBJDIR}/src/config ${FSINCLUDES} $(DEFINES) $(KOPTS) ${DBUG}
 OPTF=-O
 # WEBOPTS = -I../nsapi -DNETSCAPE_NSAPI -DNET_SSL -DXP_UNIX -DMCC_HTTPD
 
-TEST_CFLAGS=-pthread -D_REENTRANT -DAFS_PTHREAD_ENV -DAFS_FBSD40_ENV
+TEST_CFLAGS=-D_REENTRANT -DAFS_PTHREAD_ENV -DAFS_FBSD40_ENV
 TEST_LDFLAGS=
-TEST_LIBS=
+TEST_LIBS=-lc_r
 
 LIBUAFS = libuafs.a
 LIBJUAFS = libjuafs.a
Index: src/rx/rx_kcommon.c
===================================================================
RCS file: /cvs/openafs/src/rx/rx_kcommon.c,v
retrieving revision 1.40
diff -u -r1.40 rx_kcommon.c
--- src/rx/rx_kcommon.c	3 Feb 2004 06:23:39 -0000	1.40
+++ src/rx/rx_kcommon.c	9 Mar 2004 22:08:31 -0000
@@ -780,6 +780,8 @@
 #if (defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)) && defined(KERNEL_FUNNEL)
     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 #endif
+    AFS_ASSERT_GLOCK();
+    AFS_GUNLOCK();
 #if	defined(AFS_HPUX102_ENV)
 #if     defined(AFS_HPUX110_ENV)
     /* we need a file associated with the socket so sosend in NetSend 
@@ -811,6 +813,7 @@
     if (code)
 	goto bad;
 
+    memset(&myaddr, 0, sizeof myaddr);
     myaddr.sin_family = AF_INET;
     myaddr.sin_port = aport;
     myaddr.sin_addr.s_addr = 0;
@@ -856,6 +859,7 @@
     if (code) {
 	printf("sobind fails (%d)\n", (int)code);
 	soclose(newSocket);
+	AFS_GLOCK();
 	goto bad;
     }
 #else /* defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) */
@@ -890,12 +894,14 @@
 #endif /* else AFS_DARWIN_ENV */
 #endif /* else AFS_HPUX110_ENV */
 
+    AFS_GLOCK();
 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 #endif
     return (struct osi_socket *)newSocket;
 
   bad:
+    AFS_GLOCK();
 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 #endif
Index: src/rx/rx_prototypes.h
===================================================================
RCS file: /cvs/openafs/src/rx/rx_prototypes.h,v
retrieving revision 1.12
diff -u -r1.12 rx_prototypes.h
--- src/rx/rx_prototypes.h	15 Jul 2003 23:16:10 -0000	1.12
+++ src/rx/rx_prototypes.h	9 Mar 2004 22:08:31 -0000
@@ -561,9 +561,15 @@
 
 /* EXTERNAL PROTOTYPES - include here cause it causes too many issues to
    include the afs_prototypes.h file - just make sure they match */
+#ifndef afs_osi_Alloc
 extern void *afs_osi_Alloc(size_t x);
+#endif
+#ifndef afs_osi_Alloc_NoSleep
 extern void *afs_osi_Alloc_NoSleep(size_t x);
+#endif
+#ifndef afs_osi_Free
 extern void afs_osi_Free(void *x, size_t asize);
+#endif
 #ifndef afs_osi_Wakeup
 extern int afs_osi_Wakeup(void *event);
 #endif
Index: src/rx/xdr.h
===================================================================
RCS file: /cvs/openafs/src/rx/xdr.h,v
retrieving revision 1.10
diff -u -r1.10 xdr.h
--- src/rx/xdr.h	15 Jul 2003 23:16:12 -0000	1.10
+++ src/rx/xdr.h	9 Mar 2004 22:08:31 -0000
@@ -96,7 +96,9 @@
 
 /* keep here for now, 64 bit issues */
 extern void *afs_osi_Alloc(size_t x);
+#ifndef afs_osi_Alloc_NoSleep
 extern void *afs_osi_Alloc_NoSleep(size_t x);
+#endif
 extern void afs_osi_Free(void *x, size_t asize);
 
 #endif
Index: src/rx/FBSD/rx_knet.c
===================================================================
RCS file: /cvs/openafs/src/rx/FBSD/rx_knet.c,v
retrieving revision 1.13
diff -u -r1.13 rx_knet.c
--- src/rx/FBSD/rx_knet.c	15 Jul 2003 23:16:18 -0000	1.13
+++ src/rx/FBSD/rx_knet.c	9 Mar 2004 22:08:32 -0000
@@ -83,10 +83,20 @@
 {
     struct proc *p;
 
+    /*
+     * Have to drop global lock to safely do this.
+     * soclose() is currently protected by Giant,
+     * but pfind and psignal are MPSAFE.
+     */
+    AFS_GUNLOCK();
     soclose(rx_socket);
     p = pfind(rxk_ListenerPid);
     if (p)
 	psignal(p, SIGUSR1);
+#ifdef AFS_FBSD50_ENV
+    PROC_UNLOCK(p);
+#endif
+    AFS_GLOCK();
 }
 
 int
