It starts and it stops!

Garrett Wollman <[email protected]>
Newsgroups gmane.comp.file-systems.openafs.devel,gmane.comp.file-systems.openafs.freebsd
Message-ID <[email protected]>
I've finally gotten to the point where I can actually shut down the
client on FreeBSD-current without panicking.  I've also made a few
(incomplete) changes to the MI code to support linking without
libcompat (which is usually a bad idea).  (The code that I changed
should probably be refactored.)

As always, the patch is at <http://lcs.mit.edu/~wollman/openafs-fbsd52.patch>.
This time it's relative to top-of-tree.  For ease of commentary, I'm
also including it here.  The next steps would be:

- Make sure authentication works.  (Need to compile aklog for that....)
- Check all of the VNOPS with DEBUG_VFS_LOCKS to make certain that the
  locking protocol is being obeyed.
- Figure out the internal API for PAG stuff and make it do the Right
  Thing using MAC labels.
- VM system stress test (probably `make buildworld' with sources on
  AFS).
- Make sure 64-bit client ops work correctly.
- Fix compilation and test on 4.x.
- Fix compilation and test on other architectures.

? src/config/param.i386_fbsd_52.h
(To construct this file, do the obvious thing.)

Index: src/afs/afs.h
===================================================================
RCS file: /cvs/openafs/src/afs/afs.h,v
retrieving revision 1.42
diff -u -r1.42 afs.h
--- src/afs/afs.h	29 Aug 2003 22:00:04 -0000	1.42
+++ src/afs/afs.h	29 Sep 2003 03:45: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_OBSD_ENV) || defined(AFS_FBSD_ENV)
 #define vrefCount   v->v_usecount
 #else
 #define vrefCount   v.v_count
-#endif /* AFS_OBSD_ENV */
-#endif /* AFS_FBSD_ENV */
+#endif /* AFS_[OF]BSD_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_OBSD_ENV) || defined(AFS_FBSD_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_OBSD_ENV) || defined(AFS_FBSD_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.62
diff -u -r1.62 afs_call.c
--- src/afs/afs_call.c	8 Aug 2003 21:54:34 -0000	1.62
+++ src/afs/afs_call.c	29 Sep 2003 03:45:29 -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	29 Sep 2003 03:45:30 -0000
@@ -41,7 +41,7 @@
 int afs_sysnamecount = 0;
 struct volume *Initialafs_freeVolList;
 int afs_memvolumes = 0;
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_OBSD_ENV) || defined(AFS_FBSD_ENV)
 static struct vnode *volumeVnode;
 #endif
 
@@ -295,7 +295,7 @@
     struct osi_file *tfile;
 
     AFS_STATCNT(afs_InitVolumeInfo);
-#if defined(AFS_OBSD_ENV)
+#if defined(AFS_OBSD_ENV) || defined(AFS_FBSD_ENV)
     /*
      * On Open/NetBSD, we can get into big trouble if we don't hold the volume file
      * vnode.  SetupVolume holds afs_xvolume lock exclusive.
@@ -428,19 +428,24 @@
     cacheInode = filevp->i_ino;
     afs_cacheSBp = filevp->i_sb;
 #else
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_OBSD_ENV) || defined(AFS_FBSD_ENV)
     cacheInode = VTOI(filevp)->i_number;
     cacheDev.mp = filevp->v_mount;
     cacheDev.held_vnode = filevp;
+#ifdef AFS_OBSD_ENV
     AFS_HOLD(filevp);		/* Make sure mount point stays busy. XXX */
 #else
+    vref(filevp);
+    afs_cacheVfsp = filevp->v_vfsp;
+#endif
+#else
 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
     afs_InitDualFSCacheOps(filevp);
 #endif
     cacheInode = afs_vnodeToInumber(filevp);
     cacheDev.dev = afs_vnodeToDev(filevp);
     afs_cacheVfsp = filevp->v_vfsp;
-#endif /* AFS_OBSD_ENV */
+#endif /* !AFS_[FO]BSD_ENV */
 #endif /* AFS_LINUX20_ENV */
     AFS_RELE(filevp);
 #endif /* AFS_LINUX22_ENV */
@@ -494,10 +499,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 +676,19 @@
 	afs_cacheFiles = afs_cacheBlocks = 0;
 	pag_epoch = maxIHint = nihints = usedihint = 0;
 	pagCounter = 0;
+#if defined(AFS_OBSD_ENV) || defined(AFS_FBSD_ENV)
 #ifdef AFS_OBSD_ENV
 	AFS_RELE(volumeVnode);	/* let it go, finally. */
+#else
+	vrele(volumeVnode);
+#endif
 	volumeVnode = NULL;
 	if (cacheDev.held_vnode) {
+#ifdef AFS_OBSD_ENV
 	    AFS_RELE(cacheDev.held_vnode);
+#else
+	    vrele(cacheDev.held_vnode);
+#endif
 	    cacheDev.held_vnode = NULL;
 	}
 #endif
Index: src/afs/afs_osi.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_osi.c,v
retrieving revision 1.38
diff -u -r1.38 afs_osi.c
--- src/afs/afs_osi.c	27 Aug 2003 21:43:16 -0000	1.38
+++ src/afs/afs_osi.c	29 Sep 2003 03:45:31 -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	29 Sep 2003 03:45:31 -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,13 @@
 };
 
 struct osi_dev {
-#ifdef AFS_OBSD_ENV
+#if defined(AFS_OBSD_ENV) || defined(AFS_FBSD_ENV)
     struct mount *mp;
     struct vnode *held_vnode;
+/* see if we need this...
 #elif defined(AFS_FBSD50_ENV)
     struct cdev *dev;
+*/
 #elif defined(AFS_AIX42_ENV)
     dev_t dev;
 #else
@@ -81,7 +87,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	29 Sep 2003 03:45:31 -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.42
diff -u -r1.42 afs_prototypes.h
--- src/afs/afs_prototypes.h	15 Jul 2003 23:14:12 -0000	1.42
+++ src/afs/afs_prototypes.h	29 Sep 2003 03:45:32 -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.55
diff -u -r1.55 afs_vcache.c
--- src/afs/afs_vcache.c	3 Sep 2003 16:47:15 -0000	1.55
+++ src/afs/afs_vcache.c	29 Sep 2003 03:45:35 -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_OBSD_ENV) || defined(AFS_FBSD_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_OBSD_ENV) || defined(AFS_FBSD_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_OBSD_ENV) || defined(AFS_FBSD_ENV)
     if (tvc->v)
 	panic("afs_NewVCache(): free vcache with vnode attached");
 #endif
@@ -931,6 +902,32 @@
     afs_nbsd_getnewvnode(tvc);	/* includes one refcount */
     lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0);
 #endif
+#ifdef AFS_FBSD_ENV
+    {
+	struct vnode *vp;
+
+	AFS_GUNLOCK();
+	if (getnewvnode("afs", afs_globalVFS, afs_vnodeop_p, &vp))
+	    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;
@@ -955,9 +952,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_OBSD_ENV) && !defined(AFS_FBSD_ENV)
     VREFCOUNT_SET(tvc, 1);	/* us */
-#endif /* AFS_OBSD_ENV */
+#endif /* AFS_[FO]BSD_ENV */
 #endif /* AFS_OSF_ENV */
 #ifdef	AFS_AIX32_ENV
     LOCK_INIT(&tvc->pvmlock, "vcache pvmlock");
@@ -1038,14 +1035,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.
      */
@@ -1798,6 +1787,11 @@
     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
+    vn_lock(AFSTOV(tvc), LK_EXCLUSIVE | LK_RETRY, curthread);
+    vinvalbuf(AFSTOV(tvc), V_SAVE, curthread->td_ucred, curthread, PINOD, 0);
+    VOP_UNLOCK(AFSTOV(tvc), LK_EXCLUSIVE, curthread);
 #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	29 Sep 2003 03:45:35 -0000
@@ -73,7 +73,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
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	29 Sep 2003 03:45:35 -0000
@@ -21,6 +21,7 @@
 
 #include <sys/lock.h>
 #include <sys/time.h>
+#include <sys/mutex.h>
 /* #include <kern/sched_prim.h> */
 /* #include <sys/unix_defs.h> */
 
@@ -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,9 @@
 #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)
 
 #if defined(AFS_FBSD50_ENV)
 #define VT_AFS		"afs"
@@ -64,24 +73,13 @@
 #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 getpid()	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	29 Sep 2003 03:45:35 -0000
@@ -53,7 +53,12 @@
 	       struct vnode **dirvpp, struct vnode **vpp)
 {
     struct nameidata n;
-    int flags, error;
+    int flags, error, wasowned;
+
+    wasowned = mtx_owned(&afs_global_mtx);
+    if (wasowned)
+	mtx_unlock(&afs_global_mtx);
+
     flags = 0;
     flags = LOCKLEAF;
     if (followlink)
@@ -62,8 +67,11 @@
 	flags |= NOFOLLOW;
     /*   if (dirvpp) flags|=WANTPARENT; *//* XXX LOCKPARENT? */
     NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
-    if (error = namei(&n))
+    if ((error = namei(&n)) != 0) {
+	if (wasowned)
+	    mtx_lock(&afs_global_mtx);
 	return error;
+    }
     *vpp = n.ni_vp;
 /*
    if (dirvpp)
@@ -72,6 +80,8 @@
     /* should we do this? */
     VOP_UNLOCK(n.ni_vp, 0, curproc);
     NDFREE(&n, NDF_ONLY_PNBUF);
+    if (wasowned)
+	mtx_lock(&afs_global_mtx);
     return 0;
 }
 
@@ -102,4 +112,73 @@
     resettodr();
     AFS_GLOCK();
 #endif
+}
+
+/*
+ * Replace all of the bogus special-purpose memory allocators...
+ */
+void *
+osi_fbsd_alloc(size_t size, int dropglobal)
+{
+	void *rv;
+	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
+		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	29 Sep 2003 03:45:35 -0000
@@ -60,8 +60,10 @@
 	vfs_register(&afs_vfsconf);	/* doesn't fail */
 	vfs_add_vnodeops(&afs_vnodeop_opv_desc);
 	osi_Init();
+#ifdef DO_NOT_EVER_EVER_DO_THIS
 	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	29 Sep 2003 03:45:35 -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	29 Sep 2003 03:45:36 -0000
@@ -18,32 +18,31 @@
 #include "afsincludes.h"	/* Afs-based standard headers */
 #include "afs/afs_stats.h"	/* afs statistics */
 
-
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-static char waitV;
-
-
 void
 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
 {
     AFS_STATCNT(osi_InitWaitHandle);
-    achandle->proc = (caddr_t) 0;
+    cv_init(&achandle->wh_condvar, "afscondvar");
+    achandle->wh_inited = 1;
 }
 
 /* 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)
 {
-    caddr_t proc;
 
     AFS_STATCNT(osi_CancelWait);
-    proc = achandle->proc;
-    if (proc == 0)
+    /* XXX should not be necessary */
+    if (!achandle->wh_inited)
 	return;
-    achandle->proc = (caddr_t) 0;	/* so dude can figure out he was signalled */
-    afs_osi_Wakeup(&waitV);
+
+    AFS_ASSERT_GLOCK();
+    cv_signal(&achandle->wh_condvar);
 }
 
 /* afs_osi_Wait
@@ -54,31 +53,36 @@
 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
 {
     int code;
-    afs_int32 endTime;
+    struct timeval tv;
+    int ticks;
 
     AFS_STATCNT(osi_Wait);
-    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)) {
-	    /* we've been signalled */
-	    break;
-	}
-    } while (osi_Time() < endTime);
+    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);
+    }
     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 +144,7 @@
     seq = evp->seq;
     while (seq == evp->seq) {
 	AFS_ASSERT_GLOCK();
-	AFS_GUNLOCK();
-	tsleep(event, PVFS, "afs_osi_Sleep", 0);
-	AFS_GLOCK();
+	msleep(event, &afs_global_mtx, PVFS, "afsslp", 0);
     }
     relevent(evp);
 }
@@ -153,42 +155,6 @@
     afs_osi_Sleep(event);
     return 0;
 }
-
-/* osi_TimedSleep
- * 
- * Arguments:
- * event - event to sleep on
- * ams --- max sleep time in milliseconds
- * aintok - 1 if should sleep interruptibly
- *
- * Returns 0 if timeout and EINTR if signalled.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
-    int code = 0;
-    struct afs_event *evp;
-    int ticks;
-    int seq, prio;
-
-    ticks = (ams * afs_hz) / 1000;
-
-
-    evp = afs_getevent(event);
-    seq = evp->seq;
-    AFS_GUNLOCK();
-    if (aintok)
-	prio = PCATCH | PPAUSE;
-    else
-	prio = PVFS;
-    code = tsleep(event, prio, "afs_osi_TimedSleep", ticks);
-    AFS_GLOCK();
-    if (seq == evp->seq)
-	code = EINTR;
-    relevent(evp);
-    return code;
-}
-
 
 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	29 Sep 2003 03:45:36 -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)
 {
 
+    /*
+     * Releaase 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;
@@ -151,7 +149,7 @@
 	AFS_GLOCK();
 	afs_globalVFS = mp;
 	*vpp = AFSTOV(tvp);
-	tvp->v.v_flag |= VROOT;
+	tvp->v->v_flag |= VROOT;
     }
 
     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
@@ -160,15 +158,10 @@
     return error;
 }
 
+#ifndef AFS_FBSD50_ENV
 int
-afs_vget(mp, lfl, vp)
-     struct mount *mp;
-     struct vnode *vp;
-     int lfl;
+afs_vget(struct mount *mp, ino_t ino, int flags, struct vnode *vp)
 {
-#ifdef AFS_FBSD50_ENV
-    return EOPNOTSUPP;
-#else
     int error;
 
     printf("vget called. help!\n");
@@ -180,11 +173,11 @@
     if (!error)
 	insmntque(vp, afs_globalVFS);	/* take off free list */
     return error;
-#endif
 }
+#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);
@@ -217,23 +210,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 +229,11 @@
     afs_quotactl,
     afs_statfs,
     afs_sync,
+#ifdef AFS_FBSD50_ENV
+    NULL,
+#else
     afs_vget,
+#endif
     afs_fhtovp,
 #ifdef AFS_FBSD50_ENV
     vfs_stdcheckexp,
@@ -255,7 +241,6 @@
     afs_vptofh,
     afs_init,
 #ifdef AFS_FBSD50_ENV
-    vfs_stduninit,
+    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	29 Sep 2003 03:45:36 -0000
@@ -32,6 +32,31 @@
 #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.
+ */
+
+#define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curthread)
+#define unlock_vnode(v)	VOP_UNLOCK((v), 0, curthread)
+
+#ifndef AFS_FBSD50_ENV
+/* 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 +72,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 +92,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 +104,9 @@
 	    SetAfsVnode(vp);
 	}
 #endif
+	VM_OBJECT_UNLOCK(obj);
     }
-    simple_unlock(&vp->v_interlock);
+    unlock_vnode(vp);
     AFS_GLOCK();
 
     return 0;
@@ -99,25 +128,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 +186,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 +237,13 @@
     struct vm_object *obj;
 
     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);
+	VM_OBJECT_UNLOCK(obj);
     }
-    simple_unlock(&vp->v_interlock);
+    unlock_vnode(vp);
     /*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	29 Sep 2003 03:45:38 -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 *);
@@ -87,6 +135,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 */
@@ -122,7 +171,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 +537,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 +554,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 +577,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 +588,24 @@
 		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);
+    cnt.v_vnodein++;
+    cnt.v_vnodepgsin += npages;
+
     iov.iov_base = (caddr_t) kva;
     iov.iov_len = ap->a_count;
     uio.uio_iov = &iov;
@@ -455,6 +619,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 +629,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 +698,10 @@
 	    }
 	}
     }
+#ifdef AFS_FBSD50_ENV
+    vm_page_unlock_queues();
+    VM_OBJECT_UNLOCK(object);
+#endif
     return 0;
 }
 
@@ -543,16 +726,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 +749,34 @@
     struct iovec iov;
     struct buf *bp;
     vm_offset_t kva;
-    struct vcache *avc = VTOAFS(ap->a_vp);
+    struct vnode *vp;
+    struct vcache *avc;
+
+#ifdef AFS_FBSD50_ENV
+    GIANT_REQUIRED;
+#endif
 
-    if (avc->v.v_object == NULL) {
+    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);
+    cnt.v_vnodeout++;
+    cnt.v_vnodepgsout += ap->a_count;
+
     iov.iov_base = (caddr_t) kva;
     iov.iov_len = ap->a_count;
     uio.uio_iov = &iov;
@@ -600,16 +801,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];
 }
@@ -1091,6 +1292,7 @@
     if (vp->v_tag == VT_NON)
 #endif
 	return (ENOENT);
+    KASSERT(avc != NULL, ("afs_vop_lock: null vcache"));
     return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
 }
 
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:39 -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
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	29 Sep 2003 03:45:40 -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
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	29 Sep 2003 03:45:40 -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
@@ -169,7 +171,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/libafs/MakefileProto.FBSD.in
===================================================================
RCS file: /cvs/openafs/src/libafs/MakefileProto.FBSD.in,v
retrieving revision 1.22
diff -u -r1.22 MakefileProto.FBSD.in
--- src/libafs/MakefileProto.FBSD.in	1 Jul 2003 18:06:40 -0000	1.22
+++ src/libafs/MakefileProto.FBSD.in	29 Sep 2003 03:45:41 -0000
@@ -34,9 +34,11 @@
 <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/sys/i386/compile/AFS -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} 
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	29 Sep 2003 03:45:41 -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.37
diff -u -r1.37 rx_kcommon.c
--- src/rx/rx_kcommon.c	27 Aug 2003 21:43:19 -0000	1.37
+++ src/rx/rx_kcommon.c	29 Sep 2003 03:45:42 -0000
@@ -776,6 +776,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)
     /* blocking socket */
@@ -796,6 +798,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;
@@ -841,6 +844,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) */
@@ -875,12 +879,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	29 Sep 2003 03:45:43 -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	29 Sep 2003 03:45:43 -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	29 Sep 2003 03:45:44 -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
Index: src/viced/viced.c
===================================================================
RCS file: /cvs/openafs/src/viced/viced.c,v
retrieving revision 1.51
diff -u -r1.51 viced.c
--- src/viced/viced.c	24 Sep 2003 18:54:10 -0000	1.51
+++ src/viced/viced.c	29 Sep 2003 03:45:46 -0000
@@ -1564,9 +1564,12 @@
     softsig_init();
 #endif
 
+    ViceLog(0, ("Got to point 1\n"));
     /* install signal handlers for controlling the fileserver process */
     ResetCheckSignal();		/* set CheckSignal_Signal() sig handler */
+    ViceLog(0, ("Got to point 2\n"));
     ResetCheckDescriptors();	/* set CheckDescriptors_Signal() sig handler */
+    ViceLog(0, ("Got to point 3\n"));
 
 #if defined(AFS_SGI_ENV)
     /* give this guy a non-degrading priority so help busy servers */
@@ -1577,8 +1580,10 @@
 #ifndef AFS_NT40_ENV
     nice(-5);			/* TODO: */
 #endif
+    ViceLog(0, ("Got to point 4\n"));
 #endif
     assert(DInit(buffs) == 0);
+    ViceLog(0, ("Got to point 5\n"));
 
 #ifdef AFS_NT40_ENV
     if (afs_winsockInit() < 0) {
@@ -1588,6 +1593,7 @@
     }
 #endif
     CheckAdminName();
+    ViceLog(0, ("Got to point 6\n"));
 
     /* if we support more than 16 threads, then we better have the ability 
      ** to keep open a large number of files simultaneously 
Index: src/vlserver/vlprocs.c
===================================================================
RCS file: /cvs/openafs/src/vlserver/vlprocs.c,v
retrieving revision 1.10
diff -u -r1.10 vlprocs.c
--- src/vlserver/vlprocs.c	15 Jul 2003 23:17:34 -0000	1.10
+++ src/vlserver/vlprocs.c	29 Sep 2003 03:45:48 -0000
@@ -38,6 +38,12 @@
 #ifndef AFS_NT40_ENV
 #include <unistd.h>
 #endif
+#ifdef AFS_FBSD_ENV		/* XXX for now */
+#define HAVE_REGEX_H
+#endif
+#ifdef HAVE_REGEX_H		/* use POSIX regexp library */
+#include <regex.h>
+#endif
 
 extern int smallMem;
 extern extent_mod;
@@ -1376,6 +1382,10 @@
     int pollcount = 0;
     int namematchRWBK, namematchRO, thismatch, matchtype;
     char volumename[VL_MAXNAMELEN];
+#ifdef HAVE_REGEX_H
+    regex_t re;
+    int need_regfree = 0;
+#endif
 
     COUNT_REQ(VLLISTATTRIBUTESN2);
     vldbentries->nbulkentries_val = 0;
@@ -1433,11 +1443,19 @@
 	findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
 	if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
 	    sprintf(volumename, "^%s$", name);
+#ifdef HAVE_REGEX_H
+	    if (regcomp(&re, volumename, REG_BASIC | REG_NOSUB) != 0) {
+		errorcode = VL_BADNAME;
+		goto done;
+	    }
+	    need_regfree = 1;
+#else
 	    t = (char *)re_comp(volumename);
 	    if (t) {
 		errorcode = VL_BADNAME;
 		goto done;
 	    }
+#endif
 	    findname = 1;
 	}
 
@@ -1468,9 +1486,15 @@
 		    if (tentry.flags & VLF_RWEXISTS) {
 			if (findname) {
 			    sprintf(volumename, "%s", tentry.name);
+#ifdef HAVE_REGEX_H
+			    if (regexec(&re, volumename, 0, NULL, 0) == 0) {
+				thismatch = VLSF_RWVOL;
+			    }
+#else
 			    if (re_exec(volumename)) {
 				thismatch = VLSF_RWVOL;
 			    }
+#endif
 			} else {
 			    thismatch = VLSF_RWVOL;
 			}
@@ -1480,9 +1504,15 @@
 		    if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
 			if (findname) {
 			    sprintf(volumename, "%s.backup", tentry.name);
+#ifdef HAVE_REGEX_H
+			    if (regexec(&re, volumename, 0, NULL, 0) == 0) {
+				thismatch = VLSF_BACKVOL;
+			    }
+#else
 			    if (re_exec(volumename)) {
 				thismatch = VLSF_BACKVOL;
 			    }
+#endif
 			} else {
 			    thismatch = VLSF_BACKVOL;
 			}
@@ -1504,8 +1534,14 @@
 			    } else {
 				sprintf(volumename, "%s.readonly",
 					tentry.name);
+#ifdef HAVE_REGEX_H
+			    if (regexec(&re, volumename, 0, NULL, 0) == 0) {
+				thismatch = VLSF_ROVOL;
+			    }
+#else
 				if (re_exec(volumename))
 				    thismatch = VLSF_ROVOL;
+#endif
 			    }
 			} else {
 			    thismatch = VLSF_ROVOL;
@@ -1566,6 +1602,9 @@
     }
 
   done:
+    if (need_regfree)
+	regfree(&re);
+
     if (errorcode) {
 	COUNT_ABO;
 	ubik_AbortTrans(trans);
Index: src/volser/vos.c
===================================================================
RCS file: /cvs/openafs/src/volser/vos.c,v
retrieving revision 1.28
diff -u -r1.28 vos.c
--- src/volser/vos.c	15 Sep 2003 21:39:10 -0000	1.28
+++ src/volser/vos.c	29 Sep 2003 03:45:52 -0000
@@ -62,6 +62,13 @@
 #endif
 #include "volser_prototypes.h"
 
+#ifdef AFS_FBSD_ENV
+#define HAVE_REGEX_H
+#endif
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
 struct tqElem {
     afs_int32 volid;
     struct tqElem *next;
@@ -3928,6 +3935,20 @@
     if (seenprefix) {
 	for (ti = as->parms[0].items; ti; ti = ti->next) {
 	    if (strncmp(ti->data, "^", 1) == 0) {
+#ifdef HAVE_REGEX_H
+		regex_t re;
+		char errbuf[256];
+
+		code = regcomp(&re, ti->data, REG_BASIC | REG_NOSUB);
+		if (code != 0) {
+		    regerror(code, &re, errbuf, sizeof errbuf);
+		    fprintf(STDERR,
+			    "Unrecognizable -prefix regular expression: '%s': %s\n",
+			    ti->data, errbuf);
+		    exit(1);
+		}
+		regfree(&re);
+#else
 		ccode = (char *)re_comp(ti->data);
 		if (ccode) {
 		    fprintf(STDERR,
@@ -3935,12 +3956,27 @@
 			    ti->data, ccode);
 		    exit(1);
 		}
+#endif
 	    }
 	}
     }
     if (seenxprefix) {
 	for (ti = as->parms[4].items; ti; ti = ti->next) {
 	    if (strncmp(ti->data, "^", 1) == 0) {
+#ifdef HAVE_REGEX_H
+		regex_t re;
+		char errbuf[256];
+
+		code = regcomp(&re, ti->data, REG_BASIC | REG_NOSUB);
+		if (code != 0) {
+		    regerror(code, &re, errbuf, sizeof errbuf);
+		    fprintf(STDERR,
+			    "Unrecognizable -xprefix regular expression: '%s': %s\n",
+			    ti->data, errbuf);
+		    exit(1);
+		}
+		regfree(&re);
+#else
 		ccode = (char *)re_comp(ti->data);
 		if (ccode) {
 		    fprintf(STDERR,
@@ -3948,6 +3984,7 @@
 			    ti->data, ccode);
 		    exit(1);
 		}
+#endif
 	    }
 	}
     }
@@ -4012,6 +4049,22 @@
 	if (seenprefix) {
 	    for (ti = as->parms[0].items; ti; ti = ti->next) {
 		if (strncmp(ti->data, "^", 1) == 0) {
+#ifdef HAVE_REGEX_H
+		    regex_t re;
+		    char errbuf[256];
+
+		    /* XXX -- should just do the compile once! */
+		    code = regcomp(&re, ti->data, REG_BASIC | REG_NOSUB);
+		    if (code != 0) {
+			regerror(code, &re, errbuf, sizeof errbuf);
+			fprintf(STDERR,
+				"Error in -prefix regular expression: '%s': %s\n",
+				ti->data, errbuf);
+			exit(1);
+		    }
+		    match = (regexec(&re, vllist->name, 0, NULL, 0) == 0);
+		    regfree(&re);
+#else
 		    ccode = (char *)re_comp(ti->data);
 		    if (ccode) {
 			fprintf(STDERR,
@@ -4020,6 +4073,7 @@
 			exit(1);
 		    }
 		    match = (re_exec(vllist->name) == 1);
+#endif
 		} else {
 		    match =
 			(strncmp(vllist->name, ti->data, strlen(ti->data)) ==
@@ -4040,6 +4094,23 @@
 	if (match && seenxprefix) {
 	    for (ti = as->parms[4].items; ti; ti = ti->next) {
 		if (strncmp(ti->data, "^", 1) == 0) {
+#ifdef HAVE_REGEX_H
+		    regex_t re;
+		    char errbuf[256];
+
+		    /* XXX -- should just do the compile once! */
+		    code = regcomp(&re, ti->data, REG_BASIC | REG_NOSUB);
+		    if (code != 0) {
+			regerror(code, &re, errbuf, sizeof errbuf);
+			fprintf(STDERR,
+				"Error in -xprefix regular expression: '%s': %s\n",
+				ti->data, errbuf);
+			exit(1);
+		    }
+		    if (regexec(&re, vllist->name, 0, NULL, 0) == 0)
+			    match = 0;
+		    regfree(&re);
+#else
 		    ccode = (char *)re_comp(ti->data);
 		    if (ccode) {
 			fprintf(STDERR,
@@ -4051,6 +4122,7 @@
 			match = 0;
 			break;
 		    }
+#endif
 		} else {
 		    if (strncmp(vllist->name, ti->data, strlen(ti->data)) ==
 			0) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.