Index: ddb/db_ps.c
===================================================================
RCS file: /cvs/src/sys/ddb/db_ps.c,v
retrieving revision 1.8
diff -u -r1.8 db_ps.c
--- ddb/db_ps.c	12 Jul 2003 17:54:30 -0000	1.8
+++ ddb/db_ps.c	23 Feb 2004 06:27:28 -0000
@@ -40,7 +40,7 @@
 
 #include <ddb/ddb.h>
 
-static void
+static int
 db_more(int *nl)
 {
 	++*nl;
@@ -62,11 +62,14 @@
 			break;
 		default:		/* exit */
 			db_printf("\n");
-			return;
+			return(-1);
 		}
 	}
+	return(0);
 }
 
+static void db_dump_td_tokens(thread_t td);
+
 void
 db_ps(dummy1, dummy2, dummy3, dummy4)
 	db_expr_t	dummy1;
@@ -86,12 +89,15 @@
 	else
 		p = &proc0;
 
+	if (db_more(&nl) < 0)
+	    return;
 	db_printf("  pid   proc     addr    uid  ppid  pgrp  flag stat wmesg   wchan   cmd\n");
 	while (--np >= 0) {
 		/*
 		 * XXX just take 20 for now...
 		 */
-		db_more(&nl);
+		if (db_more(&nl) < 0)
+			return;
 		if (p == NULL) {
 			printf("oops, ran out of processes early!\n");
 			break;
@@ -110,6 +116,7 @@
 			db_printf("                 ");
 		}
 		db_printf(" %s\n", p->p_comm ? p->p_comm : "");
+		db_dump_td_tokens(p->p_thread);
 
 		p = p->p_list.le_next;
 		if (p == NULL && np > 0)
@@ -120,16 +127,46 @@
 	 * Dump running threads
 	 */
 	for (cpuidx = 0; cpuidx < ncpus; ++cpuidx) {
-	    thread_t td;
 	    struct globaldata *gd = &CPU_prvspace[cpuidx].mdglobaldata.mi;
+	    thread_t td;
+	    int j;
 
+	    if (db_more(&nl) < 0)
+		return;
 	    db_printf("cpu %d tdrunqmask %08x curthread %p reqflags %04x\n",
 		    gd->gd_cpuid, gd->gd_runqmask,
 		    gd->gd_curthread, gd->gd_reqflags);
+	    if (gd->gd_tokreqbase) {
+		lwkt_tokref_t ref;
+
+		if (db_more(&nl) < 0)
+		    return;
+		db_printf("      tokenrequests:");
+		for (ref = gd->gd_tokreqbase; ref; ref = ref->tr_next) {
+		    db_printf(" [r=%p,t=%p]", ref, ref->tr_tok);
+		}
+		db_printf("\n");
+	    }
+	    if (db_more(&nl) < 0)
+		return;
+	    db_printf("      INCOMMING IPIQS:");
+	    for (j = 0; j < ncpus; ++j) {
+		lwkt_ipiq_t ip = globaldata_find(j)->gd_ipiq;
+		if (ip != NULL) {
+		    ip = &ip[cpuidx];
+		    if (ip->ip_windex != ip->ip_rindex)
+			db_printf(" cpu%d:%d", j, ip->ip_windex - ip->ip_rindex);
+		}
+	    }
+	    db_printf("\n");
+
+	    if (db_more(&nl) < 0)
+		return;
 	    db_printf("  tdq     thread    pid flags  pri(act)        sp    wmesg comm\n");
 	    for (np = 0; np < 32; ++np) {
 		TAILQ_FOREACH(td, &gd->gd_tdrunq[np], td_threadq) {
-		    db_more(&nl);
+		    if (db_more(&nl) < 0)
+			return;
 		    db_printf("  %3d %p %3d %08x %3d(%3d) %p %8.8s %s\n",
 			np, td, 
 			(td->td_proc ? td->td_proc->p_pid : -1),
@@ -138,12 +175,18 @@
 			td->td_sp,
 			td->td_wmesg ? td->td_wmesg : "-",
 			td->td_proc ? td->td_proc->p_comm : td->td_comm);
+		    db_dump_td_tokens(td);
 		}
 	    }
+	    if (db_more(&nl) < 0)
+		return;
 	    db_printf("\n");
+	    if (db_more(&nl) < 0)
+		return;
 	    db_printf("  tdq     thread    pid flags  pri(act)        sp    wmesg comm\n");
 	    TAILQ_FOREACH(td, &gd->gd_tdallq, td_allq) {
-		db_more(&nl);
+		if (db_more(&nl) < 0)
+		    return;
 		db_printf("  %3d %p %3d %08x %3d(%3d) %p %8.8s %s\n",
 		    np, td, 
 		    (td->td_proc ? td->td_proc->p_pid : -1),
@@ -152,11 +195,42 @@
 		    td->td_sp,
 		    td->td_wmesg ? td->td_wmesg : "-",
 		    td->td_proc ? td->td_proc->p_comm : td->td_comm);
+		db_dump_td_tokens(td);
 	    }
 	}
-	printf("CURCPU %d CURTHREAD %p (%d)\n",
+	if (db_more(&nl) < 0)
+	    return;
+	db_printf("CURCPU %d CURTHREAD %p (%d)\n",
 	    mycpu->gd_cpuid,
 	    curthread,
 	    (curthread->td_proc ? curthread->td_proc->p_pid : -1)
 	);
+	db_dump_td_tokens(curthread);
+}
+
+static void
+db_dump_td_tokens(thread_t td)
+{
+	lwkt_tokref_t ref;
+	lwkt_token_t tok;
+
+	if (td->td_toks == NULL)
+		return;
+	db_printf("    TOKENS:");
+	for (ref = td->td_toks; ref; ref = ref->tr_next) {
+		tok = ref->tr_tok;
+
+		db_printf(" %p[tok=%p", ref, ref->tr_tok);
+		if (td->td_gd == tok->t_cpu)
+		    db_printf(",held");
+		if (ref->tr_magic == LWKT_TOKREF_MAGIC1)
+		    ;
+		else if (ref->tr_magic == LWKT_TOKREF_MAGIC2)
+		    db_printf(",wait");
+		else
+		    db_printf(",badmagic");
+		db_printf("]");
+	}
+	db_printf("\n");
 }
+
Index: dev/acpica5/acpi_ec.c
===================================================================
RCS file: /cvs/src/sys/dev/acpica5/acpi_ec.c,v
retrieving revision 1.1
diff -u -r1.1 acpi_ec.c
--- dev/acpica5/acpi_ec.c	21 Feb 2004 06:48:08 -0000	1.1
+++ dev/acpica5/acpi_ec.c	22 Feb 2004 07:24:40 -0000
@@ -269,7 +269,7 @@
 
     int			ec_glk;
     int			ec_glkhandle;
-    struct lwkt_token	ec_token;
+    struct lwkt_rwlock	ec_rwlock;
     int			ec_polldelay;
 };
 
@@ -304,13 +304,13 @@
     ACPI_STATUS	status = AE_OK;
 
     /* Always acquire this EC's mutex. */
-    lwkt_gettoken(&sc->ec_token);
+    lwkt_exlock(&sc->ec_rwlock, "acpi2");
 
     /* If _GLK is non-zero, also acquire the global lock. */
     if (sc->ec_glk) {
 	status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
 	if (ACPI_FAILURE(status))
-	    lwkt_reltoken(&sc->ec_token);
+	    lwkt_exunlock(&sc->ec_rwlock);
     }
 
     return (status);
@@ -321,7 +321,7 @@
 {
     if (sc->ec_glk)
 	AcpiReleaseGlobalLock(sc->ec_glkhandle);
-    lwkt_reltoken(&sc->ec_token);
+    lwkt_exunlock(&sc->ec_rwlock);
 }
 
 static void		EcGpeHandler(void *Context);
@@ -501,9 +501,9 @@
 	    if (sc->ec_glk != glk) {
 		ACPI_VPRINT(peer, acpi_device_get_parent_softc(peer),
 		    "Changing GLK from %d to %d\n", sc->ec_glk, glk);
-		lwkt_gettoken(&sc->ec_token);
+		lwkt_exlock(&sc->ec_rwlock, "acpi2");
 		sc->ec_glk = glk != 0 ? 1 : 0;
-		lwkt_reltoken(&sc->ec_token);
+		lwkt_exunlock(&sc->ec_rwlock);
 	    }
 	}
     }
@@ -525,7 +525,7 @@
     sc->ec_dev = dev;
     sc->ec_handle = acpi_get_handle(dev);
     sc->ec_polldelay = EC_POLL_DELAY;
-    lwkt_inittoken(&sc->ec_token);
+    lwkt_rwlock_init(&sc->ec_rwlock);
 
     /* Retrieve previously probed values via device ivars. */
     magic = acpi_get_magic(dev);
Index: dev/acpica5/Osd/OsdSynch.c
===================================================================
RCS file: /cvs/src/sys/dev/acpica5/Osd/OsdSynch.c,v
retrieving revision 1.1
diff -u -r1.1 OsdSynch.c
--- dev/acpica5/Osd/OsdSynch.c	21 Feb 2004 06:48:09 -0000	1.1
+++ dev/acpica5/Osd/OsdSynch.c	22 Feb 2004 00:34:02 -0000
@@ -349,29 +349,27 @@
 ACPI_STATUS
 AcpiOsCreateLock (ACPI_HANDLE *OutHandle)
 {
-    lwkt_token_t tok;
+    lwkt_rwlock_t lock;
 
     if (OutHandle == NULL)
 	return (AE_BAD_PARAMETER);
-    MALLOC(tok, lwkt_token_t, sizeof(*tok), M_ACPISEM, M_WAITOK | M_ZERO);
-    if (tok == NULL)
+    MALLOC(lock, lwkt_rwlock_t, sizeof(*lock), M_ACPISEM, M_WAITOK | M_ZERO);
+    if (lock == NULL)
 	return (AE_NO_MEMORY);
 
-    lwkt_inittoken(tok);
-    *OutHandle = (ACPI_HANDLE)tok;
+    lwkt_rwlock_init(lock);
+    *OutHandle = (ACPI_HANDLE)lock;
     return (AE_OK);
 }
 
 void
 AcpiOsDeleteLock (ACPI_HANDLE Handle)
 {
-#if 0
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    /*mtx_destroy(m);*/
-#endif
+    lwkt_rwlock_uninit(lock);
 }
 
 /*
@@ -382,19 +380,19 @@
 void
 AcpiOsAcquireLock (ACPI_HANDLE Handle, UINT32 Flags)
 {
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    lwkt_gettoken(tok);
+    lwkt_exlock(lock, "acpi1");
 }
 
 void
 AcpiOsReleaseLock (ACPI_HANDLE Handle, UINT32 Flags)
 {
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    lwkt_reltoken(tok);
+    lwkt_exunlock(lock);
 }
Index: dev/agp/agp.c
===================================================================
RCS file: /cvs/src/sys/dev/agp/agp.c,v
retrieving revision 1.9
diff -u -r1.9 agp.c
--- dev/agp/agp.c	20 Jan 2004 05:04:03 -0000	1.9
+++ dev/agp/agp.c	22 Feb 2004 04:50:46 -0000
@@ -278,7 +278,7 @@
 {
 	struct agp_softc *sc = device_get_softc(dev);
 	bus_release_resource(dev, SYS_RES_MEMORY, AGP_APBASE, sc->as_aperture);
-	lockmgr(&sc->as_lock, LK_DRAIN, 0, curthread); /* XXX */
+	lockmgr(&sc->as_lock, LK_DRAIN, NULL, curthread); /* XXX */
 	destroy_dev(sc->as_devnode);
 	agp_flush_cache();
 	return 0;
@@ -491,7 +491,7 @@
 	vm_page_t m;
 	int error;
 
-	lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
+	lockmgr(&sc->as_lock, LK_EXCLUSIVE, NULL, curthread); /* XXX */
 
 	if (mem->am_is_bound) {
 		device_printf(dev, "memory already bound\n");
@@ -554,7 +554,7 @@
 							   OFF_TO_IDX(k));
 					vm_page_unwire(m, 0);
 				}
-				lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+				lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
 				return error;
 			}
 		}
@@ -575,7 +575,7 @@
 	mem->am_offset = offset;
 	mem->am_is_bound = 1;
 
-	lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+	lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
 
 	return 0;
 }
@@ -587,7 +587,7 @@
 	vm_page_t m;
 	int i;
 
-	lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
+	lockmgr(&sc->as_lock, LK_EXCLUSIVE, NULL, curthread); /* XXX */
 
 	if (!mem->am_is_bound) {
 		device_printf(dev, "memory is not bound\n");
@@ -612,7 +612,7 @@
 	mem->am_offset = 0;
 	mem->am_is_bound = 0;
 
-	lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+	lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
 
 	return 0;
 }
Index: dev/disk/ccd/ccd.c
===================================================================
RCS file: /cvs/src/sys/dev/disk/ccd/ccd.c,v
retrieving revision 1.12
diff -u -r1.12 ccd.c
--- dev/disk/ccd/ccd.c	23 Sep 2003 05:03:40 -0000	1.12
+++ dev/disk/ccd/ccd.c	22 Feb 2004 05:33:17 -0000
@@ -1578,12 +1578,12 @@
 		vprint("ccdlookup: vnode info", vp);
 #endif
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	*vpp = vp;
 	return (0);
 bad:
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	/* vn_close does vrele() for vp */
 	(void)vn_close(vp, FREAD|FWRITE, td);
Index: dev/disk/vn/vn.c
===================================================================
RCS file: /cvs/src/sys/dev/disk/vn/vn.c,v
retrieving revision 1.7
diff -u -r1.7 vn.c
--- dev/disk/vn/vn.c	23 Sep 2003 05:03:46 -0000	1.7
+++ dev/disk/vn/vn.c	22 Feb 2004 05:50:14 -0000
@@ -387,12 +387,12 @@
 			auio.uio_rw = UIO_WRITE;
 		auio.uio_resid = bp->b_bcount;
 		auio.uio_td = curthread;
-		vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+		vn_lock(vn->sc_vp, NULL, LK_EXCLUSIVE | LK_RETRY, curthread);
 		if (bp->b_flags & B_READ)
 			error = VOP_READ(vn->sc_vp, &auio, IO_DIRECT, vn->sc_cred);
 		else
 			error = VOP_WRITE(vn->sc_vp, &auio, IO_NOWDRAIN, vn->sc_cred);
-		VOP_UNLOCK(vn->sc_vp, 0, curthread);
+		VOP_UNLOCK(vn->sc_vp, NULL, 0, curthread);
 		bp->b_resid = auio.uio_resid;
 
 		if (error) {
@@ -560,11 +560,11 @@
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (nd.ni_vp->v_type != VREG ||
 	    (error = VOP_GETATTR(nd.ni_vp, &vattr, td))) {
-		VOP_UNLOCK(nd.ni_vp, 0, td);
+		VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
 		(void) vn_close(nd.ni_vp, flags, td);
 		return (error ? error : EINVAL);
 	}
-	VOP_UNLOCK(nd.ni_vp, 0, td);
+	VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
 	vn->sc_secsize = DEV_BSIZE;
 	vn->sc_vp = nd.ni_vp;
 
@@ -715,9 +715,9 @@
 		auio.uio_rw = UIO_READ;
 		auio.uio_segflg = UIO_SYSSPACE;
 		auio.uio_resid = aiov.iov_len;
-		vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+		vn_lock(vn->sc_vp, NULL, LK_EXCLUSIVE | LK_RETRY, curthread);
 		error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
-		VOP_UNLOCK(vn->sc_vp, 0, curthread);
+		VOP_UNLOCK(vn->sc_vp, NULL, 0, curthread);
 		free(tmpbuf, M_TEMP);
 	}
 	return (error);
Index: dev/drm/drm_os_freebsd.h
===================================================================
RCS file: /cvs/src/sys/dev/drm/drm_os_freebsd.h,v
retrieving revision 1.8
diff -u -r1.8 drm_os_freebsd.h
--- dev/drm/drm_os_freebsd.h	13 Feb 2004 01:23:57 -0000	1.8
+++ dev/drm/drm_os_freebsd.h	22 Feb 2004 04:50:55 -0000
@@ -94,11 +94,11 @@
 #else
 #define DRM_CURPROC		curthread
 #define DRM_STRUCTPROC		struct thread
-#define DRM_SPINTYPE		struct lwkt_token
-#define DRM_SPININIT(l,name)	lwkt_inittoken(&l)
+#define DRM_SPINTYPE		struct lwkt_rwlock
+#define DRM_SPININIT(l,name)	lwkt_rwlock_init(&l)
 #define DRM_SPINUNINIT(l)
-#define DRM_SPINLOCK(l)		lwkt_gettoken(l)
-#define DRM_SPINUNLOCK(u)	lwkt_reltoken(u);
+#define DRM_SPINLOCK(l)		lwkt_exlock(l, "drm")
+#define DRM_SPINUNLOCK(u)	lwkt_exunlock(u);
 #define DRM_CURRENTPID		curthread->td_proc->p_pid
 #endif
 
@@ -107,8 +107,8 @@
  * code for that is not yet written */
 #define DRMFILE			void *
 #define DRM_IOCTL_ARGS		dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
-#define DRM_LOCK		lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_CURPROC)
-#define DRM_UNLOCK 		lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_CURPROC)
+#define DRM_LOCK		lockmgr(&dev->dev_lock, LK_EXCLUSIVE, NULL, DRM_CURPROC)
+#define DRM_UNLOCK 		lockmgr(&dev->dev_lock, LK_RELEASE, NULL, DRM_CURPROC)
 #define DRM_SUSER(td)		suser(td)
 #define DRM_TASKQUEUE_ARGS	void *arg, int pending
 #define DRM_IRQ_ARGS		void *arg
Index: dev/pccard/pccbb/pccbb.c
===================================================================
RCS file: /cvs/src/sys/dev/pccard/pccbb/pccbb.c,v
retrieving revision 1.1
diff -u -r1.1 pccbb.c
--- dev/pccard/pccbb/pccbb.c	10 Feb 2004 07:55:47 -0000	1.1
+++ dev/pccard/pccbb/pccbb.c	22 Feb 2004 04:51:14 -0000
@@ -719,14 +719,14 @@
 	if (error > 0)
 		return (ENXIO);
 
-	lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+	lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
 	bus_teardown_intr(brdev, sc->irq_res, sc->intrhand);
 	sc->flags |= CBB_KTHREAD_DONE;
 	if (sc->flags & CBB_KTHREAD_RUNNING) {
 		wakeup(sc);
 		tsleep(sc, 0, "pccbb", 0);
 	}
-	lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+	lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
 
 	bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
 	if (sc->flags & CBB_KLUDGE_ALLOC)
@@ -894,7 +894,7 @@
 		 * if there's a card already inserted, we do the
 		 * right thing.
 		 */
-		lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+		lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
 		if (sc->flags & CBB_KTHREAD_DONE)
 			break;
 
@@ -904,7 +904,7 @@
 			cbb_insert(sc);
 		else
 			cbb_removal(sc);
-		lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+		lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
 		/* mtx_unlock(&Giant); */
 
 		/*
@@ -917,7 +917,7 @@
 		    (sc->flags & CBB_KTHREAD_DONE) == 0)
 			err = tsleep(sc, 0, "pccbb", 1 * hz);
 	}
-	lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+	lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
 	sc->flags &= ~CBB_KTHREAD_RUNNING;
 	/* mtx_lock(&Giant); */
 	kthread_exit();
@@ -1019,9 +1019,9 @@
 		 * excellent results.
 		 */
 		if (sockevent & CBB_SOCKET_EVENT_CD) {
-			lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+			lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
 			sc->flags &= ~CBB_CARD_OK;
-			lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+			lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
 			wakeup(sc);
 		}
 		if (sockevent & CBB_SOCKET_EVENT_CSTS) {
Index: dev/raid/aac/aacvar.h
===================================================================
RCS file: /cvs/src/sys/dev/raid/aac/aacvar.h,v
retrieving revision 1.5
diff -u -r1.5 aacvar.h
--- dev/raid/aac/aacvar.h	13 Feb 2004 01:33:19 -0000	1.5
+++ dev/raid/aac/aacvar.h	22 Feb 2004 00:35:21 -0000
@@ -259,10 +259,10 @@
 #define AAC_LOCK_ACQUIRE(l)	mtx_lock(l)
 #define AAC_LOCK_RELEASE(l)	mtx_unlock(l)
 #else
-typedef struct lwkt_token aac_lock_t;
-#define AAC_LOCK_INIT(l, s)	lwkt_inittoken(l)
-#define AAC_LOCK_ACQUIRE(l)	lwkt_gettoken(l)
-#define AAC_LOCK_RELEASE(l)	lwkt_reltoken(l)
+typedef struct lwkt_rwlock aac_lock_t;
+#define AAC_LOCK_INIT(l, s)	lwkt_rwlock_init(l)
+#define AAC_LOCK_ACQUIRE(l)	lwkt_exlock(l, "aac")
+#define AAC_LOCK_RELEASE(l)	lwkt_exunlock(l)
 #endif
 
 #if defined(__FreeBSD__) && __FreeBSD_version >= 500005
Index: emulation/43bsd/43bsd_file.c
===================================================================
RCS file: /cvs/src/sys/emulation/43bsd/43bsd_file.c,v
retrieving revision 1.3
diff -u -r1.3 43bsd_file.c
--- emulation/43bsd/43bsd_file.c	11 Nov 2003 09:28:15 -0000	1.3
+++ emulation/43bsd/43bsd_file.c	22 Feb 2004 05:50:20 -0000
@@ -147,7 +147,7 @@
 	auio.uio_segflg = UIO_USERSPACE;
 	auio.uio_td = td;
 	auio.uio_resid = uap->count;
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	loff = auio.uio_offset = fp->f_offset;
 #	if (BYTE_ORDER != LITTLE_ENDIAN)
 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
@@ -200,7 +200,7 @@
 		}
 		FREE(dirbuf, M_TEMP);
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (error)
 		return (error);
 	if (uap->count == auio.uio_resid) {
Index: emulation/ibcs2/coff/imgact_coff.c
===================================================================
RCS file: /cvs/src/sys/emulation/ibcs2/coff/imgact_coff.c,v
retrieving revision 1.9
diff -u -r1.9 imgact_coff.c
--- emulation/ibcs2/coff/imgact_coff.c	20 Jan 2004 18:41:49 -0000	1.9
+++ emulation/ibcs2/coff/imgact_coff.c	22 Feb 2004 05:33:51 -0000
@@ -211,7 +211,7 @@
 	 * Lose the lock on the vnode. It's no longer needed, and must not
 	 * exist for the pagefault paging to work below.
 	 */
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 
   	if ((error = vm_mmap(kernel_map,
 			    (vm_offset_t *) &ptr,
@@ -284,7 +284,7 @@
     		panic(__FUNCTION__ " vm_map_remove failed");
 
  fail:
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
  unlocked_fail:
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vrele(nd.ni_vp);
Index: emulation/ibcs2/i386/ibcs2_misc.c
===================================================================
RCS file: /cvs/src/sys/emulation/ibcs2/i386/ibcs2_misc.c,v
retrieving revision 1.8
diff -u -r1.8 ibcs2_misc.c
--- emulation/ibcs2/i386/ibcs2_misc.c	20 Aug 2003 07:13:25 -0000	1.8
+++ emulation/ibcs2/i386/ibcs2_misc.c	22 Feb 2004 05:50:30 -0000
@@ -330,7 +330,7 @@
 	buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
 	buflen = min(buflen, MAXBSIZE);
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
 	aiov.iov_base = buf;
 	aiov.iov_len = buflen;
@@ -432,7 +432,7 @@
 out:
 	if (cookies)
 		free(cookies, M_TEMP);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	free(buf, M_TEMP);
 	return (error);
 }
@@ -479,7 +479,7 @@
 	buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
 	buflen = min(buflen, MAXBSIZE);
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
 	aiov.iov_base = buf;
 	aiov.iov_len = buflen;
@@ -585,7 +585,7 @@
 out:
 	if (cookies)
 		free(cookies, M_TEMP);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	free(buf, M_TEMP);
 	return (error);
 }
Index: emulation/linux/linux_file.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/linux_file.c,v
retrieving revision 1.15
diff -u -r1.15 linux_file.c
--- emulation/linux/linux_file.c	15 Nov 2003 00:40:06 -0000	1.15
+++ emulation/linux/linux_file.c	22 Feb 2004 05:50:41 -0000
@@ -290,7 +290,7 @@
 	buflen = max(LINUX_DIRBLKSIZ, nbytes);
 	buflen = min(buflen, MAXBSIZE);
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 again:
 	aiov.iov_base = buf;
@@ -429,7 +429,7 @@
 	if (cookies)
 		free(cookies, M_TEMP);
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	free(buf, M_TEMP);
 	return (error);
 }
Index: emulation/linux/linux_getcwd.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/linux_getcwd.c,v
retrieving revision 1.13
diff -u -r1.13 linux_getcwd.c
--- emulation/linux/linux_getcwd.c	9 Oct 2003 22:27:08 -0000	1.13
+++ emulation/linux/linux_getcwd.c	22 Feb 2004 05:50:48 -0000
@@ -313,7 +313,7 @@
 	 *	uvp is either NULL, or locked and held.
 	 */
 
-	error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+	error = vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (error) {
 		vrele(lvp);
 		lvp = NULL;
@@ -369,7 +369,7 @@
 				goto out;
 			}
 			VREF(lvp);
-			error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+			error = vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			if (error != 0) {
 				vrele(lvp);
 				lvp = NULL;
Index: emulation/linux/linux_misc.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/linux_misc.c,v
retrieving revision 1.18
diff -u -r1.18 linux_misc.c
--- emulation/linux/linux_misc.c	7 Jan 2004 10:54:57 -0000	1.18
+++ emulation/linux/linux_misc.c	22 Feb 2004 05:34:08 -0000
@@ -326,7 +326,7 @@
 	/*
 	 * Lock no longer needed
 	 */
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	locked = 0;
 
 	/* Pull in executable header into kernel_map */
@@ -464,7 +464,7 @@
 cleanup:
 	/* Unlock vnode if needed */
 	if (locked)
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 
 	/* Release the kernel mapping. */
 	if (a_out)
Index: emulation/linux/i386/linprocfs/linprocfs_subr.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v
retrieving revision 1.6
diff -u -r1.6 linprocfs_subr.c
--- emulation/linux/i386/linprocfs/linprocfs_subr.c	27 Aug 2003 06:30:04 -0000	1.6
+++ emulation/linux/i386/linprocfs/linprocfs_subr.c	22 Feb 2004 07:22:32 -0000
@@ -99,7 +99,7 @@
 		if (pfs->pfs_pid == pid &&
 		    pfs->pfs_type == pfs_type &&
 		    vp->v_mount == mp) {
-			if (vget(vp, 0, td))
+			if (vget(vp, NULL, 0, td))
 				goto loop;
 			*vpp = vp;
 			return (0);
Index: emulation/linux/i386/linprocfs/linprocfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v
retrieving revision 1.9
diff -u -r1.9 linprocfs_vnops.c
--- emulation/linux/i386/linprocfs/linprocfs_vnops.c	23 Sep 2003 05:03:51 -0000	1.9
+++ emulation/linux/i386/linprocfs/linprocfs_vnops.c	22 Feb 2004 05:50:36 -0000
@@ -338,7 +338,7 @@
 {
 	struct vnode *vp = ap->a_vp;
 
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 
 	return (0);
 }
@@ -669,7 +669,7 @@
 	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
 		VREF(dvp);
-		/* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
+		/* vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, curp); */
 		return (0);
 	}
 
Index: emulation/svr4/svr4_misc.c
===================================================================
RCS file: /cvs/src/sys/emulation/svr4/svr4_misc.c,v
retrieving revision 1.20
diff -u -r1.20 svr4_misc.c
--- emulation/svr4/svr4_misc.c	12 Feb 2004 23:33:26 -0000	1.20
+++ emulation/svr4/svr4_misc.c	22 Feb 2004 05:50:55 -0000
@@ -286,7 +286,7 @@
 	buflen = max(DIRBLKSIZ, nbytes);
 	buflen = min(buflen, MAXBSIZE);
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
 	aiov.iov_base = buf;
 	aiov.iov_len = buflen;
@@ -400,7 +400,7 @@
 out:
 	if (cookies)
 		free(cookies, M_TEMP);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	free(buf, M_TEMP);
 	return error;
 }
@@ -440,7 +440,7 @@
 
 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -514,7 +514,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (cookiebuf)
 		free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
@@ -609,12 +609,12 @@
 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
 		return error;
 	vp = (struct vnode *) fp->f_data;
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (vp->v_type != VDIR)
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, cred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (error)
 		return error;
 	VREF(vp);
Index: i386/conf/LINT
===================================================================
RCS file: /cvs/src/sys/i386/conf/LINT,v
retrieving revision 1.22
diff -u -r1.22 LINT
--- i386/conf/LINT	24 Feb 2004 18:11:16 -0000	1.22
+++ i386/conf/LINT	25 Feb 2004 18:12:23 -0000
@@ -2683,8 +2683,6 @@
 options		UBSEC_DEBUG	# enable debugging support: hw.ubsec.debug
 options		UBSEC_RNDTEST	# enable rndtest support
 
-device		acpica		# basic ACPI support
-
 # DRM options:
 # mgadrm:    AGP Matrox G200, G400, G450, G550
 # tdfxdrm:   3dfx Voodoo 3/4/5 and Banshee
Index: i386/i386/machdep.c
===================================================================
RCS file: /cvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.54
diff -u -r1.54 machdep.c
--- i386/i386/machdep.c	17 Feb 2004 19:38:53 -0000	1.54
+++ i386/i386/machdep.c	23 Feb 2004 05:56:32 -0000
@@ -2648,6 +2648,7 @@
 #ifdef SMP
 	cpu_get_initial_mplock();
 #endif
+	/* DEPRECATED */
 	spin_lock_init(&mcount_spinlock);
 	spin_lock_init(&fast_intr_spinlock);
 	spin_lock_init(&intr_spinlock);
@@ -2657,5 +2658,8 @@
 	spin_lock_init(&com_spinlock);
 	spin_lock_init(&clock_spinlock);
 	spin_lock_init(&cons_spinlock);
+
+	/* our token pool needs to work early */
+	lwkt_token_pool_init();
 }
 
Index: i386/i386/mp_machdep.c
===================================================================
RCS file: /cvs/src/sys/i386/i386/mp_machdep.c,v
retrieving revision 1.23
diff -u -r1.23 mp_machdep.c
--- i386/i386/mp_machdep.c	21 Feb 2004 06:37:07 -0000	1.23
+++ i386/i386/mp_machdep.c	23 Feb 2004 08:24:23 -0000
@@ -280,7 +280,7 @@
 static int	mp_capable;
 static u_int	boot_address;
 static u_int	base_memory;
-static cpumask_t smp_startup_mask = 1;	/* which cpus have been started */
+static int	mp_finish;
 
 static int	picmode;		/* 0: virtual wire mode, 1: PIC mode */
 static mpfps_t	mpfps;
@@ -298,6 +298,7 @@
 static int	start_ap(struct mdglobaldata *gd, u_int boot_addr);
 static int	apic_int_is_bus_type(int intr, int bus_type);
 
+static cpumask_t smp_startup_mask = 1;	/* which cpus have been started */
 cpumask_t smp_active_mask = 1;	/* which cpus are ready for IPIs etc? */
 SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RD, &smp_active_mask, 0, "");
 
@@ -2313,7 +2314,6 @@
  * loop for the idlethread.  Interrupts are disabled on entry and should
  * remain disabled at return.
  */
-
 void
 ap_init(void)
 {
@@ -2332,17 +2332,27 @@
 	cpu_mb1();
 
 	/*
-	 * Get the MP lock so we can finish initializing.  Note: we are
-	 * in a critical section.  td_mpcount must always be bumped prior
-	 * to obtaining the actual lock.
+	 * Interlock for finalization.  Wait until mp_finish is non-zero,
+	 * then get the MP lock.
+	 *
+	 * Note: We are in a critical section.
+	 *
+	 * Note: We have to synchronize td_mpcount to our desired MP state
+	 * before calling cpu_try_mplock().
+	 *
+	 * Note: we are the idle thread, we can only spin.
+	 *
+	 * Note: cpu_mb1() is memory volatile and prevents mp_finish from
+	 * 	 being cached.
 	 */
 	++curthread->td_mpcount;
+	while (mp_finish == 0)
+	    cpu_mb1();
 	while (cpu_try_mplock() == 0)
 	    ;
 
 	/* BSP may have changed PTD while we're waiting for the lock */
 	cpu_invltlb();
-	smp_active_mask |= 1 << mycpu->gd_cpuid;
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
 	lidt(&r_idt);
@@ -2377,27 +2387,43 @@
 	/* Set memory range attributes for this CPU to match the BSP */
 	mem_range_AP_init();
 
-	/*
-	 * AP helper function for kernel memory support.  This will create
-	 * a memory reserve for the AP that is necessary to avoid certain
-	 * memory deadlock situations, such as when the kernel_map needs
-	 * a vm_map_entry and zalloc has no free entries and tries to allocate
-	 * a new one from the ... kernel_map :-)
-	 */
-	kmem_cpu_init();
-
-	sched_thread_init();	/* startup helper thread(s) one per cpu */
 	initclocks_pcpu();	/* clock interrupts (via IPIs) */
 
 	/*
 	 * The idle loop doesn't expect the BGL to be held and while
 	 * lwkt_switch() normally cleans things up this is a special case
 	 * because we returning almost directly into the idle loop.
+	 *
+	 * The idle thread is never placed on the runq, make sure
+	 * nothing we've done put it thre.
 	 */
 	KKASSERT(curthread->td_mpcount == 1);
+	smp_active_mask |= 1 << mycpu->gd_cpuid;
 	rel_mplock();
+	KKASSERT((curthread->td_flags & TDF_RUNQ) == 0);
 }
 
+/*
+ * Get SMP fully working before we start initializing devices.
+ */
+static
+void
+ap_finish(void)
+{
+	mp_finish = 1;
+	if (bootverbose)
+		printf("Finish MP startup");
+	rel_mplock();
+	while (smp_active_mask != smp_startup_mask)
+		cpu_mb1();
+	while (cpu_try_mplock() == 0)
+		;
+	if (bootverbose)
+		printf("Active CPU Mask: %08x\n", smp_active_mask);
+}
+
+SYSINIT(finishsmp, SI_SUB_FINISH_SMP, SI_ORDER_FIRST, ap_finish, NULL)
+
 #ifdef APIC_INTR_REORDER
 /*
  *     Maintain mapping from softintr vector to isr bit in local apic.
@@ -2492,6 +2518,23 @@
 void
 cpu_send_ipiq(int dcpu)
 {
-	if ((1 << dcpu) & smp_active_mask)
-		selected_apic_ipi(1 << dcpu, XIPIQ_OFFSET, APIC_DELMODE_FIXED);
+        if ((1 << dcpu) & smp_active_mask)
+                single_apic_ipi(dcpu, XIPIQ_OFFSET, APIC_DELMODE_FIXED);
 }
+
+#if 0	/* single_apic_ipi_passive() not working yet */
+/*
+ * Returns 0 on failure, 1 on success
+ */
+int
+cpu_send_ipiq_passive(int dcpu)
+{
+        int r = 0;
+        if ((1 << dcpu) & smp_active_mask) {
+                r = single_apic_ipi_passive(dcpu, XIPIQ_OFFSET,
+                                        APIC_DELMODE_FIXED);
+        }
+	return(r);
+}
+#endif
+
Index: i386/i386/mpapic.c
===================================================================
RCS file: /cvs/src/sys/i386/i386/mpapic.c,v
retrieving revision 1.7
diff -u -r1.7 mpapic.c
--- i386/i386/mpapic.c	26 Aug 2003 21:42:18 -0000	1.7
+++ i386/i386/mpapic.c	23 Feb 2004 07:05:03 -0000
@@ -514,12 +514,13 @@
 	return 0;
 }
 
-static int
-apic_ipi_singledest(int cpu, int vector, int delivery_mode)
+void
+single_apic_ipi(int cpu, int vector, int delivery_mode)
 {
 	u_long  icr_lo;
 	u_long  icr_hi;
 
+	crit_enter();
 	if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
 	    unsigned int eflags = read_eflags();
 	    cpu_enable_intr();
@@ -538,9 +539,44 @@
 
 	/* write APIC ICR */
 	lapic.icr_lo = icr_lo;
-	return 0;
+	crit_exit();
+}
+
+#if 0	
+
+/*
+ * Returns 0 if the apic is busy, 1 if we were able to queue the request.
+ *
+ * NOT WORKING YET!  The code as-is may end up not queueing an IPI at all
+ * to the target, and the scheduler does not 'poll' for IPI messages.
+ */
+int
+single_apic_ipi_passive(int cpu, int vector, int delivery_mode)
+{
+	u_long  icr_lo;
+	u_long  icr_hi;
+
+	crit_enter();
+	if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
+	    crit_exit();
+	    return(0);
+	}
+	icr_hi = lapic.icr_hi & ~APIC_ID_MASK;
+	icr_hi |= (CPU_TO_ID(cpu) << 24);
+	lapic.icr_hi = icr_hi;
+
+	/* build IRC_LOW */
+	icr_lo = (lapic.icr_lo & APIC_RESV2_MASK)
+	    | APIC_DEST_DESTFLD | delivery_mode | vector;
+
+	/* write APIC ICR */
+	lapic.icr_lo = icr_lo;
+	crit_exit();
+	return(1);
 }
 
+#endif
+
 /*
  * Send APIC IPI 'vector' to 'target's via 'delivery_mode'.
  *
@@ -548,20 +584,16 @@
  * valid system INT vector.  Delivery mode may be either
  * APIC_DELMODE_FIXED or APIC_DELMODE_LOWPRIO.
  */
-int
+void
 selected_apic_ipi(u_int target, int vector, int delivery_mode)
 {
-	int status = 0;
-
 	crit_enter();
 	while (target) {
 		int n = bsfl(target);
 		target &= ~(1 << n);
-		if (apic_ipi_singledest(n, vector, delivery_mode) < 0)
-			status |= 1 << n;
+		single_apic_ipi(n, vector, delivery_mode);
 	}
 	crit_exit();
-	return(status);
 }
 
 #endif	/* APIC_IO */
Index: i386/i386/nexus.c
===================================================================
RCS file: /cvs/src/sys/i386/i386/nexus.c,v
retrieving revision 1.9
diff -u -r1.9 nexus.c
--- i386/i386/nexus.c	23 Feb 2004 21:23:42 -0000	1.9
+++ i386/i386/nexus.c	23 Feb 2004 21:24:01 -0000
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/nexus.c,v 1.26.2.10 2003/02/22 13:16:45 imp Exp $
- * $DragonFly: src/sys/i386/i386/nexus.c,v 1.9 2004/02/23 21:23:42 dillon Exp $
+ * $DragonFly$
  */
 
 /*
@@ -82,6 +82,7 @@
 
 static struct rman irq_rman, drq_rman, port_rman, mem_rman;
 
+static void nexus_identify(driver_t *, device_t);
 static	int nexus_probe(device_t);
 static	int nexus_attach(device_t);
 static	int nexus_print_all_resources(device_t dev);
@@ -108,6 +109,7 @@
 
 static device_method_t nexus_methods[] = {
 	/* Device interface */
+	DEVMETHOD(device_identify,	nexus_identify),
 	DEVMETHOD(device_probe,		nexus_probe),
 	DEVMETHOD(device_attach,	nexus_attach),
 	DEVMETHOD(device_detach,	bus_generic_detach),
@@ -142,9 +144,32 @@
 
 DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
 
+static void
+nexus_identify(driver_t *driver, device_t parent)
+{
+        /*
+         * Add child device with order of 1 so it gets probed
+         * after ACPI (which is at order 0.
+         */
+        if (BUS_ADD_CHILD(parent, 1, "legacy", 0) == NULL)
+                panic("legacy: could not attach");
+}
+
 static int
 nexus_probe(device_t dev)
 {
+#if 0	/* FUTURE */
+	device_t acpi;
+#endif
+
+#if 0	/* FUTURE */
+	/*
+	 * Fail to probe if ACPI is ok.
+	 */
+	acpi = devclass_get_device(devclass_find("acpi"), 0);
+	if (acpi != NULL && device_is_alive(acpi))
+		return(ENXIO);
+#endif
 
 	device_quiet(dev);	/* suppress attach message for neatness */
 
@@ -229,9 +254,15 @@
 	device_t	child;
 
 	/*
-	 * First, deal with the children we know about already
+	 * First, let our child driver's identify any child devices that
+	 * they can find.  Once that is done attach any devices that we
+	 * found.
 	 */
+#if 0 /* FUTURE */
+	bus_generic_probe(dev);
+#endif
 	bus_generic_attach(dev);
+
 	/*
 	 * And if we didn't see EISA or ISA on a pci bridge, create some
 	 * connection points now so they show up "on motherboard".
Index: i386/i386/pmap.c
===================================================================
RCS file: /cvs/src/sys/i386/i386/pmap.c,v
retrieving revision 1.31
diff -u -r1.31 pmap.c
--- i386/i386/pmap.c	21 Feb 2004 06:37:07 -0000	1.31
+++ i386/i386/pmap.c	22 Feb 2004 07:21:40 -0000
@@ -1535,7 +1535,7 @@
 	 * the SMP case.
 	 */
 	if (oldpte & PG_G)
-		cpu_invlpg(va);
+		cpu_invlpg((void *)va);
 	pmap->pm_stats.resident_count -= 1;
 	if (oldpte & PG_MANAGED) {
 		m = PHYS_TO_VM_PAGE(oldpte);
Index: i386/include/mpapic.h
===================================================================
RCS file: /cvs/src/sys/i386/include/mpapic.h,v
retrieving revision 1.6
diff -u -r1.6 mpapic.h
--- i386/include/mpapic.h	21 Feb 2004 06:37:07 -0000	1.6
+++ i386/include/mpapic.h	21 Feb 2004 21:26:02 -0000
@@ -64,18 +64,6 @@
 #ifdef SMP
 
 /*
- * send an IPI INTerrupt containing 'vector' to CPUs in 'targetMap'
- * 'targetMap' is a bitfiled of length 14,
- *   APIC #0 == bit 0, ..., APIC #14 == bit 14
- *   NOTE: these are LOGICAL APIC IDs
- */
-static __inline int
-selected_procs_ipi(int targetMap, int vector)
-{
-	return selected_apic_ipi(targetMap, vector, APIC_DELMODE_FIXED);
-}
-
-/*
  * send an IPI INTerrupt containing 'vector' to all CPUs EXCEPT myself
  */
 static __inline int
Index: i386/include/smp.h
===================================================================
RCS file: /cvs/src/sys/i386/include/smp.h,v
retrieving revision 1.10
diff -u -r1.10 smp.h
--- i386/include/smp.h	21 Feb 2004 06:37:07 -0000	1.10
+++ i386/include/smp.h	22 Feb 2004 22:50:01 -0000
@@ -128,7 +128,9 @@
 void	apic_initialize		(void);
 void	imen_dump		(void);
 int	apic_ipi		(int, int, int);
-int	selected_apic_ipi	(u_int, int, int);
+void	selected_apic_ipi	(u_int, int, int);
+void	single_apic_ipi(int cpu, int vector, int delivery_mode);
+int	single_apic_ipi_passive(int cpu, int vector, int delivery_mode);
 int	io_apic_setup		(int);
 void	io_apic_setup_intpin	(int, int);
 void	io_apic_set_id		(int, int);
@@ -144,6 +146,7 @@
 int	read_apic_timer		(void);
 void	u_sleep			(int);
 void	cpu_send_ipiq		(int);
+int	cpu_send_ipiq_passive	(int);
 
 /* global data in init_smp.c */
 extern cpumask_t		smp_active_mask;
Index: kern/imgact_elf.c
===================================================================
RCS file: /cvs/src/sys/kern/imgact_elf.c,v
retrieving revision 1.16
diff -u -r1.16 imgact_elf.c
--- kern/imgact_elf.c	20 Jan 2004 18:41:51 -0000	1.16
+++ kern/imgact_elf.c	22 Feb 2004 19:04:49 -0000
@@ -387,7 +387,7 @@
 	 */
 	error = exec_check_permissions(imgp);
 	if (error) {
-		VOP_UNLOCK(nd->ni_vp, 0, td);
+		VOP_UNLOCK(nd->ni_vp, NULL, 0, td);
 		goto fail;
 	}
 
@@ -398,7 +398,7 @@
 	 */
 	if (error == 0)
 		nd->ni_vp->v_flag |= VTEXT;
-	VOP_UNLOCK(nd->ni_vp, 0, td);
+	VOP_UNLOCK(nd->ni_vp, NULL, 0, td);
 	if (error)
                 goto fail;
 
@@ -492,6 +492,7 @@
 	const char *interp = NULL;
 	Elf_Brandinfo *brand_info;
 	char *path;
+	lwkt_tokref ilock;
 
 	error = 0;
 
@@ -525,9 +526,9 @@
 	 * a context switch.  Better safe than sorry; I really don't want
 	 * the file to change while it's being loaded.
 	 */
-	lwkt_gettoken(&imgp->vp->v_interlock);
+	lwkt_gettoken(&ilock, imgp->vp->v_interlock);
 	imgp->vp->v_flag |= VTEXT;
-	lwkt_reltoken(&imgp->vp->v_interlock);
+	lwkt_reltoken(&ilock);
 
 	vmspace = imgp->proc->p_vmspace;
 
@@ -815,7 +816,7 @@
 	fp->f_flag = O_CREAT|O_WRONLY|O_NOFOLLOW;
 	fp->f_ops = &vnops;
 	fp->f_type = DTYPE_VNODE;
-	VOP_UNLOCK(vp, 0, p->p_thread);
+	VOP_UNLOCK(vp, NULL, 0, p->p_thread);
 	
 	error = generic_elf_coredump(p, fp, limit);
 
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.27
diff -u -r1.27 init_main.c
--- kern/init_main.c	30 Jan 2004 05:42:17 -0000	1.27
+++ kern/init_main.c	23 Feb 2004 03:15:38 -0000
@@ -465,7 +465,7 @@
 	p->p_fd->fd_rdir = rootvnode;
 	VREF(p->p_fd->fd_rdir);
 	vfs_cache_setroot(rootvnode);
-	VOP_UNLOCK(rootvnode, 0, curthread);
+	VOP_UNLOCK(rootvnode, NULL, 0, curthread);
 
 	/*
 	 * Need just enough stack to hold the faked-up "execve()" arguments.
@@ -613,6 +613,7 @@
 	TAILQ_INIT(&gd->gd_systimerq);
 	gd->gd_cpuid = cpuid;
 	lwkt_gdinit(gd);
+	vm_map_entry_reserve_cpu_init(gd);
 }
 
 
Index: kern/kern_acct.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_acct.c,v
retrieving revision 1.8
diff -u -r1.8 kern_acct.c
--- kern/kern_acct.c	29 Sep 2003 18:52:06 -0000	1.8
+++ kern/kern_acct.c	22 Feb 2004 05:34:32 -0000
@@ -136,7 +136,7 @@
 		if (error)
 			return (error);
 		NDFREE(&nd, NDF_ONLY_PNBUF);
-		VOP_UNLOCK(nd.ni_vp, 0, td);
+		VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
 		if (nd.ni_vp->v_type != VREG) {
 			vn_close(nd.ni_vp, FWRITE | O_APPEND, td);
 			return (EACCES);
Index: kern/kern_acl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_acl.c,v
retrieving revision 1.5
diff -u -r1.5 kern_acl.c
--- kern/kern_acl.c	23 Sep 2003 05:03:51 -0000	1.5
+++ kern/kern_acl.c	22 Feb 2004 05:51:06 -0000
@@ -80,9 +80,9 @@
 	ucred = td->td_proc->p_ucred;
 
 	VOP_LEASE(vp, td, ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_SETACL(vp, type, &inkernacl, ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return(error);
 }
 
@@ -118,9 +118,9 @@
 	KKASSERT(td->td_proc);
 	ucred = td->td_proc->p_ucred;
 	VOP_LEASE(vp, td, ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_SETACL(vp, ACL_TYPE_DEFAULT, 0, ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.18
diff -u -r1.18 kern_descrip.c
--- kern/kern_descrip.c	17 Jan 2004 21:23:38 -0000	1.18
+++ kern/kern_descrip.c	22 Feb 2004 05:34:44 -0000
@@ -1353,7 +1353,7 @@
                        fp->f_flag = flags;
                        fp->f_ops = &vnops;
                        fp->f_type = DTYPE_VNODE;
-                       VOP_UNLOCK(nd.ni_vp, 0, td);
+                       VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
                        devnull = fd;
                } else {
                        error = kern_dup(DUP_FIXED, devnull, i, &retval);
Index: kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.19
diff -u -r1.19 kern_exec.c
--- kern/kern_exec.c	20 Jan 2004 18:41:51 -0000	1.19
+++ kern/kern_exec.c	22 Feb 2004 05:34:52 -0000
@@ -186,12 +186,12 @@
 	 */
 	error = exec_check_permissions(imgp);
 	if (error) {
-		VOP_UNLOCK(imgp->vp, 0, td);
+		VOP_UNLOCK(imgp->vp, NULL, 0, td);
 		goto exec_fail_dealloc;
 	}
 
 	error = exec_map_first_page(imgp);
-	VOP_UNLOCK(imgp->vp, 0, td);
+	VOP_UNLOCK(imgp->vp, NULL, 0, td);
 	if (error)
 		goto exec_fail_dealloc;
 
Index: kern/kern_fp.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_fp.c,v
retrieving revision 1.4
diff -u -r1.4 kern_fp.c
--- kern/kern_fp.c	19 Oct 2003 23:23:26 -0000	1.4
+++ kern/kern_fp.c	22 Feb 2004 05:35:07 -0000
@@ -105,7 +105,7 @@
 	fp->f_flag = flags;
 	fp->f_ops = &vnops;
 	fp->f_type = DTYPE_VNODE;
-	VOP_UNLOCK(nd.ni_vp, 0, td);
+	VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     } else {
 	fdrop(fp, td);
 	*fpp = NULL;
@@ -191,7 +191,7 @@
     if (flags & FWRITE)
 	vp->v_writecount++;
 done:
-    VOP_UNLOCK(vp, 0, td);
+    VOP_UNLOCK(vp, NULL, 0, td);
     return (error);
 }
 
Index: kern/kern_ktrace.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.12
diff -u -r1.12 kern_ktrace.c
--- kern/kern_ktrace.c	14 Feb 2004 12:14:30 -0000	1.12
+++ kern/kern_ktrace.c	22 Feb 2004 05:51:09 -0000
@@ -268,7 +268,7 @@
 		}
 		NDFREE(&nd, NDF_ONLY_PNBUF);
 		vp = nd.ni_vp;
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		if (vp->v_type != VREG) {
 			(void) vn_close(vp, FREAD|FWRITE, td);
 			curp->p_traceflag &= ~KTRFAC_ACTIVE;
@@ -487,14 +487,14 @@
 		if (uio != NULL)
 			kth->ktr_len += uio->uio_resid;
 	}
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	(void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 	error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred);
 	if (error == 0 && uio != NULL) {
 		(void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 		error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred);
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (!error)
 		return;
 	/*
Index: kern/kern_linker.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_linker.c,v
retrieving revision 1.17
diff -u -r1.17 kern_linker.c
--- kern/kern_linker.c	17 Jan 2004 03:24:50 -0000	1.17
+++ kern/kern_linker.c	22 Feb 2004 05:35:17 -0000
@@ -326,14 +326,14 @@
 	goto out;
     sprintf(koname, "%s.ko", filename);
 
-    lockmgr(&lock, LK_SHARED, 0, curthread);
+    lockmgr(&lock, LK_SHARED, NULL, curthread);
     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
 	if (!strcmp(lf->filename, koname))
 	    break;
 	if (!strcmp(lf->filename, filename))
 	    break;
     }
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
 out:
     if (koname)
@@ -346,11 +346,11 @@
 {
     linker_file_t lf = 0;
 
-    lockmgr(&lock, LK_SHARED, 0, curthread);
+    lockmgr(&lock, LK_SHARED, NULL, curthread);
     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link))
 	if (lf->id == fileid)
 	    break;
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
     return lf;
 }
@@ -369,7 +369,7 @@
 	filename = pathname;
 
     KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
-    lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
+    lockmgr(&lock, LK_EXCLUSIVE, NULL, curthread);
     namelen = strlen(filename) + 1;
     lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK);
     if (!lf)
@@ -392,7 +392,7 @@
     TAILQ_INSERT_TAIL(&linker_files, lf, link);
 
 out:
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
     return lf;
 }
 
@@ -409,7 +409,7 @@
 	return EPERM; 
 
     KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
-    lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
+    lockmgr(&lock, LK_EXCLUSIVE, NULL, curthread);
     if (file->refs == 1) {
 	KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
 	/*
@@ -430,7 +430,7 @@
 	    if ((error = module_unload(mod)) != 0) {
 		KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
 			       mod));
-		lockmgr(&lock, LK_RELEASE, 0, curthread);
+		lockmgr(&lock, LK_RELEASE, NULL, curthread);
 		goto out;
 	    }
 
@@ -459,7 +459,7 @@
 
     file->refs--;
     if (file->refs > 0) {
-	lockmgr(&lock, LK_RELEASE, 0, curthread);
+	lockmgr(&lock, LK_RELEASE, NULL, curthread);
 	goto out;
     }
 
@@ -470,7 +470,7 @@
     }
 
     TAILQ_REMOVE(&linker_files, file, link);
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
     for (i = 0; i < file->ndeps; i++)
 	linker_file_unload(file->deps[i]);
@@ -1129,7 +1129,7 @@
 	if (error == 0) {
 	    NDFREE(&nd, NDF_ONLY_PNBUF);
 	    type = nd.ni_vp->v_type;
-	    VOP_UNLOCK(nd.ni_vp, 0, td);
+	    VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
 	    vn_close(nd.ni_vp, FREAD, td);
 	    if (type == VREG)
 		return(result);
Index: kern/kern_lock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_lock.c,v
retrieving revision 1.9
diff -u -r1.9 kern_lock.c
--- kern/kern_lock.c	12 Nov 2003 22:08:02 -0000	1.9
+++ kern/kern_lock.c	23 Feb 2004 08:36:31 -0000
@@ -123,10 +123,9 @@
 	while ((lkp->lk_flags & wanted) != 0) {
 		lkp->lk_flags |= LK_WAIT_NONZERO;
 		lkp->lk_waitcount++;
-		lwkt_reltoken(&lkp->lk_interlock);
+		/* note: serialization lock is held through tsleep */
 		error = tsleep(lkp, lkp->lk_prio, lkp->lk_wmesg, 
 			    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
-		lwkt_gettoken(&lkp->lk_interlock);
 		if (lkp->lk_waitcount == 1) {
 			lkp->lk_flags &= ~LK_WAIT_NONZERO;
 			lkp->lk_waitcount = 0;
@@ -155,15 +154,16 @@
  */
 int
 #ifndef	DEBUG_LOCKS
-lockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
+lockmgr(struct lock *lkp, u_int flags, lwkt_tokref_t interlkp,
 	struct thread *td)
 #else
-debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
+debuglockmgr(struct lock *lkp, u_int flags, lwkt_tokref_t interlkp,
 	struct thread *td, const char *name, const char *file, int line)
 #endif
 {
 	int error;
 	int extflags;
+	lwkt_tokref ilock;
 	static int didpanic;
 
 	error = 0;
@@ -198,7 +198,7 @@
 #endif
 	}
 
-	lwkt_gettoken(&lkp->lk_interlock);
+	lwkt_gettoken(&ilock, &lkp->lk_interlock);
 	if (flags & LK_INTERLOCK)
 		lwkt_reltoken(interlkp);
 
@@ -427,7 +427,7 @@
 		break;
 
 	default:
-		lwkt_reltoken(&lkp->lk_interlock);
+		lwkt_reltoken(&ilock);
 		panic("lockmgr: unknown locktype request %d",
 		    flags & LK_TYPE_MASK);
 		/* NOTREACHED */
@@ -438,7 +438,7 @@
 		lkp->lk_flags &= ~LK_WAITDRAIN;
 		wakeup((void *)&lkp->lk_flags);
 	}
-	lwkt_reltoken(&lkp->lk_interlock);
+	lwkt_reltoken(&ilock);
 	return (error);
 }
 
@@ -456,11 +456,10 @@
 
 	while (lkp->lk_flags & LK_ALL) {
 		lkp->lk_flags |= LK_WAITDRAIN;
-		lwkt_reltoken(&lkp->lk_interlock);
+		/* interlock serialization held through tsleep */
 		error = tsleep(&lkp->lk_flags, lkp->lk_prio,
 			lkp->lk_wmesg, 
 			((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
-		lwkt_gettoken(&lkp->lk_interlock);
 		if (error)
 			return error;
 		if (extflags & LK_SLEEPFAIL) {
@@ -481,7 +480,7 @@
 	int timo;
 	int flags;
 {
-	lwkt_inittoken(&lkp->lk_interlock);
+	lwkt_token_init(&lkp->lk_interlock);
 	lkp->lk_flags = (flags & LK_EXTFLG_MASK);
 	lkp->lk_sharecount = 0;
 	lkp->lk_waitcount = 0;
@@ -498,9 +497,10 @@
 int
 lockstatus(struct lock *lkp, struct thread *td)
 {
+	lwkt_tokref ilock;
 	int lock_type = 0;
 
-	lwkt_gettoken(&lkp->lk_interlock);
+	lwkt_gettoken(&ilock, &lkp->lk_interlock);
 	if (lkp->lk_exclusivecount != 0) {
 		if (td == NULL || lkp->lk_lockholder == td)
 			lock_type = LK_EXCLUSIVE;
@@ -509,7 +509,7 @@
 	} else if (lkp->lk_sharecount != 0) {
 		lock_type = LK_SHARED;
 	}
-	lwkt_reltoken(&lkp->lk_interlock);
+	lwkt_reltoken(&ilock);
 	return (lock_type);
 }
 
@@ -520,11 +520,12 @@
 lockcount(lkp)
 	struct lock *lkp;
 {
+	lwkt_tokref ilock;
 	int count;
 
-	lwkt_gettoken(&lkp->lk_interlock);
+	lwkt_gettoken(&ilock, &lkp->lk_interlock);
 	count = lkp->lk_exclusivecount + lkp->lk_sharecount;
-	lwkt_reltoken(&lkp->lk_interlock);
+	lwkt_reltoken(&ilock);
 	return (count);
 }
 
Index: kern/kern_sig.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.26
diff -u -r1.26 kern_sig.c
--- kern/kern_sig.c	12 Feb 2004 06:57:48 -0000	1.26
+++ kern/kern_sig.c	22 Feb 2004 05:51:13 -0000
@@ -1467,7 +1467,7 @@
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vp = nd.ni_vp;
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	lf.l_whence = SEEK_SET;
 	lf.l_start = 0;
 	lf.l_len = 0;
@@ -1484,12 +1484,12 @@
 	}
 
 	VATTR_NULL(&vattr);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	vattr.va_size = 0;
 	VOP_LEASE(vp, td, cred, LEASE_WRITE);
 	VOP_SETATTR(vp, &vattr, cred, td);
 	p->p_acflag |= ACORE;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 
 	error = p->p_sysent->sv_coredump ?
 	  p->p_sysent->sv_coredump(p, vp, limit) :
Index: kern/kern_switch.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_switch.c,v
retrieving revision 1.17
diff -u -r1.17 kern_switch.c
--- kern/kern_switch.c	12 Feb 2004 06:57:48 -0000	1.17
+++ kern/kern_switch.c	23 Feb 2004 08:20:42 -0000
@@ -39,6 +39,7 @@
 #include <sys/sysctl.h>
 #include <machine/ipl.h>
 #include <machine/cpu.h>
+#include <machine/smp.h>
 
 /*
  * debugging only YYY Remove me!   define to schedule user processes only
@@ -64,8 +65,8 @@
 static u_int32_t queuebits;
 static u_int32_t rtqueuebits;
 static u_int32_t idqueuebits;
-static u_int32_t curprocmask = -1;	/* currently running a user process */
-static u_int32_t rdyprocmask;		/* ready to accept a user process */
+static cpumask_t curprocmask = -1;	/* currently running a user process */
+static cpumask_t rdyprocmask;		/* ready to accept a user process */
 static int	 runqcount;
 #ifdef SMP
 static int	 scancpu;
@@ -93,6 +94,8 @@
         &choose_affinity, 0, "chooseproc() was smart");
 #endif
 
+static void sched_thread_cpu_init(void);
+
 #define USCHED_COUNTER(td)	((td->td_gd == mycpu) ? ++usched_optimal : ++usched_steal)
 
 /*
@@ -108,11 +111,7 @@
 		TAILQ_INIT(&rtqueues[i]);
 		TAILQ_INIT(&idqueues[i]);
 	}
-#ifdef SMP
-	sched_thread_init();
-#else
 	curprocmask &= ~1;
-#endif
 }
 SYSINIT(runqueue, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, rqinit, NULL)
 
@@ -249,7 +248,7 @@
 	int cpuid;
 #ifdef SMP
 	int count;
-	u_int32_t mask;
+	cpumask_t mask;
 #endif
 
 	crit_enter();
@@ -379,6 +378,11 @@
 	 * We depress the priority check so multiple cpu bound programs
 	 * do not bounce between cpus.  Remember that the clock interrupt
 	 * will also cause all cpus to reschedule.
+	 *
+	 * We must mask against rdyprocmask or we will race in the boot
+	 * code (before all cpus have working scheduler helpers), plus
+	 * some cpus might not be operational and/or not configured to
+	 * handle user processes.
 	 */
 	if (count && remote_resched && ncpus > 1) {
 		cpuid = scancpu;
@@ -388,12 +392,14 @@
 		} while (cpuid == mycpu->gd_cpuid);
 		scancpu = cpuid;
 
-		gd = globaldata_find(cpuid);
+		if (rdyprocmask & (1 << cpuid)) {
+			gd = globaldata_find(cpuid);
 
-		if (p->p_priority / PPQ < gd->gd_upri / PPQ - 2) {
-			gd->gd_upri = p->p_priority;
-			lwkt_send_ipiq(gd, need_resched_remote, NULL);
-			++remote_resched_nonaffinity;
+			if (p->p_priority / PPQ < gd->gd_upri / PPQ - 2) {
+				gd->gd_upri = p->p_priority;
+				lwkt_send_ipiq(gd, need_resched_remote, NULL);
+				++remote_resched_nonaffinity;
+			}
 		}
 	}
 #else
@@ -625,6 +631,7 @@
 	}
 }
 
+#ifdef SMP
 
 /*
  * For SMP systems a user scheduler helper thread is created for each
@@ -634,9 +641,6 @@
  * thread for this because we need to hold the MP lock.  Additionally,
  * doing things this way allows us to HLT idle cpus on MP systems.
  */
-
-#ifdef SMP
-
 static void
 sched_thread(void *dummy)
 {
@@ -667,21 +671,43 @@
     }
 }
 
-void
-sched_thread_init(void)
+/*
+ * Setup our scheduler helpers.  Note that curprocmask bit 0 has already
+ * been cleared by rqinit() and we should not mess with it further.
+ */
+static void
+sched_thread_cpu_init(void)
 {
-    int cpuid = mycpu->gd_cpuid;
+    int i;
+
+    if (bootverbose)
+	printf("start scheduler helpers on cpus:");
 
-    lwkt_create(sched_thread, NULL, NULL, &mycpu->gd_schedthread, 
-		TDF_STOPREQ, -1,
-		"usched %d", cpuid);
-    curprocmask &= ~(1 << cpuid);	/* schedule user proc on cpu */
+    for (i = 0; i < ncpus; ++i) {
+	globaldata_t dgd = globaldata_find(i);
+	cpumask_t mask = 1 << i;
+
+	if ((mask & smp_active_mask) == 0)
+	    continue;
+
+	if (bootverbose)
+	    printf(" %d", i);
+
+	lwkt_create(sched_thread, NULL, NULL, &dgd->gd_schedthread, 
+		    TDF_STOPREQ, i, "usched %d", i);
 #ifdef ONLY_ONE_USER_CPU
-    if (cpuid)
-	curprocmask |= 1 << cpuid;	/* DISABLE USER PROCS */
+	if (i)
+	    curprocmask |= mask;	/* DISABLE USER PROCS */
+#else
+	if (i)
+	    curprocmask &= ~mask;	/* schedule user proc on cpu */
 #endif
-    rdyprocmask |= 1 << cpuid;
+	rdyprocmask |= mask;
+    }
+    if (bootverbose)
+	printf("\n");
 }
+SYSINIT(uschedtd, SI_SUB_FINISH_SMP, SI_ORDER_ANY, sched_thread_cpu_init, NULL)
 
 #endif
 
Index: kern/link_aout.c
===================================================================
RCS file: /cvs/src/sys/kern/link_aout.c,v
retrieving revision 1.9
diff -u -r1.9 link_aout.c
--- kern/link_aout.c	13 Nov 2003 22:02:42 -0000	1.9
+++ kern/link_aout.c	22 Feb 2004 05:35:28 -0000
@@ -285,7 +285,7 @@
     *result = lf;
 
 out:
-    VOP_UNLOCK(nd.ni_vp, 0, td);
+    VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     vn_close(nd.ni_vp, FREAD, td);
 
     return error;
Index: kern/link_elf.c
===================================================================
RCS file: /cvs/src/sys/kern/link_elf.c,v
retrieving revision 1.11
diff -u -r1.11 link_elf.c
--- kern/link_elf.c	17 Jan 2004 03:26:18 -0000	1.11
+++ kern/link_elf.c	22 Feb 2004 05:35:30 -0000
@@ -700,7 +700,7 @@
 	free(shdr, M_LINKER);
     if (firstpage)
 	free(firstpage, M_LINKER);
-    VOP_UNLOCK(nd.ni_vp, 0, td);
+    VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     vn_close(nd.ni_vp, FREAD, td);
 
     return error;
Index: kern/lwkt_ipiq.c
===================================================================
RCS file: /cvs/src/sys/kern/lwkt_ipiq.c,v
retrieving revision 1.3
diff -u -r1.3 lwkt_ipiq.c
--- kern/lwkt_ipiq.c	17 Feb 2004 19:38:49 -0000	1.3
+++ kern/lwkt_ipiq.c	23 Feb 2004 08:25:29 -0000
@@ -147,7 +147,7 @@
     windex = ip->ip_windex & MAXCPUFIFO_MASK;
     ip->ip_func[windex] = (ipifunc2_t)func;
     ip->ip_arg[windex] = arg;
-    /* YYY memory barrier */
+    cpu_mb1();
     ++ip->ip_windex;
     if (ip->ip_windex - ip->ip_rindex > MAXCPUFIFO / 2) {
 	unsigned int eflags = read_eflags();
@@ -166,6 +166,48 @@
 }
 
 /*
+ * Send an IPI request passively, return 0 on success and ENOENT on failure.
+ * This routine does not recursive through lwkt_process_ipiq() nor does it
+ * block trying to queue the actual IPI.  If we successfully queue the
+ * message but fail to queue the IPI, we still count it as a success.
+ * The occassional small race against a target cpu HLT is recovered at
+ * the next clock interrupt.
+ */
+int
+lwkt_send_ipiq_passive(globaldata_t target, ipifunc_t func, void *arg)
+{
+    lwkt_ipiq_t ip;
+    int windex;
+    struct globaldata *gd = mycpu;
+
+    KKASSERT(curthread->td_pri >= TDPRI_CRIT);
+    if (target == gd) {
+	func(arg);
+	return(0);
+    } 
+    ++ipiq_count;
+    ip = &gd->gd_ipiq[target->gd_cpuid];
+
+    if (ip->ip_windex - ip->ip_rindex >= MAXCPUFIFO - 1) {
+	return(ENOENT);
+    }
+    windex = ip->ip_windex & MAXCPUFIFO_MASK;
+    ip->ip_func[windex] = (ipifunc2_t)func;
+    ip->ip_arg[windex] = arg;
+    cpu_mb1();
+    ++ip->ip_windex;
+    /*
+     * passive mode doesn't work yet :-( 
+     */
+#if 1
+    cpu_send_ipiq(target->gd_cpuid);
+#else
+    cpu_send_ipiq_passive(target->gd_cpuid);
+#endif
+    return(0);
+}
+
+/*
  * deprecated, used only by fast int forwarding.
  */
 int
@@ -217,7 +259,9 @@
 	    unsigned int eflags = read_eflags();
 	    cpu_enable_intr();
 	    while ((int)(ip->ip_xindex - seq) < 0) {
+		crit_enter();
 		lwkt_process_ipiq();
+		crit_exit();
 		if (--maxc == 0)
 			printf("LWKT_WAIT_IPIQ WARNING! %d wait %d (%d)\n", mycpu->gd_cpuid, target->gd_cpuid, ip->ip_xindex - seq);
 		if (maxc < -1000000)
@@ -228,6 +272,15 @@
     }
 }
 
+int
+lwkt_seq_ipiq(globaldata_t target)
+{
+    lwkt_ipiq_t ip;
+
+    ip = &mycpu->gd_ipiq[target->gd_cpuid];
+    return(ip->ip_windex);
+}
+
 /*
  * Called from IPI interrupt (like a fast interrupt), which has placed
  * us in a critical section.  The MP lock may or may not be held.
@@ -434,7 +487,9 @@
 lwkt_cpusync_add(cpumask_t mask, lwkt_cpusync_t poll)
 {
     globaldata_t gd = mycpu;
+#ifdef SMP
     int count;
+#endif
 
     mask &= ~poll->cs_mask;
     poll->cs_mask |= mask;
Index: kern/lwkt_rwlock.c
===================================================================
RCS file: /cvs/src/sys/kern/lwkt_rwlock.c,v
retrieving revision 1.4
diff -u -r1.4 lwkt_rwlock.c
--- kern/lwkt_rwlock.c	20 Jul 2003 01:37:22 -0000	1.4
+++ kern/lwkt_rwlock.c	22 Feb 2004 07:18:34 -0000
@@ -41,17 +41,25 @@
 void
 lwkt_rwlock_init(lwkt_rwlock_t lock)
 {
-    lwkt_init_wait(&lock->rw_wait);
+    lwkt_wait_init(&lock->rw_wait);
+    lock->rw_owner = NULL;
+    lock->rw_count = 0;
+    lock->rw_requests = 0;
 }
 
-#if 0
+void
+lwkt_rwlock_uninit(lwkt_rwlock_t lock)
+{
+    /* empty */
+}
 
 void
 lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg)
 {
+    lwkt_tokref ilock;
     int gen;
 
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_gettoken(&ilock, &lock->rw_token);
     gen = lock->rw_wait.wa_gen;
     while (lock->rw_owner != curthread) {
 	if (lock->rw_owner == NULL && lock->rw_count == 0) {
@@ -60,34 +68,35 @@
 	}
 	++lock->rw_requests;
 	lwkt_block(&lock->rw_wait, wmesg, &gen);
-	lwkt_regettoken(&lock->rw_token);
 	--lock->rw_requests;
     }
     ++lock->rw_count;
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg)
 {
+    lwkt_tokref ilock;
     int gen;
 
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_gettoken(&ilock, &lock->rw_token);
     gen = lock->rw_wait.wa_gen;
     while (lock->rw_owner != NULL) {
 	++lock->rw_requests;
 	lwkt_block(&lock->rw_wait, wmesg, &gen);
-	lwkt_regettoken(&lock->rw_token);
 	--lock->rw_requests;
     }
     ++lock->rw_count;
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_exunlock(lwkt_rwlock_t lock)
 {
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_tokref ilock;
+
+    lwkt_gettoken(&ilock, &lock->rw_token);
     KASSERT(lock->rw_owner != NULL, ("lwkt_exunlock: shared lock"));
     KASSERT(lock->rw_owner == curthread, ("lwkt_exunlock: not owner"));
     if (--lock->rw_count == 0) {
@@ -95,19 +104,20 @@
 	if (lock->rw_requests)
 	    lwkt_signal(&lock->rw_wait, 1);
     }
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_shunlock(lwkt_rwlock_t lock)
 {
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_tokref ilock;
+
+    lwkt_gettoken(&ilock, &lock->rw_token);
     KASSERT(lock->rw_owner == NULL, ("lwkt_shunlock: exclusive lock"));
     if (--lock->rw_count == 0) {
 	if (lock->rw_requests)
 	    lwkt_signal(&lock->rw_wait, 1);
     }
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
-#endif
Index: kern/lwkt_thread.c
===================================================================
RCS file: /cvs/src/sys/kern/lwkt_thread.c,v
retrieving revision 1.55
diff -u -r1.55 lwkt_thread.c
--- kern/lwkt_thread.c	17 Feb 2004 19:38:49 -0000	1.55
+++ kern/lwkt_thread.c	23 Feb 2004 05:53:14 -0000
@@ -174,9 +174,12 @@
  * NOTE!  called from low level boot code, we cannot do anything fancy!
  */
 void
-lwkt_init_wait(lwkt_wait_t w)
+lwkt_wait_init(lwkt_wait_t w)
 {
+    lwkt_token_init(&w->wa_token);
     TAILQ_INIT(&w->wa_waitq);
+    w->wa_gen = 0;
+    w->wa_count = 0;
 }
 
 /*
@@ -246,6 +249,8 @@
  * NOTE! we have to be careful in regards to creating threads for other cpus
  * if SMP has not yet been activated.
  */
+#ifdef SMP
+
 static void
 lwkt_init_thread_remote(void *arg)
 {
@@ -254,6 +259,8 @@
     TAILQ_INSERT_TAIL(&td->td_gd->gd_tdallq, td, td_allq);
 }
 
+#endif
+
 void
 lwkt_init_thread(thread_t td, void *stack, int flags, struct globaldata *gd)
 {
@@ -379,7 +386,7 @@
 void
 lwkt_switch(void)
 {
-    struct globaldata *gd;
+    globaldata_t gd;
     thread_t td = curthread;
     thread_t ntd;
 #ifdef SMP
@@ -462,9 +469,24 @@
 	 *
 	 * We have to adjust the MP lock for the target thread.  If we 
 	 * need the MP lock and cannot obtain it we try to locate a
-	 * thread that does not need the MP lock.
+	 * thread that does not need the MP lock.  If we cannot, we spin
+	 * instead of HLT.
+	 *
+	 * A similar issue exists for the tokens held by the target thread.
+	 * If we cannot obtain ownership of the tokens we cannot immediately
+	 * schedule the thread.
+	 */
+
+	/*
+	 * We are switching threads.  If there are any pending requests for
+	 * tokens we can satisfy all of them here.
 	 */
 	gd = mycpu;
+#ifdef SMP
+	if (gd->gd_tokreqbase)
+		lwkt_drain_token_requests();
+#endif
+
 again:
 	if (gd->gd_runqmask) {
 	    int nq = bsrl(gd->gd_runqmask);
@@ -473,17 +495,24 @@
 		goto again;
 	    }
 #ifdef SMP
-	    if (ntd->td_mpcount && mpheld == 0 && !cpu_try_mplock()) {
-		/*
-		 * Target needs MP lock and we couldn't get it, try
-		 * to locate a thread which does not need the MP lock
-		 * to run.  If we cannot locate a thread spin in idle.
-		 */
+	    /*
+	     * If the target needs the MP lock and we couldn't get it,
+	     * or if the target is holding tokens and we could not 
+	     * gain ownership of the tokens, continue looking for a
+	     * thread to schedule and spin instead of HLT if we can't.
+	     */
+	    if ((ntd->td_mpcount && mpheld == 0 && !cpu_try_mplock()) ||
+		(ntd->td_toks && lwkt_chktokens(ntd) == 0)
+	    ) {
 		u_int32_t rqmask = gd->gd_runqmask;
 		while (rqmask) {
 		    TAILQ_FOREACH(ntd, &gd->gd_tdrunq[nq], td_threadq) {
-			if (ntd->td_mpcount == 0)
-			    break;
+			if (ntd->td_mpcount && !mpheld && !cpu_try_mplock())
+			    continue;
+			mpheld = MP_LOCK_HELD();
+			if (ntd->td_toks && !lwkt_chktokens(ntd))
+			    continue;
+			break;
 		    }
 		    if (ntd)
 			break;
@@ -603,6 +632,10 @@
      *
      * YYY The target thread must be in a critical section (else it must
      * inherit our critical section?  I dunno yet).
+     *
+     * Any tokens held by the target may not be held by thread(s) being
+     * preempted.  We take the easy way out and do not preempt if
+     * the target is holding tokens.
      */
     KASSERT(ntd->td_pri >= TDPRI_CRIT, ("BADCRIT0 %d", ntd->td_pri));
 
@@ -621,6 +654,17 @@
 	return;
     }
 #endif
+    /*
+     * Take the easy way out and do not preempt if the target is holding
+     * one or more tokens.  We could test whether the thread(s) being
+     * preempted interlock against the target thread's tokens and whether
+     * we can get all the target thread's tokens, but this situation 
+     * should not occur very often so its easier to simply not preempt.
+     */
+    if (ntd->td_toks != NULL) {
+	++preempt_miss;
+	return;
+    }
     if (td == ntd || ((td->td_flags | ntd->td_flags) & TDF_PREEMPT_LOCK)) {
 	++preempt_weird;
 	return;
@@ -754,14 +798,15 @@
 {
     thread_t td = curthread;
 
-    crit_enter();
+    crit_enter_quick(td);
     KASSERT(td->td_wait == NULL, ("lwkt_schedule_self(): td_wait not NULL!"));
+    KASSERT(td != &td->td_gd->gd_idlethread, ("lwkt_schedule_self(): scheduling gd_idlethread is illegal!"));
     _lwkt_enqueue(td);
 #ifdef _KERNEL
     if (td->td_proc && td->td_proc->p_stat == SSLEEP)
 	panic("SCHED SELF PANIC");
 #endif
-    crit_exit();
+    crit_exit_quick(td);
 }
 
 /*
@@ -776,6 +821,7 @@
 lwkt_schedule(thread_t td)
 {
 #ifdef	INVARIANTS
+    KASSERT(td != &td->td_gd->gd_idlethread, ("lwkt_schedule(): scheduling gd_idlethread is illegal!"));
     if ((td->td_flags & TDF_PREEMPT_LOCK) == 0 && td->td_proc 
 	&& td->td_proc->p_stat == SSLEEP
     ) {
@@ -807,7 +853,9 @@
 	 * (remember, wait structures use stable storage)
 	 */
 	if ((w = td->td_wait) != NULL) {
-	    if (lwkt_trytoken(&w->wa_token)) {
+	    lwkt_tokref wref;
+
+	    if (lwkt_trytoken(&wref, &w->wa_token)) {
 		TAILQ_REMOVE(&w->wa_waitq, td, td_threadq);
 		--w->wa_count;
 		td->td_wait = NULL;
@@ -828,7 +876,7 @@
 		else if (_lwkt_wantresched(td, curthread))
 		    need_resched();
 #endif
-		lwkt_reltoken(&w->wa_token);
+		lwkt_reltoken(&wref);
 	    } else {
 		lwkt_send_ipiq(w->wa_token.t_cpu, (ipifunc_t)lwkt_schedule, td);
 	    }
@@ -980,43 +1028,36 @@
     return(td->td_proc);
 }
 
-#if 0
-
 /*
- * This function deschedules the current thread and blocks on the specified
- * wait queue.  We obtain ownership of the wait queue in order to block
- * on it.  A generation number is used to interlock the wait queue in case
- * it gets signalled while we are blocked waiting on the token.
- *
- * Note: alternatively we could dequeue our thread and then message the
- * target cpu owning the wait queue.  YYY implement as sysctl.
- *
- * Note: wait queue signals normally ping-pong the cpu as an optimization.
+ * Block on the specified wait queue until signaled.  A generation number
+ * must be supplied to interlock the wait queue.  The function will
+ * return immediately if the generation number does not match the wait
+ * structure's generation number.
  */
-
 void
 lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen)
 {
     thread_t td = curthread;
+    lwkt_tokref ilock;
 
-    lwkt_gettoken(&w->wa_token);
+    lwkt_gettoken(&ilock, &w->wa_token);
+    crit_enter();
     if (w->wa_gen == *gen) {
 	_lwkt_dequeue(td);
 	TAILQ_INSERT_TAIL(&w->wa_waitq, td, td_threadq);
 	++w->wa_count;
 	td->td_wait = w;
 	td->td_wmesg = wmesg;
-again:
+    again:
 	lwkt_switch();
-	lwkt_regettoken(&w->wa_token);
 	if (td->td_wmesg != NULL) {
 	    _lwkt_dequeue(td);
 	    goto again;
 	}
     }
-    /* token might be lost, doesn't matter for gen update */
+    crit_exit();
     *gen = w->wa_gen;
-    lwkt_reltoken(&w->wa_token);
+    lwkt_reltoken(&ilock);
 }
 
 /*
@@ -1031,10 +1072,11 @@
 lwkt_signal(lwkt_wait_t w, int count)
 {
     thread_t td;
-    int count;
+    lwkt_tokref ilock;
 
-    lwkt_gettoken(&w->wa_token);
+    lwkt_gettoken(&ilock, &w->wa_token);
     ++w->wa_gen;
+    crit_enter();
     if (count < 0)
 	count = w->wa_count;
     while ((td = TAILQ_FIRST(&w->wa_waitq)) != NULL && count) {
@@ -1048,12 +1090,10 @@
 	} else {
 	    lwkt_send_ipiq(td->td_gd, (ipifunc_t)lwkt_schedule, td);
 	}
-	lwkt_regettoken(&w->wa_token);
     }
-    lwkt_reltoken(&w->wa_token);
+    crit_exit();
+    lwkt_reltoken(&ilock);
 }
-
-#endif
 
 /*
  * Create a kernel process/thread/whatever.  It shares it's address space
Index: kern/lwkt_token.c
===================================================================
RCS file: /cvs/src/sys/kern/lwkt_token.c,v
retrieving revision 1.4
diff -u -r1.4 lwkt_token.c
--- kern/lwkt_token.c	18 Feb 2004 16:31:37 -0000	1.4
+++ kern/lwkt_token.c	23 Feb 2004 18:51:04 -0000
@@ -75,10 +75,20 @@
 
 #endif
 
+#define	MAKE_TOKENS_SPIN
+/* #define MAKE_TOKENS_YIELD */
+
+#ifndef LWKT_NUM_POOL_TOKENS
+#define LWKT_NUM_POOL_TOKENS	1024	/* power of 2 */
+#endif
+#define LWKT_MASK_POOL_TOKENS	(LWKT_NUM_POOL_TOKENS - 1)
+
 #ifdef INVARIANTS
 static int token_debug = 0;
 #endif
 
+static lwkt_token	pool_tokens[LWKT_NUM_POOL_TOKENS];
+
 #ifdef _KERNEL
 
 #ifdef INVARIANTS
@@ -87,214 +97,428 @@
 
 #endif
 
-typedef struct lwkt_gettoken_req {
-    lwkt_token_t tok;
-    globaldata_t cpu;
-} lwkt_gettoken_req;
+#ifdef SMP
 
 /*
- * Acquire ownership of a token
- *
- * Acquire ownership of a token.  The token may have spl and/or critical
- * section side effects, depending on its purpose.  These side effects
- * guarentee that you will maintain ownership of the token as long as you
- * do not block.  If you block you may lose access to the token (but you
- * must still release it even if you lose your access to it).
- *
- * YYY for now we use a critical section to prevent IPIs from taking away
- * a token, but do we really only need to disable IPIs ?
- *
- * YYY certain tokens could be made to act like mutexes when performance
- * would be better (e.g. t_cpu == NULL).  This is not yet implemented.
- *
- * YYY the tokens replace 4.x's simplelocks for the most part, but this
- * means that 4.x does not expect a switch so for now we cannot switch
- * when waiting for an IPI to be returned.  
+ * Determine if we own all the tokens in the token reference list.
+ * Return 1 on success, 0 on failure. 
  *
- * YYY If the token is owned by another cpu we may have to send an IPI to
- * it and then block.   The IPI causes the token to be given away to the
- * requesting cpu, unless it has already changed hands.  Since only the
- * current cpu can give away a token it owns we do not need a memory barrier.
- * This needs serious optimization.
+ * As a side effect, queue requests for tokens we want which are owned
+ * by other cpus.  The magic number is used to communicate when the 
+ * target cpu has processed the request.  Note, however, that the
+ * target cpu may not be able to assign the token to us which is why
+ * the scheduler must spin.
  */
-
-#ifdef SMP
-
-static
-void
-lwkt_gettoken_remote(void *arg)
+int
+lwkt_chktokens(thread_t td)
 {
-    lwkt_gettoken_req *req = arg;
-    if (req->tok->t_cpu == mycpu) {
-#ifdef INVARIANTS
-	if (token_debug)
-	    printf("GT(%d,%d) ", req->tok->t_cpu->gd_cpuid, req->cpu->gd_cpuid);
-#endif
-	req->tok->t_cpu = req->cpu;
-	req->tok->t_reqcpu = req->cpu;	/* YYY leave owned by target cpu */
-	/* else set reqcpu to point to current cpu for release */
+    globaldata_t gd = td->td_gd;	/* mycpu */
+    lwkt_tokref_t refs;
+    globaldata_t dgd;
+    lwkt_token_t tok;
+    int r = 1;
+
+    for (refs = td->td_toks; refs; refs = refs->tr_next) {
+	tok = refs->tr_tok;
+	if ((dgd = tok->t_cpu) != gd) {
+	    cpu_mb1();
+	    r = 0;
+
+	    /*
+	     * Queue a request to the target cpu, exit the loop early if
+	     * we are unable to queue the IPI message.  The magic number
+	     * flags whether we have a pending ipi request queued or not.
+	     */
+	    if (refs->tr_magic == LWKT_TOKREF_MAGIC1) {
+		refs->tr_magic = LWKT_TOKREF_MAGIC2;	/* MP synched slowreq*/
+		refs->tr_reqgd = gd;
+		tok->t_reqcpu = gd;	/* MP unsynchronized 'fast' req */
+		if (lwkt_send_ipiq_passive(dgd, lwkt_reqtoken_remote, refs)) {
+		    /* failed */
+		    refs->tr_magic = LWKT_TOKREF_MAGIC1;
+		    break;
+		}
+	    }
+	}
     }
+    return(r);
 }
 
 #endif
 
+/*
+ * Check if we already own the token.  Return 1 on success, 0 on failure.
+ */
 int
-lwkt_gettoken(lwkt_token_t tok)
+lwkt_havetoken(lwkt_token_t tok)
 {
-    /*
-     * Prevent preemption so the token can't be taken away from us once
-     * we gain ownership of it.  Use a synchronous request which might
-     * block.  The request will be forwarded as necessary playing catchup
-     * to the token.
-     */
-
-    crit_enter();
-#ifdef INVARIANTS
-    if (curthread->td_pri > 1800) {
-	printf("lwkt_gettoken: %p called from %p: crit sect nesting warning\n",
-	    tok, ((int **)&tok)[-1]);
+    globaldata_t gd = mycpu;
+    thread_t td = gd->gd_curthread;
+    lwkt_tokref_t ref;
+
+    for (ref = td->td_toks; ref; ref = ref->tr_next) {
+        if (ref->tr_tok == tok)
+            return(1);
     }
-    if (curthread->td_pri > 2000) {
-	curthread->td_pri = 1000;
-	panic("too HIGH!");
+    return(0);
+}
+
+int
+lwkt_havetokref(lwkt_tokref_t xref)
+{
+    globaldata_t gd = mycpu;
+    thread_t td = gd->gd_curthread;
+    lwkt_tokref_t ref;
+
+    for (ref = td->td_toks; ref; ref = ref->tr_next) {
+        if (ref == xref)
+            return(1);
     }
-#endif
+    return(0);
+}
+
 #ifdef SMP
-    while (tok->t_cpu != mycpu) {
-	struct lwkt_gettoken_req req;
-	int seq;
-	globaldata_t dcpu;
 
-	req.cpu = mycpu;
-	req.tok = tok;
-	dcpu = tok->t_cpu;
-#ifdef INVARIANTS
-	if (token_debug)
-	    printf("REQT%d ", dcpu->gd_cpuid);
-#endif
-	seq = lwkt_send_ipiq(dcpu, lwkt_gettoken_remote, &req);
-	lwkt_wait_ipiq(dcpu, seq);
-#ifdef INVARIANTS
-	if (token_debug)
-	    printf("REQR%d ", tok->t_cpu->gd_cpuid);
-#endif
+/*
+ * Returns 1 if it is ok to give a token away, 0 if it is not.
+ */
+static int
+lwkt_oktogiveaway_token(lwkt_token_t tok)
+{
+    globaldata_t gd = mycpu;
+    lwkt_tokref_t ref;
+    thread_t td;
+
+    for (td = gd->gd_curthread; td; td = td->td_preempted) {
+	for (ref = td->td_toks; ref; ref = ref->tr_next) {
+	    if (ref->tr_tok == tok)
+		return(0);
+	}
     }
+    return(1);
+}
+
 #endif
+
+/*
+ * Acquire a serializing token
+ */
+
+static __inline
+void
+_lwkt_gettokref(lwkt_tokref_t ref)
+{
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
+
+    gd = mycpu;			/* our cpu */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1);
+    td = gd->gd_curthread;	/* our thread */
+
+    /*
+     * Link the request into our thread's list.  This interlocks against
+     * remote requests from other cpus and prevents the token from being
+     * given away if our cpu already owns it.  This also allows us to
+     * avoid using a critical section.
+     */
+    ref->tr_next = td->td_toks;
+    cpu_mb1();		/* order memory / we can be interrupted */
+    td->td_toks = ref;
+
     /*
-     * leave us in a critical section on return.  This will be undone
-     * by lwkt_reltoken().  Bump the generation number.
+     * If our cpu does not own the token then let the scheduler deal with
+     * it.  We are guarenteed to own the tokens on our thread's token
+     * list when we are switched back in.
+     *
+     * Otherwise make sure the token is not held by a thread we are
+     * preempting.  If it is, let the scheduler deal with it.
      */
-    return(++tok->t_gen);
+    tok = ref->tr_tok;
+#ifdef SMP
+    if (tok->t_cpu != gd) {
+	/*
+	 * Temporarily operate on tokens synchronously.  We have to fix
+	 * a number of interlocks and especially the softupdates code to
+	 * be able to properly yield.  ZZZ
+	 */
+#if defined(MAKE_TOKENS_SPIN)
+	int x = 40000000;
+	crit_enter();
+	while (lwkt_chktokens(td) == 0) {
+	    lwkt_process_ipiq();
+	    lwkt_drain_token_requests();
+	    if (--x == 0) {
+		x = 40000000;
+		printf("CHKTOKEN loop %d\n", gd->gd_cpuid);
+		Debugger("x");
+	    }
+	    splz();
+	}
+	crit_exit();
+#elif defined(MAKE_TOKENS_YIELD)
+	lwkt_yield();
+#else
+#error MAKE_TOKENS_XXX ?
+#endif
+	KKASSERT(tok->t_cpu == gd);
+    } else /* NOTE CONDITIONAL */
+#endif
+    if (td->td_preempted) {
+	while ((td = td->td_preempted) != NULL) {
+	    lwkt_tokref_t scan;
+	    for (scan = td->td_toks; scan; scan = scan->tr_next) {
+		if (scan->tr_tok == tok) {
+		    lwkt_yield();
+		    KKASSERT(tok->t_cpu == gd);
+		    goto breakout;
+		}
+	    }
+	}
+breakout:
+    }
+    /* 'td' variable no longer valid due to preempt loop above */
 }
 
+
 /*
- * Attempt to acquire ownership of a token.  Returns 1 on success, 0 on
- * failure.
+ * Attempt to acquire a serializing token
  */
+static __inline
 int
-lwkt_trytoken(lwkt_token_t tok)
+_lwkt_trytokref(lwkt_tokref_t ref)
 {
-    crit_enter();
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
+
+    gd = mycpu;			/* our cpu */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1);
+    td = gd->gd_curthread;	/* our thread */
+
+    /*
+     * Link the request into our thread's list.  This interlocks against
+     * remote requests from other cpus and prevents the token from being
+     * given away if our cpu already owns it.  This also allows us to
+     * avoid using a critical section.
+     */
+    ref->tr_next = td->td_toks;
+    cpu_mb1();		/* order memory / we can be interrupted */
+    td->td_toks = ref;
+
+    /*
+     * If our cpu does not own the token then stop now.
+     *
+     * Otherwise make sure the token is not held by a thread we are
+     * preempting.  If it is, stop.
+     */
+    tok = ref->tr_tok;
 #ifdef SMP
-    if (tok->t_cpu != mycpu) {
-	crit_exit();
+    if (tok->t_cpu != gd) {
+	td->td_toks = ref->tr_next;	/* remove ref */
 	return(0);
-    } 
+    } else /* NOTE CONDITIONAL */
 #endif
-    /* leave us in the critical section */
-    ++tok->t_gen;
+    if (td->td_preempted) {
+	while ((td = td->td_preempted) != NULL) {
+	    lwkt_tokref_t scan;
+	    for (scan = td->td_toks; scan; scan = scan->tr_next) {
+		if (scan->tr_tok == tok) {
+		    td = gd->gd_curthread;	/* our thread */
+		    td->td_toks = ref->tr_next;	/* remove ref */
+		    return(0);
+		}
+	    }
+	}
+    }
+    /* 'td' variable no longer valid */
     return(1);
 }
 
-/*
- * Release your ownership of a token.  Releases must occur in reverse
- * order to aquisitions, eventually so priorities can be unwound properly
- * like SPLs.  At the moment the actual implemention doesn't care.
- *
- * We can safely hand a token that we own to another cpu without notifying
- * it, but once we do we can't get it back without requesting it (unless
- * the other cpu hands it back to us before we check).
- *
- * We might have lost the token, so check that.
- *
- * Return the token's generation number.  The number is useful to callers
- * who may want to know if the token was stolen during potential blockages.
- */
-int
-lwkt_reltoken(lwkt_token_t tok)
+void
+lwkt_gettoken(lwkt_tokref_t ref, lwkt_token_t tok)
 {
-    int gen;
+    lwkt_tokref_init(ref, tok);
+    _lwkt_gettokref(ref);
+}
 
-    if (tok->t_cpu == mycpu) {
-	tok->t_cpu = tok->t_reqcpu;
-    }
-    gen = tok->t_gen;
-    crit_exit();
-    return(gen);
+void
+lwkt_gettokref(lwkt_tokref_t ref)
+{
+    _lwkt_gettokref(ref);
 }
 
-/*
- * Reacquire a token that might have been lost.  0 is returned if the 
- * generation has not changed (nobody stole the token from us), -1 is 
- * returned otherwise.  The token is reacquired regardless but the
- * generation number is not bumped further if we already own the token.
- *
- * For efficiency we inline the best-case situation for lwkt_regettoken()
- * (i.e .we still own the token).
- */
 int
-lwkt_gentoken(lwkt_token_t tok, int *gen)
+lwkt_trytoken(lwkt_tokref_t ref, lwkt_token_t tok)
 {
-    if (tok->t_cpu == mycpu && tok->t_gen == *gen)
-	return(0);
-    *gen = lwkt_regettoken(tok);
-    return(-1);
+    lwkt_tokref_init(ref, tok);
+    return(_lwkt_trytokref(ref));
+}
+
+int
+lwkt_trytokref(lwkt_tokref_t ref)
+{
+    return(_lwkt_trytokref(ref));
 }
 
 /*
- * Re-acquire a token that might have been lost.   The generation number
- * is bumped and returned regardless of whether the token had been lost
- * or not (because we only have cpu granularity we have to bump the token
- * either way).
+ * Release a serializing token
  */
-int
-lwkt_regettoken(lwkt_token_t tok)
+void
+lwkt_reltoken(lwkt_tokref *_ref)
 {
-    /* assert we are in a critical section */
-    if (tok->t_cpu != mycpu) {
-#ifdef SMP
-	while (tok->t_cpu != mycpu) {
-	    struct lwkt_gettoken_req req;
-	    int seq;
-	    globaldata_t dcpu;
+    lwkt_tokref *ref;
+    lwkt_tokref **pref;
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
 
-	    req.cpu = mycpu;
-	    req.tok = tok;
-	    dcpu = tok->t_cpu;
+    /*
+     * Guard check and stack check (if in the same stack page).  We must
+     * also wait for any action pending on remote cpus which we do by
+     * checking the magic number and yielding in a loop.
+     */
+    ref = _ref;
 #ifdef INVARIANTS
-	    if (token_debug)
-		printf("REQT%d ", dcpu->gd_cpuid);
+    if ((((intptr_t)ref ^ (intptr_t)&_ref) && ~(intptr_t)PAGE_MASK) == 0)
+	KKASSERT((char *)ref > (char *)&_ref);
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1 || 
+	     ref->tr_magic == LWKT_TOKREF_MAGIC2);
 #endif
-	    seq = lwkt_send_ipiq(dcpu, lwkt_gettoken_remote, &req);
-	    lwkt_wait_ipiq(dcpu, seq);
-#ifdef INVARIANTS
-	    if (token_debug)
-		printf("REQR%d ", tok->t_cpu->gd_cpuid);
+    /*
+     * Locate and unlink the token.  Interlock with the token's cpureq
+     * to give the token away before we release it from our thread list,
+     * which allows us to avoid using a critical section.
+     */
+    gd = mycpu;
+    td = gd->gd_curthread;
+    for (pref = &td->td_toks; (ref = *pref) != _ref; pref = &ref->tr_next) {
+	KKASSERT(ref != NULL);
+    }
+    tok = ref->tr_tok;
+    KKASSERT(tok->t_cpu == gd);
+    tok->t_cpu = tok->t_reqcpu;	/* we do not own 'tok' after this */
+    *pref = ref->tr_next;	/* note: also removes giveaway interlock */
+
+    /*
+     * If we had gotten the token opportunistically and it still happens to
+     * be queued to a target cpu, we have to wait for the target cpu
+     * to finish processing it.  This does not happen very often and does
+     * not need to be optimal.
+     */
+    while (ref->tr_magic == LWKT_TOKREF_MAGIC2) {
+#if defined(MAKE_TOKENS_SPIN)
+	crit_enter();
+#ifdef SMP
+	lwkt_process_ipiq();
 #endif
-	}
+	splz();
+	crit_exit();
+#elif defined(MAKE_TOKENS_YIELD)
+	lwkt_yield();
+#else
+#error MAKE_TOKENS_XXX ?
 #endif
     }
-    ++tok->t_gen;
-    return(tok->t_gen);
 }
 
+/*
+ * Pool tokens are used to provide a type-stable serializing token
+ * pointer that does not race against disappearing data structures.
+ *
+ * This routine is called in early boot just after we setup the BSP's
+ * globaldata structure.
+ */
 void
-lwkt_inittoken(lwkt_token_t tok)
+lwkt_token_pool_init(void)
 {
+    int i;
+
+    for (i = 0; i < LWKT_NUM_POOL_TOKENS; ++i)
+	lwkt_token_init(&pool_tokens[i]);
+}
+
+lwkt_token_t
+lwkt_token_pool_get(void *ptraddr)
+{
+    int i;
+
+    i = ((int)(intptr_t)ptraddr >> 2) ^ ((int)(intptr_t)ptraddr >> 12);
+    return(&pool_tokens[i & LWKT_MASK_POOL_TOKENS]);
+}
+
+#ifdef SMP
+
+/*
+ * This is the receiving side of a remote IPI requesting a token.  If we
+ * cannot immediately hand the token off to another cpu we queue it.
+ *
+ * NOTE!  we 'own' the ref structure, but we only 'own' the token if
+ * t_cpu == mycpu.
+ */
+void
+lwkt_reqtoken_remote(void *data)
+{
+    lwkt_tokref_t ref = data;
+    globaldata_t gd = mycpu;
+    lwkt_token_t tok = ref->tr_tok;
+
     /*
-     * Zero structure and set cpu owner and reqcpu to cpu 0.
+     * We do not have to queue the token if we can give it away
+     * immediately.  Otherwise we queue it to our globaldata structure.
      */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC2);
+    if (lwkt_oktogiveaway_token(tok)) {
+	if (tok->t_cpu == gd)
+	    tok->t_cpu = ref->tr_reqgd;
+	cpu_mb1();
+	ref->tr_magic = LWKT_TOKREF_MAGIC1;
+    } else {
+	ref->tr_gdreqnext = gd->gd_tokreqbase;
+	gd->gd_tokreqbase = ref;
+    }
+}
+
+/*
+ * Must be called from a critical section.  Satisfy all remote token
+ * requests that are pending on our globaldata structure.  The request
+ * does not have to be satisfied with a successful change of ownership
+ * but we do have to acknowledge that we have completed processing the
+ * request by setting the magic number back to MAGIC1.
+ *
+ * NOTE!  we 'own' the ref structure, but we only 'own' the token if
+ * t_cpu == mycpu.
+ */
+void
+lwkt_drain_token_requests(void)
+{
+    globaldata_t gd = mycpu;
+    lwkt_tokref_t ref;
+
+    while ((ref = gd->gd_tokreqbase) != NULL) {
+	gd->gd_tokreqbase = ref->tr_gdreqnext;
+	KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC2);
+	if (ref->tr_tok->t_cpu == gd)
+	    ref->tr_tok->t_cpu = ref->tr_reqgd;
+	cpu_mb1();
+	ref->tr_magic = LWKT_TOKREF_MAGIC1;
+    }
+}
+
+#endif
+
+/*
+ * Initialize the owner and release-to cpu to the current cpu
+ * and reset the generation count.
+ */
+void
+lwkt_token_init(lwkt_token_t tok)
+{
     tok->t_cpu = tok->t_reqcpu = mycpu;
-    tok->t_gen = 0;
 }
 
+void
+lwkt_token_uninit(lwkt_token_t tok)
+{
+    /* empty */
+}
Index: kern/subr_rman.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_rman.c,v
retrieving revision 1.5
diff -u -r1.5 subr_rman.c
--- kern/subr_rman.c	15 Nov 2003 21:05:43 -0000	1.5
+++ kern/subr_rman.c	22 Feb 2004 03:06:30 -0000
@@ -82,11 +82,12 @@
 rman_init(struct rman *rm)
 {
 	static int once;
+	lwkt_tokref ilock;
 
 	if (once == 0) {
 		once = 1;
 		TAILQ_INIT(&rman_head);
-		lwkt_inittoken(&rman_tok);
+		lwkt_token_init(&rman_tok);
 	}
 
 	if (rm->rm_type == RMAN_UNINIT)
@@ -98,11 +99,11 @@
 	rm->rm_slock = malloc(sizeof *rm->rm_slock, M_RMAN, M_NOWAIT);
 	if (rm->rm_slock == NULL)
 		return ENOMEM;
-	lwkt_inittoken(rm->rm_slock);
+	lwkt_token_init(rm->rm_slock);
 
-	lwkt_gettoken(&rman_tok);
+	lwkt_gettoken(&ilock, &rman_tok);
 	TAILQ_INSERT_TAIL(&rman_head, rm, rm_link);
-	lwkt_reltoken(&rman_tok);
+	lwkt_reltoken(&ilock);
 	return 0;
 }
 
@@ -114,6 +115,7 @@
 rman_manage_region(struct rman *rm, u_long start, u_long end)
 {
 	struct resource *r, *s;
+	lwkt_tokref ilock;
 
 	r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
 	if (r == 0)
@@ -126,7 +128,7 @@
 	r->r_dev = 0;
 	r->r_rm = rm;
 
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 	for (s = CIRCLEQ_FIRST(&rm->rm_list);	
 	     !CIRCLEQ_TERMCOND(s, rm->rm_list) && s->r_end < r->r_start;
 	     s = CIRCLEQ_NEXT(s, r_link))
@@ -138,7 +140,7 @@
 		CIRCLEQ_INSERT_BEFORE(&rm->rm_list, s, r, r_link);
 	}
 
-	lwkt_reltoken(rm->rm_slock);
+	lwkt_reltoken(&ilock);
 	return 0;
 }
 
@@ -146,11 +148,12 @@
 rman_fini(struct rman *rm)
 {
 	struct resource *r;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 	CIRCLEQ_FOREACH(r, &rm->rm_list, r_link) {
 		if (r->r_flags & RF_ALLOCATED) {
-			lwkt_reltoken(rm->rm_slock);
+			lwkt_reltoken(&ilock);
 			return EBUSY;
 		}
 	}
@@ -164,10 +167,11 @@
 		CIRCLEQ_REMOVE(&rm->rm_list, r, r_link);
 		free(r, M_RMAN);
 	}
-	lwkt_reltoken(rm->rm_slock);
-	lwkt_gettoken(&rman_tok);
+	lwkt_reltoken(&ilock);
+	/* XXX what's the point of this if we are going to free the struct? */
+	lwkt_gettoken(&ilock, &rman_tok);
 	TAILQ_REMOVE(&rman_head, rm, rm_link);
-	lwkt_reltoken(&rman_tok);
+	lwkt_reltoken(&ilock);
 	free(rm->rm_slock, M_RMAN);
 
 	return 0;
@@ -180,6 +184,7 @@
 	u_int	want_activate;
 	struct	resource *r, *s, *rv;
 	u_long	rstart, rend;
+	lwkt_tokref ilock;
 
 	rv = 0;
 
@@ -191,7 +196,7 @@
 	want_activate = (flags & RF_ACTIVE);
 	flags &= ~RF_ACTIVE;
 
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 
 	for (r = CIRCLEQ_FIRST(&rm->rm_list); 
 	     !CIRCLEQ_TERMCOND(r, rm->rm_list) && r->r_end < start;
@@ -396,8 +401,7 @@
 			rv = 0;
 		}
 	}
-			
-	lwkt_reltoken(rm->rm_slock);
+	lwkt_reltoken(&ilock);
 	return (rv);
 }
 
@@ -441,17 +445,21 @@
 {
 	int rv;
 	struct resource *whohas;
+	lwkt_tokref ilock;
 	struct rman *rm;
 
 	rm = r->r_rm;
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 	rv = int_rman_activate_resource(rm, r, &whohas);
-	lwkt_reltoken(rm->rm_slock);
+	lwkt_reltoken(&ilock);
 	return rv;
 }
 
+#if 0
+
+/* XXX */
 int
-rman_await_resource(struct resource *r, int slpflags, int timo)
+rman_await_resource(struct resource *r, lwkt_tokref_t ilock, int slpflags, int timo)
 {
 	int	rv, s;
 	struct	resource *whohas;
@@ -459,10 +467,10 @@
 
 	rm = r->r_rm;
 	for (;;) {
-		lwkt_gettoken(rm->rm_slock);
+		lwkt_gettoken(ilock, rm->rm_slock);
 		rv = int_rman_activate_resource(rm, r, &whohas);
 		if (rv != EBUSY)
-			return (rv);	/* returns with simple token */
+			return (rv);	/* returns with ilock held */
 
 		if (r->r_sharehead == 0)
 			panic("rman_await_resource");
@@ -474,17 +482,18 @@
 		 */
 		s = splhigh();
 		whohas->r_flags |= RF_WANTED;
-		lwkt_reltoken(rm->rm_slock);	/* YYY */
 		rv = tsleep(r->r_sharehead, slpflags, "rmwait", timo);
 		if (rv) {
+			lwkt_reltoken(ilock);
 			splx(s);
 			return rv;
 		}
-		lwkt_gettoken(rm->rm_slock);
 		splx(s);
 	}
 }
 
+#endif
+
 static int
 int_rman_deactivate_resource(struct resource *r)
 {
@@ -502,12 +511,13 @@
 int
 rman_deactivate_resource(struct resource *r)
 {
-	struct	rman *rm;
+	lwkt_tokref ilock;
+	struct rman *rm;
 
 	rm = r->r_rm;
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 	int_rman_deactivate_resource(r);
-	lwkt_reltoken(rm->rm_slock);
+	lwkt_reltoken(&ilock);
 	return 0;
 }
 
@@ -602,12 +612,13 @@
 int
 rman_release_resource(struct resource *r)
 {
-	int	rv;
 	struct	rman *rm = r->r_rm;
+	lwkt_tokref ilock;
+	int	rv;
 
-	lwkt_gettoken(rm->rm_slock);
+	lwkt_gettoken(&ilock, rm->rm_slock);
 	rv = int_rman_release_resource(rm, r);
-	lwkt_reltoken(rm->rm_slock);
+	lwkt_reltoken(&ilock);
 	return (rv);
 }
 
Index: kern/tty_tty.c
===================================================================
RCS file: /cvs/src/sys/kern/tty_tty.c,v
retrieving revision 1.6
diff -u -r1.6 tty_tty.c
--- kern/tty_tty.c	26 Aug 2003 21:09:02 -0000	1.6
+++ kern/tty_tty.c	22 Feb 2004 05:51:31 -0000
@@ -90,7 +90,7 @@
 
 	if (ttyvp == NULL)
 		return (ENXIO);
-	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 #ifdef PARANOID
 	/*
 	 * Since group is tty and mode is 620 on most terminal lines
@@ -105,7 +105,7 @@
 	if (!error)
 #endif /* PARANOID */
 		error = VOP_OPEN(ttyvp, flag, NOCRED, td);
-	VOP_UNLOCK(ttyvp, 0, td);
+	VOP_UNLOCK(ttyvp, NULL, 0, td);
 	return (error);
 }
 
@@ -125,9 +125,9 @@
 	ttyvp = cttyvp(p);
 	if (ttyvp == NULL)
 		return (EIO);
-	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_READ(ttyvp, uio, flag, NOCRED);
-	VOP_UNLOCK(ttyvp, 0, td);
+	VOP_UNLOCK(ttyvp, NULL, 0, td);
 	return (error);
 }
 
@@ -147,9 +147,9 @@
 	ttyvp = cttyvp(p);
 	if (ttyvp == NULL)
 		return (EIO);
-	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
-	VOP_UNLOCK(ttyvp, 0, td);
+	VOP_UNLOCK(ttyvp, NULL, 0, td);
 	return (error);
 }
 
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.23
diff -u -r1.23 uipc_syscalls.c
--- kern/uipc_syscalls.c	20 Dec 2003 05:53:59 -0000	1.23
+++ kern/uipc_syscalls.c	22 Feb 2004 05:51:35 -0000
@@ -1484,11 +1484,11 @@
 			auio.uio_segflg = UIO_NOCOPY;
 			auio.uio_rw = UIO_READ;
 			auio.uio_td = td;
-			vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
+			vn_lock(vp, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
 			error = VOP_READ(vp, &auio, 
 				    IO_VMIO | ((MAXBSIZE / bsize) << 16),
 				    p->p_ucred);
-			VOP_UNLOCK(vp, 0, td);
+			VOP_UNLOCK(vp, NULL, 0, td);
 			vm_page_flag_clear(pg, PG_ZERO);
 			vm_page_io_finish(pg);
 			if (error) {
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.10
diff -u -r1.10 uipc_usrreq.c
--- kern/uipc_usrreq.c	9 Oct 2003 22:27:19 -0000	1.10
+++ kern/uipc_usrreq.c	22 Feb 2004 05:35:41 -0000
@@ -627,7 +627,7 @@
 	vp->v_socket = unp->unp_socket;
 	unp->unp_vnode = vp;
 	unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (0);
 }
 
Index: kern/vfs_bio.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.18
diff -u -r1.18 vfs_bio.c
--- kern/vfs_bio.c	16 Feb 2004 19:37:48 -0000	1.18
+++ kern/vfs_bio.c	22 Feb 2004 07:16:41 -0000
@@ -351,7 +351,7 @@
 
 	TAILQ_INIT(&bswlist);
 	LIST_INIT(&invalhash);
-	lwkt_inittoken(&buftimetoken);
+	lwkt_token_init(&buftimetoken);
 
 	for (i = 0; i <= bufhashmask; i++)
 		LIST_INIT(&bufhashtbl[i]);
Index: kern/vfs_cache.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_cache.c,v
retrieving revision 1.12
diff -u -r1.12 vfs_cache.c
--- kern/vfs_cache.c	18 Oct 2003 05:53:57 -0000	1.12
+++ kern/vfs_cache.c	22 Feb 2004 06:09:02 -0000
@@ -792,17 +792,17 @@
 		VREF(vp);
 		error = 0;
 	} else if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(dvp, 0, td);
+		VOP_UNLOCK(dvp, NULL, 0, td);
 		cnp->cn_flags |= CNP_PDIRUNLOCK;
-		error = vget(vp, LK_EXCLUSIVE, td);
+		error = vget(vp, NULL, LK_EXCLUSIVE, td);
 		if (!error && lockparent && (flags & CNP_ISLASTCN)) {
-			if ((error = vn_lock(dvp, LK_EXCLUSIVE, td)) == 0)
+			if ((error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td)) == 0)
 				cnp->cn_flags &= ~CNP_PDIRUNLOCK;
 		}
 	} else {
-		error = vget(vp, LK_EXCLUSIVE, td);
+		error = vget(vp, NULL, LK_EXCLUSIVE, td);
 		if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 	}
@@ -815,12 +815,12 @@
 			return (0);
 		vput(vp);
 		if (lockparent && dvp != vp && (flags & CNP_ISLASTCN)) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 	}
 	if (cnp->cn_flags & CNP_PDIRUNLOCK) {
-		error = vn_lock(dvp, LK_EXCLUSIVE, td);
+		error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		if (error)
 			return (error);
 		cnp->cn_flags &= ~CNP_PDIRUNLOCK;
Index: kern/vfs_conf.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_conf.c,v
retrieving revision 1.6
diff -u -r1.6 vfs_conf.c
--- kern/vfs_conf.c	7 Aug 2003 21:17:23 -0000	1.6
+++ kern/vfs_conf.c	22 Feb 2004 03:08:27 -0000
@@ -177,6 +177,7 @@
 	char		*vfsname, *path;
 	int		error;
 	char		patt[32];
+	lwkt_tokref	ilock;
 	int		s;
 
 	vfsname = NULL;
@@ -235,9 +236,9 @@
 	} else {
 
 		/* register with list of mounted filesystems */
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettoken(&ilock, &mountlist_token);
 		TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
-		lwkt_reltoken(&mountlist_token);
+		lwkt_reltoken(&ilock);
 
 		/* sanity check system clock against root fs timestamp */
 		inittodr(mp->mnt_time);
Index: kern/vfs_default.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_default.c,v
retrieving revision 1.8
diff -u -r1.8 vfs_default.c
--- kern/vfs_default.c	26 Aug 2003 21:09:02 -0000	1.8
+++ kern/vfs_default.c	22 Feb 2004 07:17:03 -0000
@@ -241,6 +241,7 @@
 vop_stdlock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct proc *a_p;
 	} */ *ap;
@@ -249,14 +250,14 @@
 
 	if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
 		if (ap->a_flags & LK_INTERLOCK)
-			lwkt_reltoken(&ap->a_vp->v_interlock);
+			lwkt_reltoken(ap->a_vlock);
 		return 0;
 	}
 
 #ifndef	DEBUG_LOCKS
-	return (lockmgr(l, ap->a_flags, &ap->a_vp->v_interlock, ap->a_td));
+	return (lockmgr(l, ap->a_flags, ap->a_vlock, ap->a_td));
 #else
-	return (debuglockmgr(l, ap->a_flags, &ap->a_vp->v_interlock, ap->a_td,
+	return (debuglockmgr(l, ap->a_flags, ap->a_vlock, ap->a_td,
 	    "vop_stdlock", ap->a_vp->filename, ap->a_vp->line));
 #endif
 }
@@ -265,6 +266,7 @@
 vop_stdunlock(ap)
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct thread *a_td;
 	} */ *ap;
@@ -273,12 +275,11 @@
 
 	if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
 		if (ap->a_flags & LK_INTERLOCK)
-			lwkt_reltoken(&ap->a_vp->v_interlock);
+			lwkt_reltoken(ap->a_vlock);
 		return 0;
 	}
 
-	return (lockmgr(l, ap->a_flags | LK_RELEASE,
-		    &ap->a_vp->v_interlock, ap->a_td));
+	return (lockmgr(l, ap->a_flags | LK_RELEASE, ap->a_vlock, ap->a_td));
 }
 
 int
@@ -355,6 +356,7 @@
 vop_sharedlock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct proc *a_p;
 	} */ *ap;
@@ -379,7 +381,7 @@
 
 	if (l == NULL) {
 		if (ap->a_flags & LK_INTERLOCK)
-			lwkt_reltoken(&ap->a_vp->v_interlock);
+			lwkt_reltoken(ap->a_vlock);
 		return 0;
 	}
 	switch (flags & LK_TYPE_MASK) {
@@ -409,9 +411,9 @@
 	if (flags & LK_INTERLOCK)
 		vnflags |= LK_INTERLOCK;
 #ifndef	DEBUG_LOCKS
-	return (lockmgr(l, vnflags, &vp->v_interlock, ap->a_td));
+	return (lockmgr(l, vnflags, ap->a_vlock, ap->a_td));
 #else
-	return (debuglockmgr(l, vnflags, &vp->v_interlock, ap->a_td,
+	return (debuglockmgr(l, vnflags, ap->a_vlock, ap->a_td,
 	    "vop_sharedlock", vp->filename, vp->line));
 #endif
 }
@@ -426,6 +428,7 @@
 vop_nolock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct proc *a_p;
 	} */ *ap;
@@ -466,14 +469,14 @@
 	}
 	if (flags & LK_INTERLOCK)
 		vnflags |= LK_INTERLOCK;
-	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
+	return(lockmgr(vp->v_vnlock, vnflags, ap->a_vlock, ap->a_p));
 #else /* for now */
 	/*
 	 * Since we are not using the lock manager, we must clear
 	 * the interlock here.
 	 */
 	if (ap->a_flags & LK_INTERLOCK)
-		lwkt_reltoken(&ap->a_vp->v_interlock);
+		lwkt_reltoken(ap->a_vlock);
 	return (0);
 #endif
 }
@@ -485,12 +488,13 @@
 vop_nounlock(ap)
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct proc *a_p;
 	} */ *ap;
 {
 	if (ap->a_flags & LK_INTERLOCK)
-		lwkt_reltoken(&ap->a_vp->v_interlock);
+		lwkt_reltoken(ap->a_vlock);
 	return (0);
 }
 
@@ -547,9 +551,9 @@
 		vp->v_usecount--;
 	} else {
 		if (object->flags & OBJ_DEAD) {
-			VOP_UNLOCK(vp, 0, td);
+			VOP_UNLOCK(vp, NULL, 0, td);
 			tsleep(object, 0, "vodead", 0);
-			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			goto retry;
 		}
 	}
Index: kern/vfs_lookup.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.9
diff -u -r1.9 vfs_lookup.c
--- kern/vfs_lookup.c	9 Nov 2003 20:29:59 -0000	1.9
+++ kern/vfs_lookup.c	22 Feb 2004 06:04:47 -0000
@@ -182,7 +182,7 @@
 			return (0);
 		}
 		if ((cnp->cn_flags & CNP_LOCKPARENT) && ndp->ni_pathlen == 1)
-			VOP_UNLOCK(ndp->ni_dvp, 0, cnp->cn_td);
+			VOP_UNLOCK(ndp->ni_dvp, NULL, 0, cnp->cn_td);
 		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
 			error = ELOOP;
 			break;
@@ -314,7 +314,7 @@
 	cnp->cn_flags &= ~CNP_ISSYMLINK;
 	dp = ndp->ni_startdir;
 	ndp->ni_startdir = NULLVP;
-	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 dirloop:
 	/*
@@ -394,7 +394,7 @@
 		}
 		ndp->ni_vp = dp;
 		if (!(cnp->cn_flags & (CNP_LOCKPARENT | CNP_LOCKLEAF)))
-			VOP_UNLOCK(dp, 0, cnp->cn_td);
+			VOP_UNLOCK(dp, NULL, 0, cnp->cn_td);
 		/* XXX This should probably move to the top of function. */
 		if (cnp->cn_flags & CNP_SAVESTART)
 			panic("lookup: CNP_SAVESTART");
@@ -434,7 +434,7 @@
 			dp = dp->v_mount->mnt_vnodecovered;
 			vput(tdp);
 			VREF(dp);
-			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		}
 	}
 
@@ -461,7 +461,7 @@
 			else
 				vput(tdp);
 			VREF(dp);
-			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			goto unionlookup;
 		}
 
@@ -516,9 +516,9 @@
 	 */
 	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
 	       (cnp->cn_flags & CNP_NOCROSSMOUNT) == 0) {
-		if (vfs_busy(mp, 0, 0, td))
+		if (vfs_busy(mp, 0, NULL, td))
 			continue;
-		VOP_UNLOCK(dp, 0, td);
+		VOP_UNLOCK(dp, NULL, 0, td);
 		error = VFS_ROOT(mp, &tdp);
 		vfs_unbusy(mp, td);
 		if (error) {
@@ -590,13 +590,13 @@
 		vrele(ndp->ni_dvp);
 
 	if ((cnp->cn_flags & CNP_LOCKLEAF) == 0)
-		VOP_UNLOCK(dp, 0, td);
+		VOP_UNLOCK(dp, NULL, 0, td);
 	return (0);
 
 bad2:
 	if ((cnp->cn_flags & (CNP_LOCKPARENT | CNP_PDIRUNLOCK)) == CNP_LOCKPARENT &&
 	    *ndp->ni_next == '\0')
-		VOP_UNLOCK(ndp->ni_dvp, 0, td);
+		VOP_UNLOCK(ndp->ni_dvp, NULL, 0, td);
 	vrele(ndp->ni_dvp);
 bad:
 	if (dpunlocked)
@@ -638,7 +638,7 @@
 	rdonly = cnp->cn_flags & CNP_RDONLY;
 	cnp->cn_flags &= ~CNP_ISSYMLINK;
 	dp = dvp;
-	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 /* dirloop: */
 	/*
@@ -672,7 +672,7 @@
 			goto bad;
 		}
 		if (!(cnp->cn_flags & CNP_LOCKLEAF))
-			VOP_UNLOCK(dp, 0, td);
+			VOP_UNLOCK(dp, NULL, 0, td);
 		*vpp = dp;
 		/* XXX This should probably move to the top of function. */
 		if (cnp->cn_flags & CNP_SAVESTART)
@@ -736,12 +736,12 @@
 		vfs_object_create(dp, cnp->cn_td);
 
 	if ((cnp->cn_flags & CNP_LOCKLEAF) == 0)
-		VOP_UNLOCK(dp, 0, td);
+		VOP_UNLOCK(dp, NULL, 0, td);
 	return (0);
 
 bad2:
 	if ((cnp->cn_flags & CNP_LOCKPARENT) && (cnp->cn_flags & CNP_ISLASTCN))
-		VOP_UNLOCK(dvp, 0, td);
+		VOP_UNLOCK(dvp, NULL, 0, td);
 	vrele(dvp);
 bad:
 	vput(dp);
Index: kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.25
diff -u -r1.25 vfs_subr.c
--- kern/vfs_subr.c	10 Feb 2004 07:34:42 -0000	1.25
+++ kern/vfs_subr.c	24 Feb 2004 19:00:44 -0000
@@ -87,7 +87,7 @@
 static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
 
 static void	insmntque (struct vnode *vp, struct mount *mp);
-static void	vclean (struct vnode *vp, int flags, struct thread *td);
+static void	vclean (struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td);
 static unsigned long	numvnodes;
 static void	vlruvp(struct vnode *vp);
 SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, "");
@@ -195,12 +195,12 @@
 		    (5 * (sizeof(struct vm_object) + sizeof(struct vnode))));
 
 	minvnodes = desiredvnodes / 4;
-	lwkt_inittoken(&mountlist_token);
-	lwkt_inittoken(&mntvnode_token);
-	lwkt_inittoken(&mntid_token);
-	lwkt_inittoken(&spechash_token);
+	lwkt_token_init(&mountlist_token);
+	lwkt_token_init(&mntvnode_token);
+	lwkt_token_init(&mntid_token);
+	lwkt_token_init(&spechash_token);
 	TAILQ_INIT(&vnode_free_list);
-	lwkt_inittoken(&vnode_free_list_token);
+	lwkt_token_init(&vnode_free_list_token);
 	vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5);
 	/*
 	 * Initialize the filesystem syncer.
@@ -215,8 +215,7 @@
  * unmounting. Interlock is not released on failure.
  */
 int
-vfs_busy(struct mount *mp, int flags, struct lwkt_token *interlkp,
-	struct thread *td)
+vfs_busy(struct mount *mp, int flags, lwkt_tokref_t interlkp, struct thread *td)
 {
 	int lkflags;
 
@@ -224,19 +223,16 @@
 		if (flags & LK_NOWAIT)
 			return (ENOENT);
 		mp->mnt_kern_flag |= MNTK_MWAIT;
-		if (interlkp) {
-			lwkt_reltoken(interlkp);
-		}
 		/*
 		 * Since all busy locks are shared except the exclusive
 		 * lock granted when unmounting, the only place that a
 		 * wakeup needs to be done is at the release of the
 		 * exclusive lock at the end of dounmount.
+		 *
+		 * note: interlkp is a serializer and thus can be safely
+		 * held through any sleep
 		 */
 		tsleep((caddr_t)mp, 0, "vfs_busy", 0);
-		if (interlkp) {
-			lwkt_gettoken(interlkp);
-		}
 		return (ENOENT);
 	}
 	lkflags = LK_SHARED | LK_NOPAUSE;
@@ -279,7 +275,7 @@
 	mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
 	bzero((char *)mp, (u_long)sizeof(struct mount));
 	lockinit(&mp->mnt_lock, 0, "vfslock", VLKTIMEOUT, LK_NOPAUSE);
-	(void)vfs_busy(mp, LK_NOWAIT, 0, td);
+	vfs_busy(mp, LK_NOWAIT, NULL, td);
 	TAILQ_INIT(&mp->mnt_nvnodelist);
 	TAILQ_INIT(&mp->mnt_reservedvnlist);
 	mp->mnt_nvnodelistsize = 0;
@@ -334,17 +330,17 @@
 	fsid_t *fsid;
 {
 	struct mount *mp;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
 		if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
 		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
-			lwkt_reltoken(&mountlist_token);
-			return (mp);
+			break;
 	    }
 	}
-	lwkt_reltoken(&mountlist_token);
-	return ((struct mount *) 0);
+	lwkt_reltoken(&ilock);
+	return (mp);
 }
 
 /*
@@ -364,10 +360,11 @@
 	struct mount *mp;
 {
 	static u_int16_t mntid_base;
+	lwkt_tokref ilock;
 	fsid_t tfsid;
 	int mtype;
 
-	lwkt_gettoken(&mntid_token);
+	lwkt_gettoken(&ilock, &mntid_token);
 	mtype = mp->mnt_vfc->vfc_typenum;
 	tfsid.val[1] = mtype;
 	mtype = (mtype & 0xFF) << 24;
@@ -380,7 +377,7 @@
 	}
 	mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
 	mp->mnt_stat.f_fsid.val[1] = tfsid.val[1];
-	lwkt_reltoken(&mntid_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -474,11 +471,12 @@
 vlrureclaim(struct mount *mp)
 {
 	struct vnode *vp;
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 	int done;
 	int trigger;
 	int usevnodes;
 	int count;
-	int gen;
 
 	/*
 	 * Calculate the trigger point, don't allow user
@@ -493,32 +491,61 @@
 	trigger = vmstats.v_page_count * 2 / usevnodes;
 
 	done = 0;
-	gen = lwkt_gettoken(&mntvnode_token);
+	lwkt_gettoken(&ilock, &mntvnode_token);
 	count = mp->mnt_nvnodelistsize / 10 + 1;
 	while (count && (vp = TAILQ_FIRST(&mp->mnt_nvnodelist)) != NULL) {
+		/*
+		 * __VNODESCAN__
+		 *
+		 * The VP will stick around while we hold mntvnode_token,
+		 * at least until we block, so we can safely do an initial
+		 * check.  But we have to check again after obtaining
+		 * the vnode interlock.  vp->v_interlock points to stable
+		 * storage so it's ok if the vp gets ripped out from
+		 * under us while we are blocked.
+		 */
+		if (vp->v_type == VNON ||
+		    vp->v_type == VBAD ||
+		    !VMIGHTFREE(vp) ||		/* critical path opt */
+		    (vp->v_object &&
+		     vp->v_object->resident_page_count >= trigger)
+		) {
+			TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
+			TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes);
+			--count;
+			continue;
+		}
+
+		/*
+		 * Get the interlock, delay moving the node to the tail so
+		 * we don't race against new additions to the mountlist.
+		 */
+		lwkt_gettoken(&vlock, vp->v_interlock);
+		if (TAILQ_FIRST(&mp->mnt_nvnodelist) != vp) {
+			lwkt_reltoken(&vlock);
+			continue;
+		}
 		TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
-		TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
+		TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes);
 
-		if (vp->v_type != VNON &&
-		    vp->v_type != VBAD &&
-		    VMIGHTFREE(vp) &&		/* critical path opt */
-		    (vp->v_object == NULL || vp->v_object->resident_page_count < trigger)
+		/*
+		 * Must check again
+		 */
+		if (vp->v_type == VNON ||
+		    vp->v_type == VBAD ||
+		    !VMIGHTFREE(vp) ||		/* critical path opt */
+		    (vp->v_object &&
+		     vp->v_object->resident_page_count >= trigger)
 		) {
-			lwkt_gettoken(&vp->v_interlock);
-			if (lwkt_gentoken(&mntvnode_token, &gen) == 0) {
-				if (VMIGHTFREE(vp)) {
-					vgonel(vp, curthread);
-					done++;
-				} else {
-					lwkt_reltoken(&vp->v_interlock);
-				}
-			} else {
-				lwkt_reltoken(&vp->v_interlock);
-			}
+			lwkt_reltoken(&vlock);
+			--count;
+			continue;
 		}
+		vgonel(vp, &vlock, curthread);
+		++done;
 		--count;
 	}
-	lwkt_reltoken(&mntvnode_token);
+	lwkt_reltoken(&ilock);
 	return done;
 }
 
@@ -534,6 +561,7 @@
 vnlru_proc(void)
 {
 	struct mount *mp, *nmp;
+	lwkt_tokref ilock;
 	int s;
 	int done;
 	struct thread *td = curthread;
@@ -551,18 +579,18 @@
 			continue;
 		}
 		done = 0;
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettoken(&ilock, &mountlist_token);
 		for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-			if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+			if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
 				nmp = TAILQ_NEXT(mp, mnt_list);
 				continue;
 			}
 			done += vlrureclaim(mp);
-			lwkt_gettoken(&mountlist_token);
+			lwkt_gettokref(&ilock);
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			vfs_unbusy(mp, td);
 		}
-		lwkt_reltoken(&mountlist_token);
+		lwkt_reltoken(&ilock);
 		if (done == 0) {
 			vnlru_nowhere++;
 			tsleep(td, 0, "vlrup", hz * 3);
@@ -594,11 +622,12 @@
 	struct vnode **vpp;
 {
 	int s;
-	int gen;
-	int vgen;
 	struct thread *td = curthread;	/* XXX */
 	struct vnode *vp = NULL;
+	struct vnode *xvp;
 	vm_object_t object;
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 
 	s = splbio();
 
@@ -622,96 +651,96 @@
 	 * a new vnode if we can't find one or if we have not reached a
 	 * good minimum for good LRU performance.
 	 */
-	gen = lwkt_gettoken(&vnode_free_list_token);
+	lwkt_gettoken(&ilock, &vnode_free_list_token);
 	if (freevnodes >= wantfreevnodes && numvnodes >= minvnodes) {
 		int count;
 
 		for (count = 0; count < freevnodes; count++) {
+			/*
+			 * __VNODESCAN__
+			 *
+			 * Pull the next vnode off the free list and do some
+			 * sanity checks.  Note that regardless of how we
+			 * block, if freevnodes is non-zero there had better
+			 * be something on the list.
+			 */
 			vp = TAILQ_FIRST(&vnode_free_list);
 			if (vp == NULL || vp->v_usecount)
 				panic("getnewvnode: free vnode isn't");
 
 			/*
-			 * Get the vnode's interlock, then re-obtain 
-			 * vnode_free_list_token in case we lost it.  If we
-			 * did lose it while getting the vnode interlock,
-			 * even if we got it back again, then retry.
+			 * Move the vnode to the end of the list so other
+			 * processes do not double-block trying to recycle
+			 * the same vnode (as an optimization), then get
+			 * the interlock.
+			 */
+			TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+			TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+			lwkt_gettoken(&vlock, vp->v_interlock);
+
+			/*
+			 * Check that the vnode is still on the free list.
+			 * This normally devolves into a degenerate case so
+			 * it is optimal.   Loop up if it isn't.
 			 */
-			vgen = lwkt_gettoken(&vp->v_interlock);
-			if (lwkt_gentoken(&vnode_free_list_token, &gen) != 0) {
-				--count;
-				lwkt_reltoken(&vp->v_interlock);
+			TAILQ_FOREACH_REVERSE(xvp, &vnode_free_list, 
+			    freelst, v_freelist) {
+				if (vp == xvp)
+					break;
+			}
+			if (vp != xvp) {
 				vp = NULL;
 				continue;
 			}
 
 			/*
-			 * Whew!  We have both tokens.  Since we didn't lose
-			 * the free list VFREE had better still be set.  But
-			 * we aren't out of the woods yet.  We have to get
-			 * the object (may block).  If the vnode is not 
-			 * suitable then move it to the end of the list
-			 * if we can.  If we can't move it to the end of the
-			 * list retry again.
+			 * We now safely own the vnode.  If the vnode has
+			 * an object do not recycle it if its VM object
+			 * has resident pages or references.
 			 */
 			if ((VOP_GETVOBJECT(vp, &object) == 0 &&
 			    (object->resident_page_count || object->ref_count))
 			) {
-				if (lwkt_gentoken(&vp->v_interlock, &vgen) == 0 &&
-				   lwkt_gentoken(&vnode_free_list_token, &gen) == 0
-				) {
-					TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
-					TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
-				} else {
-					--count;
-				}
-				lwkt_reltoken(&vp->v_interlock);
+				lwkt_reltoken(&vlock);
 				vp = NULL;
 				continue;
 			}
 
 			/*
-			 * Still not out of the woods.  VOBJECT might have
-			 * blocked, if we did not retain our tokens we have
-			 * to retry.
+			 * We can almost reuse this vnode.  But we don't want
+			 * to recycle it if the vnode has children in the
+			 * namecache because that breaks the namecache's
+			 * path element chain.  (YYY use nc_refs for the
+			 * check?)
 			 */
-			if (lwkt_gentoken(&vp->v_interlock, &vgen) != 0 ||
-			    lwkt_gentoken(&vnode_free_list_token, &gen) != 0) {
-				--count;
-				vp = NULL;
-				continue;
-			}
-			TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
 			KKASSERT(vp->v_flag & VFREE);
+			TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
 
-			/*
-			 * If we have children in the namecache we cannot
-			 * reuse the vnode yet because it will break the
-			 * namecache chain (YYY use nc_refs for the check?)
-			 */
-			if (TAILQ_FIRST(&vp->v_namecache)) {
-				if (cache_leaf_test(vp) < 0) {
-					lwkt_reltoken(&vp->v_interlock);
-					TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
-					vp = NULL;
-					continue;
-				}
+			if (TAILQ_FIRST(&vp->v_namecache) == NULL ||
+			    cache_leaf_test(vp) >= 0) {
+				/* ok, we can reuse this vnode */
+				break;
 			}
-			break;
+			lwkt_reltoken(&vlock);
+			TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+			vp = NULL;
 		}
 	}
 
+	/*
+	 * If vp is non-NULL we hold it's interlock.
+	 */
 	if (vp) {
 		vp->v_flag |= VDOOMED;
 		vp->v_flag &= ~VFREE;
 		freevnodes--;
-		lwkt_reltoken(&vnode_free_list_token);
+		lwkt_reltoken(&ilock);
 		cache_purge(vp);	/* YYY may block */
 		vp->v_lease = NULL;
 		if (vp->v_type != VBAD) {
-			vgonel(vp, td);
+			vgonel(vp, &vlock, td);
 		} else {
-			lwkt_reltoken(&vp->v_interlock);
+			lwkt_reltoken(&vlock);
 		}
 
 #ifdef INVARIANTS
@@ -734,11 +763,11 @@
 		vp->v_socket = 0;
 		vp->v_writecount = 0;	/* XXX */
 	} else {
-		lwkt_reltoken(&vnode_free_list_token);
-		vp = (struct vnode *) zalloc(vnode_zone);
-		bzero((char *) vp, sizeof *vp);
-		lwkt_inittoken(&vp->v_interlock);
-		lwkt_inittoken(&vp->v_pollinfo.vpi_token);
+		lwkt_reltoken(&ilock);
+		vp = zalloc(vnode_zone);
+		bzero(vp, sizeof(*vp));
+		vp->v_interlock = lwkt_token_pool_get(vp);
+		lwkt_token_init(&vp->v_pollinfo.vpi_token);
 		vp->v_dd = vp;
 		cache_purge(vp);
 		TAILQ_INIT(&vp->v_namecache);
@@ -768,8 +797,9 @@
 	struct vnode *vp;
 	struct mount *mp;
 {
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&mntvnode_token);
+	lwkt_gettoken(&ilock, &mntvnode_token);
 	/*
 	 * Delete from old mount point vnode list, if on one.
 	 */
@@ -783,12 +813,12 @@
 	 * Insert into list of vnodes for the new mount point, if available.
 	 */
 	if ((vp->v_mount = mp) == NULL) {
-		lwkt_reltoken(&mntvnode_token);
+		lwkt_reltoken(&ilock);
 		return;
 	}
 	TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
 	mp->mnt_nvnodelistsize++;
-	lwkt_reltoken(&mntvnode_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -824,6 +854,7 @@
 	struct buf *nbp, *blist;
 	int s, error;
 	vm_object_t object;
+	lwkt_tokref vlock;
 
 	if (flags & V_SAVE) {
 		s = splbio();
@@ -920,12 +951,12 @@
 	/*
 	 * Destroy the copy in the VM cache, too.
 	 */
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (VOP_GETVOBJECT(vp, &object) == 0) {
 		vm_object_page_remove(object, 0, 0,
 			(flags & V_SAVE) ? TRUE : FALSE);
 	}
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 
 	if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) || !TAILQ_EMPTY(&vp->v_cleanblkhd))
 		panic("vinvalbuf: flush failed");
@@ -1186,9 +1217,9 @@
 
 		while ((vp = LIST_FIRST(slp)) != NULL) {
 			if (VOP_ISLOCKED(vp, NULL) == 0) {
-				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+				vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				(void) VOP_FSYNC(vp, MNT_LAZY, td);
-				VOP_UNLOCK(vp, 0, td);
+				VOP_UNLOCK(vp, NULL, 0, td);
 			}
 			s = splbio();
 			if (LIST_FIRST(slp) == vp) {
@@ -1516,14 +1547,15 @@
 void
 addalias(struct vnode *nvp, dev_t dev)
 {
+	lwkt_tokref ilock;
 
 	if (nvp->v_type != VBLK && nvp->v_type != VCHR)
 		panic("addalias on non-special vnode");
 
 	nvp->v_rdev = dev;
-	lwkt_gettoken(&spechash_token);
+	lwkt_gettoken(&ilock, &spechash_token);
 	SLIST_INSERT_HEAD(&dev->si_hlist, nvp, v_specnext);
-	lwkt_reltoken(&spechash_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -1535,18 +1567,27 @@
  * been changed to a new file system type).
  */
 int
-vget(vp, flags, td)
-	struct vnode *vp;
-	int flags;
-	struct thread *td;
+vget(struct vnode *vp, lwkt_tokref_t vlock, int flags, thread_t td)
 {
 	int error;
+	lwkt_tokref vvlock;
+
+	/*
+	 * We need the interlock to safely modify the v_ fields.
+	 */
+	if ((flags & LK_INTERLOCK) == 0) {
+		lwkt_gettoken(&vvlock, vp->v_interlock);
+		vlock = &vvlock;
+	}
 
 	/*
 	 * If the vnode is in the process of being cleaned out for
 	 * another use, we wait for the cleaning to finish and then
 	 * return failure. Cleaning is determined by checking that
 	 * the VXLOCK flag is set.
+	 *
+	 * XXX note: v_flag not protected here if interlock != vnode's
+	 * interlock ZZZ
 	 */
 	if (vp->v_flag & VXLOCK) {
 		if (vp->v_vxproc == curproc) {
@@ -1556,6 +1597,7 @@
 #endif
 		} else {
 			vp->v_flag |= VXWANT;
+			lwkt_reltoken(vlock);
 			tsleep((caddr_t)vp, 0, "vget", 0);
 			return (ENOENT);
 		}
@@ -1569,14 +1611,10 @@
 	 */
 	vp->v_usecount++;	/* XXX MP */
 
-	if ((flags & LK_INTERLOCK) == 0) {
-		lwkt_gettoken(&vp->v_interlock);
-	}
-
 	if (VSHOULDBUSY(vp))
 		vbusy(vp);
 	if (flags & LK_TYPE_MASK) {
-		if ((error = vn_lock(vp, flags | LK_INTERLOCK, td)) != 0) {
+		if ((error = vn_lock(vp, vlock, flags | LK_INTERLOCK, td)) != 0) {
 			/*
 			 * must expand vrele here because we do not want
 			 * to call VOP_INACTIVE if the reference count
@@ -1585,17 +1623,17 @@
 			 * before sleeping so that multiple processes do
 			 * not try to recycle it.
 			 */
-			lwkt_gettoken(&vp->v_interlock);
+			lwkt_gettokref(vlock);
 			vp->v_usecount--;
 			if (VSHOULDFREE(vp))
 				vfree(vp);
 			else
 				vlruvp(vp);
-			lwkt_reltoken(&vp->v_interlock);
+			lwkt_reltoken(vlock);
 		}
 		return (error);
 	}
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(vlock);
 	return (0);
 }
 
@@ -1613,16 +1651,15 @@
 vrele(struct vnode *vp)
 {
 	struct thread *td = curthread;	/* XXX */
+	lwkt_tokref vlock;
 
 	KASSERT(vp != NULL, ("vrele: null vp"));
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 
 	if (vp->v_usecount > 1) {
-
 		vp->v_usecount--;
-		lwkt_reltoken(&vp->v_interlock);
-
+		lwkt_reltoken(&vlock);
 		return;
 	}
 
@@ -1635,7 +1672,7 @@
 		 * the vnode before calling VOP_INACTIVE
 		 */
 
-		if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0)
+		if (vn_lock(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0)
 			VOP_INACTIVE(vp, td);
 		if (VSHOULDFREE(vp))
 			vfree(vp);
@@ -1644,8 +1681,8 @@
 	} else {
 #ifdef DIAGNOSTIC
 		vprint("vrele: negative ref count", vp);
-		lwkt_reltoken(&vp->v_interlock);
 #endif
+		lwkt_reltoken(&vlock);
 		panic("vrele: negative ref cnt");
 	}
 }
@@ -1654,14 +1691,15 @@
 vput(struct vnode *vp)
 {
 	struct thread *td = curthread;	/* XXX */
+	lwkt_tokref vlock;
 
 	KASSERT(vp != NULL, ("vput: null vp"));
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 
 	if (vp->v_usecount > 1) {
 		vp->v_usecount--;
-		VOP_UNLOCK(vp, LK_INTERLOCK, td);
+		VOP_UNLOCK(vp, &vlock, LK_INTERLOCK, td);
 		return;
 	}
 
@@ -1672,7 +1710,7 @@
 		 * If we are doing a vpu, the node is already locked,
 		 * so we just need to release the vnode mutex.
 		 */
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		VOP_INACTIVE(vp, td);
 		if (VSHOULDFREE(vp))
 			vfree(vp);
@@ -1682,6 +1720,7 @@
 #ifdef DIAGNOSTIC
 		vprint("vput: negative ref count", vp);
 #endif
+		lwkt_reltoken(&vlock);
 		panic("vput: negative ref cnt");
 	}
 }
@@ -1720,6 +1759,78 @@
 	splx(s);
 }
 
+int
+vmntvnodescan(
+    struct mount *mp, 
+    int (*fastfunc)(struct mount *mp, struct vnode *vp, void *data),
+    int (*slowfunc)(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data),
+    void *data
+) {
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
+	struct vnode *pvp;
+	struct vnode *vp;
+	int r = 0;
+
+	/*
+	 * Scan the vnodes on the mount's vnode list.  Use a placemarker
+	 */
+	pvp = zalloc(vnode_zone);
+	pvp->v_flag |= VPLACEMARKER;
+
+	lwkt_gettoken(&ilock, &mntvnode_token);
+	TAILQ_INSERT_HEAD(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+
+	while ((vp = TAILQ_NEXT(pvp, v_nmntvnodes)) != NULL) {
+		/*
+		 * Move the placemarker and skip other placemarkers we
+		 * encounter.  The nothing can get in our way so the
+		 * mount point on the vp must be valid.
+		 */
+		TAILQ_REMOVE(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+		TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, pvp, v_nmntvnodes);
+		if (vp->v_flag & VPLACEMARKER)
+			continue;
+		KKASSERT(vp->v_mount == mp);
+
+		/*
+		 * Quick test
+		 */
+		if (fastfunc) {
+			if ((r = fastfunc(mp, vp, data)) < 0)
+				continue;
+			if (r)
+				break;
+		}
+
+		/*
+		 * Get the vnodes interlock and make sure it is still on the
+		 * mount list.  Skip it if it has moved (we may encounter it
+		 * later).  Then do the with-interlock test.  The callback
+		 * is responsible for releasing the vnode interlock.
+		 *
+		 * The interlock is type-stable.
+		 */
+		if (slowfunc) {
+			lwkt_gettoken(&vlock, vp->v_interlock);
+			if (vp != TAILQ_PREV(pvp, vnodelst, v_nmntvnodes)) {
+				printf("vmntvnodescan (debug info only): f=%p vp=%p vnode ripped out from under us\n", slowfunc, vp);
+				lwkt_reltoken(&vlock);
+				continue;
+			}
+			if ((r = slowfunc(mp, vp, &vlock, data)) != 0) {
+				KKASSERT(lwkt_havetokref(&vlock) == 0);
+				break;
+			}
+			KKASSERT(lwkt_havetokref(&vlock) == 0);
+		}
+	}
+	TAILQ_REMOVE(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+	zfree(vnode_zone, pvp);
+	lwkt_reltoken(&ilock);
+	return(r);
+}
+
 /*
  * Remove any vnodes in the vnode table belonging to mount point mp.
  *
@@ -1745,6 +1856,14 @@
 SYSCTL_INT(_debug, OID_AUTO, busyprt, CTLFLAG_RW, &busyprt, 0, "");
 #endif
 
+static int vflush_scan(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data);
+
+struct vflush_info {
+	int flags;
+	int busy;
+	thread_t td;
+};
+
 int
 vflush(mp, rootrefs, flags)
 	struct mount *mp;
@@ -1752,9 +1871,10 @@
 	int flags;
 {
 	struct thread *td = curthread;	/* XXX */
-	struct vnode *vp, *nvp, *rootvp = NULL;
-	struct vattr vattr;
-	int busy = 0, error;
+	struct vnode *rootvp = NULL;
+	int error;
+	lwkt_tokref vlock;
+	struct vflush_info vflush_info;
 
 	if (rootrefs > 0) {
 		KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0,
@@ -1767,90 +1887,28 @@
 			return (error);
 		vput(rootvp);
 	}
-	lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp; vp = nvp) {
-		/*
-		 * Make sure this vnode wasn't reclaimed in getnewvnode().
-		 * Start over if it has (it won't be on the list anymore).
-		 */
-		if (vp->v_mount != mp)
-			goto loop;
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-
-		lwkt_gettoken(&vp->v_interlock);
-		/*
-		 * Skip over a vnodes marked VSYSTEM.
-		 */
-		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
-			lwkt_reltoken(&vp->v_interlock);
-			continue;
-		}
-		/*
-		 * If WRITECLOSE is set, flush out unlinked but still open
-		 * files (even if open only for reading) and regular file
-		 * vnodes open for writing. 
-		 */
-		if ((flags & WRITECLOSE) &&
-		    (vp->v_type == VNON ||
-		    (VOP_GETATTR(vp, &vattr, td) == 0 &&
-		    vattr.va_nlink > 0)) &&
-		    (vp->v_writecount == 0 || vp->v_type != VREG)) {
-			lwkt_reltoken(&vp->v_interlock);
-			continue;
-		}
 
-		/*
-		 * With v_usecount == 0, all we need to do is clear out the
-		 * vnode data structures and we are done.
-		 */
-		if (vp->v_usecount == 0) {
-			lwkt_reltoken(&mntvnode_token);
-			vgonel(vp, td);
-			lwkt_gettoken(&mntvnode_token);
-			continue;
-		}
+	vflush_info.busy = 0;
+	vflush_info.flags = flags;
+	vflush_info.td = td;
+	vmntvnodescan(mp, NULL, vflush_scan, &vflush_info);
 
-		/*
-		 * If FORCECLOSE is set, forcibly close the vnode. For block
-		 * or character devices, revert to an anonymous device. For
-		 * all other files, just kill them.
-		 */
-		if (flags & FORCECLOSE) {
-			lwkt_reltoken(&mntvnode_token);
-			if (vp->v_type != VBLK && vp->v_type != VCHR) {
-				vgonel(vp, td);
-			} else {
-				vclean(vp, 0, td);
-				vp->v_op = spec_vnodeop_p;
-				insmntque(vp, (struct mount *) 0);
-			}
-			lwkt_gettoken(&mntvnode_token);
-			continue;
-		}
-#ifdef DIAGNOSTIC
-		if (busyprt)
-			vprint("vflush: busy vnode", vp);
-#endif
-		lwkt_reltoken(&vp->v_interlock);
-		busy++;
-	}
-	lwkt_reltoken(&mntvnode_token);
 	if (rootrefs > 0 && (flags & FORCECLOSE) == 0) {
 		/*
 		 * If just the root vnode is busy, and if its refcount
 		 * is equal to `rootrefs', then go ahead and kill it.
 		 */
-		lwkt_gettoken(&rootvp->v_interlock);
-		KASSERT(busy > 0, ("vflush: not busy"));
+		lwkt_gettoken(&vlock, rootvp->v_interlock);
+		KASSERT(vflush_info.busy > 0, ("vflush: not busy"));
 		KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs"));
-		if (busy == 1 && rootvp->v_usecount == rootrefs) {
-			vgonel(rootvp, td);
-			busy = 0;
-		} else
-			lwkt_reltoken(&rootvp->v_interlock);
+		if (vflush_info.busy == 1 && rootvp->v_usecount == rootrefs) {
+			vgonel(rootvp, &vlock, td);
+			vflush_info.busy = 0;
+		} else {
+			lwkt_reltoken(&vlock);
+		}
 	}
-	if (busy)
+	if (vflush_info.busy)
 		return (EBUSY);
 	for (; rootrefs > 0; rootrefs--)
 		vrele(rootvp);
@@ -1858,6 +1916,70 @@
 }
 
 /*
+ * The scan callback is made with an interlocked vnode.
+ */
+static int
+vflush_scan(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
+{
+	struct vflush_info *info = data;
+	struct vattr vattr;
+
+	/*
+	 * Skip over a vnodes marked VSYSTEM.
+	 */
+	if ((info->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+
+	/*
+	 * If WRITECLOSE is set, flush out unlinked but still open
+	 * files (even if open only for reading) and regular file
+	 * vnodes open for writing. 
+	 */
+	if ((info->flags & WRITECLOSE) &&
+	    (vp->v_type == VNON ||
+	    (VOP_GETATTR(vp, &vattr, info->td) == 0 &&
+	    vattr.va_nlink > 0)) &&
+	    (vp->v_writecount == 0 || vp->v_type != VREG)) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+
+	/*
+	 * With v_usecount == 0, all we need to do is clear out the
+	 * vnode data structures and we are done.
+	 */
+	if (vp->v_usecount == 0) {
+		vgonel(vp, vlock, info->td);
+		return(0);
+	}
+
+	/*
+	 * If FORCECLOSE is set, forcibly close the vnode. For block
+	 * or character devices, revert to an anonymous device. For
+	 * all other files, just kill them.
+	 */
+	if (info->flags & FORCECLOSE) {
+		if (vp->v_type != VBLK && vp->v_type != VCHR) {
+			vgonel(vp, vlock, info->td);
+		} else {
+			vclean(vp, vlock, 0, info->td);
+			vp->v_op = spec_vnodeop_p;
+			insmntque(vp, (struct mount *) 0);
+		}
+		return(0);
+	}
+#ifdef DIAGNOSTIC
+	if (busyprt)
+		vprint("vflush: busy vnode", vp);
+#endif
+	lwkt_reltoken(vlock);
+	++info->busy;
+	return(0);
+}
+
+/*
  * We do not want to recycle the vnode too quickly.
  *
  * XXX we can't move vp's around the nvnodelist without really screwing
@@ -1869,12 +1991,13 @@
 {
 #if 0
 	struct mount *mp;
+	lwkt_tokref ilock;
 
 	if ((mp = vp->v_mount) != NULL) {
-		lwkt_gettoken(&mntvnode_token);
+		lwkt_gettoken(&ilock, &mntvnode_token); /* ZZZ */
 		TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
 		TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
-		lwkt_reltoken(&mntvnode_token);
+		lwkt_reltoken(&ilock);
 	}
 #endif
 }
@@ -1883,7 +2006,7 @@
  * Disassociate the underlying file system from a vnode.
  */
 static void
-vclean(struct vnode *vp, int flags, struct thread *td)
+vclean(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td)
 {
 	int active;
 
@@ -1910,7 +2033,7 @@
 	 * For active vnodes, it ensures that no other activity can
 	 * occur while the underlying object is being cleaned out.
 	 */
-	VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td);
+	VOP_LOCK(vp, vlock, LK_DRAIN | LK_INTERLOCK, td);
 
 	/*
 	 * Clean out any buffers associated with the vnode.
@@ -1933,7 +2056,7 @@
 		 * Any other processes trying to obtain this lock must first
 		 * wait for VXLOCK to clear, then call the new lock operation.
 		 */
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 	}
 	/*
 	 * Reclaim the vnode.
@@ -1946,7 +2069,7 @@
 		 * Inline copy of vrele() since VOP_INACTIVE
 		 * has already been called.
 		 */
-		lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(vlock, vp->v_interlock);
 		if (--vp->v_usecount <= 0) {
 #ifdef DIAGNOSTIC
 			if (vp->v_usecount < 0 || vp->v_writecount != 0) {
@@ -1956,7 +2079,7 @@
 #endif
 			vfree(vp);
 		}
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(vlock);
 	}
 
 	cache_purge(vp);
@@ -1991,6 +2114,7 @@
 	} */ *ap;
 {
 	struct vnode *vp, *vq;
+	lwkt_tokref ilock;
 	dev_t dev;
 
 	KASSERT((ap->a_flags & REVOKEALL) != 0, ("vop_revoke"));
@@ -2002,15 +2126,15 @@
 	 */
 	if (vp->v_flag & VXLOCK) {
 		vp->v_flag |= VXWANT;
-		lwkt_reltoken(&vp->v_interlock);
+		/*lwkt_reltoken(vlock); ZZZ */
 		tsleep((caddr_t)vp, 0, "vop_revokeall", 0);
 		return (0);
 	}
 	dev = vp->v_rdev;
 	for (;;) {
-		lwkt_gettoken(&spechash_token);
+		lwkt_gettoken(&ilock, &spechash_token);
 		vq = SLIST_FIRST(&dev->si_hlist);
-		lwkt_reltoken(&spechash_token);
+		lwkt_reltoken(&ilock);
 		if (!vq)
 			break;
 		vgone(vq);
@@ -2023,17 +2147,18 @@
  * Release the passed interlock if the vnode will be recycled.
  */
 int
-vrecycle(struct vnode *vp, struct lwkt_token *inter_lkp, struct thread *td)
+vrecycle(struct vnode *vp, lwkt_tokref_t inter_lkp, struct thread *td)
 {
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_tokref vlock;
+
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (vp->v_usecount == 0) {
-		if (inter_lkp) {
+		if (inter_lkp)
 			lwkt_reltoken(inter_lkp);
-		}
-		vgonel(vp, td);
+		vgonel(vp, &vlock, td);
 		return (1);
 	}
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	return (0);
 }
 
@@ -2045,17 +2170,19 @@
 vgone(struct vnode *vp)
 {
 	struct thread *td = curthread;	/* XXX */
+	lwkt_tokref vlock;
 
-	lwkt_gettoken(&vp->v_interlock);
-	vgonel(vp, td);
+	lwkt_gettoken(&vlock, vp->v_interlock);
+	vgonel(vp, &vlock, td);
 }
 
 /*
  * vgone, with the vp interlock held.
  */
 void
-vgonel(struct vnode *vp, struct thread *td)
+vgonel(struct vnode *vp, lwkt_tokref_t vlock, struct thread *td)
 {
+	lwkt_tokref ilock;
 	int s;
 
 	/*
@@ -2064,7 +2191,7 @@
 	 */
 	if (vp->v_flag & VXLOCK) {
 		vp->v_flag |= VXWANT;
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(vlock);
 		tsleep((caddr_t)vp, 0, "vgone", 0);
 		return;
 	}
@@ -2072,8 +2199,8 @@
 	/*
 	 * Clean out the filesystem specific data.
 	 */
-	vclean(vp, DOCLOSE, td);
-	lwkt_gettoken(&vp->v_interlock);
+	vclean(vp, vlock, DOCLOSE, td);
+	lwkt_gettokref(vlock);
 
 	/*
 	 * Delete from old mount point vnode list, if on one.
@@ -2085,10 +2212,10 @@
 	 * if it is on one.
 	 */
 	if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) {
-		lwkt_gettoken(&spechash_token);
+		lwkt_gettoken(&ilock, &spechash_token);
 		SLIST_REMOVE(&vp->v_hashchain, vp, vnode, v_specnext);
 		freedev(vp->v_rdev);
-		lwkt_reltoken(&spechash_token);
+		lwkt_reltoken(&ilock);
 		vp->v_rdev = NULL;
 	}
 
@@ -2104,19 +2231,18 @@
 	 */
 	if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) {
 		s = splbio();
-		lwkt_gettoken(&vnode_free_list_token);
+		lwkt_gettoken(&ilock, &vnode_free_list_token);
 		if (vp->v_flag & VFREE)
 			TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
 		else
 			freevnodes++;
 		vp->v_flag |= VFREE;
 		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
-		lwkt_reltoken(&vnode_free_list_token);
+		lwkt_reltoken(&ilock);
 		splx(s);
 	}
-
 	vp->v_type = VBAD;
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(vlock);
 }
 
 /*
@@ -2128,17 +2254,18 @@
 	enum vtype type;
 	struct vnode **vpp;
 {
+	lwkt_tokref ilock;
 	struct vnode *vp;
 
-	lwkt_gettoken(&spechash_token);
+	lwkt_gettoken(&ilock, &spechash_token);
 	SLIST_FOREACH(vp, &dev->si_hlist, v_specnext) {
 		if (type == vp->v_type) {
 			*vpp = vp;
-			lwkt_reltoken(&spechash_token);
+			lwkt_reltoken(&ilock);
 			return (1);
 		}
 	}
-	lwkt_reltoken(&spechash_token);
+	lwkt_reltoken(&ilock);
 	return (0);
 }
 
@@ -2149,14 +2276,15 @@
 vcount(vp)
 	struct vnode *vp;
 {
+	lwkt_tokref ilock;
 	struct vnode *vq;
 	int count;
 
 	count = 0;
-	lwkt_gettoken(&spechash_token);
+	lwkt_gettoken(&ilock, &spechash_token);
 	SLIST_FOREACH(vq, &vp->v_hashchain, v_specnext)
 		count += vq->v_usecount;
-	lwkt_reltoken(&spechash_token);
+	lwkt_reltoken(&ilock);
 	return (count);
 }
 
@@ -2234,13 +2362,14 @@
 DB_SHOW_COMMAND(lockedvnodes, lockedvnodes)
 {
 	struct thread *td = curthread;	/* XXX */
+	lwkt_tokref ilock;
 	struct mount *mp, *nmp;
 	struct vnode *vp;
 
 	printf("Locked vnodes\n");
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
@@ -2248,11 +2377,11 @@
 			if (VOP_ISLOCKED(vp, NULL))
 				vprint((char *)0, vp);
 		}
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettokref(&ilock);
 		nmp = TAILQ_NEXT(mp, mnt_list);
 		vfs_unbusy(mp, td);
 	}
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 }
 #endif
 
@@ -2346,6 +2475,8 @@
 	struct proc *p = curproc;	/* XXX */
 	struct mount *mp, *nmp;
 	struct vnode *nvp, *vp;
+	lwkt_tokref ilock;
+	lwkt_tokref jlock;
 	int error;
 
 #define VPTRSZ	sizeof (struct vnode *)
@@ -2356,14 +2487,14 @@
 		return (SYSCTL_OUT(req, 0,
 			(numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ)));
 
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, p)) {
+		if (vfs_busy(mp, LK_NOWAIT, &ilock, p)) {
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
+		lwkt_gettoken(&jlock, &mntvnode_token);
 again:
-		lwkt_gettoken(&mntvnode_token);
 		for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 		     vp != NULL;
 		     vp = nvp) {
@@ -2372,23 +2503,21 @@
 			 * this filesystem.  RACE: could have been
 			 * recycled onto the same filesystem.
 			 */
-			if (vp->v_mount != mp) {
-				lwkt_reltoken(&mntvnode_token);
+			if (vp->v_mount != mp)
 				goto again;
-			}
 			nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-			lwkt_reltoken(&mntvnode_token);
 			if ((error = SYSCTL_OUT(req, &vp, VPTRSZ)) ||
-			    (error = SYSCTL_OUT(req, vp, VNODESZ)))
+			    (error = SYSCTL_OUT(req, vp, VNODESZ))) {
+				lwkt_reltoken(&jlock);
 				return (error);
-			lwkt_gettoken(&mntvnode_token);
+			}
 		}
-		lwkt_reltoken(&mntvnode_token);
-		lwkt_gettoken(&mountlist_token);
-		nmp = TAILQ_NEXT(mp, mnt_list);
+		lwkt_reltoken(&jlock);
+		lwkt_gettokref(&ilock);
+		nmp = TAILQ_NEXT(mp, mnt_list);	/* ZZZ */
 		vfs_unbusy(mp, p);
 	}
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 
 	return (0);
 }
@@ -2720,10 +2849,11 @@
 	struct thread *td = curthread;	/* XXX */
 	struct vnode *vp, *nvp;
 	struct vm_object *obj;
+	lwkt_tokref ilock;
 	int tries;
 
 	tries = 5;
-	lwkt_gettoken(&mntvnode_token);
+	lwkt_gettoken(&ilock, &mntvnode_token);
 loop:
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
 		if (vp->v_mount != mp) {
@@ -2743,15 +2873,13 @@
 		 */
 		if ((vp->v_flag & VOBJDIRTY) &&
 		    (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) {
-			lwkt_reltoken(&mntvnode_token);
-			if (!vget(vp,
+			if (!vget(vp, NULL,
 			    LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, td)) {
 				if (VOP_GETVOBJECT(vp, &obj) == 0) {
 					vm_object_page_clean(obj, 0, 0, flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC);
 				}
 				vput(vp);
 			}
-			lwkt_gettoken(&mntvnode_token);
 			if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp) {
 				if (--tries > 0)
 					goto loop;
@@ -2759,7 +2887,7 @@
 			}
 		}
 	}
-	lwkt_reltoken(&mntvnode_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -2777,13 +2905,13 @@
 }
 
 void
-vfree(vp)
-	struct vnode *vp;
+vfree(struct vnode *vp)
 {
+	lwkt_tokref ilock;
 	int s;
 
 	s = splbio();
-	lwkt_gettoken(&vnode_free_list_token);
+	lwkt_gettoken(&ilock, &vnode_free_list_token);
 	KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free"));
 	if (vp->v_flag & VAGE) {
 		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
@@ -2791,7 +2919,7 @@
 		TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
 	}
 	freevnodes++;
-	lwkt_reltoken(&vnode_free_list_token);
+	lwkt_reltoken(&ilock);
 	vp->v_flag &= ~VAGE;
 	vp->v_flag |= VFREE;
 	splx(s);
@@ -2801,14 +2929,15 @@
 vbusy(vp)
 	struct vnode *vp;
 {
+	lwkt_tokref ilock;
 	int s;
 
 	s = splbio();
-	lwkt_gettoken(&vnode_free_list_token);
+	lwkt_gettoken(&ilock, &vnode_free_list_token);
 	KASSERT((vp->v_flag & VFREE) != 0, ("vnode not free"));
 	TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
 	freevnodes--;
-	lwkt_reltoken(&vnode_free_list_token);
+	lwkt_reltoken(&ilock);
 	vp->v_flag &= ~(VFREE|VAGE);
 	splx(s);
 }
@@ -2824,7 +2953,9 @@
 int
 vn_pollrecord(struct vnode *vp, struct thread *td, int events)
 {
-	lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
 	if (vp->v_pollinfo.vpi_revents & events) {
 		/*
 		 * This leaves events we are not interested
@@ -2836,12 +2967,12 @@
 		events &= vp->v_pollinfo.vpi_revents;
 		vp->v_pollinfo.vpi_revents &= ~events;
 
-		lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+		lwkt_reltoken(&ilock);
 		return events;
 	}
 	vp->v_pollinfo.vpi_events |= events;
 	selrecord(td, &vp->v_pollinfo.vpi_selinfo);
-	lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+	lwkt_reltoken(&ilock);
 	return 0;
 }
 
@@ -2856,7 +2987,9 @@
 	struct vnode *vp;
 	short events;
 {
-	lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
 	if (vp->v_pollinfo.vpi_events & events) {
 		/*
 		 * We clear vpi_events so that we don't
@@ -2873,7 +3006,7 @@
 		vp->v_pollinfo.vpi_revents |= events;
 		selwakeup(&vp->v_pollinfo.vpi_selinfo);
 	}
-	lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -2885,12 +3018,14 @@
 vn_pollgone(vp)
 	struct vnode *vp;
 {
-	lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
 	if (vp->v_pollinfo.vpi_events) {
 		vp->v_pollinfo.vpi_events = 0;
 		selwakeup(&vp->v_pollinfo.vpi_selinfo);
 	}
-	lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+	lwkt_reltoken(&ilock);
 }
 
 
@@ -2978,6 +3113,7 @@
 	struct vnode *syncvp = ap->a_vp;
 	struct mount *mp = syncvp->v_mount;
 	struct thread *td = ap->a_td;
+	lwkt_tokref ilock;
 	int asyncflag;
 
 	/*
@@ -2995,9 +3131,9 @@
 	 * Walk the list of vnodes pushing all that are dirty and
 	 * not already on the sync list.
 	 */
-	lwkt_gettoken(&mountlist_token);
-	if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &mountlist_token, td) != 0) {
-		lwkt_reltoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
+	if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &ilock, td) != 0) {
+		lwkt_reltoken(&ilock);
 		return (0);
 	}
 	asyncflag = mp->mnt_flag & MNT_ASYNC;
@@ -3138,7 +3274,7 @@
 	if (!(flags & NDF_NO_DVP_UNLOCK) &&
 	    (ndp->ni_cnd.cn_flags & CNP_LOCKPARENT) &&
 	    ndp->ni_dvp != ndp->ni_vp) {
-		VOP_UNLOCK(ndp->ni_dvp, 0, ndp->ni_cnd.cn_td);
+		VOP_UNLOCK(ndp->ni_dvp, NULL, 0, ndp->ni_cnd.cn_td);
 	}
 	if (!(flags & NDF_NO_DVP_RELE) &&
 	    (ndp->ni_cnd.cn_flags & (CNP_LOCKPARENT|CNP_WANTPARENT))) {
@@ -3147,7 +3283,7 @@
 	}
 	if (!(flags & NDF_NO_VP_UNLOCK) &&
 	    (ndp->ni_cnd.cn_flags & CNP_LOCKLEAF) && ndp->ni_vp) {
-		VOP_UNLOCK(ndp->ni_vp, 0, ndp->ni_cnd.cn_td);
+		VOP_UNLOCK(ndp->ni_vp, NULL, 0, ndp->ni_cnd.cn_td);
 	}
 	if (!(flags & NDF_NO_VP_RELE) &&
 	    ndp->ni_vp) {
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.28
diff -u -r1.28 vfs_syscalls.c
--- kern/vfs_syscalls.c	14 Nov 2003 19:31:22 -0000	1.28
+++ kern/vfs_syscalls.c	22 Feb 2004 19:06:21 -0000
@@ -108,6 +108,8 @@
 	struct vattr va;
 	struct nameidata nd;
 	char fstypename[MFSNAMELEN];
+	lwkt_tokref vlock;
+	lwkt_tokref ilock;
 
 	if (usermount == 0 && (error = suser(td)))
 		return (error);
@@ -159,23 +161,23 @@
 			vput(vp);
 			return (error);
 		}
-		if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
+		if (vfs_busy(mp, LK_NOWAIT, NULL, td)) {
 			vput(vp);
 			return (EBUSY);
 		}
-		lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(&vlock, vp->v_interlock);
 		if ((vp->v_flag & VMOUNT) != 0 ||
 		    vp->v_mountedhere != NULL) {
-			lwkt_reltoken(&vp->v_interlock);
+			lwkt_reltoken(&vlock);
 			vfs_unbusy(mp, td);
 			vput(vp);
 			return (EBUSY);
 		}
 		vp->v_flag |= VMOUNT;
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		mp->mnt_flag |=
 		    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		goto update;
 	}
 	/*
@@ -230,15 +232,15 @@
 			return (ENODEV);
 		}
 	}
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if ((vp->v_flag & VMOUNT) != 0 ||
 	    vp->v_mountedhere != NULL) {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		vput(vp);
 		return (EBUSY);
 	}
 	vp->v_flag |= VMOUNT;
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 
 	/*
 	 * Allocate and initialize the filesystem.
@@ -249,7 +251,7 @@
 	TAILQ_INIT(&mp->mnt_reservedvnlist);
 	mp->mnt_nvnodelistsize = 0;
 	lockinit(&mp->mnt_lock, 0, "vfslock", 0, LK_NOPAUSE);
-	(void)vfs_busy(mp, LK_NOWAIT, 0, td);
+	vfs_busy(mp, LK_NOWAIT, NULL, td);
 	mp->mnt_op = vfsp->vfc_vfsops;
 	mp->mnt_vfc = vfsp;
 	vfsp->vfc_refcount++;
@@ -259,7 +261,7 @@
 	mp->mnt_vnodecovered = vp;
 	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
 	mp->mnt_iosize_max = DFLTPHYS;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 update:
 	/*
 	 * Set the mount level flags.
@@ -300,36 +302,36 @@
 			mp->mnt_syncer = NULL;
 		}
 		vfs_unbusy(mp, td);
-		lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(&vlock, vp->v_interlock);
 		vp->v_flag &= ~VMOUNT;
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		vrele(vp);
 		return (error);
 	}
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	/*
 	 * Put the new filesystem on the mount list after root.
 	 */
 	cache_purge(vp);
 	if (!error) {
-		lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(&vlock, vp->v_interlock);
 		vp->v_flag &= ~VMOUNT;
 		vp->v_mountedhere = mp;
-		lwkt_reltoken(&vp->v_interlock);
-		lwkt_gettoken(&mountlist_token);
+		lwkt_reltoken(&vlock);
+		lwkt_gettoken(&ilock, &mountlist_token);
 		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
-		lwkt_reltoken(&mountlist_token);
+		lwkt_reltoken(&ilock);
 		checkdirs(vp);
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			error = vfs_allocate_syncvnode(mp);
 		vfs_unbusy(mp, td);
 		if ((error = VFS_START(mp, 0, td)) != 0)
 			vrele(vp);
 	} else {
-		lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(&vlock, vp->v_interlock);
 		vp->v_flag &= ~VMOUNT;
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		mp->mnt_vfc->vfc_refcount--;
 		vfs_unbusy(mp, td);
 		free((caddr_t)mp, M_MOUNT);
@@ -443,10 +445,11 @@
 	struct vnode *coveredvp;
 	int error;
 	int async_flag;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
-		lwkt_reltoken(&mountlist_token);
+		lwkt_reltoken(&ilock);
 		return (EBUSY);
 	}
 	mp->mnt_kern_flag |= MNTK_UNMOUNT;
@@ -454,7 +457,7 @@
 	if (flags & MNT_FORCE)
 		mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 	error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
-	    ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_token, td);
+	    ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &ilock, td);
 	if (error) {
 		mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 		if (mp->mnt_kern_flag & MNTK_MWAIT)
@@ -475,14 +478,14 @@
 	     (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) ||
 	    (flags & MNT_FORCE))
 		error = VFS_UNMOUNT(mp, flags, td);
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettokref(&ilock);
 	if (error) {
 		if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
 			(void) vfs_allocate_syncvnode(mp);
 		mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 		mp->mnt_flag |= async_flag;
 		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
-		    &mountlist_token, td);
+		    &ilock, td);
 		if (mp->mnt_kern_flag & MNTK_MWAIT)
 			wakeup((caddr_t)mp);
 		return (error);
@@ -495,7 +498,7 @@
 	mp->mnt_vfc->vfc_refcount--;
 	if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
 		panic("unmount: dangling vnode");
-	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_token, td);
+	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &ilock, td);
 	if (mp->mnt_kern_flag & MNTK_MWAIT)
 		wakeup((caddr_t)mp);
 	free((caddr_t)mp, M_MOUNT);
@@ -517,11 +520,12 @@
 {
 	struct thread *td = curthread;
 	struct mount *mp, *nmp;
+	lwkt_tokref ilock;
 	int asyncflag;
 
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
@@ -532,11 +536,11 @@
 			VFS_SYNC(mp, MNT_NOWAIT, td);
 			mp->mnt_flag |= asyncflag;
 		}
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettokref(&ilock);
 		nmp = TAILQ_NEXT(mp, mnt_list);
 		vfs_unbusy(mp, td);
 	}
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 #if 0
 /*
  * XXX don't call vfs_bufstats() yet because that routine
@@ -693,14 +697,15 @@
 	struct mount *mp, *nmp;
 	struct statfs *sp;
 	caddr_t sfsp;
+	lwkt_tokref ilock;
 	long count, maxcount, error;
 
 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
 	sfsp = (caddr_t)SCARG(uap, buf);
 	count = 0;
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
@@ -714,7 +719,7 @@
 			if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
 			    (SCARG(uap, flags) & MNT_WAIT)) &&
 			    (error = VFS_STATFS(mp, sp, td))) {
-				lwkt_gettoken(&mountlist_token);
+				lwkt_gettokref(&ilock);
 				nmp = TAILQ_NEXT(mp, mnt_list);
 				vfs_unbusy(mp, td);
 				continue;
@@ -728,11 +733,11 @@
 			sfsp += sizeof(*sp);
 		}
 		count++;
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettokref(&ilock);
 		nmp = TAILQ_NEXT(mp, mnt_list);
 		vfs_unbusy(mp, td);
 	}
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 	if (sfsp && count > maxcount)
 		uap->sysmsg_result = maxcount;
 	else
@@ -761,13 +766,13 @@
 		return (error);
 	vp = (struct vnode *)fp->f_data;
 	VREF(vp);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (vp->v_type != VDIR)
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
 	while (!error && (mp = vp->v_mountedhere) != NULL) {
-		if (vfs_busy(mp, 0, 0, td))
+		if (vfs_busy(mp, 0, NULL, td))
 			continue;
 		error = VFS_ROOT(mp, &tdp);
 		vfs_unbusy(mp, td);
@@ -780,7 +785,7 @@
 		vput(vp);
 		return (error);
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	vrele(fdp->fd_cdir);
 	fdp->fd_cdir = vp;
 	return (0);
@@ -919,7 +924,7 @@
 	if (error)
 		vput(vp);
 	else
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -997,7 +1002,7 @@
 	if (fp->f_count == 1) {
 		KASSERT(fdp->fd_ofiles[indx] != fp,
 		    ("Open file descriptor lost all refs"));
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		vn_close(vp, flags & FMASK, td);
 		fdrop(fp, td);
 		*res = indx;
@@ -1019,7 +1024,7 @@
 		type = F_FLOCK;
 		if ((flags & FNONBLOCK) == 0)
 			type |= F_WAIT;
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 			/*
 			 * lock request failed.  Normally close the descriptor
@@ -1034,13 +1039,13 @@
 			fdrop(fp, td);
 			return (error);
 		}
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		fp->f_flag |= FHASLOCK;
 	}
 	/* assert that vn_open created a backing object if one is needed */
 	KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
 		("open: vmio vnode has no backing object after vn_open"));
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 
 	/*
 	 * release our private reference, leaving the one associated with the
@@ -1407,7 +1412,7 @@
 		return (error);
 	vp = nd->ni_vp;
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	if (vp->v_type == VDIR)
 		error = EPERM;		/* POSIX */
@@ -1818,11 +1823,11 @@
 		return (error);
 
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	VATTR_NULL(&vattr);
 	vattr.va_flags = flags;
 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -1877,11 +1882,11 @@
 	struct vattr vattr;
 
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	VATTR_NULL(&vattr);
 	vattr.va_mode = mode & ALLPERMS;
 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return error;
 }
 
@@ -1969,12 +1974,12 @@
 	struct vattr vattr;
 
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	VATTR_NULL(&vattr);
 	vattr.va_uid = uid;
 	vattr.va_gid = gid;
 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return error;
 }
 
@@ -2075,14 +2080,14 @@
 	struct vattr vattr;
 
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	VATTR_NULL(&vattr);
 	vattr.va_atime = ts[0];
 	vattr.va_mtime = ts[1];
 	if (nullflag)
 		vattr.va_vaflags |= VA_UTIMES_NULL;
 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return error;
 }
 
@@ -2211,7 +2216,7 @@
 	vp = nd->ni_vp;
 	NDFREE(nd, NDF_ONLY_PNBUF);
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (vp->v_type == VDIR)
 		error = EISDIR;
 	else if ((error = vn_writechk(vp)) == 0 &&
@@ -2261,7 +2266,7 @@
 		return (EINVAL);
 	vp = (struct vnode *)fp->f_data;
 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (vp->v_type == VDIR)
 		error = EISDIR;
 	else if ((error = vn_writechk(vp)) == 0) {
@@ -2269,7 +2274,7 @@
 		vattr.va_size = length;
 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -2307,14 +2312,14 @@
 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 		return (error);
 	vp = (struct vnode *)fp->f_data;
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (VOP_GETVOBJECT(vp, &obj) == 0)
 		vm_object_page_clean(obj, 0, 0, 0);
 	if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) == 0 &&
 	    vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
 	    bioops.io_fsync)
 		error = (*bioops.io_fsync)(vp);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -2583,12 +2588,12 @@
 	auio.uio_segflg = UIO_USERSPACE;
 	auio.uio_td = td;
 	auio.uio_resid = count;
-	/* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	/* vn_lock(vp, NULL, LK_SHARED | LK_RETRY, td); */
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	loff = auio.uio_offset = fp->f_offset;
 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
 	fp->f_offset = auio.uio_offset;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (error)
 		return (error);
 	if (count == auio.uio_resid) {
@@ -2845,9 +2850,9 @@
 			goto bad;
 	}
 	if (fmode & O_TRUNC) {
-		VOP_UNLOCK(vp, 0, td);				/* XXX */
+		VOP_UNLOCK(vp, NULL, 0, td);			/* XXX */
 		VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
 		VATTR_NULL(vap);
 		vap->va_size = 0;
 		error = VOP_SETATTR(vp, vap, p->p_ucred, td);
@@ -2898,7 +2903,7 @@
 		type = F_FLOCK;
 		if ((fmode & FNONBLOCK) == 0)
 			type |= F_WAIT;
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 			/*
 			 * lock request failed.  Normally close the descriptor
@@ -2916,13 +2921,13 @@
 			fdrop(fp, td);
 			return (error);
 		}
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		fp->f_flag |= FHASLOCK;
 	}
 	if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
 		vfs_object_create(vp, td);
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	fdrop(fp, td);
 	uap->sysmsg_result = indx;
 	return (0);
Index: kern/vfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.15
diff -u -r1.15 vfs_vnops.c
--- kern/vfs_vnops.c	9 Oct 2003 22:27:19 -0000	1.15
+++ kern/vfs_vnops.c	22 Feb 2004 19:06:24 -0000
@@ -174,9 +174,9 @@
 		}
 	}
 	if (fmode & O_TRUNC) {
-		VOP_UNLOCK(vp, 0, td);				/* XXX */
+		VOP_UNLOCK(vp, NULL, 0, td);			/* XXX */
 		VOP_LEASE(vp, td, cred, LEASE_WRITE);
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
 		VATTR_NULL(vap);
 		vap->va_size = 0;
 		error = VOP_SETATTR(vp, vap, cred, td);
@@ -291,7 +291,7 @@
 	int error;
 
 	if ((ioflg & IO_NODELOCKED) == 0)
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	auio.uio_iov = &aiov;
 	auio.uio_iovcnt = 1;
 	aiov.iov_base = base;
@@ -312,7 +312,7 @@
 		if (auio.uio_resid && error == 0)
 			error = EIO;
 	if ((ioflg & IO_NODELOCKED) == 0)
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -380,7 +380,7 @@
 	if (fp->f_flag & O_DIRECT)
 		ioflag |= IO_DIRECT;
 	VOP_LEASE(vp, td, cred, LEASE_READ);
-	vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
 	if ((flags & FOF_OFFSET) == 0)
 		uio->uio_offset = fp->f_offset;
 
@@ -390,7 +390,7 @@
 	if ((flags & FOF_OFFSET) == 0)
 		fp->f_offset = uio->uio_offset;
 	fp->f_nextoff = uio->uio_offset;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -425,7 +425,7 @@
 	    (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
 		ioflag |= IO_SYNC;
 	VOP_LEASE(vp, td, cred, LEASE_WRITE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if ((flags & FOF_OFFSET) == 0)
 		uio->uio_offset = fp->f_offset;
 	ioflag |= sequential_heuristic(uio, fp);
@@ -433,7 +433,7 @@
 	if ((flags & FOF_OFFSET) == 0)
 		fp->f_offset = uio->uio_offset;
 	fp->f_nextoff = uio->uio_offset;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (error);
 }
 
@@ -626,20 +626,23 @@
  */
 int
 #ifndef	DEBUG_LOCKS
-vn_lock(struct vnode *vp, int flags, struct thread *td)
+vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td)
 #else
-debug_vn_lock(struct vnode *vp, int flags, struct thread *td,
-		const char *filename, int line)
+debug_vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, 
+		struct thread *td, const char *filename, int line)
 #endif
 {
 	int error;
+	lwkt_tokref vvlock;
 	
 	do {
-		if ((flags & LK_INTERLOCK) == 0)
-			lwkt_gettoken(&vp->v_interlock);
+		if ((flags & LK_INTERLOCK) == 0) {
+			lwkt_gettoken(&vvlock, vp->v_interlock);
+			vlock = &vvlock;
+		}
 		if ((vp->v_flag & VXLOCK) && vp->v_vxproc != curproc) {
 			vp->v_flag |= VXWANT;
-			lwkt_reltoken(&vp->v_interlock);
+			lwkt_reltoken(vlock);
 			tsleep((caddr_t)vp, 0, "vn_lock", 0);
 			error = ENOENT;
 		} else {
@@ -652,7 +655,7 @@
 			vp->filename = filename;
 			vp->line = line;
 #endif
-			error = VOP_LOCK(vp,
+			error = VOP_LOCK(vp, vlock,
 				    flags | LK_NOPAUSE | LK_INTERLOCK, td);
 			if (error == 0)
 				return (error);
Index: kern/vnode_if.src
===================================================================
RCS file: /cvs/src/sys/kern/vnode_if.src,v
retrieving revision 1.5
diff -u -r1.5 vnode_if.src
--- kern/vnode_if.src	9 Oct 2003 22:27:19 -0000	1.5
+++ kern/vnode_if.src	22 Feb 2004 07:09:12 -0000
@@ -379,6 +379,7 @@
 #
 vop_lock {
 	IN struct vnode *vp;
+	IN struct lwkt_tokref *vlock;
 	IN int flags;
 	IN struct thread *td;
 };
@@ -388,6 +389,7 @@
 #
 vop_unlock {
 	IN struct vnode *vp;
+	IN struct lwkt_tokref *vlock;
 	IN int flags;
 	IN struct thread *td;
 };
Index: netproto/ncp/ncp_conn.c
===================================================================
RCS file: /cvs/src/sys/netproto/ncp/ncp_conn.c,v
retrieving revision 1.6
diff -u -r1.6 ncp_conn.c
--- netproto/ncp/ncp_conn.c	10 Nov 2003 06:12:14 -0000	1.6
+++ netproto/ncp/ncp_conn.c	22 Feb 2004 04:58:39 -0000
@@ -80,13 +80,13 @@
 int
 ncp_conn_locklist(int flags, struct thread *td)
 {
-	return lockmgr(&listlock, flags | LK_CANRECURSE, 0, td);
+	return lockmgr(&listlock, flags | LK_CANRECURSE, NULL, td);
 }
 
 void
 ncp_conn_unlocklist(struct thread *td)
 {
-	lockmgr(&listlock, LK_RELEASE, 0, td);
+	lockmgr(&listlock, LK_RELEASE, NULL, td);
 }
 
 int
@@ -110,17 +110,17 @@
 	int error;
 
 	if (conn->nc_id == 0) return EACCES;
-	error = lockmgr(&conn->nc_lock, LK_EXCLUSIVE | LK_CANRECURSE, 0, td);
+	error = lockmgr(&conn->nc_lock, LK_EXCLUSIVE | LK_CANRECURSE, NULL, td);
 	if (error == ERESTART)
 		return EINTR;
 	error = ncp_chkintr(conn, td);
 	if (error) {
-		lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
+		lockmgr(&conn->nc_lock, LK_RELEASE, NULL, td);
 		return error;
 	}
 
 	if (conn->nc_id == 0) {
-		lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
+		lockmgr(&conn->nc_lock, LK_RELEASE, NULL, td);
 		return EACCES;
 	}
 	conn->td = td;	/* who currently operates */
@@ -170,7 +170,7 @@
 	 * note, that LK_RELASE will do wakeup() instead of wakeup_one().
 	 * this will do a little overhead
 	 */
-	lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
+	lockmgr(&conn->nc_lock, LK_RELEASE, NULL, td);
 }
 
 int 
@@ -239,7 +239,7 @@
 	/*
 	 * if signal is raised - how I do react ?
 	 */
-	lockmgr(&ncp->nc_lock, LK_DRAIN, 0, ncp->td);
+	lockmgr(&ncp->nc_lock, LK_DRAIN, NULL, ncp->td);
 	while (ncp->nc_lwant) {
 		printf("lwant = %d\n", ncp->nc_lwant);
 		tsleep(&ncp->nc_lwant, 0, "ncpdr", 2*hz);
@@ -406,14 +406,14 @@
 ncp_conn_gethandle(struct ncp_conn *conn, struct thread *td, struct ncp_handle **handle){
 	struct ncp_handle *refp;
 
-	lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
+	lockmgr(&lhlock, LK_EXCLUSIVE, NULL, td);
 	SLIST_FOREACH(refp, &lhlist, nh_next)
 		if (refp->nh_conn == conn && td == refp->nh_td) break;
 	if (refp) {
 		conn->ref_cnt++;
 		refp->nh_ref++;
 		*handle = refp;
-		lockmgr(&lhlock, LK_RELEASE, 0, td);
+		lockmgr(&lhlock, LK_RELEASE, NULL, td);
 		return 0;
 	}
 	MALLOC(refp,struct ncp_handle *,sizeof(struct ncp_handle),M_NCPDATA,
@@ -425,7 +425,7 @@
 	refp->nh_id = ncp_next_handle++;
 	*handle = refp;
 	conn->ref_cnt++;
-	lockmgr(&lhlock, LK_RELEASE, 0, td);
+	lockmgr(&lhlock, LK_RELEASE, NULL, td);
 	return 0;
 }
 /*
@@ -435,7 +435,7 @@
 ncp_conn_puthandle(struct ncp_handle *handle, struct thread *td, int force) {
 	struct ncp_handle *refp = handle;
 
-	lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
+	lockmgr(&lhlock, LK_EXCLUSIVE, NULL, td);
 	refp->nh_ref--;
 	refp->nh_conn->ref_cnt--;
 	if (force) {
@@ -446,7 +446,7 @@
 		SLIST_REMOVE(&lhlist, refp, ncp_handle, nh_next);
 		FREE(refp, M_NCPDATA);
 	}
-	lockmgr(&lhlock, LK_RELEASE, 0, td);
+	lockmgr(&lhlock, LK_RELEASE, NULL, td);
 	return 0;
 }
 /*
@@ -456,10 +456,10 @@
 ncp_conn_findhandle(int connHandle, struct thread *td, struct ncp_handle **handle) {
 	struct ncp_handle *refp;
 
-	lockmgr(&lhlock, LK_SHARED, 0, td);
+	lockmgr(&lhlock, LK_SHARED, NULL, td);
 	SLIST_FOREACH(refp, &lhlist, nh_next)
 		if (refp->nh_td == td && refp->nh_id == connHandle) break;
-	lockmgr(&lhlock, LK_RELEASE, 0, td);
+	lockmgr(&lhlock, LK_RELEASE, NULL, td);
 	if (refp == NULL) {
 		return EBADF;
 	}
@@ -474,7 +474,7 @@
 	struct ncp_handle *hp, *nhp;
 	int haveone = 0;
 
-	lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
+	lockmgr(&lhlock, LK_EXCLUSIVE, NULL, td);
 	for (hp = SLIST_FIRST(&lhlist); hp; hp = nhp) {
 		nhp = SLIST_NEXT(hp, nh_next);
 		if (hp->nh_td != td) continue;
@@ -483,7 +483,7 @@
 		SLIST_REMOVE(&lhlist, hp, ncp_handle, nh_next);
 		FREE(hp, M_NCPDATA);
 	}
-	lockmgr(&lhlock, LK_RELEASE, 0, td);
+	lockmgr(&lhlock, LK_RELEASE, NULL, td);
 	return haveone;
 }
 /*
Index: netproto/smb/smb_conn.c
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_conn.c,v
retrieving revision 1.6
diff -u -r1.6 smb_conn.c
--- netproto/smb/smb_conn.c	10 Nov 2003 06:12:16 -0000	1.6
+++ netproto/smb/smb_conn.c	22 Feb 2004 07:36:13 -0000
@@ -82,7 +82,7 @@
 {
 
 	smb_co_init(&smb_vclist, SMBL_SM, "smbsm", curthread);
-	smb_co_unlock(&smb_vclist, 0, curthread);
+	smb_co_unlock(&smb_vclist, NULL, 0, curthread);
 	return 0;
 }
 
@@ -102,13 +102,13 @@
 static int
 smb_sm_lockvclist(int flags, struct thread *td)
 {
-	return smb_co_lock(&smb_vclist, flags | LK_CANRECURSE, td);
+	return smb_co_lock(&smb_vclist, NULL, flags | LK_CANRECURSE, td);
 }
 
 static void
 smb_sm_unlockvclist(struct thread *td)
 {
-	smb_co_unlock(&smb_vclist, LK_RELEASE, td);
+	smb_co_unlock(&smb_vclist, NULL, LK_RELEASE, td);
 }
 
 static int
@@ -226,7 +226,7 @@
 	lockinit(&cp->co_lock, 0, objname, 0, 0);
 	cp->co_level = level;
 	cp->co_usecount = 1;
-	KASSERT(smb_co_lock(cp, LK_EXCLUSIVE, td) == 0,
+	KASSERT(smb_co_lock(cp, NULL, LK_EXCLUSIVE, td) == 0,
 	    ("smb_co_init: lock failed"));
 }
 
@@ -246,7 +246,7 @@
 		cp->co_gone(cp, scred);
 	parent = cp->co_parent;
 	if (parent) {
-		smb_co_lock(parent, LK_EXCLUSIVE, scred->scr_td);
+		smb_co_lock(parent, NULL, LK_EXCLUSIVE, scred->scr_td);
 		SLIST_REMOVE(&parent->co_children, cp, smb_connobj, co_next);
 		smb_co_put(parent, scred);
 	}
@@ -257,48 +257,53 @@
 void
 smb_co_ref(struct smb_connobj *cp, struct thread *td)
 {
+	smb_ilock ilock;
 
-	SMB_CO_LOCK(cp);
+	SMB_CO_LOCK(&ilock, cp);
 	cp->co_usecount++;
-	SMB_CO_UNLOCK(cp);
+	SMB_CO_UNLOCK(&ilock);
 }
 
 void
 smb_co_rele(struct smb_connobj *cp, struct smb_cred *scred)
 {
 	struct thread *td = scred->scr_td;
+	smb_ilock ilock;
 
-	SMB_CO_LOCK(cp);
+	SMB_CO_LOCK(&ilock, cp);
 	if (cp->co_usecount > 1) {
 		cp->co_usecount--;
-		SMB_CO_UNLOCK(cp);
+		SMB_CO_UNLOCK(&ilock);
 		return;
 	}
 	if (cp->co_usecount == 0) {
 		SMBERROR("negative use_count for object %d", cp->co_level);
-		SMB_CO_UNLOCK(cp);
+		SMB_CO_UNLOCK(&ilock);
 		return;
 	}
 	cp->co_usecount--;
 	cp->co_flags |= SMBO_GONE;
 
-	lockmgr(&cp->co_lock, LK_DRAIN | LK_INTERLOCK, &cp->co_interlock, td);
+	lockmgr(&cp->co_lock, LK_DRAIN | LK_INTERLOCK, &ilock, td);
 	smb_co_gone(cp, scred);
 }
 
 int
-smb_co_get(struct smb_connobj *cp, int flags, struct smb_cred *scred)
+smb_co_get(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct smb_cred *scred)
 {
 	int error;
+	smb_ilock iilock;
 
-	if ((flags & LK_INTERLOCK) == 0)
-		SMB_CO_LOCK(cp);
+	if ((flags & LK_INTERLOCK) == 0) {
+		SMB_CO_LOCK(&iilock, cp);
+		ilock = &iilock;
+	}
 	cp->co_usecount++;
-	error = smb_co_lock(cp, flags | LK_INTERLOCK, scred->scr_td);
+	error = smb_co_lock(cp, ilock, flags | LK_INTERLOCK, scred->scr_td);
 	if (error) {
-		SMB_CO_LOCK(cp);
+		SMB_CO_LOCK(ilock, cp);
 		cp->co_usecount--;
-		SMB_CO_UNLOCK(cp);
+		SMB_CO_UNLOCK(ilock);
 		return error;
 	}
 	return 0;
@@ -309,9 +314,10 @@
 {
 	struct thread *td = scred->scr_td;
 	int flags;
+	smb_ilock ilock;
 
 	flags = LK_RELEASE;
-	SMB_CO_LOCK(cp);
+	SMB_CO_LOCK(&ilock, cp);
 	if (cp->co_usecount > 1) {
 		cp->co_usecount--;
 	} else if (cp->co_usecount == 1) {
@@ -321,7 +327,7 @@
 	} else {
 		SMBERROR("negative usecount");
 	}
-	lockmgr(&cp->co_lock, LK_RELEASE | LK_INTERLOCK, &cp->co_interlock, td);
+	lockmgr(&cp->co_lock, LK_RELEASE | LK_INTERLOCK, &ilock, td);
 	if ((cp->co_flags & SMBO_GONE) == 0)
 		return;
 	lockmgr(&cp->co_lock, LK_DRAIN, NULL, td);
@@ -335,9 +341,8 @@
 }
 
 int
-smb_co_lock(struct smb_connobj *cp, int flags, struct thread *td)
+smb_co_lock(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct thread *td)
 {
-
 	if (cp->co_flags & SMBO_GONE)
 		return EINVAL;
 	if ((flags & LK_TYPE_MASK) == 0)
@@ -347,13 +352,13 @@
 		SMBERROR("recursive lock for object %d\n", cp->co_level);
 		return 0;
 	}
-	return lockmgr(&cp->co_lock, flags, &cp->co_interlock, td);
+	return lockmgr(&cp->co_lock, flags, ilock, td);
 }
 
 void
-smb_co_unlock(struct smb_connobj *cp, int flags, struct thread *td)
+smb_co_unlock(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct thread *td)
 {
-	(void)lockmgr(&cp->co_lock, flags | LK_RELEASE, &cp->co_interlock, td);
+	lockmgr(&cp->co_lock, flags | LK_RELEASE, ilock, td);
 }
 
 static void
@@ -502,7 +507,7 @@
 int
 smb_vc_get(struct smb_vc *vcp, int flags, struct smb_cred *scred)
 {
-	return smb_co_get(VCTOCP(vcp), flags, scred);
+	return smb_co_get(VCTOCP(vcp), NULL, flags, scred);
 }
 
 void
@@ -514,13 +519,13 @@
 int
 smb_vc_lock(struct smb_vc *vcp, int flags, struct thread *td)
 {
-	return smb_co_lock(VCTOCP(vcp), flags, td);
+	return smb_co_lock(VCTOCP(vcp), NULL, flags, td);
 }
 
 void
 smb_vc_unlock(struct smb_vc *vcp, int flags, struct thread *td)
 {
-	smb_co_unlock(VCTOCP(vcp), flags, td);
+	smb_co_unlock(VCTOCP(vcp), NULL, flags, td);
 }
 
 int
@@ -646,10 +651,11 @@
 smb_vc_nextmid(struct smb_vc *vcp)
 {
 	u_short r;
+	smb_ilock ilock;
 
-	SMB_CO_LOCK(&vcp->obj);
+	SMB_CO_LOCK(&ilock, &vcp->obj);
 	r = vcp->vc_mid++;
-	SMB_CO_UNLOCK(&vcp->obj);
+	SMB_CO_UNLOCK(&ilock);
 	return r;
 }
 
@@ -743,7 +749,7 @@
 int
 smb_share_get(struct smb_share *ssp, int flags, struct smb_cred *scred)
 {
-	return smb_co_get(SSTOCP(ssp), flags, scred);
+	return smb_co_get(SSTOCP(ssp), NULL, flags, scred);
 }
 
 void
@@ -755,13 +761,13 @@
 int
 smb_share_lock(struct smb_share *ssp, int flags, struct thread *td)
 {
-	return smb_co_lock(SSTOCP(ssp), flags, td);
+	return smb_co_lock(SSTOCP(ssp), NULL, flags, td);
 }
 
 void
 smb_share_unlock(struct smb_share *ssp, int flags, struct thread *td)
 {
-	smb_co_unlock(SSTOCP(ssp), flags, td);
+	smb_co_unlock(SSTOCP(ssp), NULL, flags, td);
 }
 
 int
Index: netproto/smb/smb_conn.h
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_conn.h,v
retrieving revision 1.4
diff -u -r1.4 smb_conn.h
--- netproto/smb/smb_conn.h	7 Aug 2003 21:17:38 -0000	1.4
+++ netproto/smb/smb_conn.h	22 Feb 2004 07:35:29 -0000
@@ -199,8 +199,8 @@
 typedef void smb_co_gone_t (struct smb_connobj *cp, struct smb_cred *scred);
 typedef void smb_co_free_t (struct smb_connobj *cp);
 
-#define	SMB_CO_LOCK(cp)		smb_sl_lock(&(cp)->co_interlock)
-#define	SMB_CO_UNLOCK(cp)	smb_sl_unlock(&(cp)->co_interlock)
+#define	SMB_CO_LOCK(ilock, cp)	smb_sl_lock(ilock, &(cp)->co_interlock)
+#define	SMB_CO_UNLOCK(ilock)	smb_sl_unlock(ilock)
 
 struct smb_connobj {
 	int			co_level;	/* SMBL_ */
@@ -231,8 +231,8 @@
 /*
  * This lock protects vc_flags
  */
-#define	SMBC_ST_LOCK(vcp)	smb_sl_lock(&(vcp)->vc_stlock)
-#define	SMBC_ST_UNLOCK(vcp)	smb_sl_unlock(&(vcp)->vc_stlock)
+#define	SMBC_ST_LOCK(ilock, vcp)	smb_sl_lock(ilock, &(vcp)->vc_stlock)
+#define	SMBC_ST_UNLOCK(ilock)		smb_sl_unlock(ilock)
 
 
 struct smb_vc {
@@ -284,9 +284,9 @@
 /*
  * This lock protects ss_flags
  */
-#define	SMBS_ST_LOCK(ssp)	smb_sl_lock(&(ssp)->ss_stlock)
-#define	SMBS_ST_LOCKPTR(ssp)	(&(ssp)->ss_stlock)
-#define	SMBS_ST_UNLOCK(ssp)	smb_sl_unlock(&(ssp)->ss_stlock)
+#define	SMBS_ST_LOCK(ilock, ssp)	smb_sl_lock(ilock, &(ssp)->ss_stlock)
+#define	SMBS_ST_LOCKPTR(ssp)		(&(ssp)->ss_stlock)
+#define	SMBS_ST_UNLOCK(ilock)		smb_sl_unlock(ilock)
 
 struct smb_share {
 	struct smb_connobj obj;
@@ -359,10 +359,10 @@
  */
 void smb_co_ref(struct smb_connobj *cp, struct thread *td);
 void smb_co_rele(struct smb_connobj *cp, struct smb_cred *scred);
-int  smb_co_get(struct smb_connobj *cp, int flags, struct smb_cred *scred);
+int  smb_co_get(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct smb_cred *scred);
 void smb_co_put(struct smb_connobj *cp, struct smb_cred *scred);
-int  smb_co_lock(struct smb_connobj *cp, int flags, struct thread *td);
-void smb_co_unlock(struct smb_connobj *cp, int flags, struct thread *td);
+int  smb_co_lock(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct thread *td);
+void smb_co_unlock(struct smb_connobj *cp, smb_ilock *ilock, int flags, struct thread *td);
 
 /*
  * session level functions
Index: netproto/smb/smb_iod.c
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_iod.c,v
retrieving revision 1.7
diff -u -r1.7 smb_iod.c
--- netproto/smb/smb_iod.c	7 Aug 2003 21:17:39 -0000	1.7
+++ netproto/smb/smb_iod.c	22 Feb 2004 07:07:31 -0000
@@ -53,12 +53,12 @@
 #define	SMBIOD_PING_TIMO	60	/* seconds */
 
 #define	SMB_IOD_EVLOCKPTR(iod)	(&((iod)->iod_evlock))
-#define	SMB_IOD_EVLOCK(iod)	smb_sl_lock(&((iod)->iod_evlock))
-#define	SMB_IOD_EVUNLOCK(iod)	smb_sl_unlock(&((iod)->iod_evlock))
+#define	SMB_IOD_EVLOCK(ilock, iod)	smb_sl_lock(ilock, &((iod)->iod_evlock))
+#define	SMB_IOD_EVUNLOCK(ilock)	smb_sl_unlock(ilock)
 
 #define	SMB_IOD_RQLOCKPTR(iod)	(&((iod)->iod_rqlock))
-#define	SMB_IOD_RQLOCK(iod)	smb_sl_lock(&((iod)->iod_rqlock))
-#define	SMB_IOD_RQUNLOCK(iod)	smb_sl_unlock(&((iod)->iod_rqlock))
+#define	SMB_IOD_RQLOCK(ilock, iod)	smb_sl_lock(ilock, &((iod)->iod_rqlock))
+#define	SMB_IOD_RQUNLOCK(ilock)	smb_sl_unlock(ilock)
 
 #define	smb_iod_wakeup(iod)	wakeup(&(iod)->iod_flags)
 
@@ -74,30 +74,36 @@
 static __inline void
 smb_iod_rqprocessed(struct smb_rq *rqp, int error)
 {
-	SMBRQ_SLOCK(rqp);
+	smb_ilock ilock;
+
+	SMBRQ_SLOCK(&ilock, rqp);
 	rqp->sr_lerror = error;
 	rqp->sr_rpgen++;
 	rqp->sr_state = SMBRQ_NOTIFIED;
 	wakeup(&rqp->sr_state);
-	SMBRQ_SUNLOCK(rqp);
+	SMBRQ_SUNLOCK(&ilock);
 }
 
 static void
 smb_iod_invrq(struct smbiod *iod)
 {
 	struct smb_rq *rqp;
+	smb_ilock ilock;
 
 	/*
 	 * Invalidate all outstanding requests for this connection
 	 */
-	SMB_IOD_RQLOCK(iod);
+	SMB_IOD_RQLOCK(&ilock, iod);
 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
+#if 0
+		/* this makes no sense whatsoever XXX */
 		if (rqp->sr_flags & SMBR_INTERNAL)
 			SMBRQ_SUNLOCK(rqp);
+#endif
 		rqp->sr_flags |= SMBR_RESTART;
 		smb_iod_rqprocessed(rqp, ENOTCONN);
 	}
-	SMB_IOD_RQUNLOCK(iod);
+	SMB_IOD_RQUNLOCK(&ilock);
 }
 
 static void
@@ -185,6 +191,7 @@
 smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
 {
 	int error;
+	smb_ilock ilock;
 
 	if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
 		if (iod->iod_state != SMBIOD_ST_DEAD)
@@ -195,13 +202,13 @@
 			return error;
 	}
 	SMBIODEBUG("tree reconnect\n");
-	SMBS_ST_LOCK(ssp);
+	SMBS_ST_LOCK(&ilock, ssp);
 	ssp->ss_flags |= SMBS_RECONNECTING;
-	SMBS_ST_UNLOCK(ssp);
+	SMBS_ST_UNLOCK(&ilock);
 	error = smb_smb_treeconnect(ssp, &iod->iod_scred);
-	SMBS_ST_LOCK(ssp);
+	SMBS_ST_LOCK(&ilock, ssp);
 	ssp->ss_flags &= ~SMBS_RECONNECTING;
-	SMBS_ST_UNLOCK(ssp);
+	SMBS_ST_UNLOCK(&ilock);
 	wakeup(&ssp->ss_vcgenid);
 	return error;
 }
@@ -284,6 +291,8 @@
 	u_char *hp;
 	u_short mid;
 	int error;
+	smb_ilock ilock;
+	smb_ilock jlock;
 
 	switch (iod->iod_state) {
 	    case SMBIOD_ST_NOTCONN:
@@ -324,27 +333,27 @@
 		}
 		mid = SMB_HDRMID(hp);
 		SMBSDEBUG("mid %04x\n", (u_int)mid);
-		SMB_IOD_RQLOCK(iod);
+		SMB_IOD_RQLOCK(&ilock, iod);
 		TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
 			if (rqp->sr_mid != mid)
 				continue;
-			SMBRQ_SLOCK(rqp);
+			SMBRQ_SLOCK(&jlock, rqp);
 			if (rqp->sr_rp.md_top == NULL) {
 				md_initm(&rqp->sr_rp, m);
 			} else {
 				if (rqp->sr_flags & SMBR_MULTIPACKET) {
 					md_append_record(&rqp->sr_rp, m);
 				} else {
-					SMBRQ_SUNLOCK(rqp);
+					SMBRQ_SUNLOCK(&jlock);
 					SMBERROR("duplicate response %d (ignored)\n", mid);
 					break;
 				}
 			}
-			SMBRQ_SUNLOCK(rqp);
+			SMBRQ_SUNLOCK(&jlock);
 			smb_iod_rqprocessed(rqp, 0);
 			break;
 		}
-		SMB_IOD_RQUNLOCK(iod);
+		SMB_IOD_RQUNLOCK(&ilock);
 		if (rqp == NULL) {
 			SMBERROR("drop resp with mid %d\n", (u_int)mid);
 /*			smb_printrqlist(vcp);*/
@@ -354,13 +363,13 @@
 	/*
 	 * check for interrupts
 	 */
-	SMB_IOD_RQLOCK(iod);
+	SMB_IOD_RQLOCK(&ilock, iod);
 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
 		if (smb_proc_intr(rqp->sr_cred->scr_td)) {
 			smb_iod_rqprocessed(rqp, EINTR);
 		}
 	}
-	SMB_IOD_RQUNLOCK(iod);
+	SMB_IOD_RQUNLOCK(&ilock);
 	return 0;
 }
 
@@ -369,20 +378,21 @@
 {
 	struct smbiod_event *evp;
 	int error;
+	smb_ilock ilock;
 
 	SMBIODEBUG("\n");
 	evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
 	evp->ev_type = event;
 	evp->ev_ident = ident;
-	SMB_IOD_EVLOCK(iod);
+	SMB_IOD_EVLOCK(&ilock, iod);
 	STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
 	if ((event & SMBIOD_EV_SYNC) == 0) {
-		SMB_IOD_EVUNLOCK(iod);
+		SMB_IOD_EVUNLOCK(&ilock);
 		smb_iod_wakeup(iod);
 		return 0;
 	}
 	smb_iod_wakeup(iod);
-	smb_sleep(evp, SMB_IOD_EVLOCKPTR(iod), PDROP, "90evw", 0);
+	smb_sleep(evp, &ilock, PDROP, "90evw", 0);
 	error = evp->ev_error;
 	free(evp, M_SMBIOD);
 	return error;
@@ -397,14 +407,15 @@
 {
 	struct smb_vc *vcp = rqp->sr_vc;
 	struct smbiod *iod = vcp->vc_iod;
+	smb_ilock ilock;
 	int error;
 
 	SMBIODEBUG("\n");
 	if (rqp->sr_cred->scr_td == iod->iod_td) {
 		rqp->sr_flags |= SMBR_INTERNAL;
-		SMB_IOD_RQLOCK(iod);
+		SMB_IOD_RQLOCK(&ilock, iod);
 		TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
-		SMB_IOD_RQUNLOCK(iod);
+		SMB_IOD_RQUNLOCK(&ilock);
 		for (;;) {
 			if (smb_iod_sendrq(iod, rqp) != 0) {
 				smb_iod_dead(iod);
@@ -434,7 +445,7 @@
 		break;
 	}
 
-	SMB_IOD_RQLOCK(iod);
+	SMB_IOD_RQLOCK(&ilock, iod);
 	for (;;) {
 		if (vcp->vc_maxmux == 0) {
 			SMBERROR("maxmux == 0\n");
@@ -443,12 +454,11 @@
 		if (iod->iod_muxcnt < vcp->vc_maxmux)
 			break;
 		iod->iod_muxwant++;
-		smb_sleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
-		    0, "90mux", 0);
+		smb_sleep(&iod->iod_muxwant, &ilock, 0, "90mux", 0);
 	}
 	iod->iod_muxcnt++;
 	TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
-	SMB_IOD_RQUNLOCK(iod);
+	SMB_IOD_RQUNLOCK(&ilock);
 	smb_iod_wakeup(iod);
 	return 0;
 }
@@ -458,18 +468,19 @@
 {
 	struct smb_vc *vcp = rqp->sr_vc;
 	struct smbiod *iod = vcp->vc_iod;
+	smb_ilock ilock;
 
 	SMBIODEBUG("\n");
 	if (rqp->sr_flags & SMBR_INTERNAL) {
-		SMB_IOD_RQLOCK(iod);
+		SMB_IOD_RQLOCK(&ilock, iod);
 		TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
-		SMB_IOD_RQUNLOCK(iod);
+		SMB_IOD_RQUNLOCK(&ilock);
 		return 0;
 	}
-	SMB_IOD_RQLOCK(iod);
+	SMB_IOD_RQLOCK(&ilock, iod);
 	while (rqp->sr_flags & SMBR_XLOCK) {
 		rqp->sr_flags |= SMBR_XLOCKWANT;
-		smb_sleep(rqp, SMB_IOD_RQLOCKPTR(iod), 0, "90xrm", 0);
+		smb_sleep(rqp, &ilock, 0, "90xrm", 0);
 	}
 	TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
 	iod->iod_muxcnt--;
@@ -477,7 +488,7 @@
 		iod->iod_muxwant--;
 		wakeup(&iod->iod_muxwant);
 	}
-	SMB_IOD_RQUNLOCK(iod);
+	SMB_IOD_RQUNLOCK(&ilock);
 	return 0;
 }
 
@@ -485,6 +496,7 @@
 smb_iod_waitrq(struct smb_rq *rqp)
 {
 	struct smbiod *iod = rqp->sr_vc->vc_iod;
+	smb_ilock ilock;
 	int error;
 
 	SMBIODEBUG("\n");
@@ -500,21 +512,21 @@
 		return rqp->sr_lerror;
 
 	}
-	SMBRQ_SLOCK(rqp);
+	SMBRQ_SLOCK(&ilock, rqp);
 	if (rqp->sr_rpgen == rqp->sr_rplast)
-		smb_sleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), 0, "90wrq", 0);
+		smb_sleep(&rqp->sr_state, &ilock, 0, "90wrq", 0);
 	rqp->sr_rplast++;
-	SMBRQ_SUNLOCK(rqp);
+	SMBRQ_SUNLOCK(&ilock);
 	error = rqp->sr_lerror;
 	if (rqp->sr_flags & SMBR_MULTIPACKET) {
 		/*
 		 * If request should stay in the list, then reinsert it
 		 * at the end of queue so other waiters have chance to concur
 		 */
-		SMB_IOD_RQLOCK(iod);
+		SMB_IOD_RQLOCK(&ilock, iod);
 		TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
 		TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
-		SMB_IOD_RQUNLOCK(iod);
+		SMB_IOD_RQUNLOCK(&ilock);
 	} else
 		smb_iod_removerq(rqp);
 	return error;
@@ -527,20 +539,21 @@
 	struct smb_vc *vcp = iod->iod_vc;
 	struct smb_rq *rqp;
 	struct timespec ts, tstimeout;
+	smb_ilock ilock;
 	int herror;
 
 	herror = 0;
 	/*
 	 * Loop through the list of requests and send them if possible
 	 */
-	SMB_IOD_RQLOCK(iod);
+	SMB_IOD_RQLOCK(&ilock, iod);
 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
 		switch (rqp->sr_state) {
 		    case SMBRQ_NOTSENT:
 			rqp->sr_flags |= SMBR_XLOCK;
-			SMB_IOD_RQUNLOCK(iod);
+			SMB_IOD_RQUNLOCK(&ilock);
 			herror = smb_iod_sendrq(iod, rqp);
-			SMB_IOD_RQLOCK(iod);
+			SMB_IOD_RQLOCK(&ilock, iod);
 			rqp->sr_flags &= ~SMBR_XLOCK;
 			if (rqp->sr_flags & SMBR_XLOCKWANT) {
 				rqp->sr_flags &= ~SMBR_XLOCKWANT;
@@ -561,7 +574,7 @@
 		if (herror)
 			break;
 	}
-	SMB_IOD_RQUNLOCK(iod);
+	SMB_IOD_RQUNLOCK(&ilock);
 	if (herror == ENOTCONN)
 		smb_iod_dead(iod);
 	return 0;
@@ -577,6 +590,7 @@
 	struct smbiod_event *evp;
 /*	struct timespec tsnow;*/
 	int error;
+	smb_ilock ilock;
 
 	SMBIODEBUG("\n");
 	error = 0;
@@ -585,15 +599,15 @@
 	 * Check all interesting events
 	 */
 	for (;;) {
-		SMB_IOD_EVLOCK(iod);
+		SMB_IOD_EVLOCK(&ilock, iod);
 		evp = STAILQ_FIRST(&iod->iod_evlist);
 		if (evp == NULL) {
-			SMB_IOD_EVUNLOCK(iod);
+			SMB_IOD_EVUNLOCK(&ilock);
 			break;
 		}
 		STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
 		evp->ev_type |= SMBIOD_EV_PROCESSING;
-		SMB_IOD_EVUNLOCK(iod);
+		SMB_IOD_EVUNLOCK(&ilock);
 		switch (evp->ev_type & SMBIOD_EV_MASK) {
 		    case SMBIOD_EV_CONNECT:
 			iod->iod_state = SMBIOD_ST_RECONNECT;
@@ -612,9 +626,9 @@
 			break;
 		}
 		if (evp->ev_type & SMBIOD_EV_SYNC) {
-			SMB_IOD_EVLOCK(iod);
+			SMB_IOD_EVLOCK(&ilock, iod);
 			wakeup(evp);
-			SMB_IOD_EVUNLOCK(iod);
+			SMB_IOD_EVUNLOCK(&ilock);
 		} else
 			free(evp, M_SMBIOD);
 	}
Index: netproto/smb/smb_rq.c
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_rq.c,v
retrieving revision 1.6
diff -u -r1.6 smb_rq.c
--- netproto/smb/smb_rq.c	7 Aug 2003 21:17:39 -0000	1.6
+++ netproto/smb/smb_rq.c	22 Feb 2004 07:05:08 -0000
@@ -172,23 +172,24 @@
 {
 	struct smb_share *ssp = rqp->sr_share;
 	int error;
+	smb_ilock ilock;
 
 	if (ssp == NULL || rqp->sr_cred == &rqp->sr_vc->vc_iod->iod_scred) {
 		return smb_iod_addrq(rqp);
 	}
 	for (;;) {
-		SMBS_ST_LOCK(ssp);
+		SMBS_ST_LOCK(&ilock, ssp);
 		if (ssp->ss_flags & SMBS_RECONNECTING) {
-			smb_sleep(&ssp->ss_vcgenid, SMBS_ST_LOCKPTR(ssp),
-			    PDROP, "90trcn", hz);
+			smb_sleep(&ssp->ss_vcgenid, &ilock, 
+				PDROP, "90trcn", hz);
 			if (smb_proc_intr(rqp->sr_cred->scr_td))
 				return EINTR;
 			continue;
 		}
 		if (smb_share_valid(ssp) || (ssp->ss_flags & SMBS_CONNECTED) == 0) {
-			SMBS_ST_UNLOCK(ssp);
+			SMBS_ST_UNLOCK(&ilock);
 		} else {
-			SMBS_ST_UNLOCK(ssp);
+			SMBS_ST_UNLOCK(&ilock);
 			error = smb_iod_request(rqp->sr_vc->vc_iod,
 			    SMBIOD_EV_TREECONNECT | SMBIOD_EV_SYNC, ssp);
 			if (error)
@@ -438,6 +439,7 @@
 	u_int16_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp;
 	u_int16_t tmp, bc, dcount;
 	u_int8_t wc;
+	smb_ilock ilock;
 
 	error = smb_rq_reply(rqp);
 	if (error)
@@ -446,9 +448,9 @@
 		/* 
 		 * this is an interim response, ignore it.
 		 */
-		SMBRQ_SLOCK(rqp);
+		SMBRQ_SLOCK(&ilock, rqp);
 		md_next_record(&rqp->sr_rp);
-		SMBRQ_SUNLOCK(rqp);
+		SMBRQ_SUNLOCK(&ilock);
 		return 0;
 	}
 	/*
@@ -524,9 +526,9 @@
 		/*
 		 * We're done with this reply, look for the next one.
 		 */
-		SMBRQ_SLOCK(rqp);
+		SMBRQ_SLOCK(&ilock, rqp);
 		md_next_record(&rqp->sr_rp);
-		SMBRQ_SUNLOCK(rqp);
+		SMBRQ_SUNLOCK(&ilock);
 		error = smb_rq_reply(rqp);
 		if (error)
 			break;
Index: netproto/smb/smb_rq.h
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_rq.h,v
retrieving revision 1.2
diff -u -r1.2 smb_rq.h
--- netproto/smb/smb_rq.h	17 Jun 2003 04:28:54 -0000	1.2
+++ netproto/smb/smb_rq.h	22 Feb 2004 07:01:30 -0000
@@ -56,8 +56,8 @@
 #define	SMBT2_RESTART		0x0008
 #define	SMBT2_NORESTART		0x0010
 
-#define SMBRQ_SLOCK(rqp)	smb_sl_lock(&(rqp)->sr_slock)
-#define SMBRQ_SUNLOCK(rqp)	smb_sl_unlock(&(rqp)->sr_slock)
+#define SMBRQ_SLOCK(ilock, rqp)	smb_sl_lock(ilock, &(rqp)->sr_slock)
+#define SMBRQ_SUNLOCK(ilock)	smb_sl_unlock(ilock)
 #define SMBRQ_SLOCKPTR(rqp)	(&(rqp)->sr_slock)
 
 
Index: netproto/smb/smb_subr.c
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_subr.c,v
retrieving revision 1.9
diff -u -r1.9 smb_subr.c
--- netproto/smb/smb_subr.c	9 Nov 2003 02:22:37 -0000	1.9
+++ netproto/smb/smb_subr.c	22 Feb 2004 06:57:57 -0000
@@ -429,15 +429,13 @@
  * since we blocked, so reget or release as appropriate.
  */
 int
-smb_sleep(void *chan, struct lwkt_token *mtx, int slpflags, const char *wmesg, int timo)
+smb_sleep(void *chan, struct lwkt_tokref *ilock, int slpflags, const char *wmesg, int timo)
 {
 	int error;
 
 	error = tsleep(chan, slpflags, wmesg, timo);
-	if ((slpflags & PDROP) == 0 && mtx)
-		lwkt_regettoken(mtx);
-	else
-		lwkt_reltoken(mtx);
+	if ((slpflags & PDROP) && ilock)
+		lwkt_reltoken(ilock);
 	return error;
 }
 
Index: netproto/smb/smb_subr.h
===================================================================
RCS file: /cvs/src/sys/netproto/smb/smb_subr.h,v
retrieving revision 1.7
diff -u -r1.7 smb_subr.h
--- netproto/smb/smb_subr.h	15 Nov 2003 21:05:43 -0000	1.7
+++ netproto/smb/smb_subr.h	22 Feb 2004 05:05:13 -0000
@@ -80,10 +80,11 @@
 
 #define	lockdestroy(lock)
 #define	smb_slock			lwkt_token
-#define	smb_sl_init(mtx, desc)		lwkt_inittoken(mtx)
-#define	smb_sl_destroy(mtx)
-#define	smb_sl_lock(mtx)		lwkt_gettoken(mtx)
-#define	smb_sl_unlock(mtx)		lwkt_reltoken(mtx)
+#define	smb_ilock			lwkt_tokref
+#define	smb_sl_init(tok, desc)		lwkt_token_init(tok)
+#define	smb_sl_destroy(tok)
+#define	smb_sl_lock(ilock, tok)		lwkt_gettoken(ilock, tok)
+#define	smb_sl_unlock(ilock)		lwkt_reltoken(ilock)
 
 #define SMB_STRFREE(p)	do { if (p) smb_strfree(p); } while(0)
 
@@ -139,7 +140,8 @@
 struct mbchain;
 struct proc;
 struct thread;
-struct lwkt_token;
+struct lwkt_tokref;
+struct lwkt_rwlock;
 struct smb_vc;
 struct smb_rq;
 
@@ -171,7 +173,7 @@
  */
 int kthread_create2(void (*func)(void *), void *arg,
     struct proc **newpp, int flags, const char *fmt, ...);
-int smb_sleep(void *chan, struct lwkt_token *mtx, int slpflags, const char *wmesg, int timo);
+int smb_sleep(void *chan, struct lwkt_tokref *ilock, int slpflags, const char *wmesg, int timo);
 
 
 #endif /* !_NETSMB_SMB_SUBR_H_ */
Index: sys/buf2.h
===================================================================
RCS file: /cvs/src/sys/sys/buf2.h,v
retrieving revision 1.6
diff -u -r1.6 buf2.h
--- sys/buf2.h	20 Aug 2003 07:31:21 -0000	1.6
+++ sys/buf2.h	24 Feb 2004 18:36:33 -0000
@@ -63,15 +63,16 @@
 static __inline int
 BUF_LOCK(struct buf *bp, int locktype)
 {
+	lwkt_tokref ilock;
 	int s, ret;
 
 	s = splbio();
-	lwkt_gettoken(&buftimetoken);
+	lwkt_gettoken(&ilock, &buftimetoken);
 	locktype |= LK_INTERLOCK;
 	bp->b_lock.lk_wmesg = buf_wmesg;
 	bp->b_lock.lk_prio = 0;		/* tsleep flags */
 	/* bp->b_lock.lk_timo = 0;   not necessary */
-	ret = lockmgr(&(bp)->b_lock, locktype, &buftimetoken, curthread);
+	ret = lockmgr(&(bp)->b_lock, locktype, &ilock, curthread);
 	splx(s);
 	return ret;
 }
@@ -82,15 +83,16 @@
 static __inline int
 BUF_TIMELOCK(struct buf *bp, int locktype, char *wmesg, int catch, int timo)
 {
+	lwkt_tokref ilock;
 	int s, ret;
 
 	s = splbio();
-	lwkt_gettoken(&buftimetoken);
+	lwkt_gettoken(&ilock, &buftimetoken);
 	locktype |= LK_INTERLOCK | LK_TIMELOCK;
 	bp->b_lock.lk_wmesg = wmesg;
 	bp->b_lock.lk_prio = catch;	/* tsleep flags */
 	bp->b_lock.lk_timo = timo;
-	ret = lockmgr(&(bp)->b_lock, (locktype), &buftimetoken, curthread);
+	ret = lockmgr(&(bp)->b_lock, locktype, &ilock, curthread);
 	splx(s);
 	return ret;
 }
Index: sys/globaldata.h
===================================================================
RCS file: /cvs/src/sys/sys/globaldata.h,v
retrieving revision 1.26
diff -u -r1.26 globaldata.h
--- sys/globaldata.h	20 Feb 2004 17:11:08 -0000	1.26
+++ sys/globaldata.h	21 Feb 2004 22:06:58 -0000
@@ -119,6 +119,7 @@
 
 	struct pipe	*gd_pipeq;		/* cache pipe structures */
 	int		gd_pipeqcount;		/* number of structures */
+	lwkt_tokref_t 	gd_tokreqbase;		/* requests from other cpus */
 	/* extended by <machine/pcpu.h> */
 };
 
Index: sys/kernel.h
===================================================================
RCS file: /cvs/src/sys/sys/kernel.h,v
retrieving revision 1.9
diff -u -r1.9 kernel.h
--- sys/kernel.h	25 Feb 2004 17:38:51 -0000	1.9
+++ sys/kernel.h	25 Feb 2004 18:12:25 -0000
@@ -128,6 +128,7 @@
 	SI_SUB_CONFIGURE	= 0x3800000,	/* Configure devices */
 	SI_SUB_VFS		= 0x4000000,	/* virtual file system*/
 	SI_SUB_CLOCKS		= 0x4800000,	/* real time and stat clocks*/
+	SI_SUB_FINISH_SMP	= 0x5000000,	/* finish setting up cpus */
 	SI_SUB_CLIST		= 0x5800000,	/* clists*/
 	SI_SUB_SYSV_SHM		= 0x6400000,	/* System V shared memory*/
 	SI_SUB_SYSV_SEM		= 0x6800000,	/* System V semaphores*/
Index: sys/lock.h
===================================================================
RCS file: /cvs/src/sys/sys/lock.h,v
retrieving revision 1.7
diff -u -r1.7 lock.h
--- sys/lock.h	21 Nov 2003 22:46:13 -0000	1.7
+++ sys/lock.h	22 Feb 2004 05:21:17 -0000
@@ -193,7 +193,7 @@
 			int flags);
 #ifdef DEBUG_LOCKS
 int	debuglockmgr (struct lock *, u_int flags,
-			struct lwkt_token *, struct thread *p,
+			struct lwkt_tokref *, struct thread *p,
 			const char *,
 			const char *,
 			int);
@@ -202,7 +202,7 @@
 	    "lockmgr", __FILE__, __LINE__)
 #else
 int	lockmgr (struct lock *, u_int flags,
-			struct lwkt_token *, struct thread *td);
+			struct lwkt_tokref *, struct thread *td);
 #endif
 void	lockmgr_printinfo (struct lock *);
 int	lockstatus (struct lock *, struct thread *);
Index: sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.8
diff -u -r1.8 mount.h
--- sys/mount.h	2 Feb 2004 05:43:15 -0000	1.8
+++ sys/mount.h	22 Feb 2004 19:54:00 -0000
@@ -111,6 +111,9 @@
  * will become the dirty list and mnt_reservedvnlist will become the 'clean'
  * list.  Filesystem kld's syncing code should remain compatible since
  * they only need to scan the dirty vnode list (nvnodelist -> dirtyvnodelist).
+ *
+ * NOTE: Any vnode marked VPLACEMARKER is a placemarker and should ALWAYS BE
+ * SKIPPED.  NO OTHER FIELDS IN SUCH VNODES ARE VALID.
  */
 TAILQ_HEAD(vnodelst, vnode);
 
@@ -435,7 +438,7 @@
 int	vfs_lock (struct mount *);         /* lock a vfs */
 void	vfs_msync (struct mount *, int);
 void	vfs_unlock (struct mount *);       /* unlock a vfs */
-int	vfs_busy (struct mount *, int, struct lwkt_token *, struct thread *);
+int	vfs_busy (struct mount *, int, struct lwkt_tokref *, struct thread *);
 int	vfs_export			    /* process mount export info */
 	  (struct mount *, struct netexport *, struct export_args *);
 struct	netcred *vfs_export_lookup	    /* lookup host in fs export list */
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.42
diff -u -r1.42 proc.h
--- sys/proc.h	30 Jan 2004 05:42:18 -0000	1.42
+++ sys/proc.h	23 Feb 2004 01:11:53 -0000
@@ -449,7 +449,6 @@
 int	cpu_coredump (struct thread *, struct vnode *, struct ucred *);
 void	setsugid (void);
 void	faultin (struct proc *p);
-void	sched_thread_init(void);
 
 u_int32_t	procrunnable (void);
 
Index: sys/rman.h
===================================================================
RCS file: /cvs/src/sys/sys/rman.h,v
retrieving revision 1.6
diff -u -r1.6 rman.h
--- sys/rman.h	21 Feb 2004 09:17:10 -0000	1.6
+++ sys/rman.h	22 Feb 2004 07:12:15 -0000
@@ -77,6 +77,9 @@
 
 enum	rman_type { RMAN_UNINIT = 0, RMAN_GAUGE, RMAN_ARRAY };
 
+struct lwkt_token;
+struct lwkt_tokref;
+
 struct	rman {
 	struct	resource_head 	rm_list;
 	struct	lwkt_token 	*rm_slock; /* mutex used to protect rm_list */
@@ -91,7 +94,7 @@
 #ifdef _KERNEL
 
 int	rman_activate_resource(struct resource *r);
-int	rman_await_resource(struct resource *r, int slpflags, int timo);
+int	rman_await_resource(struct resource *r, struct lwkt_tokref *ilock, int slpflags, int timo);
 int	rman_deactivate_resource(struct resource *r);
 int	rman_fini(struct rman *rm);
 int	rman_init(struct rman *rm);
Index: sys/thread.h
===================================================================
RCS file: /cvs/src/sys/sys/thread.h,v
retrieving revision 1.46
diff -u -r1.46 thread.h
--- sys/thread.h	17 Feb 2004 19:38:50 -0000	1.46
+++ sys/thread.h	23 Feb 2004 04:18:12 -0000
@@ -31,6 +31,7 @@
 struct thread;
 struct lwkt_queue;
 struct lwkt_token;
+struct lwkt_tokref;
 struct lwkt_wait;
 struct lwkt_ipiq;
 struct lwkt_cpu_msg;
@@ -43,6 +44,7 @@
 
 typedef struct lwkt_queue	*lwkt_queue_t;
 typedef struct lwkt_token	*lwkt_token_t;
+typedef struct lwkt_tokref	*lwkt_tokref_t;
 typedef struct lwkt_wait	*lwkt_wait_t;
 typedef struct lwkt_cpu_msg	*lwkt_cpu_msg_t;
 typedef struct lwkt_cpu_port	*lwkt_cpu_port_t;
@@ -72,17 +74,44 @@
 #endif
 
 /*
- * Tokens arbitrate access to information.  They are 'soft' arbitrators
- * in that they are associated with cpus rather then threads, making the
- * optimal aquisition case very fast if your cpu already happens to own the
- * token you are requesting.
+ * Tokens are used to serialize access to information.  They are 'soft'
+ * serialization entities that only stay in effect while the thread is
+ * running.  If the thread blocks, other threads can run holding the same
+ * tokens.  The tokens are reacquired when the original thread resumes.
+ *
+ * A thread can depend on its serialization remaining intact through a
+ * preemption.  An interrupt which attempts to use the same token as the
+ * thread being preempted will reschedule itself for non-preemptive
+ * operation, so the new token code is capable of interlocking against
+ * interrupts as well as other cpus.
+ *
+ * Tokens are managed through a helper reference structure, lwkt_tokref,
+ * which is typically declared on the caller's stack.  Multiple tokref's
+ * may reference the same token.
  */
 typedef struct lwkt_token {
-    struct globaldata *t_cpu;	/* the current owner of the token */
-    struct globaldata *t_reqcpu;/* return ownership to this cpu on release */
-    int		t_gen;		/* generation number */
+    struct globaldata	*t_cpu;		/* the current owner of the token */
+    struct globaldata	*t_reqcpu;	/* requesting cpu */
+    int			t_unused01;	/* (used to be generation number) */
 } lwkt_token;
 
+typedef struct lwkt_tokref {
+    lwkt_token_t	tr_tok;		/* token in question */
+    __uint32_t		tr_magic;	/* sanity check */
+    lwkt_tokref_t	tr_next;	/* linked list */
+    lwkt_tokref_t	tr_gdreqnext;	/* based at gd_tokreqbase */
+    struct globaldata	*tr_reqgd;	/* requesting cpu */
+} lwkt_tokref;
+
+#define LWKT_TOKREF_MAGIC1		\
+			((__uint32_t)0x544f4b52)	/* normal */
+#define LWKT_TOKREF_MAGIC2		\
+			((__uint32_t)0x544f4b53)	/* pending req */
+#define LWKT_TOKREF_INIT(tok)		\
+			{ tok, LWKT_TOKREF_MAGIC1 }
+#define LWKT_TOKREF_DECLARE(name, tok)	\
+			lwkt_tokref name = LWKT_TOKREF_INIT(tok)
+
 /*
  * Wait structures deal with blocked threads.  Due to the way remote cpus
  * interact with these structures stable storage must be used.
@@ -96,6 +125,7 @@
 
 #define MAXCPUFIFO      16	/* power of 2 */
 #define MAXCPUFIFO_MASK	(MAXCPUFIFO - 1)
+#define LWKT_MAXTOKENS	16	/* max tokens beneficially held by thread */
 
 /*
  * Always cast to ipifunc_t when registering an ipi.  The actual ipi function
@@ -207,6 +237,7 @@
     char	td_comm[MAXCOMLEN+1]; /* typ 16+1 bytes */
     struct thread *td_preempted; /* we preempted this thread */
     struct caps_kinfo *td_caps;	/* list of client and server registrations */
+    lwkt_tokref_t td_toks;	/* tokens beneficially held */
     struct md_thread td_mach;
 };
 
@@ -283,7 +314,7 @@
 extern void lwkt_set_comm(thread_t td, const char *ctl, ...);
 extern void lwkt_wait_free(struct thread *td);
 extern void lwkt_free_thread(struct thread *td);
-extern void lwkt_init_wait(struct lwkt_wait *w);
+extern void lwkt_wait_init(struct lwkt_wait *w);
 extern void lwkt_gdinit(struct globaldata *gd);
 extern void lwkt_switch(void);
 extern void lwkt_maybe_switch(void);
@@ -295,28 +326,44 @@
 extern void lwkt_acquire(thread_t td);
 extern void lwkt_yield(void);
 extern void lwkt_yield_quick(void);
+extern void lwkt_token_wait(void);
 extern void lwkt_hold(thread_t td);
 extern void lwkt_rele(thread_t td);
 
 extern void lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen);
 extern void lwkt_signal(lwkt_wait_t w, int count);
-extern int lwkt_trytoken(lwkt_token_t tok);
-extern int lwkt_gettoken(lwkt_token_t tok);
-extern int lwkt_gentoken(lwkt_token_t tok, int *gen);
-extern int lwkt_reltoken(lwkt_token_t tok);
-extern void lwkt_inittoken(lwkt_token_t tok);
-extern int  lwkt_regettoken(lwkt_token_t tok);
+
+extern int lwkt_havetoken(lwkt_token_t tok);
+extern int lwkt_havetokref(lwkt_tokref_t xref);
+extern void lwkt_gettoken(lwkt_tokref_t ref, lwkt_token_t tok);
+extern int lwkt_trytoken(lwkt_tokref_t ref, lwkt_token_t tok);
+extern void lwkt_gettokref(lwkt_tokref_t ref);
+extern int  lwkt_trytokref(lwkt_tokref_t ref);
+extern void lwkt_reltoken(lwkt_tokref_t ref);
+extern void lwkt_reqtoken_remote(void *data);
+extern int  lwkt_chktokens(thread_t td);
+extern void lwkt_drain_token_requests(void);
+extern void lwkt_token_init(lwkt_token_t tok);
+extern void lwkt_token_uninit(lwkt_token_t tok);
+
+extern void lwkt_token_pool_init(void);
+extern lwkt_token_t lwkt_token_pool_get(void *ptraddr);
+
 extern void lwkt_rwlock_init(lwkt_rwlock_t lock);
+extern void lwkt_rwlock_uninit(lwkt_rwlock_t lock);
 extern void lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg);
 extern void lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg);
 extern void lwkt_exunlock(lwkt_rwlock_t lock);
 extern void lwkt_shunlock(lwkt_rwlock_t lock);
+
 extern void lwkt_setpri(thread_t td, int pri);
 extern void lwkt_setpri_self(int pri);
 extern int  lwkt_send_ipiq(struct globaldata *targ, ipifunc_t func, void *arg);
+extern int  lwkt_send_ipiq_passive(struct globaldata *targ, ipifunc_t func, void *arg);
 extern int  lwkt_send_ipiq_bycpu(int dcpu, ipifunc_t func, void *arg);
 extern int  lwkt_send_ipiq_mask(cpumask_t mask, ipifunc_t func, void *arg);
 extern void lwkt_wait_ipiq(struct globaldata *targ, int seq);
+extern int  lwkt_seq_ipiq(struct globaldata *targ);
 extern void lwkt_process_ipiq(void);
 #ifdef _KERNEL
 extern void lwkt_process_ipiq_frame(struct intrframe frame);
Index: sys/thread2.h
===================================================================
RCS file: /cvs/src/sys/sys/thread2.h,v
retrieving revision 1.12
diff -u -r1.12 thread2.h
--- sys/thread2.h	10 Feb 2004 07:34:43 -0000	1.12
+++ sys/thread2.h	21 Feb 2004 22:23:41 -0000
@@ -102,10 +102,16 @@
     curthread->td_pri = cpri;
 }
 
-static __inline int
-lwkt_havetoken(lwkt_token_t tok)
+/*
+ * Initialize a tokref_t.  We only need to initialize the token pointer
+ * and the magic number.  We do not have to initialize tr_next, tr_gdreqnext,
+ * or tr_reqgd.
+ */
+static __inline void
+lwkt_tokref_init(lwkt_tokref_t ref, lwkt_token_t tok)
 {
-    return (tok->t_cpu == mycpu);
+    ref->tr_magic = LWKT_TOKREF_MAGIC1;
+    ref->tr_tok = tok;
 }
 
 /*
Index: sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.9
diff -u -r1.9 vnode.h
--- sys/vnode.h	20 Jan 2004 18:41:51 -0000	1.9
+++ sys/vnode.h	22 Feb 2004 21:34:42 -0000
@@ -116,7 +116,7 @@
 	daddr_t	v_lasta;			/* last allocation */
 	int	v_clen;				/* length of current cluster */
 	struct vm_object *v_object;		/* Place to store VM object */
-	struct	lwkt_token v_interlock;		/* lock on usecount and flag */
+	lwkt_token_t v_interlock;		/* lock on usecount and flag */
 	struct	lock *v_vnlock;			/* used for non-locking fs's */
 	enum	vtagtype v_tag;			/* type of underlying data */
 	void 	*v_data;			/* private data for fs */
@@ -175,6 +175,7 @@
 #define	VONWORKLST	0x200000 /* On syncer work-list */
 #define	VMOUNT		0x400000 /* Mount in progress */
 #define VOBJDIRTY	0x800000 /* object might be dirty */
+#define VPLACEMARKER	0x1000000 /* dummy vnode placemarker */
 
 /*
  * Vnode attributes.  A field value of VNOVAL represents a field whose value
@@ -325,8 +326,8 @@
 	(((vp)->v_flag & VFREE) && \
 	 ((vp)->v_holdcnt || (vp)->v_usecount))
 
-#define	VI_LOCK(vp)	lwkt_gettoken(&(vp)->v_interlock)
-#define	VI_UNLOCK(vp)	lwkt_reltoken(&(vp)->v_interlock)
+#define	VI_LOCK(vlock, vp)	lwkt_gettoken(vlock, (vp)->v_interlock)
+#define	VI_UNLOCK(vlock, vp)	lwkt_reltoken(vlock)
 
 #endif /* _KERNEL */
 
@@ -576,24 +577,29 @@
 void	vfs_add_vnodeops (const void *);
 void	vfs_rm_vnodeops (const void *);
 int	vflush (struct mount *mp, int rootrefs, int flags);
-int 	vget (struct vnode *vp, int lockflag, struct thread *td);
+int	vmntvnodescan(struct mount *mp, 
+	    int (*fastfunc)(struct mount *mp, struct vnode *vp, void *data),
+	    int (*slowfunc)(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data),
+	    void *data);
+
+int 	vget (struct vnode *vp, lwkt_tokref_t vlock, int lockflag, struct thread *td);
 void 	vgone (struct vnode *vp);
-void	vgonel (struct vnode *vp, struct thread *td);
+void	vgonel (struct vnode *vp, lwkt_tokref_t vlock, struct thread *td);
 void	vhold (struct vnode *);
 int	vinvalbuf (struct vnode *vp, int save, 
 	    struct thread *td, int slpflag, int slptimeo);
 int	vtruncbuf (struct vnode *vp, struct thread *td,
 		off_t length, int blksize);
 void	vprint (char *label, struct vnode *vp);
-int	vrecycle (struct vnode *vp, struct lwkt_token *inter_lkp,
+int	vrecycle (struct vnode *vp, struct lwkt_tokref *inter_lkp,
 	    struct thread *td);
 int 	vn_close (struct vnode *vp, int flags, struct thread *td);
 int	vn_isdisk (struct vnode *vp, int *errp);
-int	vn_lock (struct vnode *vp, int flags, struct thread *td);
+int	vn_lock (struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td);
 #ifdef	DEBUG_LOCKS
-int	debug_vn_lock (struct vnode *vp, int flags, struct thread *td,
+int	debug_vn_lock (struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td,
 	    const char *filename, int line);
-#define vn_lock(vp,flags,p) debug_vn_lock(vp,flags,p,__FILE__,__LINE__)
+#define vn_lock(vp,vlock,flags,p) debug_vn_lock(vp,vlock,flags,p,__FILE__,__LINE__)
 #endif
 int 	vn_open (struct nameidata *ndp, int fmode, int cmode);
 void	vn_pollevent (struct vnode *vp, int events);
Index: vfs/coda/coda_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/coda/coda_subr.c,v
retrieving revision 1.5
diff -u -r1.5 coda_subr.c
--- vfs/coda/coda_subr.c	12 Nov 2003 22:08:09 -0000	1.5
+++ vfs/coda/coda_subr.c	22 Feb 2004 19:54:49 -0000
@@ -315,9 +315,11 @@
 	int count = 0, bad = 0;
 loop:
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp; vp = nvp) {
+		nvp = TAILQ_NEXT(vp, v_nmntvnodes);	/* ZZZ */
+		if (vp->v_flag & VPLACEMARKER)
+			continue;
 		if (vp->v_mount != mp)
 			goto loop;
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
 		cp = VTOC(vp);
 		count++;
 		if (!(cp->c_flags & C_UNMOUNTING)) {
Index: vfs/coda/coda_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/coda/coda_vfsops.c,v
retrieving revision 1.10
diff -u -r1.10 coda_vfsops.c
--- vfs/coda/coda_vfsops.c	23 Sep 2003 05:03:52 -0000	1.10
+++ vfs/coda/coda_vfsops.c	22 Feb 2004 06:11:37 -0000
@@ -314,11 +314,11 @@
 	    { /* Found valid root. */
 		*vpp = mi->mi_rootvp;
 		/* On Mach, this is vref.  On NetBSD, VOP_LOCK */
-#if	1
+#if 1
 		vref(*vpp);
-		vn_lock(*vpp, LK_EXCLUSIVE, td);
+		vn_lock(*vpp, NULL, LK_EXCLUSIVE, td);
 #else
-		vget(*vpp, LK_EXCLUSIVE, td);
+		vget(*vpp, NULL, LK_EXCLUSIVE, td);
 #endif
 		MARK_INT_SAT(CODA_ROOT_STATS);
 		return(0);
@@ -339,9 +339,9 @@
 	*vpp = mi->mi_rootvp;
 #if	1
 	vref(*vpp);
-	vn_lock(*vpp, LK_EXCLUSIVE, td);
+	vn_lock(*vpp, NULL, LK_EXCLUSIVE, td);
 #else
-	vget(*vpp, LK_EXCLUSIVE, td);
+	vget(*vpp, NULL, LK_EXCLUSIVE, td);
 #endif
 
 	MARK_INT_SAT(CODA_ROOT_STATS);
@@ -359,9 +359,9 @@
 	*vpp = mi->mi_rootvp;
 #if	1
 	vref(*vpp);
-	vn_lock(*vpp, LK_EXCLUSIVE, td);
+	vn_lock(*vpp, NULL, LK_EXCLUSIVE, td);
 #else
-	vget(*vpp, LK_EXCLUSIVE, td);
+	vget(*vpp, NULL, LK_EXCLUSIVE, td);
 #endif
 
 	MARK_INT_FAIL(CODA_ROOT_STATS);
Index: vfs/coda/coda_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/coda/coda_vnops.c,v
retrieving revision 1.13
diff -u -r1.13 coda_vnops.c
--- vfs/coda/coda_vnops.c	16 Feb 2004 19:56:26 -0000	1.13
+++ vfs/coda/coda_vnops.c	22 Feb 2004 07:30:02 -0000
@@ -272,7 +272,7 @@
 	return (error);
 
     /* We get the vnode back locked.  Needs unlocked */
-    VOP_UNLOCK(vp, 0, td);
+    VOP_UNLOCK(vp, NULL, 0, td);
     /* Keep a reference until the close comes in. */
     vref(*vpp);                
 
@@ -450,7 +450,7 @@
 	     * We get the vnode back locked in both Mach and
 	     * NetBSD.  Needs unlocked 
 	     */
-	    VOP_UNLOCK(cfvp, 0, td);
+	    VOP_UNLOCK(cfvp, NULL, 0, td);
 	}
 	else {
 	    opened_internally = 1;
@@ -916,7 +916,7 @@
 	    printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n",
 	    	   vp->v_usecount, vp, cp);
 #endif
-	lockmgr(&cp->c_lock, LK_RELEASE, &vp->v_interlock, td);
+	lockmgr(&cp->c_lock, LK_RELEASE, NULL, td);
     } else {
 #ifdef OLD_DIAGNOSTIC
 	if (CTOV(cp)->v_usecount) {
@@ -926,7 +926,7 @@
 	    panic("coda_inactive:  cp->ovp != NULL");
 	}
 #endif
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	vgone(vp);
     }
 
@@ -1072,7 +1072,7 @@
      */
     if (!error || (error == EJUSTRETURN)) {
 	if (!(cnp->cn_flags & CNP_LOCKPARENT) || !(cnp->cn_flags & CNP_ISLASTCN)) {
-	    if ((error = VOP_UNLOCK(dvp, 0, td))) {
+	    if ((error = VOP_UNLOCK(dvp, NULL, 0, td))) {
 		return error; 
 	    }	    
 	    /* 
@@ -1080,7 +1080,7 @@
 	     * lock it without bothering to check anything else. 
 	     */
 	    if (*ap->a_vpp) {
-		if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) {
+		if ((error = VOP_LOCK(*ap->a_vpp, NULL, LK_EXCLUSIVE, td))) {
 		    printf("coda_lookup: ");
 		    panic("unlocked parent but couldn't lock child");
 		}
@@ -1089,7 +1089,7 @@
 	    /* The parent is locked, and may be the same as the child */
 	    if (*ap->a_vpp && (*ap->a_vpp != dvp)) {
 		/* Different, go ahead and lock it. */
-		if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) {
+		if ((error = VOP_LOCK(*ap->a_vpp, NULL, LK_EXCLUSIVE, td))) {
 		    printf("coda_lookup: ");
 		    panic("unlocked parent but couldn't lock child");
 		}
@@ -1178,7 +1178,7 @@
 
     if (!error) {
 	if (cnp->cn_flags & CNP_LOCKLEAF) {
-	    if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) {
+	    if ((error = VOP_LOCK(*ap->a_vpp, NULL, LK_EXCLUSIVE, td))) {
 		printf("coda_create: ");
 		panic("unlocked parent but couldn't lock child");
 	    }
@@ -1780,9 +1780,9 @@
     }
 
 #ifndef	DEBUG_LOCKS
-    return (lockmgr(&cp->c_lock, ap->a_flags, &vp->v_interlock, td));
+    return (lockmgr(&cp->c_lock, ap->a_flags, ap->a_vlock, td));
 #else
-    return (debuglockmgr(&cp->c_lock, ap->a_flags, &vp->v_interlock, td,
+    return (debuglockmgr(&cp->c_lock, ap->a_flags, ap->a_vlock, td,
 			 "coda_lock", vp->filename, vp->line));
 #endif
 }
@@ -1805,7 +1805,7 @@
 		  cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique));
     }
 
-    return (lockmgr(&cp->c_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock, td));
+    return (lockmgr(&cp->c_lock, ap->a_flags | LK_RELEASE, ap->a_vlock, td));
 }
 
 int
Index: vfs/deadfs/dead_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/deadfs/dead_vnops.c,v
retrieving revision 1.6
diff -u -r1.6 dead_vnops.c
--- vfs/deadfs/dead_vnops.c	20 Aug 2003 09:56:31 -0000	1.6
+++ vfs/deadfs/dead_vnops.c	22 Feb 2004 06:21:10 -0000
@@ -201,6 +201,7 @@
 dead_lock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct proc *a_p;
 	} */ *ap;
@@ -212,7 +213,7 @@
 	 * the interlock here.
 	 */
 	if (ap->a_flags & LK_INTERLOCK) {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(ap->a_vlock);
 		ap->a_flags &= ~LK_INTERLOCK;
 	}
 	if (!chkvnlock(vp))
Index: vfs/fdesc/fdesc_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/fdesc/fdesc_vfsops.c,v
retrieving revision 1.5
diff -u -r1.5 fdesc_vfsops.c
--- vfs/fdesc/fdesc_vfsops.c	20 Aug 2003 09:56:31 -0000	1.5
+++ vfs/fdesc/fdesc_vfsops.c	22 Feb 2004 05:54:09 -0000
@@ -149,7 +149,7 @@
 	 */
 	vp = VFSTOFDESC(mp)->f_root;
 	VREF(vp);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	*vpp = vp;
 	return (0);
 }
Index: vfs/fdesc/fdesc_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/fdesc/fdesc_vnops.c,v
retrieving revision 1.8
diff -u -r1.8 fdesc_vnops.c
--- vfs/fdesc/fdesc_vnops.c	23 Sep 2003 05:03:52 -0000	1.8
+++ vfs/fdesc/fdesc_vnops.c	22 Feb 2004 06:11:53 -0000
@@ -112,7 +112,7 @@
 loop:
 	LIST_FOREACH(fd, fc, fd_hash) {
 		if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
-			if (vget(fd->fd_vnode, 0, td))
+			if (vget(fd->fd_vnode, NULL, 0, td))
 				goto loop;
 			*vpp = fd->fd_vnode;
 			return (error);
@@ -191,11 +191,11 @@
 		goto bad;
 	}
 
-	VOP_UNLOCK(dvp, 0, td);
+	VOP_UNLOCK(dvp, NULL, 0, td);
 	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
 		VREF(dvp);	
-		vn_lock(dvp, LK_SHARED | LK_RETRY, td);
+		vn_lock(dvp, NULL, LK_SHARED | LK_RETRY, td);
 		return (0);
 	}
 
@@ -227,12 +227,12 @@
 	if (error)
 		goto bad;
 	VTOFDESC(fvp)->fd_fd = fd;
-	vn_lock(fvp, LK_SHARED | LK_RETRY, td);
+	vn_lock(fvp, NULL, LK_SHARED | LK_RETRY, td);
 	*vpp = fvp;
 	return (0);
 
 bad:
-	vn_lock(dvp, LK_SHARED | LK_RETRY, td);
+	vn_lock(dvp, NULL, LK_SHARED | LK_RETRY, td);
 	*vpp = NULL;
 	return (error);
 }
@@ -514,7 +514,7 @@
 	 * Clear out the v_type field to avoid
 	 * nasty things happening in vgone().
 	 */
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 	vp->v_type = VNON;
 	return (0);
 }
Index: vfs/fifofs/fifo_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/fifofs/fifo_vnops.c,v
retrieving revision 1.12
diff -u -r1.12 fifo_vnops.c
--- vfs/fifofs/fifo_vnops.c	4 Sep 2003 23:46:59 -0000	1.12
+++ vfs/fifofs/fifo_vnops.c	22 Feb 2004 05:54:29 -0000
@@ -225,10 +225,10 @@
 	}
 	if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
 		if (fip->fi_writers == 0) {
-			VOP_UNLOCK(vp, 0, ap->a_td);
+			VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 			error = tsleep((caddr_t)&fip->fi_readers,
 			    PCATCH, "fifoor", 0);
-			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
+			vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
 			if (error)
 				goto bad;
 			/*
@@ -246,10 +246,10 @@
 			}
 		} else {
 			if (fip->fi_readers == 0) {
-				VOP_UNLOCK(vp, 0, ap->a_td);
+				VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 				error = tsleep((caddr_t)&fip->fi_writers,
 				    PCATCH, "fifoow", 0);
-				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
+				vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
 				if (error)
 					goto bad;
 				/*
@@ -293,10 +293,10 @@
 	if (ap->a_ioflag & IO_NDELAY)
 		rso->so_state |= SS_NBIO;
 	startresid = uio->uio_resid;
-	VOP_UNLOCK(ap->a_vp, 0, td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, td);
 	error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
 	    (struct mbuf **)0, (int *)0);
-	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (ap->a_ioflag & IO_NDELAY)
 		rso->so_state &= ~SS_NBIO;
 	return (error);
@@ -325,10 +325,10 @@
 #endif
 	if (ap->a_ioflag & IO_NDELAY)
 		wso->so_state |= SS_NBIO;
-	VOP_UNLOCK(ap->a_vp, 0, td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, td);
 	error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
 		       (struct mbuf *)0, 0, td);
-	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (ap->a_ioflag & IO_NDELAY)
 		wso->so_state &= ~SS_NBIO;
 	return (error);
@@ -510,7 +510,7 @@
 		struct thread *a_td;
 	} */ *ap;
 {
-	VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/gnu/ext2fs/ext2_lookup.c
===================================================================
RCS file: /cvs/src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v
retrieving revision 1.8
diff -u -r1.8 ext2_lookup.c
--- vfs/gnu/ext2fs/ext2_lookup.c	9 Oct 2003 22:27:22 -0000	1.8
+++ vfs/gnu/ext2fs/ext2_lookup.c	22 Feb 2004 05:54:35 -0000
@@ -539,7 +539,7 @@
 		 */
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent)
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 		return (EJUSTRETURN);
 	}
 	/*
@@ -617,7 +617,7 @@
 		}
 		*vpp = tdp;
 		if (!lockparent)
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 		return (0);
 	}
 
@@ -642,7 +642,7 @@
 		*vpp = tdp;
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent)
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 		return (0);
 	}
 
@@ -667,13 +667,13 @@
 	 */
 	pdp = vdp;
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(pdp, 0, td);	/* race to get the inode */
+		VOP_UNLOCK(pdp, NULL, 0, td);	/* race to get the inode */
 		if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) {
-			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			return (error);
 		}
 		if (lockparent && (flags & CNP_ISLASTCN) &&
-		    (error = vn_lock(pdp, LK_EXCLUSIVE, td))) {
+		    (error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td))) {
 			vput(tdp);
 			return (error);
 		}
@@ -685,7 +685,7 @@
 		if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
 			return (error);
 		if (!lockparent || !(flags & CNP_ISLASTCN))
-			VOP_UNLOCK(pdp, 0, td);
+			VOP_UNLOCK(pdp, NULL, 0, td);
 		*vpp = tdp;
 	}
 
Index: vfs/gnu/ext2fs/ext2_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v
retrieving revision 1.11
diff -u -r1.11 ext2_vfsops.c
--- vfs/gnu/ext2fs/ext2_vfsops.c	23 Sep 2003 05:03:52 -0000	1.11
+++ vfs/gnu/ext2fs/ext2_vfsops.c	22 Feb 2004 22:18:12 -0000
@@ -211,7 +211,7 @@
 			flags = WRITECLOSE;
 			if (mp->mnt_flag & MNT_FORCE)
 				flags |= FORCECLOSE;
-			if (vfs_busy(mp, LK_NOWAIT, 0, td))
+			if (vfs_busy(mp, LK_NOWAIT, NULL, td))
 				return (EBUSY);
 			error = ext2_flushfiles(mp, flags, td);
 			vfs_unbusy(mp, td);
@@ -235,13 +235,13 @@
 			 * that user has necessary permissions on the device.
 			 */
 			if (cred->cr_uid != 0) {
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+				vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
 				    cred, td)) != 0) {
-					VOP_UNLOCK(devvp, 0, td);
+					VOP_UNLOCK(devvp, NULL, 0, td);
 					return (error);
 				}
-				VOP_UNLOCK(devvp, 0, td);
+				VOP_UNLOCK(devvp, NULL, 0, td);
 			}
 
 			if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
@@ -291,12 +291,12 @@
 		accessmode = VREAD;
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			accessmode |= VWRITE;
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		if ((error = VOP_ACCESS(devvp, accessmode, cred, td)) != 0) {
 			vput(devvp);
 			return (error);
 		}
-		VOP_UNLOCK(devvp, 0, td);
+		VOP_UNLOCK(devvp, NULL, 0, td);
 	}
 
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
@@ -520,19 +520,31 @@
  *	5) invalidate all cached file data.
  *	6) re-read inode data for all active vnodes.
  */
+static int ext2_reload_scan1(struct mount *mp, struct vnode *vp, void *rescan);
+static int ext2_reload_scan2(struct mount *mp, struct vnode *vp, 
+				lwkt_tokref_t vlock, void *rescan);
+
+struct scaninfo {
+	int rescan;
+	int allerror;
+	int waitfor;
+	thread_t td;
+	struct vnode *devvp;
+	struct ext2_sb_info *fs;
+};
+
 static int
 ext2_reload(mountp, cred, td)
 	struct mount *mountp;
 	struct ucred *cred;
 	struct thread *td;
 {
-	struct vnode *vp, *nvp, *devvp;
-	struct inode *ip;
+	struct vnode *devvp;
 	struct buf *bp;
 	struct ext2_super_block * es;
 	struct ext2_sb_info *fs;
 	int error;
-	int gen;
+	struct scaninfo scaninfo;
 
 	if ((mountp->mnt_flag & MNT_RDONLY) == 0)
 		return (EINVAL);
@@ -566,54 +578,66 @@
 #endif
 	brelse(bp);
 
-	gen = lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mountp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-		KKASSERT(vp->v_mount == mountp);
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		/*
-		 * Step 4: invalidate all inactive vnodes.
-		 */
-  		if (vrecycle(vp, NULL, td)) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-  			goto loop;
-		}
-		/*
-		 * Step 5: invalidate all cached file data.
-		 */
-		lwkt_gettoken(&vp->v_interlock);
-		if (lwkt_gentoken(&mntvnode_token, &gen)) {
-			lwkt_reltoken(&vp->v_interlock);
-			goto loop;
-		}
-		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		if (vinvalbuf(vp, 0, td, 0, 0))
-			panic("ext2_reload: dirty2");
-		/*
-		 * Step 6: re-read inode data for all active vnodes.
-		 */
-		ip = VTOI(vp);
-		error =
-		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
-			    (int)fs->s_blocksize, &bp);
-		if (error) {
-			vput(vp);
-			lwkt_reltoken(&mntvnode_token);
-			return (error);
-		}
-		ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + 
-		    EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)), 
-		    &ip->i_din);
-		brelse(bp);
+	scaninfo.rescan = 1;
+	scaninfo.td = td;
+	scaninfo.devvp = devvp;
+	scaninfo.fs = fs;
+	while (error == 0 && scaninfo.rescan) {
+	    scaninfo.rescan = 0;
+	    error = vmntvnodescan(mountp, ext2_reload_scan1, 
+				ext2_reload_scan2, &scaninfo);
+	}
+	return(error);
+}
+
+static int
+ext2_reload_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+	struct scaninfo *info = data;
+
+	/*
+	 * Step 4: invalidate all inactive vnodes.
+	 */
+	if (vrecycle(vp, NULL, curthread)) {
+		info->rescan = 1;
+		return(-1);	/* continue loop, do not call scan2 */
+	}
+	return(0);
+}
+
+static int
+ext2_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct inode *ip;
+	struct buf *bp;
+	int error;
+
+	/*
+	 * Step 5: invalidate all cached file data.
+	 */
+	if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) {
+		info->rescan = 1;
+		return(0);
+	}
+	if (vinvalbuf(vp, 0, info->td, 0, 0))
+		panic("ext2_reload: dirty2");
+	/*
+	 * Step 6: re-read inode data for all active vnodes.
+	 */
+	ip = VTOI(vp);
+	error = bread(info->devvp, fsbtodb(info->fs, ino_to_fsba(info->fs, ip->i_number)),
+		    (int)info->fs->s_blocksize, &bp);
+	if (error) {
 		vput(vp);
-		if (lwkt_gentoken(&mntvnode_token, &gen))
-			goto loop;
+		return (error);
 	}
-	lwkt_reltoken(&mntvnode_token);
-	return (0);
+	ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + 
+	    EXT2_INODE_SIZE * ino_to_fsbo(info->fs, ip->i_number)), 
+	    &ip->i_din);
+	brelse(bp);
+	vput(vp);
+	return(0);
 }
 
 /*
@@ -653,9 +677,9 @@
 #endif
 
 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return (error);
 	if (devvp->v_rdev->si_iosize_max != 0)
@@ -911,73 +935,47 @@
  *
  * Note: we are always called with the filesystem marked `MPBUSY'.
  */
+
+static int ext2_sync_scan(struct mount *mp, struct vnode *vp, 
+		lwkt_tokref_t vlock, void *data);
+
 static int
 ext2_sync(mp, waitfor, td)
 	struct mount *mp;
 	int waitfor;
 	struct thread *td;
 {
-	struct vnode *nvp, *vp;
-	struct inode *ip;
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct ext2_sb_info *fs;
-	int error, allerror = 0;
-	int gen;
+	struct scaninfo scaninfo;
+	int error;
 
 	fs = ump->um_e2fs;
 	if (fs->s_dirt != 0 && fs->s_rd_only != 0) {		/* XXX */
 		printf("fs = %s\n", fs->fs_fsmnt);
 		panic("ext2_sync: rofs mod");
 	}
+
 	/*
 	 * Write back each (modified) inode.
 	 */
-	gen = lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-		/*
-		 * If the vnode that we are about to sync is no longer
-		 * associated with this mount point, start over.
-		 */
-		if (vp->v_mount != mp) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		lwkt_gettoken(&vp->v_interlock);
-		if (lwkt_gentoken(&mntvnode_token, &gen)) {
-			lwkt_reltoken(&vp->v_interlock);
-			goto loop;
-		}
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		ip = VTOI(vp);
-		if (vp->v_type == VNON ||
-		    ((ip->i_flag &
-		    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
-		    (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) {
-			lwkt_reltoken(&vp->v_interlock);
-			continue;
-		}
-		error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
-		if (error) {
-			if (error == ENOENT)
-				goto loop;
-			continue;
-		}
-		if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
-			allerror = error;
-		VOP_UNLOCK(vp, 0, td);
-		vrele(vp);
-		lwkt_gentoken(&mntvnode_token, &gen);
+	scaninfo.allerror = 0;
+	scaninfo.rescan = 1;
+	scaninfo.waitfor = waitfor;
+	scaninfo.td = td;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		vmntvnodescan(mp, NULL, ext2_sync_scan, &scaninfo);
 	}
-	lwkt_reltoken(&mntvnode_token);
+
 	/*
 	 * Force stale file system control information to be flushed.
 	 */
 	if (waitfor != MNT_LAZY) {
-		vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
-			allerror = error;
-		VOP_UNLOCK(ump->um_devvp, 0, td);
+			scaninfo.allerror = error;
+		VOP_UNLOCK(ump->um_devvp, NULL, 0, td);
 	}
 #if QUOTA
 	qsync(mp);
@@ -989,9 +987,38 @@
 		fs->s_dirt = 0;
 		fs->s_es->s_wtime = time_second;
 		if ((error = ext2_sbupdate(ump, waitfor)) != 0)
-			allerror = error;
+			scaninfo.allerror = error;
+	}
+	return (scaninfo.allerror);
+}
+
+static int
+ext2_sync_scan(struct mount *mp, struct vnode *vp, 
+		lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct inode *ip;
+	int error;
+
+	ip = VTOI(vp);
+	if (vp->v_type == VNON ||
+	    ((ip->i_flag &
+	    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
+	    (TAILQ_EMPTY(&vp->v_dirtyblkhd) || info->waitfor == MNT_LAZY))) {
+		lwkt_reltoken(vlock);
+		return(0);
 	}
-	return (allerror);
+	error = vget(vp, vlock, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, info->td);
+	if (error) {
+		if (error == ENOENT)
+			info->rescan = 1;
+		return(0);
+	}
+	if ((error = VOP_FSYNC(vp, info->waitfor, info->td)) != 0)
+		info->allerror = error;
+	VOP_UNLOCK(vp, NULL, 0, info->td);
+	vrele(vp);
+	return(0);
 }
 
 /*
Index: vfs/gnu/ext2fs/ext2_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v
retrieving revision 1.9
diff -u -r1.9 ext2_vnops.c
--- vfs/gnu/ext2fs/ext2_vnops.c	23 Sep 2003 05:03:52 -0000	1.9
+++ vfs/gnu/ext2fs/ext2_vnops.c	22 Feb 2004 05:54:54 -0000
@@ -352,7 +352,7 @@
 		error = EXDEV;
 		goto out2;
 	}
-	if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) {
+	if (tdvp != vp && (error = vn_lock(vp, NULL, LK_EXCLUSIVE, td))) {
 		goto out2;
 	}
 	ip = VTOI(vp);
@@ -375,7 +375,7 @@
 	}
 out1:
 	if (tdvp != vp)
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 out2:
 	return (error);
 }
@@ -447,18 +447,18 @@
 		goto abortit;
 	}
 
-	if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0)
+	if ((error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td)) != 0)
 		goto abortit;
 	dp = VTOI(fdvp);
 	ip = VTOI(fvp);
  	if (ip->i_nlink >= LINK_MAX) {
- 		VOP_UNLOCK(fvp, 0, td);
+ 		VOP_UNLOCK(fvp, NULL, 0, td);
  		error = EMLINK;
  		goto abortit;
  	}
 	if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
 	    || (dp->i_flags & APPEND)) {
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		error = EPERM;
 		goto abortit;
 	}
@@ -469,7 +469,7 @@
 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
 		    dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & CNP_ISDOTDOT ||
 		    (ip->i_flag & IN_RENAME)) {
-			VOP_UNLOCK(fvp, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			error = EINVAL;
 			goto abortit;
 		}
@@ -497,7 +497,7 @@
 	ip->i_nlink++;
 	ip->i_flag |= IN_CHANGE;
 	if ((error = UFS_UPDATE(fvp, 1)) != 0) {
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		goto bad;
 	}
 
@@ -512,7 +512,7 @@
 	 * call to checkpath().
 	 */
 	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td);
-	VOP_UNLOCK(fvp, 0, td);
+	VOP_UNLOCK(fvp, NULL, 0, td);
 	if (oldparent != dp->i_number)
 		newparent = dp->i_number;
 	if (doingdirectory && newparent) {
@@ -735,7 +735,7 @@
 out:
 	if (doingdirectory)
 		ip->i_flag &= ~IN_RENAME;
-	if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
+	if (vn_lock(fvp, NULL, LK_EXCLUSIVE, td) == 0) {
 		ip->i_nlink--;
 		ip->i_flag |= IN_CHANGE;
 		ip->i_flag &= ~IN_RENAME;
@@ -965,7 +965,7 @@
 	dp->i_nlink--;
 	dp->i_flag |= IN_CHANGE;
 	cache_purge(dvp);
-	VOP_UNLOCK(dvp, 0, td);
+	VOP_UNLOCK(dvp, NULL, 0, td);
 	/*
 	 * Truncate inode.  The only stuff left
 	 * in the directory is "." and "..".  The
@@ -980,7 +980,7 @@
 	ip->i_nlink -= 2;
 	error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred, td);
 	cache_purge(ITOV(ip));
-	vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 out:
 	return (error);
 }
Index: vfs/gnu/ext2fs/fs.h
===================================================================
RCS file: /cvs/src/sys/vfs/gnu/ext2fs/fs.h,v
retrieving revision 1.3
diff -u -r1.3 fs.h
--- vfs/gnu/ext2fs/fs.h	26 Jun 2003 20:27:51 -0000	1.3
+++ vfs/gnu/ext2fs/fs.h	22 Feb 2004 05:55:02 -0000
@@ -154,8 +154,8 @@
  * I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
  */
 #define  DEVVP(inode)		(VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
-#define  lock_super(devvp)   	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curthread)
-#define  unlock_super(devvp) 	VOP_UNLOCK(devvp, 0, curthread)
+#define  lock_super(devvp)   	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, curthread)
+#define  unlock_super(devvp) 	VOP_UNLOCK(devvp, NULL, 0, curthread)
 
 /*
  * To lock a buffer, set the B_LOCKED flag and then brelse() it. To unlock,
Index: vfs/hpfs/hpfs.h
===================================================================
RCS file: /cvs/src/sys/vfs/hpfs/hpfs.h,v
retrieving revision 1.9
diff -u -r1.9 hpfs.h
--- vfs/hpfs/hpfs.h	5 Feb 2004 21:03:37 -0000	1.9
+++ vfs/hpfs/hpfs.h	22 Feb 2004 06:13:49 -0000
@@ -399,10 +399,10 @@
 #define	LOCKMGR(a, b, c, d)	lockmgr((a), (b), (c))
 #else  /* defined(__DragonFly__) */
 #define HASHINIT(a, b, c, d)	hashinit((a), (b), (d))
-#define VOP__LOCK(a, b, c)	VOP_LOCK((a), (b), (c))
-#define VOP__UNLOCK(a, b, c)	VOP_UNLOCK((a), (b), (c))
-#define VGET(a, b, c)		vget((a), (b), (c))
-#define VN_LOCK(a, b, c)	vn_lock((a), (b), (c))
+#define VOP__LOCK(a, b, c)	VOP_LOCK((a), NULL, (b), (c))
+#define VOP__UNLOCK(a, b, c)	VOP_UNLOCK((a), NULL, (b), (c))
+#define VGET(a, b, c)		vget((a), NULL, (b), (c))
+#define VN_LOCK(a, b, c)	vn_lock((a), NULL, (b), (c))
 #define	LOCKMGR(a, b, c, d)	lockmgr((a), (b), (c), (d))
 #endif
 
Index: vfs/hpfs/hpfs_hash.c
===================================================================
RCS file: /cvs/src/sys/vfs/hpfs/hpfs_hash.c,v
retrieving revision 1.9
diff -u -r1.9 hpfs_hash.c
--- vfs/hpfs/hpfs_hash.c	19 Oct 2003 21:24:55 -0000	1.9
+++ vfs/hpfs/hpfs_hash.c	22 Feb 2004 20:57:06 -0000
@@ -69,7 +69,7 @@
 	lockinit (&hpfs_hphash_lock, 0, "hpfs_hphashlock", 0, 0);
 	hpfs_hphashtbl = HASHINIT(desiredvnodes, M_HPFSHASH, M_WAITOK,
 	    &hpfs_hphash);
-	lwkt_inittoken(&hpfs_hphash_token);
+	lwkt_token_init(&hpfs_hphash_token);
 }
 
 /*
@@ -78,11 +78,12 @@
 int
 hpfs_hphash_uninit(struct vfsconf *vfc)
 {
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&hpfs_hphash_token);
+	lwkt_gettoken(&ilock, &hpfs_hphash_token);
 	if (hpfs_hphashtbl)
 		free(hpfs_hphashtbl, M_HPFSHASH);
-	lwkt_reltoken(&hpfs_hphash_token);
+	lwkt_reltoken(&ilock);
 
 	return 0;
 }
@@ -97,12 +98,14 @@
 	lsn_t ino;
 {
 	struct hpfsnode *hp;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&hpfs_hphash_token);
-	for (hp = HPNOHASH(dev, ino)->lh_first; hp; hp = hp->h_hash.le_next)
+	lwkt_gettoken(&ilock, &hpfs_hphash_token);
+	for (hp = HPNOHASH(dev, ino)->lh_first; hp; hp = hp->h_hash.le_next) {
 		if (ino == hp->h_no && dev == hp->h_dev)
 			break;
-	lwkt_reltoken(&hpfs_hphash_token);
+	}
+	lwkt_reltoken(&ilock);
 
 	return (hp);
 }
@@ -114,30 +117,40 @@
 	struct thread *td;
 {
 	struct hpfsnode *hp;
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 	struct vnode *vp;
-	int gen;
 
-	gen = lwkt_gettoken(&hpfs_hphash_token);
+	lwkt_gettoken(&ilock, &hpfs_hphash_token);
 loop:
 	for (hp = HPNOHASH(dev, ino)->lh_first; hp; hp = hp->h_hash.le_next) {
-		if (ino == hp->h_no && dev == hp->h_dev) {
-			vp = HPTOV(hp);
-			lwkt_gettoken (&vp->v_interlock);
-			if (lwkt_gentoken(&hpfs_hphash_token, &gen))
-				goto loop;
-			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-				gen = lwkt_regettoken(&hpfs_hphash_token);
-				goto loop;
-			}
-			if (lwkt_reltoken(&hpfs_hphash_token) != gen) {
-				vput(vp);
-				gen = lwkt_gettoken(&hpfs_hphash_token);
-				goto loop;
-			}
-			return (vp);
+		if (ino != hp->h_no || dev != hp->h_dev)
+			continue;
+		vp = HPTOV(hp);
+		lwkt_gettoken (&vlock, vp->v_interlock);
+
+		/*
+		 * We must check to see if the inode has been ripped
+		 * out from under us after blocking.
+		 */
+		for (hp = HPNOHASH(dev, ino)->lh_first; hp; hp = hp->h_hash.le_next) {
+			if (ino == hp->h_no && dev == hp->h_dev)
+				break;
+		}
+		if (hp == NULL || vp != HPTOV(hp)) {
+			lwkt_reltoken(&vlock);
+			goto loop;
 		}
+
+		/*
+		 * Or if the vget fails (due to a race)
+		 */
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td))
+			goto loop;
+		lwkt_reltoken(&ilock);
+		return (vp);
 	}
-	lwkt_reltoken(&hpfs_hphash_token);
+	lwkt_reltoken(&ilock);
 	return (NULLVP);
 }
 
@@ -149,12 +162,13 @@
 	struct hpfsnode *hp;
 {
 	struct hphashhead *hpp;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&hpfs_hphash_token);
+	lwkt_gettoken(&ilock, &hpfs_hphash_token);
 	hpp = HPNOHASH(hp->h_dev, hp->h_no);
 	hp->h_flag |= H_HASHED;
 	LIST_INSERT_HEAD(hpp, hp, h_hash);
-	lwkt_reltoken(&hpfs_hphash_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -164,7 +178,9 @@
 hpfs_hphashrem(hp)
 	struct hpfsnode *hp;
 {
-	lwkt_gettoken(&hpfs_hphash_token);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &hpfs_hphash_token);
 	if (hp->h_flag & H_HASHED) {
 		hp->h_flag &= ~H_HASHED;
 		LIST_REMOVE(hp, h_hash);
@@ -173,5 +189,5 @@
 		hp->h_hash.le_prev = NULL;
 #endif
 	}
-	lwkt_reltoken(&hpfs_hphash_token);
+	lwkt_reltoken(&ilock);
 }
Index: vfs/hpfs/hpfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/hpfs/hpfs_vfsops.c,v
retrieving revision 1.12
diff -u -r1.12 hpfs_vfsops.c
--- vfs/hpfs/hpfs_vfsops.c	5 Feb 2004 21:03:37 -0000	1.12
+++ vfs/hpfs/hpfs_vfsops.c	22 Feb 2004 07:20:18 -0000
@@ -668,7 +668,7 @@
 	if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 
 		vp->v_flag |= VROOT;
 
-	lwkt_inittoken(&hp->h_interlock);
+	lwkt_token_init(&hp->h_interlock);
 	lockinit(&hp->h_lock, 0, "hpnode", VLKTIMEOUT, 0);
 
 	hp->h_flag = H_INVAL;
Index: vfs/isofs/cd9660/cd9660_lookup.c
===================================================================
RCS file: /cvs/src/sys/vfs/isofs/cd9660/cd9660_lookup.c,v
retrieving revision 1.8
diff -u -r1.8 cd9660_lookup.c
--- vfs/isofs/cd9660/cd9660_lookup.c	9 Oct 2003 22:27:24 -0000	1.8
+++ vfs/isofs/cd9660/cd9660_lookup.c	22 Feb 2004 05:57:18 -0000
@@ -352,16 +352,16 @@
 	 * it's a relocated directory.
 	 */
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(pdp, 0, td);	/* race to get the inode */
+		VOP_UNLOCK(pdp, NULL, 0, td);	/* race to get the inode */
 		error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
 					     dp->i_ino != ino, ep);
 		brelse(bp);
 		if (error) {
-			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			return (error);
 		}
 		if (lockparent && (flags & CNP_ISLASTCN)) {
-			if ((error = vn_lock(pdp, LK_EXCLUSIVE, td)) != 0) {
+			if ((error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td)) != 0) {
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 				vput(tdp);
 				return (error);
@@ -381,7 +381,7 @@
 			return (error);
 		if (!lockparent || !(flags & CNP_ISLASTCN)) {
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
-			VOP_UNLOCK(pdp, 0, td);
+			VOP_UNLOCK(pdp, NULL, 0, td);
 		}
 		*vpp = tdp;
 	}
Index: vfs/isofs/cd9660/cd9660_node.c
===================================================================
RCS file: /cvs/src/sys/vfs/isofs/cd9660/cd9660_node.c,v
retrieving revision 1.8
diff -u -r1.8 cd9660_node.c
--- vfs/isofs/cd9660/cd9660_node.c	18 Oct 2003 20:15:06 -0000	1.8
+++ vfs/isofs/cd9660/cd9660_node.c	22 Feb 2004 21:37:24 -0000
@@ -75,7 +75,7 @@
 {
 
 	isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
-	lwkt_inittoken(&cd9660_ihash_token);
+	lwkt_token_init(&cd9660_ihash_token);
 	return (0);
 }
 
@@ -101,32 +101,35 @@
 {
 	struct thread *td = curthread;		/* XXX */
 	struct iso_node *ip;
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 	struct vnode *vp;
-	int gen;
 
-	gen = lwkt_gettoken(&cd9660_ihash_token);
+	lwkt_gettoken(&ilock, &cd9660_ihash_token);
 loop:
 	for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
-		if (inum == ip->i_number && dev == ip->i_dev) {
-			vp = ITOV(ip);
-			lwkt_gettoken(&vp->v_interlock); /* YYY */
-			if (lwkt_gentoken(&cd9660_ihash_token, &gen) != 0) {
-				lwkt_reltoken(&vp->v_interlock);
-				goto loop;
-			}
-			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-				lwkt_gentoken(&cd9660_ihash_token, &gen);
-				goto loop;
-			}
-			if (lwkt_reltoken(&cd9660_ihash_token) != gen) {
-				vput(vp);
-				gen = lwkt_gettoken(&cd9660_ihash_token);
-				goto loop;
-			}
-			return (vp);
+		if (inum != ip->i_number || dev != ip->i_dev)
+			continue;
+		vp = ITOV(ip);
+		lwkt_gettoken(&vlock, vp->v_interlock);
+		/*
+		 * We must check to see if the inode has been ripped
+		 * out from under us after blocking.
+		 */   
+		for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
+			if (inum == ip->i_number && dev == ip->i_dev)
+				break;
 		}
+		if (ip == NULL || ITOV(ip) != vp) {
+			lwkt_reltoken(&vlock);
+			goto loop;
+		}
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td))
+			goto loop;
+		lwkt_reltoken(&ilock);
+		return (vp);
 	}
-	lwkt_reltoken(&cd9660_ihash_token);
+	lwkt_reltoken(&ilock);
 	return (NULL);
 }
 
@@ -138,15 +141,16 @@
 {
 	struct thread *td = curthread;	/* XXX */
 	struct iso_node **ipp, *iq;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&cd9660_ihash_token);
+	lwkt_gettoken(&ilock, &cd9660_ihash_token);
 	ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
 	if ((iq = *ipp) != NULL)
 		iq->i_prev = &ip->i_next;
 	ip->i_next = iq;
 	ip->i_prev = ipp;
 	*ipp = ip;
-	lwkt_reltoken(&cd9660_ihash_token);
+	lwkt_reltoken(&ilock);
 
 	lockmgr(&ip->i_lock, LK_EXCLUSIVE, NULL, td);
 }
@@ -159,8 +163,9 @@
 	struct iso_node *ip;
 {
 	struct iso_node *iq;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&cd9660_ihash_token);
+	lwkt_gettoken(&ilock, &cd9660_ihash_token);
 	if ((iq = ip->i_next) != NULL)
 		iq->i_prev = ip->i_prev;
 	*ip->i_prev = iq;
@@ -168,7 +173,7 @@
 	ip->i_next = NULL;
 	ip->i_prev = NULL;
 #endif
-	lwkt_reltoken(&cd9660_ihash_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -191,7 +196,7 @@
 		vprint("cd9660_inactive: pushing active", vp);
 
 	ip->i_flag = 0;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	/*
 	 * If we are done with the inode, reclaim it
 	 * so that it can be reused immediately.
Index: vfs/isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.11
diff -u -r1.11 cd9660_vfsops.c
--- vfs/isofs/cd9660/cd9660_vfsops.c	23 Sep 2003 05:03:52 -0000	1.11
+++ vfs/isofs/cd9660/cd9660_vfsops.c	22 Feb 2004 05:57:25 -0000
@@ -150,9 +150,9 @@
 	}
 	args.flags = ISOFSMNT_ROOT;
 
-	vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(rootvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(rootvp, FREAD, FSCRED, td);
-	VOP_UNLOCK(rootvp, 0, td);
+	VOP_UNLOCK(rootvp, NULL, 0, td);
 	if (error)
 		return (error);
 
@@ -230,7 +230,7 @@
 	 * or has superuser abilities
 	 */
 	accessmode = VREAD;
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_ACCESS(devvp, accessmode, td->td_proc->p_ucred, td);
 	if (error) 
 		error = suser(td);
@@ -238,7 +238,7 @@
 		vput(devvp);
 		return (error);
 	}
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
 		error = iso_mountfs(devvp, mp, td, &args);
@@ -305,9 +305,9 @@
 	if ((error = vinvalbuf(devvp, V_SAVE, td, 0, 0)))
 		return (error);
 
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(devvp, FREAD, FSCRED, td);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return error;
 	if (devvp->v_rdev->si_iosize_max != 0)
Index: vfs/mfs/mfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/mfs/mfs_vnops.c,v
retrieving revision 1.10
diff -u -r1.10 mfs_vnops.c
--- vfs/mfs/mfs_vnops.c	20 Aug 2003 09:56:32 -0000	1.10
+++ vfs/mfs/mfs_vnops.c	22 Feb 2004 05:39:33 -0000
@@ -374,7 +374,7 @@
 	if (bufq_first(&mfsp->buf_queue) != NULL)
 		panic("mfs_inactive: not inactive (next buffer %p)",
 			bufq_first(&mfsp->buf_queue));
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/msdosfs/msdosfs_denode.c
===================================================================
RCS file: /cvs/src/sys/vfs/msdosfs/msdosfs_denode.c,v
retrieving revision 1.9
diff -u -r1.9 msdosfs_denode.c
--- vfs/msdosfs/msdosfs_denode.c	18 Oct 2003 20:15:08 -0000	1.9
+++ vfs/msdosfs/msdosfs_denode.c	22 Feb 2004 21:37:37 -0000
@@ -104,7 +104,7 @@
 	struct vfsconf *vfsp;
 {
 	dehashtbl = hashinit(desiredvnodes/2, M_MSDOSFSMNT, &dehash);
-	lwkt_inittoken(&dehash_token);
+	lwkt_token_init(&dehash_token);
 	return (0);
 }
 
@@ -126,35 +126,43 @@
 {
 	struct thread *td = curthread;	/* XXX */
 	struct denode *dep;
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 	struct vnode *vp;
-	int gen;
 
-	gen = lwkt_gettoken(&dehash_token);
+	lwkt_gettoken(&ilock, &dehash_token);
 loop:
 	for (dep = DEHASH(dev, dirclust, diroff); dep; dep = dep->de_next) {
-		if (dirclust == dep->de_dirclust
-		    && diroff == dep->de_diroffset
-		    && dev == dep->de_dev
-		    && dep->de_refcnt != 0) {
-			vp = DETOV(dep);
-			lwkt_gettoken(&vp->v_interlock);
-			if (lwkt_gentoken(&dehash_token, &gen) != 0) {
-				lwkt_reltoken(&vp->v_interlock);
-				goto loop;
-			}
-			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-				lwkt_gentoken(&dehash_token, &gen);
-				goto loop;
-			}
-			if (lwkt_reltoken(&dehash_token) != gen) {
-				vput(vp);
-				gen = lwkt_gettoken(&dehash_token);
-				goto loop;
+		if (dirclust != dep->de_dirclust
+		    || diroff != dep->de_diroffset
+		    || dev != dep->de_dev
+		    || dep->de_refcnt == 0) {
+			continue;
+		}
+		vp = DETOV(dep);
+		lwkt_gettoken(&vlock, vp->v_interlock);
+		/*
+		 * We must check to see if the inode has been ripped
+		 * out from under us after blocking.
+		 */
+		for (dep = DEHASH(dev, dirclust, diroff); dep; dep = dep->de_next) {
+			if (dirclust == dep->de_dirclust
+			    && diroff == dep->de_diroffset
+			    && dev == dep->de_dev
+			    && dep->de_refcnt != 0) {
+				break;
 			}
-			return (dep);
 		}
+		if (dep == NULL || DETOV(dep) != vp) {
+			lwkt_reltoken(&vlock);
+			goto loop;
+		}
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td))
+			goto loop;
+		lwkt_reltoken(&ilock);
+		return (dep);
 	}
-	lwkt_reltoken(&dehash_token);
+	lwkt_reltoken(&ilock);
 	return (NULL);
 }
 
@@ -163,8 +171,9 @@
 	struct denode *dep;
 {
 	struct denode **depp, *deq;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&dehash_token);
+	lwkt_gettoken(&ilock, &dehash_token);
 	depp = &DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset);
 	deq = *depp;
 	if (deq)
@@ -172,7 +181,7 @@
 	dep->de_next = deq;
 	dep->de_prev = depp;
 	*depp = dep;
-	lwkt_reltoken(&dehash_token);
+	lwkt_reltoken(&ilock);
 }
 
 static void
@@ -180,8 +189,9 @@
 	struct denode *dep;
 {
 	struct denode *deq;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&dehash_token);
+	lwkt_gettoken(&ilock, &dehash_token);
 	deq = dep->de_next;
 	if (deq)
 		deq->de_prev = dep->de_prev;
@@ -190,7 +200,7 @@
 	dep->de_next = NULL;
 	dep->de_prev = NULL;
 #endif
-	lwkt_reltoken(&dehash_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -723,7 +733,7 @@
 	deupdat(dep, 0);
 
 out:
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 	/*
 	 * If we are done with the denode, reclaim it
 	 * so that it can be reused immediately.
Index: vfs/msdosfs/msdosfs_lookup.c
===================================================================
RCS file: /cvs/src/sys/vfs/msdosfs/msdosfs_lookup.c,v
retrieving revision 1.7
diff -u -r1.7 msdosfs_lookup.c
--- vfs/msdosfs/msdosfs_lookup.c	9 Oct 2003 22:27:26 -0000	1.7
+++ vfs/msdosfs/msdosfs_lookup.c	22 Feb 2004 05:57:31 -0000
@@ -366,7 +366,7 @@
 		 */
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (EJUSTRETURN);
@@ -457,7 +457,7 @@
 			return (error);
 		*vpp = DETOV(tdp);
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (0);
@@ -490,7 +490,7 @@
 		*vpp = DETOV(tdp);
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (0);
@@ -517,16 +517,16 @@
 	 */
 	pdp = vdp;
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(pdp, 0, td);
+		VOP_UNLOCK(pdp, NULL, 0, td);
 		cnp->cn_flags |= CNP_PDIRUNLOCK;
 		error = deget(pmp, cluster, blkoff,  &tdp);
 		if (error) {
-			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td); 
+			vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td); 
 			cnp->cn_flags &= ~CNP_PDIRUNLOCK;
 			return (error);
 		}
 		if (lockparent && (flags & CNP_ISLASTCN)) {
-			error = vn_lock(pdp, LK_EXCLUSIVE, td);
+			error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td);
 			if (error) {
 				vput(DETOV(tdp));
 				return (error);
@@ -541,7 +541,7 @@
 		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
 			return (error);
 		if (!lockparent || !(flags & CNP_ISLASTCN)) {
-			VOP_UNLOCK(pdp, 0, td);
+			VOP_UNLOCK(pdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		*vpp = DETOV(tdp);
Index: vfs/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.10
diff -u -r1.10 msdosfs_vfsops.c
--- vfs/msdosfs/msdosfs_vfsops.c	5 Feb 2004 21:03:37 -0000	1.10
+++ vfs/msdosfs/msdosfs_vfsops.c	22 Feb 2004 22:07:38 -0000
@@ -271,14 +271,14 @@
 			 */
 			if (p->p_ucred->cr_uid != 0) {
 				devvp = pmp->pm_devvp;
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+				vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				error = VOP_ACCESS(devvp, VREAD | VWRITE,
 						   p->p_ucred, td);
 				if (error) {
-					VOP_UNLOCK(devvp, 0, td);
+					VOP_UNLOCK(devvp, NULL, 0, td);
 					return (error);
 				}
-				VOP_UNLOCK(devvp, 0, td);
+				VOP_UNLOCK(devvp, NULL, 0, td);
 			}
 			pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
 		}
@@ -320,13 +320,13 @@
 		accessmode = VREAD;
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			accessmode |= VWRITE;
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		error = VOP_ACCESS(devvp, accessmode, p->p_ucred, td);
 		if (error) {
 			vput(devvp);
 			return (error);
 		}
-		VOP_UNLOCK(devvp, 0, td);
+		VOP_UNLOCK(devvp, NULL, 0, td);
 	}
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
 		error = mountmsdosfs(devvp, mp, td, &args);
@@ -395,16 +395,16 @@
 		return (error);
 	if (vcount(devvp) > 1 && devvp != rootvp)
 		return (EBUSY);
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = vinvalbuf(devvp, V_SAVE, td, 0, 0);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return (error);
 
 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return (error);
 
@@ -846,17 +846,25 @@
 	return (0);
 }
 
+struct scaninfo {
+	int rescan;
+	int allerror;
+	int waitfor;
+	thread_t td;
+};
+
+static int msdosfs_sync_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data);
+
 static int
 msdosfs_sync(mp, waitfor, td)
 	struct mount *mp;
 	int waitfor;
 	struct thread *td;
 {
-	struct vnode *vp, *nvp;
-	struct denode *dep;
 	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
-	int error, allerror = 0;
-	int gen;
+	struct scaninfo scaninfo;
+	int error;
 
 	/*
 	 * If we ever switch to not updating all of the fats all the time,
@@ -871,63 +879,53 @@
 	}
 	/*
 	 * Write back each (modified) denode.
-	 *
-	 * YYY gen number handling needs more work.
 	 */
-	gen = lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-		lwkt_gettoken(&vp->v_interlock);
-		/*
-		 * If the vnode that we are about to sync is no longer
-		 * associated with this mount point, start over.  If
-		 * we lost the mntvnode token, start over.
-		 */
-		if (vp->v_mount != mp) {
-			lwkt_reltoken(&vp->v_interlock);
-			goto loop;
-		}
-		if (lwkt_gentoken(&mntvnode_token, &gen) != 0) {
-			lwkt_reltoken(&vp->v_interlock);
-			goto loop;
-		}
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		dep = VTODE(vp);
-		if (vp->v_type == VNON ||
-		    ((dep->de_flag &
-		    (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 &&
-		    (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) {
-			lwkt_reltoken(&vp->v_interlock);
-			continue;
-		}
-		lwkt_reltoken(&mntvnode_token);
-		error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
-		if (error) {
-			lwkt_gettoken(&mntvnode_token);
-			if (error == ENOENT)
-				goto loop;
-			continue;
-		}
-		error = VOP_FSYNC(vp, waitfor, td);
-		if (error)
-			allerror = error;
-		VOP_UNLOCK(vp, 0, td);
-		vrele(vp);
-		lwkt_gettoken(&mntvnode_token);
+	scaninfo.allerror = 0;
+	scaninfo.rescan = 1;
+	scaninfo.td = td;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		vmntvnodescan(mp, NULL, msdosfs_sync_scan, &scaninfo);
 	}
-	lwkt_reltoken(&mntvnode_token);
 
 	/*
 	 * Flush filesystem control info.
 	 */
 	if (waitfor != MNT_LAZY) {
-		vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY, td);
-		error = VOP_FSYNC(pmp->pm_devvp, waitfor, td);
-		if (error)
-			allerror = error;
-		VOP_UNLOCK(pmp->pm_devvp, 0, td);
+		vn_lock(pmp->pm_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+		if ((error = VOP_FSYNC(pmp->pm_devvp, waitfor, td)) != 0)
+			scaninfo.allerror = error;
+		VOP_UNLOCK(pmp->pm_devvp, NULL, 0, td);
 	}
-	return (allerror);
+	return (scaninfo.allerror);
+}
+
+static int msdosfs_sync_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct denode *dep;
+	int error;
+
+	dep = VTODE(vp);
+	if (vp->v_type == VNON ||
+	    ((dep->de_flag &
+	    (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 &&
+	    (TAILQ_EMPTY(&vp->v_dirtyblkhd) || info->waitfor == MNT_LAZY))) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+	error = vget(vp, vlock, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, info->td);
+	if (error) {
+		if (error == ENOENT)
+			info->rescan = 1;
+		return(0);
+	}
+	if ((error = VOP_FSYNC(vp, info->waitfor, info->td)) != 0)
+		info->allerror = error;
+	VOP_UNLOCK(vp, NULL, 0, info->td);
+	vrele(vp);
+	return(0);
 }
 
 static int
Index: vfs/msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.12
diff -u -r1.12 msdosfs_vnops.c
--- vfs/msdosfs/msdosfs_vnops.c	23 Sep 2003 05:03:52 -0000	1.12
+++ vfs/msdosfs/msdosfs_vnops.c	22 Feb 2004 19:07:23 -0000
@@ -233,16 +233,16 @@
 	struct vnode *vp = ap->a_vp;
 	struct denode *dep = VTODE(vp);
 	struct timespec ts;
+	lwkt_tokref vlock;
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (vp->v_usecount > 1) {
 		getnanotime(&ts);
-		lwkt_regettoken(&vp->v_interlock);
 		if (vp->v_usecount > 1) {
 			DETIMES(dep, &ts, &ts, &ts);
 		}
 	}
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	return 0;
 }
 
@@ -1050,7 +1050,7 @@
 		goto abortit;
 	}
 
-	error = vn_lock(fvp, LK_EXCLUSIVE, td);
+	error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td);
 	if (error)
 		goto abortit;
 	dp = VTODE(fdvp);
@@ -1071,7 +1071,7 @@
 		    (fcnp->cn_flags & CNP_ISDOTDOT) ||
 		    (tcnp->cn_flags & CNP_ISDOTDOT) ||
 		    (ip->de_flag & DE_RENAME)) {
-			VOP_UNLOCK(fvp, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			error = EINVAL;
 			goto abortit;
 		}
@@ -1102,7 +1102,7 @@
 	 * call to doscheckpath().
 	 */
 	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td);
-	VOP_UNLOCK(fvp, 0, td);
+	VOP_UNLOCK(fvp, NULL, 0, td);
 	if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster)
 		newparent = 1;
 	if (doingdirectory && newparent) {
@@ -1171,7 +1171,7 @@
 	if ((fcnp->cn_flags & CNP_SAVESTART) == 0)
 		panic("msdosfs_rename: lost from startdir");
 	if (!newparent)
-		VOP_UNLOCK(tdvp, 0, td);
+		VOP_UNLOCK(tdvp, NULL, 0, td);
 	if (relookup(fdvp, &fvp, fcnp) == 0)
 		vrele(fdvp);
 	if (fvp == NULL) {
@@ -1182,7 +1182,7 @@
 			panic("rename: lost dir entry");
 		vrele(ap->a_fvp);
 		if (newparent)
-			VOP_UNLOCK(tdvp, 0, td);
+			VOP_UNLOCK(tdvp, NULL, 0, td);
 		vrele(tdvp);
 		return 0;
 	}
@@ -1202,9 +1202,9 @@
 		if (doingdirectory)
 			panic("rename: lost dir entry");
 		vrele(ap->a_fvp);
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		if (newparent)
-			VOP_UNLOCK(fdvp, 0, td);
+			VOP_UNLOCK(fdvp, NULL, 0, td);
 		xp = NULL;
 	} else {
 		vrele(fvp);
@@ -1226,8 +1226,8 @@
 		if (error) {
 			bcopy(oldname, ip->de_Name, 11);
 			if (newparent)
-				VOP_UNLOCK(fdvp, 0, td);
-			VOP_UNLOCK(fvp, 0, td);
+				VOP_UNLOCK(fdvp, NULL, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			goto bad;
 		}
 		ip->de_refcnt++;
@@ -1236,8 +1236,8 @@
 		if (error) {
 			/* XXX should really panic here, fs is corrupt */
 			if (newparent)
-				VOP_UNLOCK(fdvp, 0, td);
-			VOP_UNLOCK(fvp, 0, td);
+				VOP_UNLOCK(fdvp, NULL, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			goto bad;
 		}
 		if (!doingdirectory) {
@@ -1246,8 +1246,8 @@
 			if (error) {
 				/* XXX should really panic here, fs is corrupt */
 				if (newparent)
-					VOP_UNLOCK(fdvp, 0, td);
-				VOP_UNLOCK(fvp, 0, td);
+					VOP_UNLOCK(fdvp, NULL, 0, td);
+				VOP_UNLOCK(fvp, NULL, 0, td);
 				goto bad;
 			}
 			if (ip->de_dirclust == MSDOSFSROOT)
@@ -1257,7 +1257,7 @@
 		}
 		reinsert(ip);
 		if (newparent)
-			VOP_UNLOCK(fdvp, 0, td);
+			VOP_UNLOCK(fdvp, NULL, 0, td);
 	}
 
 	/*
@@ -1275,7 +1275,7 @@
 		if (error) {
 			/* XXX should really panic here, fs is corrupt */
 			brelse(bp);
-			VOP_UNLOCK(fvp, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			goto bad;
 		}
 		dotdotp = (struct direntry *)bp->b_data + 1;
@@ -1285,12 +1285,12 @@
 		error = bwrite(bp);
 		if (error) {
 			/* XXX should really panic here, fs is corrupt */
-			VOP_UNLOCK(fvp, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			goto bad;
 		}
 	}
 
-	VOP_UNLOCK(fvp, 0, td);
+	VOP_UNLOCK(fvp, NULL, 0, td);
 bad:
 	if (xp)
 		vput(tvp);
@@ -1489,14 +1489,14 @@
 	 * the name cache.
 	 */
 	cache_purge(dvp);
-	VOP_UNLOCK(dvp, 0, td);
+	VOP_UNLOCK(dvp, NULL, 0, td);
 	/*
 	 * Truncate the directory that is being deleted.
 	 */
 	error = detrunc(ip, (u_long)0, IO_SYNC, td);
 	cache_purge(vp);
 
-	vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 out:
 	return (error);
 }
Index: vfs/nfs/nfs_node.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_node.c,v
retrieving revision 1.8
diff -u -r1.8 nfs_node.c
--- vfs/nfs/nfs_node.c	10 Oct 2003 22:01:13 -0000	1.8
+++ vfs/nfs/nfs_node.c	22 Feb 2004 06:14:58 -0000
@@ -112,7 +112,7 @@
 		    bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
 			continue;
 		vp = NFSTOV(np);
-		if (vget(vp, LK_EXCLUSIVE|LK_SLEEPFAIL, td))
+		if (vget(vp, NULL, LK_EXCLUSIVE|LK_SLEEPFAIL, td))
 			goto loop;
 		*npp = np;
 		return(0);
@@ -182,7 +182,7 @@
 	/*
 	 * Lock the new nfsnode.
 	 */
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	return (0);
 }
@@ -215,7 +215,7 @@
 		 */
 		if (ap->a_vp->v_usecount > 0)
 			(void) nfs_vinvalbuf(ap->a_vp, 0, ap->a_td, 1);
-		else if (vget(ap->a_vp, 0, ap->a_td))
+		else if (vget(ap->a_vp, NULL, 0, ap->a_td))
 			panic("nfs_inactive: lost vnode");
 		else {
 			(void) nfs_vinvalbuf(ap->a_vp, 0, ap->a_td, 1);
@@ -231,7 +231,7 @@
 	}
 	np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
 		NQNFSNONCACHE | NQNFSWRITE);
-	VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/nfs/nfs_nqlease.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_nqlease.c,v
retrieving revision 1.13
diff -u -r1.13 nfs_nqlease.c
--- vfs/nfs/nfs_nqlease.c	15 Nov 2003 21:05:44 -0000	1.13
+++ vfs/nfs/nfs_nqlease.c	22 Feb 2004 06:15:06 -0000
@@ -1081,7 +1081,7 @@
 			vp = NFSTOV(np);
 			vpid = vp->v_id;
 			if (np->n_expiry < time_second) {
-			   if (vget(vp, LK_EXCLUSIVE, td) == 0) {
+			   if (vget(vp, NULL, LK_EXCLUSIVE, td) == 0) {
 			     nmp->nm_inprog = vp;
 			     if (vpid == vp->v_id) {
 				CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
@@ -1108,7 +1108,7 @@
 			    if ((np->n_flag & (NQNFSWRITE | NQNFSNONCACHE))
 				 == NQNFSWRITE &&
 				 !TAILQ_EMPTY(&vp->v_dirtyblkhd) &&
-				 vget(vp, LK_EXCLUSIVE, td) == 0) {
+				 vget(vp, NULL, LK_EXCLUSIVE, td) == 0) {
 				 nmp->nm_inprog = vp;
 				 if (vpid == vp->v_id &&
 				     nqnfs_getlease(vp, ND_WRITE, td)==0)
@@ -1176,6 +1176,7 @@
 	struct nfsnode *np;
 	struct mount *mp, *nxtmp;
 	struct nfsmount *nmp;
+	lwkt_tokref ilock;
 	int s;
 
 	if (nqnfsstarttime != 0)
@@ -1190,9 +1191,9 @@
 	 * Search the mount list for all nqnfs mounts and do their timer
 	 * queues.
 	 */
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nxtmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
 			nxtmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
@@ -1206,11 +1207,11 @@
 				}
 			}
 		}
-		lwkt_gettoken(&mountlist_token);
+		lwkt_gettokref(&ilock);
 		nxtmp = TAILQ_NEXT(mp, mnt_list);
 		vfs_unbusy(mp, td);
 	}
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 }
 
 #ifndef NFS_NOSERVER 
Index: vfs/nfs/nfs_serv.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_serv.c,v
retrieving revision 1.12
diff -u -r1.12 nfs_serv.c
--- vfs/nfs/nfs_serv.c	30 Jan 2004 06:18:28 -0000	1.12
+++ vfs/nfs/nfs_serv.c	22 Feb 2004 05:58:05 -0000
@@ -529,7 +529,7 @@
 			 * via the original nd.  Confused?  You aren't alone!
 			 */
 			ind = nd;
-			VOP_UNLOCK(nd.ni_vp, 0, td);
+			VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
 			ind.ni_pathlen = strlen(nfs_pub.np_index);
 			ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
 			    nfs_pub.np_index;
@@ -3030,7 +3030,7 @@
 		error = 0;
 		goto nfsmout;
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 
 	/*
 	 * end section.  Allocate rbuf and continue
@@ -3047,7 +3047,7 @@
 	io.uio_rw = UIO_READ;
 	io.uio_td = NULL;
 	eofflag = 0;
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (cookies) {
 		free((caddr_t)cookies, M_TEMP);
 		cookies = NULL;
@@ -3061,7 +3061,7 @@
 		if (!error)
 			error = getret;
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (error) {
 		vrele(vp);
 		vp = NULL;
@@ -3315,7 +3315,7 @@
 		error = 0;
 		goto nfsmout;
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 again:
 	iv.iov_base = rbuf;
@@ -3328,7 +3328,7 @@
 	io.uio_rw = UIO_READ;
 	io.uio_td = NULL;
 	eofflag = 0;
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	if (cookies) {
 		free((caddr_t)cookies, M_TEMP);
 		cookies = NULL;
@@ -3336,7 +3336,7 @@
 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
 	off = (u_quad_t)io.uio_offset;
 	getret = VOP_GETATTR(vp, &at, td);
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (!cookies && !error)
 		error = NFSERR_PERM;
 	if (!error)
Index: vfs/nfs/nfs_subs.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_subs.c,v
retrieving revision 1.11
diff -u -r1.11 nfs_subs.c
--- vfs/nfs/nfs_subs.c	21 Dec 2003 12:34:08 -0000	1.11
+++ vfs/nfs/nfs_subs.c	22 Feb 2004 19:56:44 -0000
@@ -1651,7 +1651,7 @@
 		 * Validate symlink
 		 */
 		if ((cnp->cn_flags & CNP_LOCKPARENT) && ndp->ni_pathlen == 1)
-			VOP_UNLOCK(ndp->ni_dvp, 0, td);
+			VOP_UNLOCK(ndp->ni_dvp, NULL, 0, td);
 		if (!pubflag) {
 			error = EINVAL;
 			goto badlink2;
@@ -1990,7 +1990,7 @@
 	nfsrv_object_create(*vpp);
 
 	if (!lockflag)
-		VOP_UNLOCK(*vpp, 0, td);
+		VOP_UNLOCK(*vpp, NULL, 0, td);
 	return (0);
 }
 
@@ -2143,9 +2143,11 @@
 	s = splbio();
 loop:
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp; vp = nvp) {
+		nvp = TAILQ_NEXT(vp, v_nmntvnodes);	/* ZZZ */
+		if (vp->v_flag & VPLACEMARKER)
+			continue;
 		if (vp->v_mount != mp)	/* Paranoia */
 			goto loop;
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
 		for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
 			nbp = TAILQ_NEXT(bp, b_vnbufs);
 			if (BUF_REFCNT(bp) == 0 &&
Index: vfs/nfs/nfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_vfsops.c,v
retrieving revision 1.12
diff -u -r1.12 nfs_vfsops.c
--- vfs/nfs/nfs_vfsops.c	24 Feb 2004 19:22:38 -0000	1.12
+++ vfs/nfs/nfs_vfsops.c	25 Feb 2004 18:12:25 -0000
@@ -945,7 +945,7 @@
 	/*
 	 * Lose the lock but keep the ref.
 	 */
-	VOP_UNLOCK(*vpp, 0, curthread);
+	VOP_UNLOCK(*vpp, NULL, 0, curthread);
 
 	return (0);
 bad:
@@ -1062,6 +1062,8 @@
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 	     vp != NULL;
 	     vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
+		if (vp->v_flag & VPLACEMARKER)	/* ZZZ */
+			continue;
 		/*
 		 * If the vnode that we are about to sync is no longer
 		 * associated with this mount point, start over.
@@ -1071,7 +1073,7 @@
 		if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
 		    waitfor == MNT_LAZY)
 			continue;
-		if (vget(vp, LK_EXCLUSIVE, td))
+		if (vget(vp, NULL, LK_EXCLUSIVE, td))
 			goto loop;
 		error = VOP_FSYNC(vp, waitfor, td);
 		if (error)
Index: vfs/nfs/nfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nfs/nfs_vnops.c,v
retrieving revision 1.18
diff -u -r1.18 nfs_vnops.c
--- vfs/nfs/nfs_vnops.c	8 Feb 2004 05:27:42 -0000	1.18
+++ vfs/nfs/nfs_vnops.c	22 Feb 2004 06:15:15 -0000
@@ -888,14 +888,14 @@
 			VREF(newvp);
 			error = 0;
 		} else if (flags & CNP_ISDOTDOT) {
-			VOP_UNLOCK(dvp, 0, td);
-			error = vget(newvp, LK_EXCLUSIVE, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
+			error = vget(newvp, NULL, LK_EXCLUSIVE, td);
 			if (!error && lockparent && (flags & CNP_ISLASTCN))
-				error = vn_lock(dvp, LK_EXCLUSIVE, td);
+				error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		} else {
-			error = vget(newvp, LK_EXCLUSIVE, td);
+			error = vget(newvp, NULL, LK_EXCLUSIVE, td);
 			if (!lockparent || error || !(flags & CNP_ISLASTCN))
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 		}
 		if (!error) {
 			if (vpid == newvp->v_id) {
@@ -911,9 +911,9 @@
 			}
 			vput(newvp);
 			if (lockparent && dvp != newvp && (flags & CNP_ISLASTCN))
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 		}
-		error = vn_lock(dvp, LK_EXCLUSIVE, td);
+		error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		*vpp = NULLVP;
 		if (error)
 			return (error);
@@ -958,20 +958,20 @@
 		m_freem(mrep);
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent)
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 		return (0);
 	}
 
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(dvp, 0, td);
+		VOP_UNLOCK(dvp, NULL, 0, td);
 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
 		if (error) {
-			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			return (error);
 		}
 		newvp = NFSTOV(np);
 		if (lockparent && (flags & CNP_ISLASTCN) &&
-		    (error = vn_lock(dvp, LK_EXCLUSIVE, td))) {
+		    (error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td))) {
 		    	vput(newvp);
 			return (error);
 		}
@@ -985,7 +985,7 @@
 			return (error);
 		}
 		if (!lockparent || !(flags & CNP_ISLASTCN))
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 		newvp = NFSTOV(np);
 	}
 	if (v3) {
@@ -1011,7 +1011,7 @@
 		if ((cnp->cn_nameiop == NAMEI_CREATE || cnp->cn_nameiop == NAMEI_RENAME) &&
 		    (flags & CNP_ISLASTCN) && error == ENOENT) {
 			if (!lockparent)
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
 				error = EROFS;
 			else
Index: vfs/ntfs/ntfs.h
===================================================================
RCS file: /cvs/src/sys/vfs/ntfs/ntfs.h,v
retrieving revision 1.3
diff -u -r1.3 ntfs.h
--- vfs/ntfs/ntfs.h	20 Aug 2003 09:56:33 -0000	1.3
+++ vfs/ntfs/ntfs.h	22 Feb 2004 06:15:20 -0000
@@ -314,9 +314,9 @@
 #define	LOCKMGR(a, b, c)	lockmgr((a), (b), (c))
 #else /* !NetBSD */
 #define HASHINIT(a, b, c, d)	hashinit((a), (b), (d))
-#define VOP__UNLOCK(a, b, c)	VOP_UNLOCK((a), (b), (c))
-#define VGET(a, b, c)		vget((a), (b), (c))
-#define VN_LOCK(a, b, c)	vn_lock((a), (b), (c))
+#define VOP__UNLOCK(a, b, c)	VOP_UNLOCK((a), NULL, (b), (c))
+#define VGET(a, b, c)		vget((a), NULL, (b), (c))
+#define VN_LOCK(a, b, c)	vn_lock((a), NULL, (b), (c))
 #define	LOCKMGR(a, b, c)	lockmgr((a), (b), (c), NULL)
 
 #endif /* NetBSD */
Index: vfs/ntfs/ntfs_ihash.c
===================================================================
RCS file: /cvs/src/sys/vfs/ntfs/ntfs_ihash.c,v
retrieving revision 1.7
diff -u -r1.7 ntfs_ihash.c
--- vfs/ntfs/ntfs_ihash.c	29 Dec 2003 18:04:59 -0000	1.7
+++ vfs/ntfs/ntfs_ihash.c	22 Feb 2004 07:20:24 -0000
@@ -70,7 +70,7 @@
 	lockinit(&ntfs_hashlock, 0, "ntfs_nthashlock", 0, 0);
 	ntfs_nthashtbl = HASHINIT(desiredvnodes, M_NTFSNTHASH, M_WAITOK,
 	    &ntfs_nthash);
-	lwkt_inittoken(&ntfs_nthash_slock);
+	lwkt_token_init(&ntfs_nthash_slock);
 }
 
 /*
@@ -79,10 +79,12 @@
 int
 ntfs_nthash_uninit(struct vfsconf *vfc)
 {
-	lwkt_gettoken(&ntfs_nthash_slock);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &ntfs_nthash_slock);
 	if (ntfs_nthashtbl)
 		free(ntfs_nthashtbl, M_NTFSNTHASH);
-	lwkt_reltoken(&ntfs_nthash_slock);
+	lwkt_reltoken(&ilock);
 
 	return 0;
 }
@@ -97,13 +99,14 @@
 	ino_t inum;
 {
 	struct ntnode *ip;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&ntfs_nthash_slock);
+	lwkt_gettoken(&ilock, &ntfs_nthash_slock);
 	for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
 		if (inum == ip->i_number && dev == ip->i_dev)
 			break;
 	}
-	lwkt_reltoken(&ntfs_nthash_slock);
+	lwkt_reltoken(&ilock);
 
 	return (ip);
 }
@@ -116,12 +119,13 @@
 	struct ntnode *ip;
 {
 	struct nthashhead *ipp;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&ntfs_nthash_slock);
+	lwkt_gettoken(&ilock, &ntfs_nthash_slock);
 	ipp = NTNOHASH(ip->i_dev, ip->i_number);
 	LIST_INSERT_HEAD(ipp, ip, i_hash);
 	ip->i_flag |= IN_HASHED;
-	lwkt_reltoken(&ntfs_nthash_slock);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -131,7 +135,9 @@
 ntfs_nthashrem(ip)
 	struct ntnode *ip;
 {
-	lwkt_gettoken(&ntfs_nthash_slock);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &ntfs_nthash_slock);
 	if (ip->i_flag & IN_HASHED) {
 		ip->i_flag &= ~IN_HASHED;
 		LIST_REMOVE(ip, i_hash);
@@ -140,5 +146,5 @@
 		ip->i_hash.le_prev = NULL;
 #endif
 	}
-	lwkt_reltoken(&ntfs_nthash_slock);
+	lwkt_reltoken(&ilock);
 }
Index: vfs/ntfs/ntfs_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/ntfs/ntfs_subr.c,v
retrieving revision 1.10
diff -u -r1.10 ntfs_subr.c
--- vfs/ntfs/ntfs_subr.c	5 Feb 2004 21:03:37 -0000	1.10
+++ vfs/ntfs/ntfs_subr.c	22 Feb 2004 07:20:26 -0000
@@ -356,12 +356,14 @@
 ntfs_ntget(ip)
 	struct ntnode *ip;
 {
+	lwkt_tokref ilock;
+
 	dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
 		ip->i_number, ip, ip->i_usecount));
 
-	ip->i_usecount++;
-	lwkt_gettoken(&ip->i_interlock);
-	LOCKMGR(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ip->i_interlock);
+	ip->i_usecount++;	/* ZZZ */
+	lwkt_gettoken(&ilock, &ip->i_interlock);
+	LOCKMGR(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ilock);
 
 	return 0;
 }
@@ -409,7 +411,7 @@
 
 	/* init lock and lock the newborn ntnode */
 	lockinit(&ip->i_lock, 0, "ntnode", 0, LK_EXCLUSIVE);
-	lwkt_inittoken(&ip->i_interlock);
+	lwkt_token_init(&ip->i_interlock);
 	ntfs_ntget(ip);
 
 	ntfs_nthashins(ip);
@@ -435,11 +437,12 @@
 	struct ntnode *ip;
 {
 	struct ntvattr *vap;
+	lwkt_tokref ilock;
 
 	dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
 		ip->i_number, ip, ip->i_usecount));
 
-	lwkt_gettoken(&ip->i_interlock);
+	lwkt_gettoken(&ilock, &ip->i_interlock);
 	ip->i_usecount--;
 
 #ifdef DIAGNOSTIC
@@ -450,7 +453,7 @@
 #endif
 
 	if (ip->i_usecount > 0) {
-		LOCKMGR(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ip->i_interlock);
+		LOCKMGR(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ilock);
 		return;
 	}
 
@@ -465,7 +468,7 @@
 		LIST_REMOVE(vap,va_list);
 		ntfs_freentvattr(vap);
 	}
-	lwkt_reltoken(&ip->i_interlock);
+	lwkt_reltoken(&ilock);
 	vrele(ip->i_devvp);
 	FREE(ip, M_NTFSNTNODE);
 }
@@ -491,17 +494,19 @@
 ntfs_ntrele(ip)
 	struct ntnode *ip;
 {
+	lwkt_tokref ilock;
+
 	dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
 		ip->i_number, ip, ip->i_usecount));
 
-	lwkt_gettoken(&ip->i_interlock);
+	lwkt_gettoken(&ilock, &ip->i_interlock);
 	ip->i_usecount--;
 
 	if (ip->i_usecount < 0) {
 		panic("ntfs_ntrele: ino: %d usecount: %d \n",
 		      ip->i_number,ip->i_usecount);
 	}
-	lwkt_reltoken(&ip->i_interlock);
+	lwkt_reltoken(&ilock);
 }
 
 /*
Index: vfs/ntfs/ntfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/ntfs/ntfs_vfsops.c,v
retrieving revision 1.12
diff -u -r1.12 ntfs_vfsops.c
--- vfs/ntfs/ntfs_vfsops.c	5 Feb 2004 21:03:37 -0000	1.12
+++ vfs/ntfs/ntfs_vfsops.c	22 Feb 2004 05:56:51 -0000
@@ -167,8 +167,9 @@
 	struct mount *mp;
 	extern struct vnode *rootvp;
 	struct thread *td = curthread;	/* XXX */
-	int error;
 	struct ntfs_args args;
+	lwkt_tokref ilock;
+	int error;
 
 	if (root_device->dv_class != DV_DISK)
 		return (ENODEV);
@@ -197,9 +198,9 @@
 		return (error);
 	}
 
-	lwkt_gettoken(&mountlist_token);
+	lwkt_gettoken(&ilock, &mountlist_token);
 	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
-	lwkt_reltoken(&mountlist_token);
+	lwkt_reltoken(&ilock);
 	(void)ntfs_statfs(mp, &mp->mnt_stat, td);
 	vfs_unbusy(mp);
 	return (0);
@@ -983,6 +984,7 @@
 	ntfs_ntput(ip);
 
 	if (lkflags & LK_TYPE_MASK) {
+		KKASSERT((lkflags & LK_INTERLOCK) == 0);
 		error = VN_LOCK(vp, lkflags, td);
 		if (error) {
 			vput(vp);
Index: vfs/nullfs/null_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/nullfs/null_subr.c,v
retrieving revision 1.6
diff -u -r1.6 null_subr.c
--- vfs/nullfs/null_subr.c	28 Aug 2003 02:03:18 -0000	1.6
+++ vfs/nullfs/null_subr.c	22 Feb 2004 06:15:43 -0000
@@ -131,11 +131,11 @@
 			 * stuff, but we don't want to lock
 			 * the lower node.
 			 */
-			if (vget(vp, LK_EXCLUSIVE | LK_CANRECURSE, td)) {
+			if (vget(vp, NULL, LK_EXCLUSIVE | LK_CANRECURSE, td)) {
 				printf ("null_node_find: vget failed.\n");
 				goto loop;
 			}
-			VOP_UNLOCK(lowervp, 0, td);
+			VOP_UNLOCK(lowervp, NULL, 0, td);
 			return (vp);
 		}
 	}
@@ -219,7 +219,7 @@
 
 	lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, td);
 	vp->v_vnlock = lowervp->v_vnlock;
-	error = VOP_LOCK(vp, LK_EXCLUSIVE | LK_THISLAYER, td);
+	error = VOP_LOCK(vp, NULL, LK_EXCLUSIVE | LK_THISLAYER, td);
 	if (error)
 		panic("null_node_alloc: can't lock new vnode\n");
 
Index: vfs/nullfs/null_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nullfs/null_vfsops.c,v
retrieving revision 1.6
diff -u -r1.6 null_vfsops.c
--- vfs/nullfs/null_vfsops.c	23 Sep 2003 05:03:53 -0000	1.6
+++ vfs/nullfs/null_vfsops.c	22 Feb 2004 05:58:37 -0000
@@ -118,7 +118,7 @@
 	 */
 	if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) &&
 		VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) {
-		VOP_UNLOCK(mp->mnt_vnodecovered, 0, td);
+		VOP_UNLOCK(mp->mnt_vnodecovered, NULL, 0, td);
 		isvnunlocked = 1;
 	}
 	/*
@@ -131,7 +131,7 @@
 	 * Re-lock vnode.
 	 */
 	if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL))
-		vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(mp->mnt_vnodecovered, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	if (error)
 		return (error);
@@ -170,7 +170,7 @@
 	/*
 	 * Unlock the node (either the lower or the alias)
 	 */
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	/*
 	 * Make sure the node alias worked
 	 */
@@ -267,7 +267,7 @@
 		return (EDEADLK);
 	}
 #endif
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	*vpp = vp;
 	return 0;
 }
Index: vfs/nullfs/null_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nullfs/null_vnops.c,v
retrieving revision 1.8
diff -u -r1.8 null_vnops.c
--- vfs/nullfs/null_vnops.c	9 Oct 2003 22:27:27 -0000	1.8
+++ vfs/nullfs/null_vnops.c	22 Feb 2004 07:37:21 -0000
@@ -315,7 +315,7 @@
 			*(vps_p[i]) = old_vps[i];
 #if 0
 			if (reles & VDESC_VP0_WILLUNLOCK)
-				VOP_UNLOCK(*(vps_p[i]), LK_THISLAYER, curproc);
+				VOP_UNLOCK(*(vps_p[i]), NULL, LK_THISLAYER, curproc);
 #endif
 			if (reles & VDESC_VP0_WILLRELE)
 				vrele(*(vps_p[i]));
@@ -388,7 +388,7 @@
 	 * tracked by underlying filesystem.
 	 */
 	if (cnp->cn_flags & CNP_PDIRUNLOCK)
-		VOP_UNLOCK(dvp, LK_THISLAYER, td);
+		VOP_UNLOCK(dvp, NULL, LK_THISLAYER, td);
 	if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
 		if (ldvp == lvp) {
 			*ap->a_vpp = dvp;
@@ -575,6 +575,7 @@
 null_lock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct thread *a_td;
 	} */ *ap;
@@ -589,11 +590,11 @@
 		if (vp->v_vnlock != NULL) {
 			/* lock is shared across layers */
 			if (flags & LK_INTERLOCK)
-				lwkt_reltoken(&vp->v_interlock);
+				lwkt_reltoken(ap->a_vlock);
 			return 0;
 		}
 		error = lockmgr(&np->null_lock, flags & ~LK_THISLAYER,
-		    &vp->v_interlock, ap->a_td);
+		    ap->a_vlock, ap->a_td);
 		return (error);
 	}
 
@@ -610,9 +611,9 @@
 			NULLFSDEBUG("null_lock: avoiding LK_DRAIN\n");
 			return(lockmgr(vp->v_vnlock,
 				(flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE,
-				&vp->v_interlock, ap->a_td));
+				ap->a_vlock, ap->a_td));
 		}
-		return(lockmgr(vp->v_vnlock, flags, &vp->v_interlock, ap->a_td));
+		return(lockmgr(vp->v_vnlock, flags, ap->a_vlock, ap->a_td));
 	}
 	/*
 	 * To prevent race conditions involving doing a lookup
@@ -624,21 +625,21 @@
 	 */
 	lvp = NULLVPTOLOWERVP(vp);
 	if (lvp == NULL)
-		return (lockmgr(&np->null_lock, flags, &vp->v_interlock, ap->a_td));
+		return (lockmgr(&np->null_lock, flags, ap->a_vlock, ap->a_td));
 	if (flags & LK_INTERLOCK) {
-		VI_UNLOCK(vp);
+		VI_UNLOCK(ap->a_vlock, vp);
 		flags &= ~LK_INTERLOCK;
 	}
 	if ((flags & LK_TYPE_MASK) == LK_DRAIN) {
-		error = VOP_LOCK(lvp,
+		error = VOP_LOCK(lvp, ap->a_vlock,
 			(flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE, ap->a_td);
 	} else
-		error = VOP_LOCK(lvp, flags, ap->a_td);
+		error = VOP_LOCK(lvp, ap->a_vlock, flags, ap->a_td);
 	if (error)
 		return (error);
-	error = lockmgr(&np->null_lock, flags, &vp->v_interlock, ap->a_td);
+	error = lockmgr(&np->null_lock, flags, ap->a_vlock, ap->a_td);
 	if (error)
-		VOP_UNLOCK(lvp, 0, ap->a_td);
+		VOP_UNLOCK(lvp, NULL, 0, ap->a_td);
 	return (error);
 }
 
@@ -651,6 +652,7 @@
 null_unlock(ap)
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct thread *a_td;
 	} */ *ap;
@@ -665,21 +667,22 @@
 			return 0;	/* the lock is shared across layers */
 		flags &= ~LK_THISLAYER;
 		return (lockmgr(vp->v_vnlock, flags | LK_RELEASE,
-			&vp->v_interlock, ap->a_td));
+			ap->a_vlock, ap->a_td));
 	}
 	lvp = NULLVPTOLOWERVP(vp);
 	if (lvp == NULL)
-		return (lockmgr(&np->null_lock, flags | LK_RELEASE, &vp->v_interlock, ap->a_td));
+		return (lockmgr(&np->null_lock, flags | LK_RELEASE, ap->a_vlock, ap->a_td));
 	if ((flags & LK_THISLAYER) == 0) {
 		if (flags & LK_INTERLOCK) {
-			VI_UNLOCK(vp);
+			VI_UNLOCK(ap->a_vlock, vp);
 			flags &= ~LK_INTERLOCK;
 		}
-		VOP_UNLOCK(lvp, flags, ap->a_td);
-	} else
+		VOP_UNLOCK(lvp, ap->a_vlock, flags, ap->a_td);
+	} else {
 		flags &= ~LK_THISLAYER;
+	}
 	ap->a_flags = flags;
-	return (lockmgr(&np->null_lock, flags | LK_RELEASE, &vp->v_interlock, ap->a_td));
+	return (lockmgr(&np->null_lock, flags | LK_RELEASE, ap->a_vlock, ap->a_td));
 }
 
 static int
@@ -720,8 +723,9 @@
 	xp->null_lowervp = NULLVP;
 	if (vp->v_vnlock != NULL) {
 		vp->v_vnlock = &xp->null_lock;	/* we no longer share the lock */
-	} else
-		VOP_UNLOCK(vp, LK_THISLAYER, ap->a_td);
+	} else {
+		VOP_UNLOCK(vp, NULL, LK_THISLAYER, ap->a_td);
+	}
 
 	vput(lowervp);
 	/*
Index: vfs/nwfs/nwfs_node.c
===================================================================
RCS file: /cvs/src/sys/vfs/nwfs/nwfs_node.c,v
retrieving revision 1.9
diff -u -r1.9 nwfs_node.c
--- vfs/nwfs/nwfs_node.c	10 Nov 2003 06:12:17 -0000	1.9
+++ vfs/nwfs/nwfs_node.c	22 Feb 2004 19:07:26 -0000
@@ -140,17 +140,17 @@
 	struct nwnode_hash_head *nhpp;
 	struct nwmount *nmp = VFSTONWFS(mp);
 	struct vnode *vp;
+	lwkt_tokref vlock;
 	int error;
-	int gen;
 
 loop:
 	lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, td);
 rescan:
 	if (nwfs_hashlookup(nmp, fid, &np) == 0) {
 		vp = NWTOV(np);
-		gen = lwkt_gettoken(&vp->v_interlock);
+		lwkt_gettoken(&vlock, vp->v_interlock);
 		lockmgr(&nwhashlock, LK_RELEASE, NULL, td);
-		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td))
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td))
 			goto loop;
 		*vpp = vp;
 		return(0);
@@ -190,7 +190,7 @@
 	lockinit(&np->n_lock, 0, "nwnode", VLKTIMEOUT, LK_CANRECURSE);
 	nhpp = NWNOHASH(fid);
 	LIST_INSERT_HEAD(nhpp, np, n_hash);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	lockmgr(&nwhashlock, LK_RELEASE, NULL, td);
 	return 0;
 }
@@ -268,7 +268,7 @@
 		error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, td, cred);
 		np->opened = 0;
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (np->n_flag & NSHOULDFREE) {
 		cache_purge(vp);
 		vgone(vp);
Index: vfs/nwfs/nwfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nwfs/nwfs_vfsops.c,v
retrieving revision 1.8
diff -u -r1.8 nwfs_vfsops.c
--- vfs/nwfs/nwfs_vfsops.c	20 Jan 2004 05:04:07 -0000	1.8
+++ vfs/nwfs/nwfs_vfsops.c	22 Feb 2004 19:57:26 -0000
@@ -224,7 +224,7 @@
 	/*
 	 * Lose the lock but keep the ref.
 	 */
-	VOP_UNLOCK(vp, 0, curthread);
+	VOP_UNLOCK(vp, NULL, 0, curthread);
 	NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_usecount);
 	return error;
 bad:
@@ -289,7 +289,7 @@
 	conn = NWFSTOCONN(nmp);
 	if (nmp->n_root) {
 		*vpp = NWTOV(nmp->n_root);
-		while (vget(*vpp, LK_EXCLUSIVE, curthread) != 0) /* XXX */
+		while (vget(*vpp, NULL, LK_EXCLUSIVE, curthread) != 0) /* XXX */
 			;
 		return 0;
 	}
@@ -494,6 +494,8 @@
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 	     vp != NULL;
 	     vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
+		if (vp->v_flag & VPLACEMARKER)	/* ZZZ */
+			continue;
 		/*
 		 * If the vnode that we are about to sync is no longer
 		 * associated with this mount point, start over.
@@ -503,7 +505,7 @@
 		if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
 		    waitfor == MNT_LAZY)
 			continue;
-		if (vget(vp, LK_EXCLUSIVE, td))
+		if (vget(vp, NULL, LK_EXCLUSIVE, td))
 			goto loop;
 		error = VOP_FSYNC(vp, waitfor, td);
 		if (error)
Index: vfs/nwfs/nwfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/nwfs/nwfs_vnops.c,v
retrieving revision 1.9
diff -u -r1.9 nwfs_vnops.c
--- vfs/nwfs/nwfs_vnops.c	9 Oct 2003 22:27:27 -0000	1.9
+++ vfs/nwfs/nwfs_vnops.c	22 Feb 2004 19:07:29 -0000
@@ -242,30 +242,31 @@
 {
 	struct vnode *vp = ap->a_vp;
 	struct nwnode *np = VTONW(vp);
+	lwkt_tokref vlock;
 	int error;
 
 	NCPVNDEBUG("name=%s,td=%p,c=%d\n",np->n_name,ap->a_td,np->opened);
 
 	if (vp->v_type == VDIR) return 0;	/* nothing to do now */
 	error = 0;
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (np->opened == 0) {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		return 0;
 	}
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	error = nwfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettokref(&vlock);
 	if (np->opened == 0) {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		return 0;
 	}
 	if (--np->opened == 0) {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 		error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, 
 		   ap->a_td, proc0.p_ucred);
 	} else {
-		lwkt_reltoken(&vp->v_interlock);
+		lwkt_reltoken(&vlock);
 	}
 	np->n_atime = 0;
 	return (error);
@@ -960,14 +961,14 @@
 			error = 0;
 			NCPVNDEBUG("cached '.'");
 		} else if (flags & CNP_ISDOTDOT) {
-			VOP_UNLOCK(dvp, 0, td);	/* unlock parent */
-			error = vget(vp, LK_EXCLUSIVE, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);	/* unlock parent */
+			error = vget(vp, NULL, LK_EXCLUSIVE, td);
 			if (!error && lockparent && islastcn)
-				error = vn_lock(dvp, LK_EXCLUSIVE, td);
+				error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		} else {
-			error = vget(vp, LK_EXCLUSIVE, td);
+			error = vget(vp, NULL, LK_EXCLUSIVE, td);
 			if (!lockparent || error || !islastcn)
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 		}
 		if (!error) {
 			if (vpid == vp->v_id) {
@@ -982,9 +983,9 @@
 			}
 			vput(vp);
 			if (lockparent && dvp != vp && islastcn)
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 		}
-		error = vn_lock(dvp, LK_EXCLUSIVE, td);
+		error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		*vpp = NULLVP;
 		if (error)
 			return (error);
@@ -1027,7 +1028,7 @@
 		if ((nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME) && wantparent && islastcn) {
 			cnp->cn_flags |= CNP_SAVENAME;
 			if (!lockparent)
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 			return (EJUSTRETURN);
 		}
 		return ENOENT;
@@ -1047,7 +1048,7 @@
 		if (error) return (error);
 		*vpp = vp;
 		cnp->cn_flags |= CNP_SAVENAME;	/* I free it later */
-		if (!lockparent) VOP_UNLOCK(dvp,0,td);
+		if (!lockparent) VOP_UNLOCK(dvp, NULL, 0, td);
 		return (0);
 	}
 	if (nameiop == NAMEI_RENAME && islastcn && wantparent) {
@@ -1059,18 +1060,18 @@
 		*vpp = vp;
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent)
-			VOP_UNLOCK(dvp,0,td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 		return (0);
 	}
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(dvp, 0, td);		/* race to get the inode */
+		VOP_UNLOCK(dvp, NULL, 0, td);	/* race to get the inode */
 		error = nwfs_nget(mp, fid, NULL, NULL, &vp);
 		if (error) {
-			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			return (error);
 		}
 		if (lockparent && islastcn &&
-		    (error = vn_lock(dvp, LK_EXCLUSIVE, td))) {
+		    (error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td))) {
 		    	vput(vp);
 			return (error);
 		}
@@ -1084,7 +1085,7 @@
 		*vpp = vp;
 		NCPVNDEBUG("lookup: getnewvp!\n");
 		if (!lockparent || !islastcn)
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 	}
 	if ((cnp->cn_flags & CNP_MAKEENTRY)/* && !islastcn*/) {
 		VTONW(*vpp)->n_ctime = VTONW(*vpp)->n_vattr.va_ctime.tv_sec;
Index: vfs/portal/portal_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/portal/portal_vfsops.c,v
retrieving revision 1.5
diff -u -r1.5 portal_vfsops.c
--- vfs/portal/portal_vfsops.c	20 Aug 2003 09:56:33 -0000	1.5
+++ vfs/portal/portal_vfsops.c	22 Feb 2004 05:59:01 -0000
@@ -210,7 +210,7 @@
 	 */
 	vp = VFSTOPORTAL(mp)->pm_root;
 	VREF(vp);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	*vpp = vp;
 	return (0);
 }
Index: vfs/portal/portal_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/portal/portal_vnops.c,v
retrieving revision 1.8
diff -u -r1.8 portal_vnops.c
--- vfs/portal/portal_vnops.c	23 Sep 2003 05:03:53 -0000	1.8
+++ vfs/portal/portal_vnops.c	22 Feb 2004 05:44:25 -0000
@@ -537,7 +537,7 @@
 	} */ *ap;
 {
 
-	VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/procfs/procfs_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/procfs/procfs_subr.c,v
retrieving revision 1.5
diff -u -r1.5 procfs_subr.c
--- vfs/procfs/procfs_subr.c	7 Aug 2003 21:17:43 -0000	1.5
+++ vfs/procfs/procfs_subr.c	22 Feb 2004 06:16:13 -0000
@@ -98,7 +98,7 @@
 		if (pfs->pfs_pid == pid &&
 		    pfs->pfs_type == pfs_type &&
 		    vp->v_mount == mp) {
-			if (vget(vp, 0, td))
+			if (vget(vp, NULL, 0, td))
 				goto loop;
 			*vpp = vp;
 			return (0);
Index: vfs/procfs/procfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/procfs/procfs_vnops.c,v
retrieving revision 1.10
diff -u -r1.10 procfs_vnops.c
--- vfs/procfs/procfs_vnops.c	23 Sep 2003 05:03:53 -0000	1.10
+++ vfs/procfs/procfs_vnops.c	22 Feb 2004 05:59:06 -0000
@@ -363,7 +363,7 @@
 {
 	struct vnode *vp = ap->a_vp;
 
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 
 	return (0);
 }
@@ -717,7 +717,7 @@
 	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
 		VREF(dvp);
-		/* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
+		/* vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, curp); */
 		return (0);
 	}
 
Index: vfs/smbfs/smbfs_io.c
===================================================================
RCS file: /cvs/src/sys/vfs/smbfs/smbfs_io.c,v
retrieving revision 1.9
diff -u -r1.9 smbfs_io.c
--- vfs/smbfs/smbfs_io.c	10 Nov 2003 06:12:17 -0000	1.9
+++ vfs/smbfs/smbfs_io.c	22 Feb 2004 05:59:14 -0000
@@ -205,10 +205,10 @@
 	if (vp->v_type == VDIR) {
 		lks = LK_EXCLUSIVE;/*lockstatus(&vp->v_lock, td);*/
 		if (lks == LK_SHARED)
-			vn_lock(vp, LK_UPGRADE | LK_RETRY, td);
+			vn_lock(vp, NULL, LK_UPGRADE | LK_RETRY, td);
 		error = smbfs_readvdir(vp, uiop, cred);
 		if (lks == LK_SHARED)
-			vn_lock(vp, LK_DOWNGRADE | LK_RETRY, td);
+			vn_lock(vp, NULL, LK_DOWNGRADE | LK_RETRY, td);
 		return error;
 	}
 
Index: vfs/smbfs/smbfs_node.c
===================================================================
RCS file: /cvs/src/sys/vfs/smbfs/smbfs_node.c,v
retrieving revision 1.8
diff -u -r1.8 smbfs_node.c
--- vfs/smbfs/smbfs_node.c	10 Nov 2003 06:12:17 -0000	1.8
+++ vfs/smbfs/smbfs_node.c	22 Feb 2004 06:16:20 -0000
@@ -169,6 +169,7 @@
 	struct smbnode *np, *np2, *dnp;
 	struct vnode *vp;
 	u_long hashval;
+	lwkt_tokref vlock;
 	int error;
 
 	*vpp = NULL;
@@ -180,7 +181,7 @@
 		if (dvp == NULL)
 			return EINVAL;
 		vp = VTOSMB(VTOSMB(dvp)->n_parent)->n_vnode;
-		error = vget(vp, LK_EXCLUSIVE, td);
+		error = vget(vp, NULL, LK_EXCLUSIVE, td);
 		if (error == 0)
 			*vpp = vp;
 		return error;
@@ -203,9 +204,9 @@
 		if (np->n_parent != dvp ||
 		    np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0)
 			continue;
-		VI_LOCK(vp);
+		VI_LOCK(&vlock, vp);
 		smbfs_hash_unlock(smp, td);
-		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
 			goto retry;
 		*vpp = vp;
 		return 0;
@@ -243,7 +244,7 @@
 		SMBERROR("new vnode '%s' born without parent ?\n", np->n_name);
 
 	lockinit(&np->n_lock, 0, "smbnode", VLKTIMEOUT, LK_CANRECURSE);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	smbfs_hash_lock(smp, td);
 	LIST_FOREACH(np2, nhpp, n_hash) {
@@ -295,6 +296,7 @@
 	struct vnode *dvp;
 	struct smbnode *np = VTOSMB(vp);
 	struct smbmount *smp = VTOSMBFS(vp);
+	lwkt_tokref vlock;
 	
 	SMBVDEBUG("%s,%d\n", np->n_name, vp->v_usecount);
 
@@ -316,9 +318,9 @@
 		smbfs_name_free(np->n_name);
 	FREE(np, M_SMBNODE);
 	if (dvp) {
-		VI_LOCK(dvp);
+		VI_LOCK(&vlock, dvp);
 		if (dvp->v_usecount >= 1) {
-			VI_UNLOCK(dvp);
+			VI_UNLOCK(&vlock, dvp);
 			vrele(dvp);
 			/*
 			 * Indicate that we released something; see comment
@@ -326,7 +328,7 @@
 			 */
 			smp->sm_didrele = 1;
 		} else {
-			VI_UNLOCK(dvp);
+			VI_UNLOCK(&vlock, dvp);
 			SMBERROR("BUG: negative use count for parent!\n");
 		}
 	}
@@ -358,7 +360,7 @@
 		   &np->n_mtime, &scred);
 		np->n_opencount = 0;
 	}
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (0);
 }
 /*
Index: vfs/smbfs/smbfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/smbfs/smbfs_vfsops.c,v
retrieving revision 1.9
diff -u -r1.9 smbfs_vfsops.c
--- vfs/smbfs/smbfs_vfsops.c	12 Feb 2004 23:36:28 -0000	1.9
+++ vfs/smbfs/smbfs_vfsops.c	22 Feb 2004 19:57:42 -0000
@@ -224,7 +224,7 @@
 	error = smbfs_root(mp, &vp);
 	if (error)
 		goto bad;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	SMBVDEBUG("root.v_usecount = %d\n", vp->v_usecount);
 
 #ifdef DIAGNOSTICS
@@ -318,7 +318,7 @@
 	}
 	if (smp->sm_root) {
 		*vpp = SMBTOV(smp->sm_root);
-		return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
+		return vget(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	}
 	smb_makescred(&scred, td, cred);
 	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
@@ -447,6 +447,8 @@
 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 	     vp != NULL;
 	     vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
+		if (vp->v_flag & VPLACEMARKER)	/* ZZZ */
+			continue;
 		/*
 		 * If the vnode that we are about to sync is no longer
 		 * associated with this mount point, start over.
@@ -456,7 +458,7 @@
 		if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
 		    waitfor == MNT_LAZY)
 			continue;
-		if (vget(vp, LK_EXCLUSIVE, td))
+		if (vget(vp, NULL, LK_EXCLUSIVE, td))
 			goto loop;
 		error = VOP_FSYNC(vp, waitfor, td);
 		if (error)
Index: vfs/smbfs/smbfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/smbfs/smbfs_vnops.c,v
retrieving revision 1.10
diff -u -r1.10 smbfs_vnops.c
--- vfs/smbfs/smbfs_vnops.c	22 Dec 2003 17:41:08 -0000	1.10
+++ vfs/smbfs/smbfs_vnops.c	22 Feb 2004 06:16:37 -0000
@@ -289,16 +289,17 @@
 	struct vnode *vp = ap->a_vp;
 	struct thread *td = ap->a_td;
 	int error, dolock;
+	lwkt_tokref vlock;
 
-	VI_LOCK(vp);
+	VI_LOCK(&vlock, vp);
 	dolock = (vp->v_flag & VXLOCK) == 0;
 	if (dolock)
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td);
+		vn_lock(vp, &vlock, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td);
 	else
-		VI_UNLOCK(vp);
+		VI_UNLOCK(&vlock, vp);
 	error = smbfs_closel(ap);
 	if (dolock)
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 	return error;
 }
 
@@ -1185,18 +1186,18 @@
 			error = 0;
 			SMBVDEBUG("cached '.'\n");
 		} else if (flags & CNP_ISDOTDOT) {
-			VOP_UNLOCK(dvp, 0, td);	/* unlock parent */
+			VOP_UNLOCK(dvp, NULL, 0, td);	/* unlock parent */
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
-			error = vget(vp, LK_EXCLUSIVE, td);
+			error = vget(vp, NULL, LK_EXCLUSIVE, td);
 			if (!error && lockparent && islastcn) {
-				error = vn_lock(dvp, LK_EXCLUSIVE, td);
+				error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 				if (error == 0)
 					cnp->cn_flags &= ~CNP_PDIRUNLOCK;
 			}
 		} else {
-			error = vget(vp, LK_EXCLUSIVE, td);
+			error = vget(vp, NULL, LK_EXCLUSIVE, td);
 			if (!lockparent || error || !islastcn) {
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 			}
 		}
@@ -1213,9 +1214,9 @@
 			}
 			vput(vp);
 			if (lockparent && dvp != vp && islastcn)
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 		}
-		error = vn_lock(dvp, LK_EXCLUSIVE, td);
+		error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 		*vpp = NULLVP;
 		if (error) {
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
@@ -1252,7 +1253,7 @@
 				return error;
 			cnp->cn_flags |= CNP_SAVENAME;
 			if (!lockparent) {
-				VOP_UNLOCK(dvp, 0, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 			}
 			return (EJUSTRETURN);
@@ -1279,7 +1280,7 @@
 		*vpp = vp;
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return 0;
@@ -1296,20 +1297,20 @@
 		*vpp = vp;
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return 0;
 	}
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(dvp, 0, td);
+		VOP_UNLOCK(dvp, NULL, 0, td);
 		error = smbfs_nget(mp, dvp, name, nmlen, NULL, &vp);
 		if (error) {
-			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			return error;
 		}
 		if (lockparent && islastcn) {
-			error = vn_lock(dvp, LK_EXCLUSIVE, td);
+			error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
 			if (error) {
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 				vput(vp);
@@ -1327,7 +1328,7 @@
 		*vpp = vp;
 		SMBVDEBUG("lookup: getnewvp!\n");
 		if (!lockparent || !islastcn) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 	}
Index: vfs/specfs/spec_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/specfs/spec_vnops.c,v
retrieving revision 1.12
diff -u -r1.12 spec_vnops.c
--- vfs/specfs/spec_vnops.c	20 Aug 2003 09:56:33 -0000	1.12
+++ vfs/specfs/spec_vnops.c	22 Feb 2004 05:59:41 -0000
@@ -190,9 +190,9 @@
 	if (dev_dflags(dev) & D_TTY)
 		vp->v_flag |= VISTTY;
 
-	VOP_UNLOCK(vp, 0, ap->a_td);
+	VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 	error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_td);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
 
 	if (error)
 		return (error);
@@ -249,9 +249,9 @@
 	if (uio->uio_resid == 0)
 		return (0);
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	error = dev_dread(dev, uio, ap->a_ioflag);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	return (error);
 }
 
@@ -279,9 +279,9 @@
 	uio = ap->a_uio;
 	td = uio->uio_td;
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	error = dev_dwrite(dev, uio, ap->a_ioflag);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	return (error);
 }
 
@@ -427,7 +427,7 @@
 	} */ *ap;
 {
 
-	VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/ufs/ffs_rawread.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ffs_rawread.c,v
retrieving revision 1.6
diff -u -r1.6 ffs_rawread.c
--- vfs/ufs/ffs_rawread.c	8 Sep 2003 18:26:39 -0000	1.6
+++ vfs/ufs/ffs_rawread.c	22 Feb 2004 05:32:51 -0000
@@ -105,7 +105,7 @@
 		if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE) {
 			upgraded = 1;
 			/* Upgrade to exclusive lock, this might block */
-			VOP_LOCK(vp, LK_UPGRADE | LK_NOPAUSE, td);
+			VOP_LOCK(vp, NULL, LK_UPGRADE | LK_NOPAUSE, td);
 		} else
 			upgraded = 0;
 		
@@ -125,7 +125,7 @@
 			if (error != 0) {
 				splx(spl);
 				if (upgraded != 0)
-					VOP_LOCK(vp, LK_DOWNGRADE, td);
+					VOP_LOCK(vp, NULL, LK_DOWNGRADE, td);
 				return (error);
 			}
 		}
@@ -134,7 +134,7 @@
 			splx(spl);
 			if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) != 0) {
 				if (upgraded != 0)
-					VOP_LOCK(vp, LK_DOWNGRADE, td);
+					VOP_LOCK(vp, NULL, LK_DOWNGRADE, td);
 				return (error);
 			}
 			spl = splbio();
@@ -144,7 +144,7 @@
 		}
 		splx(spl);
 		if (upgraded != 0)
-			VOP_LOCK(vp, LK_DOWNGRADE, td);
+			VOP_LOCK(vp, NULL, LK_DOWNGRADE, td);
 	} else {
 		splx(spl);
 	}
Index: vfs/ufs/ffs_softdep.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ffs_softdep.c,v
retrieving revision 1.12
diff -u -r1.12 ffs_softdep.c
--- vfs/ufs/ffs_softdep.c	16 Feb 2004 19:48:51 -0000	1.12
+++ vfs/ufs/ffs_softdep.c	22 Feb 2004 05:59:47 -0000
@@ -820,9 +820,9 @@
 			if (softdep_process_worklist(oldmnt) == 0)
 				break;
 		}
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		error = VOP_FSYNC(devvp, MNT_WAIT, td);
-		VOP_UNLOCK(devvp, 0, td);
+		VOP_UNLOCK(devvp, NULL, 0, td);
 		if (error)
 			break;
 	}
@@ -3978,9 +3978,9 @@
 		 * ufs_lookup for details on possible races.
 		 */
 		FREE_LOCK(&lk);
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 		error = VFS_VGET(mnt, parentino, &pvp);
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		if (error != 0)
 			return (error);
 		if (flushparent) {
Index: vfs/ufs/ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ffs_vfsops.c,v
retrieving revision 1.13
diff -u -r1.13 ffs_vfsops.c
--- vfs/ufs/ffs_vfsops.c	8 Feb 2004 05:56:10 -0000	1.13
+++ vfs/ufs/ffs_vfsops.c	22 Feb 2004 22:33:53 -0000
@@ -224,13 +224,13 @@
 			 * that user has necessary permissions on the device.
 			 */
 			if (cred->cr_uid != 0) {
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+				vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
 				    cred, td)) != 0) {
-					VOP_UNLOCK(devvp, 0, td);
+					VOP_UNLOCK(devvp, NULL, 0, td);
 					return (error);
 				}
-				VOP_UNLOCK(devvp, 0, td);
+				VOP_UNLOCK(devvp, NULL, 0, td);
 			}
 
 			fs->fs_flags &= ~FS_UNCLEAN;
@@ -304,12 +304,12 @@
 		accessmode = VREAD;
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			accessmode |= VWRITE;
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		if ((error = VOP_ACCESS(devvp, accessmode, cred, td)) != 0) {
 			vput(devvp);
 			return (error);
 		}
-		VOP_UNLOCK(devvp, 0, td);
+		VOP_UNLOCK(devvp, NULL, 0, td);
 	}
 
 	if (mp->mnt_flag & MNT_UPDATE) {
@@ -419,19 +419,32 @@
  *	5) invalidate all cached file data.
  *	6) re-read inode data for all active vnodes.
  */
+
+static int ffs_reload_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int ffs_reload_scan2(struct mount *mp, struct vnode *vp,
+				lwkt_tokref_t vlock, void *data);
+
+struct scaninfo {
+	int rescan;
+	struct fs *fs;
+	struct vnode *devvp;
+	thread_t td;
+	int waitfor;
+	int allerror;
+};
+
 static int
 ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td)
 {
-	struct vnode *vp, *nvp, *devvp;
-	struct inode *ip;
+	struct vnode *devvp;
 	void *space;
 	struct buf *bp;
 	struct fs *fs, *newfs;
 	struct partinfo dpart;
 	dev_t dev;
 	int i, blks, size, error;
-	int gen;
-	int vgen;
+	lwkt_tokref vlock;
+	struct scaninfo scaninfo;
 	int32_t *lp;
 
 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
@@ -440,9 +453,9 @@
 	 * Step 1: invalidate all cached meta-data.
 	 */
 	devvp = VFSTOUFS(mp)->um_devvp;
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = vinvalbuf(devvp, 0, td, 0, 0);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		panic("ffs_reload: dirty1");
 
@@ -453,10 +466,10 @@
 	 * block device.  See ffs_mountmfs() for more details.
 	 */
 	if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		vfs_object_create(devvp, td);
-		lwkt_gettoken(&devvp->v_interlock);
-		VOP_UNLOCK(devvp, LK_INTERLOCK, td);
+		lwkt_gettoken(&vlock, devvp->v_interlock);
+		VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td);
 	}
 
 	/*
@@ -522,57 +535,69 @@
 			*lp++ = fs->fs_contigsumsize;
 	}
 
-	gen = lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-		if (vp->v_mount != mp) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		/*
-		 * Step 4: invalidate all inactive vnodes. 
-		 */
-		if (vrecycle(vp, NULL, td)) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		/*
-		 * Step 5: invalidate all cached file data.
-		 */
-		vgen = lwkt_gettoken(&vp->v_interlock);
-		if (lwkt_gentoken(&mntvnode_token, &gen) != 0 ||
-		    lwkt_gentoken(&vp->v_interlock, &vgen) != 0) {
-			lwkt_reltoken(&vp->v_interlock);
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-			lwkt_gentoken(&mntvnode_token, &gen);
-			goto loop;
-		}
-		if (vinvalbuf(vp, 0, td, 0, 0))
-			panic("ffs_reload: dirty2");
-		/*
-		 * Step 6: re-read inode data for all active vnodes.
-		 */
-		ip = VTOI(vp);
-		error =
-		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
-		    (int)fs->fs_bsize, &bp);
-		if (error) {
-			vput(vp);
-			lwkt_reltoken(&mntvnode_token);
-			return (error);
-		}
-		ip->i_din = *((struct dinode *)bp->b_data +
-		    ino_to_fsbo(fs, ip->i_number));
-		ip->i_effnlink = ip->i_nlink;
-		brelse(bp);
+	scaninfo.rescan = 0;
+	scaninfo.fs = fs;
+	scaninfo.devvp = devvp;
+	scaninfo.td = td;
+	while (error == 0 && scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		error = vmntvnodescan(mp, ffs_reload_scan1, 
+				    ffs_reload_scan2, &scaninfo);
+	}
+	return(error);
+}
+
+static 
+int
+ffs_reload_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+	struct scaninfo *info = data;
+
+	/*
+	 * Step 4: invalidate all inactive vnodes. 
+	 */
+	if (vrecycle(vp, NULL, curthread)) {
+		info->rescan = 1;
+		return(-1);	/* continue loop, do not call scan2 */
+	}
+	return(0);
+}
+
+static
+int
+ffs_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct inode *ip;
+	struct buf *bp;
+	int error;
+
+	/*
+	 * Step 5: invalidate all cached file data.
+	 */
+	if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) {
+		info->rescan = 1;
+		return(0);
+	}
+	if (vinvalbuf(vp, 0, info->td, 0, 0))
+		panic("ffs_reload: dirty2");
+	/*
+	 * Step 6: re-read inode data for all active vnodes.
+	 */
+	ip = VTOI(vp);
+	error = bread(info->devvp,
+			fsbtodb(info->fs, ino_to_fsba(info->fs, ip->i_number)),
+			(int)info->fs->fs_bsize, &bp);
+	if (error) {
 		vput(vp);
+		return (error);
 	}
-	lwkt_reltoken(&mntvnode_token);
-	return (0);
+	ip->i_din = *((struct dinode *)bp->b_data +
+	    ino_to_fsbo(info->fs, ip->i_number));
+	ip->i_effnlink = ip->i_nlink;
+	brelse(bp);
+	vput(vp);
+	return(0);
 }
 
 /*
@@ -592,6 +617,7 @@
 	struct partinfo dpart;
 	void *space;
 	int error, i, blks, size, ronly;
+	lwkt_tokref vlock;
 	int32_t *lp;
 	u_int64_t maxfilesize;					/* XXX */
 	size_t strsize;
@@ -611,9 +637,9 @@
 
 	if (ncount > 1 && devvp != rootvp)
 		return (EBUSY);
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = vinvalbuf(devvp, V_SAVE, td, 0, 0);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return (error);
 
@@ -624,16 +650,16 @@
 	 * increases the opportunity for metadata caching.
 	 */
 	if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
-		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		vfs_object_create(devvp, td);
-		lwkt_gettoken(&devvp->v_interlock);
-		VOP_UNLOCK(devvp, LK_INTERLOCK, td);
+		lwkt_gettoken(&vlock, devvp->v_interlock);
+		VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td);
 	}
 
 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
-	VOP_UNLOCK(devvp, 0, td);
+	VOP_UNLOCK(devvp, NULL, 0, td);
 	if (error)
 		return (error);
 	if (devvp->v_rdev->si_iosize_max != 0)
@@ -911,9 +937,9 @@
 	/*
 	 * Flush filesystem metadata.
 	 */
-	vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, td);
-	VOP_UNLOCK(ump->um_devvp, 0, td);
+	VOP_UNLOCK(ump->um_devvp, NULL, 0, td);
 	return (error);
 }
 
@@ -955,88 +981,47 @@
  *
  * Note: we are always called with the filesystem marked `MPBUSY'.
  */
+
+
+static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int ffs_sync_scan2(struct mount *mp, struct vnode *vp,
+                lwkt_tokref_t vlock, void *data);
+
 int
 ffs_sync(struct mount *mp, int waitfor, struct thread *td)
 {
-	struct vnode *nvp, *vp;
-	struct inode *ip;
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct fs *fs;
-	int error, allerror = 0;
+	int error;
+	struct scaninfo scaninfo;
 
 	fs = ump->um_fs;
 	if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {		/* XXX */
 		printf("fs = %s\n", fs->fs_fsmnt);
 		panic("ffs_sync: rofs mod");
 	}
+
 	/*
 	 * Write back each (modified) inode.
 	 */
-	lwkt_gettoken(&mntvnode_token);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-		/*
-		 * If the vnode that we are about to sync is no longer
-		 * associated with this mount point, start over.
-		 */
-		if (vp->v_mount != mp)
-			goto loop;
-
-		/*
-		 * Depend on the mntvnode_token to keep things stable enough
-		 * for a quick test.  Since there might be hundreds of 
-		 * thousands of vnodes, we cannot afford even a subroutine
-		 * call unless there's a good chance that we have work to do.
-		 */
-		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		ip = VTOI(vp);
-		if (vp->v_type == VNON || ((ip->i_flag &
-		     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
-		     TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
-			continue;
-		}
-		if (vp->v_type != VCHR) {
-			lwkt_reltoken(&mntvnode_token);
-			error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT, td);
-			if (error) {
-				lwkt_gettoken(&mntvnode_token);
-				if (error == ENOENT)
-					goto loop;
-			} else {
-				if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
-					allerror = error;
-				VOP_UNLOCK(vp, 0, td);
-				vrele(vp);
-				lwkt_gettoken(&mntvnode_token);
-			}
-		} else {
-			/*
-			 * We must reference the vp to prevent it from
-			 * getting ripped out from under UFS_UPDATE, since
-			 * we are not holding a vnode lock.  XXX why aren't
-			 * we holding a vnode lock?
-			 */
-			VREF(vp);
-			lwkt_reltoken(&mntvnode_token);
-			/* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
-			UFS_UPDATE(vp, 0);
-			vrele(vp);
-			lwkt_gettoken(&mntvnode_token);
-		}
-		if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp)
-			goto loop;
+	scaninfo.allerror = 0;
+	scaninfo.rescan = 1;
+	scaninfo.waitfor = waitfor;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		vmntvnodescan(mp, ffs_sync_scan1, ffs_sync_scan2, &scaninfo);
 	}
-	lwkt_reltoken(&mntvnode_token);
+
 	/*
 	 * Force stale file system control information to be flushed.
 	 */
 	if (waitfor != MNT_LAZY) {
 		if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
 			waitfor = MNT_NOWAIT;
-		vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
-			allerror = error;
-		VOP_UNLOCK(ump->um_devvp, 0, td);
+			scaninfo.allerror = error;
+		VOP_UNLOCK(ump->um_devvp, NULL, 0, td);
 	}
 #ifdef QUOTA
 	qsync(mp);
@@ -1045,8 +1030,75 @@
 	 * Write back modified superblock.
 	 */
 	if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
-		allerror = error;
-	return (allerror);
+		scaninfo.allerror = error;
+	return (scaninfo.allerror);
+}
+
+static
+int
+ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+	struct inode *ip;
+
+	/*
+	 * Depend on the mount list's vnode lock to keep things stable 
+	 * enough for a quick test.  Since there might be hundreds of 
+	 * thousands of vnodes, we cannot afford even a subroutine
+	 * call unless there's a good chance that we have work to do.
+	 */
+	ip = VTOI(vp);
+	if (vp->v_type == VNON || ((ip->i_flag &
+	     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
+	     TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
+		return(-1);
+	}
+	return(0);
+}
+
+static
+int 
+ffs_sync_scan2(struct mount *mp, struct vnode *vp,
+                lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	thread_t td = curthread;	/* XXX */
+	struct inode *ip;
+	int error;
+
+	/*
+	 * We have to recheck after having obtained the vnode interlock.
+	 */
+	ip = VTOI(vp);
+	if (vp->v_type == VNON || ((ip->i_flag &
+	     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
+	     TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+	if (vp->v_type != VCHR) {
+		error = vget(vp, vlock, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT, td);
+		if (error) {
+			if (error == ENOENT)
+				info->rescan = 1;
+		} else {
+			if ((error = VOP_FSYNC(vp, info->waitfor, td)) != 0)
+				info->allerror = error;
+			VOP_UNLOCK(vp, NULL, 0, td);
+			vrele(vp);
+		}
+	} else {
+		/*
+		 * We must reference the vp to prevent it from
+		 * getting ripped out from under UFS_UPDATE, since
+		 * we are not holding a vnode lock.
+		 */
+		VREF(vp);
+		lwkt_reltoken(vlock);
+		/* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
+		UFS_UPDATE(vp, 0);
+		vrele(vp);
+	}
+	return(0);
 }
 
 /*
Index: vfs/ufs/ufs_ihash.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_ihash.c,v
retrieving revision 1.10
diff -u -r1.10 ufs_ihash.c
--- vfs/ufs/ufs_ihash.c	15 Jan 2004 20:17:36 -0000	1.10
+++ vfs/ufs/ufs_ihash.c	22 Feb 2004 21:21:27 -0000
@@ -63,7 +63,7 @@
 ufs_ihashinit()
 {
 	ihashtbl = hashinit(desiredvnodes, M_UFSIHASH, &ihash);
-	lwkt_inittoken(&ufs_ihash_token);
+	lwkt_token_init(&ufs_ihash_token);
 }
 
 /*
@@ -76,13 +76,14 @@
 	ino_t inum;
 {
 	struct inode *ip;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&ufs_ihash_token);
+	lwkt_gettoken(&ilock, &ufs_ihash_token);
 	for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
 		if (inum == ip->i_number && dev == ip->i_dev)
 			break;
 	}
-	lwkt_reltoken(&ufs_ihash_token);
+	lwkt_reltoken(&ilock);
 
 	if (ip)
 		return (ITOV(ip));
@@ -93,50 +94,45 @@
  * Use the device/inum pair to find the incore inode, and return a pointer
  * to it. If it is in core, but locked, wait for it.
  *
- * Any time we potentially block we must regenerate the token using 
- * lwkt_gentoken(), which at the same time checks the generation number
- * indicating whether another entity stole the token while we were blocked.
- * In the best case lwkt_gentoken().   The code below is probably overkill,
- * but it is particularly important to check the generation number after
- * acquiring the vnode lock to ensure that the inode association is still
- * valid.
+ * Note that the serializing tokens do not prevent other processes from
+ * playing with the data structure being protected while we are blocked.
+ * They do protect us from preemptive interrupts which might try to
+ * play with the protected data structure.
  */
 struct vnode *
 ufs_ihashget(dev_t dev, ino_t inum)
 {
 	struct thread *td = curthread;	/* XXX */
+	lwkt_tokref ilock;
+	lwkt_tokref vlock;
 	struct inode *ip;
 	struct vnode *vp;
-	int gen;
 
-	gen = lwkt_gettoken(&ufs_ihash_token);
+	lwkt_gettoken(&ilock, &ufs_ihash_token);
 loop:
 	for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
-		if (inum == ip->i_number && dev == ip->i_dev) {
-			vp = ITOV(ip);
-			vhold(vp);
-			lwkt_gettoken(&vp->v_interlock);
-			if (lwkt_gentoken(&ufs_ihash_token, &gen) != 0) {
-				lwkt_reltoken(&vp->v_interlock);
-				vdrop(vp);
-				goto loop;
-			}
-			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
-				vdrop(vp);
-				lwkt_gentoken(&ufs_ihash_token, &gen);
-				goto loop;
-			}
-			if (lwkt_reltoken(&ufs_ihash_token) != gen) {
-				vdrop(vp);
-				vput(vp);
-				gen = lwkt_gettoken(&ufs_ihash_token);
-				goto loop;
-			}
-			vdrop(vp);
-			return (vp);
+		if (inum != ip->i_number || dev != ip->i_dev)
+			continue;
+		vp = ITOV(ip);
+		lwkt_gettoken(&vlock, vp->v_interlock);
+		/*
+		 * We must check to see if the inode has been ripped
+		 * out from under us after blocking.
+		 */
+		for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
+			if (inum == ip->i_number && dev == ip->i_dev)
+				break;
 		}
+		if (ip == NULL || ITOV(ip) != vp) {
+			lwkt_reltoken(&vlock);
+			goto loop;
+		}
+		if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td))
+			goto loop;
+		lwkt_reltoken(&ilock);
+		return (vp);
 	}
-	lwkt_reltoken(&ufs_ihash_token);
+	lwkt_reltoken(&ilock);
 	return (NULL);
 }
 
@@ -148,15 +144,16 @@
 {
 	struct thread *td = curthread;		/* XXX */
 	struct ihashhead *ipp;
+	lwkt_tokref ilock;
 
 	/* lock the inode, then put it on the appropriate hash list */
 	lockmgr(&ip->i_lock, LK_EXCLUSIVE, NULL, td);
 
-	lwkt_gettoken(&ufs_ihash_token);
+	lwkt_gettoken(&ilock, &ufs_ihash_token);
 	ipp = INOHASH(ip->i_dev, ip->i_number);
 	LIST_INSERT_HEAD(ipp, ip, i_hash);
 	ip->i_flag |= IN_HASHED;
-	lwkt_reltoken(&ufs_ihash_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -166,7 +163,9 @@
 ufs_ihashrem(ip)
 	struct inode *ip;
 {
-	lwkt_gettoken(&ufs_ihash_token);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &ufs_ihash_token);
 	if (ip->i_flag & IN_HASHED) {
 		ip->i_flag &= ~IN_HASHED;
 		LIST_REMOVE(ip, i_hash);
@@ -175,5 +174,5 @@
 		ip->i_hash.le_prev = NULL;
 #endif
 	}
-	lwkt_reltoken(&ufs_ihash_token);
+	lwkt_reltoken(&ilock);
 }
Index: vfs/ufs/ufs_inode.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_inode.c,v
retrieving revision 1.6
diff -u -r1.6 ufs_inode.c
--- vfs/ufs/ufs_inode.c	7 Aug 2003 21:17:44 -0000	1.6
+++ vfs/ufs/ufs_inode.c	22 Feb 2004 05:45:51 -0000
@@ -97,7 +97,7 @@
 	if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))
 		UFS_UPDATE(vp, 0);
 out:
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	/*
 	 * If we are done with the inode, reclaim it
 	 * so that it can be reused immediately.
Index: vfs/ufs/ufs_lookup.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_lookup.c,v
retrieving revision 1.8
diff -u -r1.8 ufs_lookup.c
--- vfs/ufs/ufs_lookup.c	9 Oct 2003 22:27:27 -0000	1.8
+++ vfs/ufs/ufs_lookup.c	22 Feb 2004 06:00:25 -0000
@@ -443,7 +443,7 @@
 		 */
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (EJUSTRETURN);
@@ -507,10 +507,10 @@
 			return (0);
 		}
 		if (flags & CNP_ISDOTDOT)
-			VOP_UNLOCK(vdp, 0, td);	/* race to get the inode */
+			VOP_UNLOCK(vdp, NULL, 0, td);/* race to get the inode */
 		error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
 		if (flags & CNP_ISDOTDOT) {
-			if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0)
+			if (vn_lock(vdp, NULL, LK_EXCLUSIVE | LK_RETRY, td) != 0)
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		if (error)
@@ -530,7 +530,7 @@
 		}
 		*vpp = tdp;
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (0);
@@ -552,10 +552,10 @@
 		if (dp->i_number == dp->i_ino)
 			return (EISDIR);
 		if (flags & CNP_ISDOTDOT)
-			VOP_UNLOCK(vdp, 0, td);	/* race to get the inode */
+			VOP_UNLOCK(vdp, NULL, 0, td);	/* race to get the inode */
 		error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
 		if (flags & CNP_ISDOTDOT) {
-			if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0)
+			if (vn_lock(vdp, NULL, LK_EXCLUSIVE | LK_RETRY, td) != 0)
 				cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		if (error)
@@ -563,7 +563,7 @@
 		*vpp = tdp;
 		cnp->cn_flags |= CNP_SAVENAME;
 		if (!lockparent) {
-			VOP_UNLOCK(vdp, 0, td);
+			VOP_UNLOCK(vdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		return (0);
@@ -590,15 +590,15 @@
 	 */
 	pdp = vdp;
 	if (flags & CNP_ISDOTDOT) {
-		VOP_UNLOCK(pdp, 0, td);	/* race to get the inode */
+		VOP_UNLOCK(pdp, NULL, 0, td);	/* race to get the inode */
 		cnp->cn_flags |= CNP_PDIRUNLOCK;
 		if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) {
-			if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td) == 0)
+			if (vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td) == 0)
 				cnp->cn_flags &= ~CNP_PDIRUNLOCK;
 			return (error);
 		}
 		if (lockparent && (flags & CNP_ISLASTCN)) {
-			if ((error = vn_lock(pdp, LK_EXCLUSIVE, td)) != 0) {
+			if ((error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td)) != 0) {
 				vput(tdp);
 				return (error);
 			}
@@ -613,7 +613,7 @@
 		if (error)
 			return (error);
 		if (!lockparent || !(flags & CNP_ISLASTCN)) {
-			VOP_UNLOCK(pdp, 0, td);
+			VOP_UNLOCK(pdp, NULL, 0, td);
 			cnp->cn_flags |= CNP_PDIRUNLOCK;
 		}
 		*vpp = tdp;
@@ -945,14 +945,14 @@
 	 */
 	if (error == 0 && dp->i_endoff && dp->i_endoff < dp->i_size) {
 		if (tvp != NULL)
-			VOP_UNLOCK(tvp, 0, td);
+			VOP_UNLOCK(tvp, NULL, 0, td);
 #ifdef UFS_DIRHASH
 		if (dp->i_dirhash != NULL)
 			ufsdirhash_dirtrunc(dp, dp->i_endoff);
 #endif
 		(void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cred, td);
 		if (tvp != NULL)
-			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(tvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	}
 	return (error);
 }
Index: vfs/ufs/ufs_quota.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_quota.c,v
retrieving revision 1.11
diff -u -r1.11 ufs_quota.c
--- vfs/ufs/ufs_quota.c	23 Sep 2003 05:03:53 -0000	1.11
+++ vfs/ufs/ufs_quota.c	22 Feb 2004 21:58:04 -0000
@@ -380,9 +380,18 @@
  * Code to process quotactl commands.
  */
 
+struct scaninfo {
+	thread_t td;
+	int rescan;
+	int type;
+};
+
 /*
  * Q_QUOTAON - set up a quota file for a particular file system.
  */
+static int quotaon_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data);
+
 int
 quotaon(td, mp, type, fname)
 	struct thread *td;
@@ -392,11 +401,11 @@
 {
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct vnode *vp, **vpp;
-	struct vnode *nextvp;
 	struct dquot *dq;
 	int error;
 	struct nameidata nd;
 	struct ucred *cred;
+	struct scaninfo scaninfo;
 
 	KKASSERT(td->td_proc);
 	cred = td->td_proc->p_ucred;
@@ -408,7 +417,7 @@
 		return (error);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vp = nd.ni_vp;
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (vp->v_type != VREG) {
 		(void) vn_close(vp, FREAD|FWRITE, td);
 		return (EACCES);
@@ -438,21 +447,13 @@
 	 * adding references to quota file being opened.
 	 * NB: only need to add dquot's for inodes being modified.
 	 */
-again:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nextvp) {
-		nextvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		if (vp->v_type == VNON || vp->v_writecount == 0)
-			continue;
-		if (vget(vp, LK_EXCLUSIVE, td))
-			goto again;
-		error = getinoquota(VTOI(vp));
-		if (error) {
-			vput(vp);
+	scaninfo.rescan = 1;
+	scaninfo.td = td;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		error = vmntvnodescan(mp, NULL, quotaon_scan, &scaninfo);
+		if (error)
 			break;
-		}
-		vput(vp);
-		if (TAILQ_NEXT(vp, v_nmntvnodes) != nextvp || vp->v_mount != mp)
-			goto again;
 	}
 	ump->um_qflags[type] &= ~QTF_OPENING;
 	if (error)
@@ -460,19 +461,42 @@
 	return (error);
 }
 
+static
+int
+quotaon_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data)
+{
+	int error;
+	struct scaninfo *info = data;
+
+	if (vp->v_type == VNON || vp->v_writecount == 0) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+	if (vget(vp, vlock, LK_INTERLOCK|LK_EXCLUSIVE, info->td)) {
+		info->rescan = 1;
+		return(0);
+	}
+	error = getinoquota(VTOI(vp));
+	vput(vp);
+	return(error);
+}
+
 /*
  * Q_QUOTAOFF - turn off disk quotas for a filesystem.
  */
+
+static int quotaoff_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data);
+
 int
 quotaoff(struct thread *td, struct mount *mp, int type)
 {
-	struct vnode *vp;
-	struct vnode *qvp, *nextvp;
+	struct vnode *qvp;
 	struct ufsmount *ump = VFSTOUFS(mp);
-	struct dquot *dq;
-	struct inode *ip;
 	struct ucred *cred;
 	int error;
+	struct scaninfo scaninfo;
 
 	KKASSERT(td->td_proc);
 	cred = td->td_proc->p_ucred;
@@ -480,24 +504,17 @@
 	if ((qvp = ump->um_quotas[type]) == NULLVP)
 		return (0);
 	ump->um_qflags[type] |= QTF_CLOSING;
+
 	/*
 	 * Search vnodes associated with this mount point,
 	 * deleting any references to quota file being closed.
 	 */
-again:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nextvp) {
-		nextvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		if (vp->v_type == VNON)
-			continue;
-		if (vget(vp, LK_EXCLUSIVE, td))
-			goto again;
-		ip = VTOI(vp);
-		dq = ip->i_dquot[type];
-		ip->i_dquot[type] = NODQUOT;
-		dqrele(vp, dq);
-		vput(vp);
-		if (TAILQ_NEXT(vp, v_nmntvnodes) != nextvp || vp->v_mount != mp)
-			goto again;
+	scaninfo.rescan = 1;
+	scaninfo.td = td;
+	scaninfo.type = type;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		vmntvnodescan(mp, NULL, quotaoff_scan, &scaninfo);
 	}
 	dqflush(qvp);
 	qvp->v_flag &= ~VSYSTEM;
@@ -506,14 +523,40 @@
 	crfree(ump->um_cred[type]);
 	ump->um_cred[type] = NOCRED;
 	ump->um_qflags[type] &= ~QTF_CLOSING;
-	for (type = 0; type < MAXQUOTAS; type++)
+	for (type = 0; type < MAXQUOTAS; type++) {
 		if (ump->um_quotas[type] != NULLVP)
 			break;
+	}
 	if (type == MAXQUOTAS)
 		mp->mnt_flag &= ~MNT_QUOTA;
 	return (error);
 }
 
+static
+int
+quotaoff_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct dquot *dq;
+	struct inode *ip;
+
+	if (vp->v_type == VNON) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+	if (vget(vp, vlock, LK_INTERLOCK|LK_EXCLUSIVE, info->td)) {
+		info->rescan = 1;
+		return(0);
+	}
+	ip = VTOI(vp);
+	dq = ip->i_dquot[info->type];
+	ip->i_dquot[info->type] = NODQUOT;
+	dqrele(vp, dq);
+	vput(vp);
+	return(0);
+}
+
 /*
  * Q_GETQUOTA - return current values in a dqblk structure.
  */
@@ -647,15 +690,16 @@
 /*
  * Q_SYNC - sync quota files to disk.
  */
+
+static int qsync_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data);
 int
 qsync(struct mount *mp)
 {
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct thread *td = curthread;		/* XXX */
-	struct vnode *vp, *nextvp;
-	struct dquot *dq;
-	int i, error;
-	int gen;
+	struct scaninfo scaninfo;
+	int i;
 
 	/*
 	 * Check if the mount point has any quotas.
@@ -670,41 +714,44 @@
 	 * Search vnodes associated with this mount point,
 	 * synchronizing any modified dquot structures.
 	 */
-	gen = lwkt_gettoken(&mntvnode_token);
-again:
-	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nextvp) {
-		if (vp->v_mount != mp)
-			goto again;
-		nextvp = TAILQ_NEXT(vp, v_nmntvnodes);
-		if (vp->v_type == VNON)
-			continue;
-		lwkt_gettoken(&vp->v_interlock);
-		if (lwkt_gentoken(&mntvnode_token, &gen) != 0) {
-			lwkt_reltoken(&vp->v_interlock);
-			goto again;
-		}
-		error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
-		if (error) {
-			if (error == ENOENT) {
-				lwkt_gentoken(&mntvnode_token, &gen);
-				goto again;
-			}
-			continue;
-		}
-		for (i = 0; i < MAXQUOTAS; i++) {
-			dq = VTOI(vp)->i_dquot[i];
-			if (dq != NODQUOT && (dq->dq_flags & DQ_MOD))
-				dqsync(vp, dq);
-		}
-		vput(vp);
-		lwkt_gentoken(&mntvnode_token, &gen);
-		if (TAILQ_NEXT(vp, v_nmntvnodes) != nextvp)
-			goto again;
+	scaninfo.rescan = 1;
+	scaninfo.td = td;
+	while (scaninfo.rescan) {
+		scaninfo.rescan = 0;
+		vmntvnodescan(mp, NULL, qsync_scan, &scaninfo);
 	}
-	lwkt_reltoken(&mntvnode_token);
 	return (0);
 }
 
+static
+int
+qsync_scan(struct mount *mp, struct vnode *vp,
+		lwkt_tokref_t vlock, void *data)
+{
+	struct scaninfo *info = data;
+	struct dquot *dq;
+	int error;
+	int i;
+
+	if (vp->v_type == VNON) {
+		lwkt_reltoken(vlock);
+		return(0);
+	}
+	error = vget(vp, vlock, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, info->td);
+	if (error) {
+		if (error == ENOENT)
+			info->rescan = 1;
+		return(0);
+	}
+	for (i = 0; i < MAXQUOTAS; i++) {
+		dq = VTOI(vp)->i_dquot[i];
+		if (dq != NODQUOT && (dq->dq_flags & DQ_MOD))
+			dqsync(vp, dq);
+	}
+	vput(vp);
+	return(0);
+}
+
 /*
  * Code pertaining to management of the in-core dquot data structures.
  */
@@ -800,7 +847,7 @@
 	 * Initialize the contents of the dquot structure.
 	 */
 	if (vp != dqvp)
-		vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(dqvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	LIST_INSERT_HEAD(dqh, dq, dq_hash);
 	DQREF(dq);
 	dq->dq_flags = DQ_LOCK;
@@ -820,7 +867,7 @@
 	if (auio.uio_resid == sizeof(struct dqblk) && error == 0)
 		bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk));
 	if (vp != dqvp)
-		VOP_UNLOCK(dqvp, 0, td);
+		VOP_UNLOCK(dqvp, NULL, 0, td);
 	if (dq->dq_flags & DQ_WANT)
 		wakeup((caddr_t)dq);
 	dq->dq_flags = 0;
@@ -905,13 +952,13 @@
 	if ((dqvp = dq->dq_ump->um_quotas[dq->dq_type]) == NULLVP)
 		panic("dqsync: file");
 	if (vp != dqvp)
-		vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(dqvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	while (dq->dq_flags & DQ_LOCK) {
 		dq->dq_flags |= DQ_WANT;
 		(void) tsleep((caddr_t)dq, 0, "dqsync", 0);
 		if ((dq->dq_flags & DQ_MOD) == 0) {
 			if (vp != dqvp)
-				VOP_UNLOCK(dqvp, 0, td);
+				VOP_UNLOCK(dqvp, NULL, 0, td);
 			return (0);
 		}
 	}
@@ -932,7 +979,7 @@
 		wakeup((caddr_t)dq);
 	dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT);
 	if (vp != dqvp)
-		VOP_UNLOCK(dqvp, 0, td);
+		VOP_UNLOCK(dqvp, NULL, 0, td);
 	return (error);
 }
 
Index: vfs/ufs/ufs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_vfsops.c,v
retrieving revision 1.5
diff -u -r1.5 ufs_vfsops.c
--- vfs/ufs/ufs_vfsops.c	7 Aug 2003 21:17:44 -0000	1.5
+++ vfs/ufs/ufs_vfsops.c	22 Feb 2004 06:06:07 -0000
@@ -123,7 +123,7 @@
 	type = cmds & SUBCMDMASK;
 	if ((u_int)type >= MAXQUOTAS)
 		return (EINVAL);
-	if (vfs_busy(mp, LK_NOWAIT, 0, td))
+	if (vfs_busy(mp, LK_NOWAIT, NULL, td))
 		return (0);
 
 	switch (cmd) {
Index: vfs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_vnops.c,v
retrieving revision 1.10
diff -u -r1.10 ufs_vnops.c
--- vfs/ufs/ufs_vnops.c	23 Sep 2003 05:03:53 -0000	1.10
+++ vfs/ufs/ufs_vnops.c	22 Feb 2004 19:07:55 -0000
@@ -293,11 +293,12 @@
 	} */ *ap;
 {
 	struct vnode *vp = ap->a_vp;
+	lwkt_tokref vlock;
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (vp->v_usecount > 1)
 		ufs_itimes(vp);
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	return (0);
 }
 
@@ -747,7 +748,7 @@
 		error = EXDEV;
 		goto out2;
 	}
-	if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) {
+	if (tdvp != vp && (error = vn_lock(vp, NULL, LK_EXCLUSIVE, td))) {
 		goto out2;
 	}
 	ip = VTOI(vp);
@@ -779,7 +780,7 @@
 	}
 out1:
 	if (tdvp != vp)
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 out2:
 	VN_KNOTE(vp, NOTE_LINK);
 	VN_KNOTE(tdvp, NOTE_WRITE);
@@ -927,18 +928,18 @@
 		goto abortit;
 	}
 
-	if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0)
+	if ((error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td)) != 0)
 		goto abortit;
 	dp = VTOI(fdvp);
 	ip = VTOI(fvp);
 	if (ip->i_nlink >= LINK_MAX) {
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		error = EMLINK;
 		goto abortit;
 	}
 	if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
 	    || (dp->i_flags & APPEND)) {
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		error = EPERM;
 		goto abortit;
 	}
@@ -949,7 +950,7 @@
 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
 		    dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & CNP_ISDOTDOT ||
 		    (ip->i_flag & IN_RENAME)) {
-			VOP_UNLOCK(fvp, 0, td);
+			VOP_UNLOCK(fvp, NULL, 0, td);
 			error = EINVAL;
 			goto abortit;
 		}
@@ -982,7 +983,7 @@
 		softdep_change_linkcnt(ip);
 	if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) |
 				       DOINGASYNC(fvp)))) != 0) {
-		VOP_UNLOCK(fvp, 0, td);
+		VOP_UNLOCK(fvp, NULL, 0, td);
 		goto bad;
 	}
 
@@ -997,7 +998,7 @@
 	 * call to checkpath().
 	 */
 	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td);
-	VOP_UNLOCK(fvp, 0, td);
+	VOP_UNLOCK(fvp, NULL, 0, td);
 	if (oldparent != dp->i_number)
 		newparent = dp->i_number;
 	if (doingdirectory && newparent) {
@@ -1215,7 +1216,7 @@
 out:
 	if (doingdirectory)
 		ip->i_flag &= ~IN_RENAME;
-	if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
+	if (vn_lock(fvp, NULL, LK_EXCLUSIVE, td) == 0) {
 		ip->i_effnlink--;
 		ip->i_nlink--;
 		ip->i_flag |= IN_CHANGE;
@@ -1841,11 +1842,12 @@
 	} */ *ap;
 {
 	struct vnode *vp = ap->a_vp;
+	lwkt_tokref vlock;
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (vp->v_usecount > 1)
 		ufs_itimes(vp);
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
 
@@ -1915,11 +1917,12 @@
 	} */ *ap;
 {
 	struct vnode *vp = ap->a_vp;
+	lwkt_tokref vlock;
 
-	lwkt_gettoken(&vp->v_interlock);
+	lwkt_gettoken(&vlock, vp->v_interlock);
 	if (vp->v_usecount > 1)
 		ufs_itimes(vp);
-	lwkt_reltoken(&vp->v_interlock);
+	lwkt_reltoken(&vlock);
 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }
 
@@ -2188,6 +2191,7 @@
 {
 	struct vnode *vp = ap->a_vp;
 	struct knote *kn = ap->a_kn;
+	lwkt_tokref ilock;
 
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
@@ -2205,9 +2209,9 @@
 
 	kn->kn_hook = (caddr_t)vp;
 
-	lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+	lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
 	SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext);
-	lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+	lwkt_reltoken(&ilock);
 
 	return (0);
 }
@@ -2216,11 +2220,12 @@
 filt_ufsdetach(struct knote *kn)
 {
 	struct vnode *vp = (struct vnode *)kn->kn_hook;
+	lwkt_tokref ilock;
 
-	lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+	lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
 	SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note,
 	    kn, knote, kn_selnext);
-	lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+	lwkt_reltoken(&ilock);
 }
 
 /*ARGSUSED*/
Index: vfs/umapfs/umap_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/umapfs/umap_subr.c,v
retrieving revision 1.5
diff -u -r1.5 umap_subr.c
--- vfs/umapfs/umap_subr.c	20 Aug 2003 09:56:34 -0000	1.5
+++ vfs/umapfs/umap_subr.c	22 Feb 2004 06:17:17 -0000
@@ -168,7 +168,7 @@
 			 * stuff, but we don't want to lock
 			 * the lower node.
 			 */
-			if (vget(vp, 0, td)) {
+			if (vget(vp, NULL, 0, td)) {
 #ifdef DEBUG
 				printf ("umap_node_find: vget failed.\n");
 #endif
Index: vfs/umapfs/umap_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/umapfs/umap_vfsops.c,v
retrieving revision 1.8
diff -u -r1.8 umap_vfsops.c
--- vfs/umapfs/umap_vfsops.c	23 Sep 2003 05:03:54 -0000	1.8
+++ vfs/umapfs/umap_vfsops.c	22 Feb 2004 06:00:43 -0000
@@ -204,7 +204,7 @@
 	/*
 	 * Unlock the node (either the lower or the alias)
 	 */
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	/*
 	 * Make sure the node alias worked
 	 */
@@ -307,7 +307,7 @@
 	 */
 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
 	VREF(vp);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	*vpp = vp;
 	return (0);
 }
Index: vfs/umapfs/umap_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/umapfs/umap_vnops.c,v
retrieving revision 1.5
diff -u -r1.5 umap_vnops.c
--- vfs/umapfs/umap_vnops.c	20 Aug 2003 09:56:34 -0000	1.5
+++ vfs/umapfs/umap_vnops.c	22 Feb 2004 06:22:08 -0000
@@ -359,6 +359,7 @@
 umap_lock(ap)
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct thread *a_td;
 	} */ *ap;
@@ -407,7 +408,7 @@
 	 *
 	 */
 	VOP_INACTIVE(lowervp, ap->a_td);
-	VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
+	VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td);
 	return (0);
 }
 
Index: vfs/union/union_subr.c
===================================================================
RCS file: /cvs/src/sys/vfs/union/union_subr.c,v
retrieving revision 1.9
diff -u -r1.9 union_subr.c
--- vfs/union/union_subr.c	9 Oct 2003 22:27:27 -0000	1.9
+++ vfs/union/union_subr.c	22 Feb 2004 06:17:29 -0000
@@ -403,7 +403,7 @@
 			    (un->un_uppervp == uppervp ||
 			     un->un_uppervp == NULLVP) &&
 			    (UNIONTOV(un)->v_mount == mp)) {
-				if (vget(UNIONTOV(un), 0,
+				if (vget(UNIONTOV(un), NULL, 0,
 				    cnp ? cnp->cn_td : NULL)) {
 					union_list_unlock(hash);
 					goto loop;
@@ -444,21 +444,21 @@
 				 * while moving up the tree).
 				 */
 				VREF(dvp);
-				VOP_UNLOCK(dvp, 0, td);
-				error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td);
-				vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+				VOP_UNLOCK(dvp, NULL, 0, td);
+				error = vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE, td);
+				vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				vrele(dvp);
 			} else {
 				/*
 				 * our new un is under dvp
 				 */
-				error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td);
+				error = vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE, td);
 			}
 		} else if (dvp == NULLVP) {
 			/*
 			 * dvp is NULL, we need to lock un.
 			 */
-			error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td);
+			error = vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE, td);
 		} else {
 			/*
 			 * dvp == un->un_vnode, we are already locked.
@@ -567,7 +567,7 @@
 	bzero(un, sizeof(*un));
 
 	lockinit(&un->un_lock, 0, "unlock", VLKTIMEOUT, 0);
-	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	un->un_vnode = *vpp;
 	un->un_uppervp = uppervp;
@@ -749,9 +749,9 @@
 	 * If the user does not have read permission, the vnode should not
 	 * be copied to upper layer.
 	 */
-	vn_lock(un->un_lowervp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(un->un_lowervp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_ACCESS(un->un_lowervp, VREAD, cred, td);
-	VOP_UNLOCK(un->un_lowervp, 0, td);
+	VOP_UNLOCK(un->un_lowervp, NULL, 0, td);
 	if (error)
 		return (error);
 
@@ -767,20 +767,20 @@
 		 * XX - should not ignore errors
 		 * from VOP_CLOSE
 		 */
-		vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		error = VOP_OPEN(lvp, FREAD, cred, td);
 		if (error == 0 && vn_canvmio(lvp) == TRUE)
 			error = vfs_object_create(lvp, td);
 		if (error == 0) {
 			error = union_copyfile(lvp, uvp, cred, td);
-			VOP_UNLOCK(lvp, 0, td);
+			VOP_UNLOCK(lvp, NULL, 0, td);
 			(void) VOP_CLOSE(lvp, FREAD, td);
 		}
 		if (error == 0)
 			UDEBUG(("union: copied up %s\n", un->un_path));
 
 	}
-	VOP_UNLOCK(uvp, 0, td);
+	VOP_UNLOCK(uvp, NULL, 0, td);
 	union_newupper(un, uvp);
 	KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
 	union_vn_close(uvp, FWRITE, cred, td);
@@ -860,7 +860,7 @@
 	cn->cn_consume = cnp->cn_consume;
 
 	VREF(dvp);
-	VOP_UNLOCK(dvp, 0, cnp->cn_td);
+	VOP_UNLOCK(dvp, NULL, 0, cnp->cn_td);
 
 	/*
 	 * Pass dvp unlocked and referenced on call to relookup().
@@ -869,7 +869,7 @@
 	 */
 
 	if ((error = relookup(dvp, vpp, cn)) != 0) {
-		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_td);
+		vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, cnp->cn_td);
 		return(error);
 	}
 
@@ -1224,7 +1224,7 @@
 	struct union_node *un;
 	int error;
 
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	dircache = VTOUNION(vp)->un_dircache;
 
 	nvp = NULLVP;
@@ -1250,7 +1250,7 @@
 	if (*vpp == NULLVP)
 		goto out;
 
-	/*vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);*/
+	/*vn_lock(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td);*/
 	UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? (*vpp)->v_usecount : -99)));
 	VREF(*vpp);
 	error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, NULL, *vpp, NULLVP, 0);
@@ -1263,7 +1263,7 @@
 	un->un_dircache = dircache;
 
 out:
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	return (nvp);
 }
 
@@ -1335,7 +1335,7 @@
 				vput(lvp);
 				return (error);
 			}
-			VOP_UNLOCK(lvp, 0, td);
+			VOP_UNLOCK(lvp, NULL, 0, td);
 			fp->f_data = (caddr_t) lvp;
 			fp->f_offset = 0;
 			error = vn_close(*vp, FREAD, td);
Index: vfs/union/union_vfsops.c
===================================================================
RCS file: /cvs/src/sys/vfs/union/union_vfsops.c,v
retrieving revision 1.7
diff -u -r1.7 union_vfsops.c
--- vfs/union/union_vfsops.c	9 Oct 2003 22:27:27 -0000	1.7
+++ vfs/union/union_vfsops.c	22 Feb 2004 19:59:11 -0000
@@ -129,7 +129,7 @@
 	 * Unlock lower node to avoid deadlock.
 	 */
 	if (lowerrootvp->v_op == union_vnodeop_p)
-		VOP_UNLOCK(lowerrootvp, 0, td);
+		VOP_UNLOCK(lowerrootvp, NULL, 0, td);
 #endif
 
 	/*
@@ -143,7 +143,7 @@
 
 #if 0
 	if (lowerrootvp->v_op == union_vnodeop_p)
-		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(lowerrootvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 #endif
 	if (error)
 		goto bad;
@@ -341,6 +341,8 @@
 		for (n = 0, vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 		    vp != NULLVP;
 		    vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
+			if (vp->v_flag & VPLACEMARKER)	/* ZZZ */
+				continue;
 			n++;
 		}
 
Index: vfs/union/union_vnops.c
===================================================================
RCS file: /cvs/src/sys/vfs/union/union_vnops.c,v
retrieving revision 1.9
diff -u -r1.9 union_vnops.c
--- vfs/union/union_vnops.c	9 Oct 2003 22:27:27 -0000	1.9
+++ vfs/union/union_vnops.c	22 Feb 2004 06:24:12 -0000
@@ -116,7 +116,7 @@
 
 	if ((uppervp = un->un_uppervp) != NULL) {
 		VREF(uppervp);
-		vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
+		vn_lock(uppervp, NULL, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
 	}
 	KASSERT((uppervp == NULL || uppervp->v_usecount > 0), ("uppervp usecount is 0"));
 	return(uppervp);
@@ -139,7 +139,7 @@
 		vp = union_lock_upper(un, td);
 	} else if ((vp = un->un_lowervp) != NULL) {
 		VREF(vp);
-		vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
 	}
 	return(vp);
 }
@@ -202,7 +202,7 @@
 			dvp = dvp->v_mount->mnt_vnodecovered;
 			VREF(dvp);
 			vput(tdvp);
-			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		}
 	}
 
@@ -233,7 +233,7 @@
 	UDEBUG(("parentdir %p result %p flag %lx\n", dvp, tdvp, cnp->cn_flags));
 
 	if (dvp != tdvp && (cnp->cn_flags & CNP_ISLASTCN) == 0)
-		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 	/*
 	 * Lastly check if the current node is a mount point in
@@ -253,7 +253,7 @@
 	) {
 		int relock_pdvp = 0;
 
-		if (vfs_busy(mp, 0, 0, td))
+		if (vfs_busy(mp, 0, NULL, td))
 			continue;
 
 		if (dvp == *pdvp)
@@ -265,7 +265,7 @@
 		vfs_unbusy(mp, td);
 
 		if (relock_pdvp)
-			vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(*pdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 		if (error) {
 			*vpp = NULL;
@@ -446,7 +446,7 @@
 		 * to us so we NULL it out.
 		 */
 		VREF(lowerdvp);
-		vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(lowerdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp);
 		if (lowerdvp == lowervp)
 			vrele(lowerdvp);
@@ -470,7 +470,7 @@
 		if ((cnp->cn_flags & CNP_ISDOTDOT) && dun->un_pvp != NULLVP) {
 			if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) {
 				VREF(lowervp);
-				vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, td);
+				vn_lock(lowervp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 				lerror = 0;
 			}
 		}
@@ -533,11 +533,11 @@
 	 */
 
 	if (uppervp && uppervp != upperdvp)
-		VOP_UNLOCK(uppervp, 0, td);
+		VOP_UNLOCK(uppervp, NULL, 0, td);
 	if (lowervp)
-		VOP_UNLOCK(lowervp, 0, td);
+		VOP_UNLOCK(lowervp, NULL, 0, td);
 	if (upperdvp)
-		VOP_UNLOCK(upperdvp, 0, td);
+		VOP_UNLOCK(upperdvp, NULL, 0, td);
 
 	error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
 			      uppervp, lowervp, 1);
@@ -600,7 +600,7 @@
 	if (*ap->a_vpp != dvp) {
 		if ((error == 0 || error == EJUSTRETURN) &&
 		    (!lockparent || (cnp->cn_flags & CNP_ISLASTCN) == 0)) {
-			VOP_UNLOCK(dvp, 0, td);
+			VOP_UNLOCK(dvp, NULL, 0, td);
 		}
 	}
 
@@ -648,7 +648,7 @@
 		error = VOP_CREATE(dvp, NCPNULL, &vp, cnp, ap->a_vap);
 		if (error == 0) {
 			mp = ap->a_dvp->v_mount;
-			VOP_UNLOCK(vp, 0, td);
+			VOP_UNLOCK(vp, NULL, 0, td);
 			UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_usecount));
 			error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
 				cnp, vp, NULLVP, 1);
@@ -756,7 +756,7 @@
 		} else {
 			un->un_openl++;
 			VREF(tvp);
-			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(tvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 			tvpisupper = 0;
 		}
 	}
@@ -864,7 +864,7 @@
 	}
 
 	if ((vp = un->un_lowervp) != NULLVP) {
-		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 		ap->a_vp = vp;
 
 		/*
@@ -885,7 +885,7 @@
 				error = VCALL(vp, VOFFSET(vop_access), ap);
 			}
 		}
-		VOP_UNLOCK(vp, 0, td);
+		VOP_UNLOCK(vp, NULL, 0, td);
 	}
 	return(error);
 }
@@ -1317,24 +1317,24 @@
 		struct union_node *tun = VTOUNION(ap->a_vp);
 
 		if (tun->un_uppervp == NULLVP) {
-			vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
+			vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 #if 0
 			if (dun->un_uppervp == tun->un_dirvp) {
 				if (dun->un_flags & UN_ULOCK) {
 					dun->un_flags &= ~UN_ULOCK;
-					VOP_UNLOCK(dun->un_uppervp, 0, td);
+					VOP_UNLOCK(dun->un_uppervp, NULL, 0, td);
 				}
 			}
 #endif
 			error = union_copyup(tun, 1, cnp->cn_cred, td);
 #if 0
 			if (dun->un_uppervp == tun->un_dirvp) {
-				vn_lock(dun->un_uppervp,
+				vn_lock(dun->un_uppervp, NULL,
 					    LK_EXCLUSIVE | LK_RETRY, td);
 				dun->un_flags |= UN_ULOCK;
 			}
 #endif
-			VOP_UNLOCK(ap->a_vp, 0, td);
+			VOP_UNLOCK(ap->a_vp, NULL, 0, td);
 		}
 		vp = tun->un_uppervp;
 	}
@@ -1352,15 +1352,15 @@
 	if ((tdvp = union_lock_upper(dun, td)) == NULLVP)
 		return (EROFS);
 
-	VOP_UNLOCK(ap->a_tdvp, 0, td);		/* unlock calling node */
-	error = VOP_LINK(tdvp, NCPNULL, vp, cnp);	/* call link on upper */
+	VOP_UNLOCK(ap->a_tdvp, NULL, 0, td);	/* unlock calling node */
+	error = VOP_LINK(tdvp, NCPNULL, vp, cnp); /* call link on upper */
 
 	/*
 	 * We have to unlock tdvp prior to relocking our calling node in
 	 * order to avoid a deadlock.
 	 */
 	union_unlock_upper(tdvp, td);
-	vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(ap->a_tdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	return (error);
 }
 
@@ -1417,9 +1417,9 @@
 		if (un->un_uppervp == NULLVP) {
 			switch(fvp->v_type) {
 			case VREG:
-				vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td);
+				vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td);
 				error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_td);
-				VOP_UNLOCK(un->un_vnode, 0, ap->a_fcnp->cn_td);
+				VOP_UNLOCK(un->un_vnode, NULL, 0, ap->a_fcnp->cn_td);
 				if (error)
 					goto bad;
 				break;
@@ -1435,12 +1435,12 @@
 #if 0
 				vrele(fvp);
 				fvp = NULL;
-				vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td);
+				vn_lock(fdvp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td);
 				error = union_mkshadow(um, fdvp, 
 					    ap->a_fcnp, &un->un_uppervp);
-				VOP_UNLOCK(fdvp, 0, ap->a_fcnp->cn_td);
+				VOP_UNLOCK(fdvp, NULL, 0, ap->a_fcnp->cn_td);
 				if (un->un_uppervp)
-					VOP_UNLOCK(un->un_uppervp, 0, ap->a_fcnp->cn_td);
+					VOP_UNLOCK(un->un_uppervp, NULL, 0, ap->a_fcnp->cn_td);
 				if (error)
 					goto bad;
 				break;
@@ -1551,7 +1551,7 @@
 		union_unlock_upper(upperdvp, td);
 
 		if (error == 0) {
-			VOP_UNLOCK(vp, 0, td);
+			VOP_UNLOCK(vp, NULL, 0, td);
 			UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_usecount));
 			error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
 				ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
@@ -1721,11 +1721,11 @@
 #if 0
 	if ((un->un_flags & UN_ULOCK) && un->un_uppervp) {
 		un->un_flags &= ~UN_ULOCK;
-		VOP_UNLOCK(un->un_uppervp, 0, td);
+		VOP_UNLOCK(un->un_uppervp, NULL, 0, td);
 	}
 #endif
 
-	VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 
 	if ((un->un_flags & UN_CACHED) == 0)
 		vgone(vp);
@@ -1768,10 +1768,12 @@
 		if (un->un_uppervp != NULLVP && 
 		    (flags & LK_TYPE_MASK) == LK_EXCLUSIVE) {
 			if ((un->un_flags & UN_ULOCK) == 0 && vp->v_usecount) {
-				error = vn_lock(un->un_uppervp, flags, td);
+				error = vn_lock(un->un_uppervp, ap->a_vlock,
+						flags, td);
 				if (error) {
 					struct vop_unlock_args uap = { 0 };
 					uap.a_vp = ap->a_vp;
+					uap.a_vlock = ap->a_vlock;
 					uap.a_flags = ap->a_flags;
 					uap.a_td = ap->a_td;
 					vop_stdunlock(&uap);
@@ -1794,6 +1796,7 @@
 union_unlock(ap)
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		lwkt_tokref_t a_vlock;
 		int a_flags;
 		struct thread *a_td;
 	} */ *ap;
@@ -1816,7 +1819,7 @@
 	if ((un->un_flags & UN_ULOCK) && 
 	    lockstatus(&un->un_lock, NULL) != LK_EXCLUSIVE) {
 		un->un_flags &= ~UN_ULOCK;
-		VOP_UNLOCK(un->un_uppervp, LK_EXCLUSIVE, td);
+		VOP_UNLOCK(un->un_uppervp, NULL, LK_EXCLUSIVE, td);
 	}
 #endif
 	return(error);
Index: vm/vm_contig.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_contig.c,v
retrieving revision 1.5
diff -u -r1.5 vm_contig.c
--- vm/vm_contig.c	18 Feb 2004 16:28:21 -0000	1.5
+++ vm/vm_contig.c	22 Feb 2004 06:02:28 -0000
@@ -126,10 +126,10 @@
 		if (m->dirty) {
 			object = m->object;
 			if (object->type == OBJT_VNODE) {
-				vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY,
-					curthread);
+				vn_lock(object->handle, NULL,
+					LK_EXCLUSIVE | LK_RETRY, curthread);
 				vm_object_page_clean(object, 0, 0, OBJPC_SYNC);
-				VOP_UNLOCK(object->handle, 0, curthread);
+				VOP_UNLOCK(object->handle, NULL, 0, curthread);
 				return (TRUE);
 			} else if (object->type == OBJT_SWAP ||
 					object->type == OBJT_DEFAULT) {
Index: vm/vm_extern.h
===================================================================
RCS file: /cvs/src/sys/vm/vm_extern.h,v
retrieving revision 1.9
diff -u -r1.9 vm_extern.h
--- vm/vm_extern.h	20 Jan 2004 18:41:52 -0000	1.9
+++ vm/vm_extern.h	23 Feb 2004 00:21:38 -0000
@@ -70,7 +70,6 @@
 void kmem_free (vm_map_t, vm_offset_t, vm_size_t);
 void kmem_free_wakeup (vm_map_t, vm_offset_t, vm_size_t);
 void kmem_init (vm_offset_t, vm_offset_t);
-void kmem_cpu_init (void);
 vm_offset_t kmem_malloc (vm_map_t, vm_size_t, boolean_t);
 vm_map_t kmem_suballoc (vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t);
 void munmapfd (struct proc *, int);
Index: vm/vm_fault.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_fault.c,v
retrieving revision 1.10
diff -u -r1.10 vm_fault.c
--- vm/vm_fault.c	20 Jan 2004 05:04:08 -0000	1.10
+++ vm/vm_fault.c	22 Feb 2004 05:26:34 -0000
@@ -649,7 +649,7 @@
 				 * grab the lock if we need to
 				 */
 				(fs.lookup_still_valid ||
-				 lockmgr(&fs.map->lock, LK_EXCLUSIVE|LK_NOWAIT, (void *)0, curthread) == 0)
+				 lockmgr(&fs.map->lock, LK_EXCLUSIVE|LK_NOWAIT, NULL, curthread) == 0)
 			    ) {
 				
 				fs.lookup_still_valid = 1;
Index: vm/vm_glue.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_glue.c,v
retrieving revision 1.19
diff -u -r1.19 vm_glue.c
--- vm/vm_glue.c	14 Jan 2004 23:26:14 -0000	1.19
+++ vm/vm_glue.c	22 Feb 2004 05:26:41 -0000
@@ -498,7 +498,7 @@
 			 */
 			if (lockmgr(&vm->vm_map.lock,
 					LK_EXCLUSIVE | LK_NOWAIT,
-					(void *)0, curthread)) {
+					NULL, curthread)) {
 				vmspace_free(vm);
 				continue;
 			}
Index: vm/vm_init.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_init.c,v
retrieving revision 1.4
diff -u -r1.4 vm_init.c
--- vm/vm_init.c	27 Aug 2003 01:43:08 -0000	1.4
+++ vm/vm_init.c	23 Feb 2004 03:38:00 -0000
@@ -113,7 +113,6 @@
 	vm_object_init();
 	vm_map_startup();
 	kmem_init(virtual_avail, virtual_end);
-	kmem_cpu_init();
 	pmap_init(avail_start, avail_end);
 	vm_pager_init();
 }
Index: vm/vm_kern.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_kern.c,v
retrieving revision 1.14
diff -u -r1.14 vm_kern.c
--- vm/vm_kern.c	20 Jan 2004 05:04:08 -0000	1.14
+++ vm/vm_kern.c	23 Feb 2004 00:18:43 -0000
@@ -536,17 +536,3 @@
 	vm_map_entry_release(count);
 }
 
-/*
- *	kmem_cpu_init:
- *
- *	Load up extra vm_map_entry structures in each cpu's globaldata
- *	cache.  These allow us to expand the mapent zone for kernel_map.
- *	Without them we would get into a recursion deadlock trying to
- *	reserve map entries (reserve->zalloc->kmem_alloc->reserve->...)
- */
-void
-kmem_cpu_init(void)
-{
-	vm_map_entry_reserve(MAP_RESERVE_COUNT * 2);
-}
-
Index: vm/vm_map.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_map.c,v
retrieving revision 1.21
diff -u -r1.21 vm_map.c
--- vm/vm_map.c	20 Jan 2004 18:41:52 -0000	1.21
+++ vm/vm_map.c	23 Feb 2004 03:37:19 -0000
@@ -330,6 +330,22 @@
 }
 
 /*
+ *      vm_map_entry_cpu_init:
+ *
+ *	Set an initial negative count so the first attempt to reserve
+ *	space preloads a bunch of vm_map_entry's for this cpu.  This
+ *	routine is called in early boot so we cannot just call
+ *	vm_map_entry_reserve().
+ *
+ *	May be called for a gd other then mycpu.
+ */
+void
+vm_map_entry_reserve_cpu_init(globaldata_t gd)
+{
+	gd->gd_vme_avail -= MAP_RESERVE_COUNT * 2;
+}
+
+/*
  *	vm_map_entry_reserve:
  *
  *	Reserves vm_map_entry structures so code later on can manipulate
@@ -2188,14 +2204,15 @@
 			int flags;
 
 			vm_object_reference(object);
-			vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curthread);
+			vn_lock(object->handle, NULL,
+				LK_EXCLUSIVE | LK_RETRY, curthread);
 			flags = (syncio || invalidate) ? OBJPC_SYNC : 0;
 			flags |= invalidate ? OBJPC_INVAL : 0;
 			vm_object_page_clean(object,
 			    OFF_TO_IDX(offset),
 			    OFF_TO_IDX(offset + size + PAGE_MASK),
 			    flags);
-			VOP_UNLOCK(object->handle, 0, curthread);
+			VOP_UNLOCK(object->handle, NULL, 0, curthread);
 			vm_object_deallocate(object);
 		}
 		if (object && invalidate &&
Index: vm/vm_map.h
===================================================================
RCS file: /cvs/src/sys/vm/vm_map.h,v
retrieving revision 1.11
diff -u -r1.11 vm_map.h
--- vm/vm_map.h	20 Jan 2004 18:41:52 -0000	1.11
+++ vm/vm_map.h	23 Feb 2004 01:20:28 -0000
@@ -257,20 +257,13 @@
  *		as unbraced elements in a higher level statement.
  */
 
-#define	vm_map_lock_drain_interlock(map) \
-	do { \
-		lockmgr(&(map)->lock, LK_DRAIN|LK_INTERLOCK, \
-			&(map)->ref_lock, curthread); \
-		(map)->timestamp++; \
-	} while(0)
-
 #ifdef DIAGNOSTIC
 /* #define MAP_LOCK_DIAGNOSTIC 1 */
 #ifdef MAP_LOCK_DIAGNOSTIC
 #define	vm_map_lock(map) \
 	do { \
 		printf ("locking map LK_EXCLUSIVE: 0x%x\n", map); \
-		if (lockmgr(&(map)->lock, LK_EXCLUSIVE, (void *)0, curthread) != 0) { \
+		if (lockmgr(&(map)->lock, LK_EXCLUSIVE, NULL, curthread) != 0) { \
 			panic("vm_map_lock: failed to get lock"); \
 		} \
 		(map)->timestamp++; \
@@ -278,7 +271,7 @@
 #else
 #define	vm_map_lock(map) \
 	do { \
-		if (lockmgr(&(map)->lock, LK_EXCLUSIVE, (void *)0, curthread) != 0) { \
+		if (lockmgr(&(map)->lock, LK_EXCLUSIVE, NULL, curthread) != 0) { \
 			panic("vm_map_lock: failed to get lock"); \
 		} \
 		(map)->timestamp++; \
@@ -287,7 +280,7 @@
 #else
 #define	vm_map_lock(map) \
 	do { \
-		lockmgr(&(map)->lock, LK_EXCLUSIVE, (void *)0, curthread); \
+		lockmgr(&(map)->lock, LK_EXCLUSIVE, NULL, curthread); \
 		(map)->timestamp++; \
 	} while(0)
 #endif /* DIAGNOSTIC */
@@ -296,25 +289,25 @@
 #define	vm_map_unlock(map) \
 	do { \
 		printf ("locking map LK_RELEASE: 0x%x\n", map); \
-		lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curthread); \
+		lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread); \
 	} while (0)
 #define	vm_map_lock_read(map) \
 	do { \
 		printf ("locking map LK_SHARED: 0x%x\n", map); \
-		lockmgr(&(map)->lock, LK_SHARED, (void *)0, curthread); \
+		lockmgr(&(map)->lock, LK_SHARED, NULL, curthread); \
 	} while (0)
 #define	vm_map_unlock_read(map) \
 	do { \
 		printf ("locking map LK_RELEASE: 0x%x\n", map); \
-		lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curthread); \
+		lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread); \
 	} while (0)
 #else
 #define	vm_map_unlock(map) \
-	lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curthread)
+	lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread)
 #define	vm_map_lock_read(map) \
-	lockmgr(&(map)->lock, LK_SHARED, (void *)0, curthread) 
+	lockmgr(&(map)->lock, LK_SHARED, NULL, curthread) 
 #define	vm_map_unlock_read(map) \
-	lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curthread)
+	lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread)
 #endif
 
 static __inline__ int
@@ -323,7 +316,7 @@
 #if defined(MAP_LOCK_DIAGNOSTIC)
 	printf("locking map LK_EXCLUPGRADE: 0x%x\n", map); 
 #endif
-	error = lockmgr(&map->lock, LK_EXCLUPGRADE, (void *)0, td);
+	error = lockmgr(&map->lock, LK_EXCLUPGRADE, NULL, td);
 	if (error == 0)
 		map->timestamp++;
 	return error;
@@ -335,24 +328,26 @@
 #define vm_map_lock_downgrade(map) \
 	do { \
 		printf ("locking map LK_DOWNGRADE: 0x%x\n", map); \
-		lockmgr(&(map)->lock, LK_DOWNGRADE, (void *)0, curthread); \
+		lockmgr(&(map)->lock, LK_DOWNGRADE, NULL, curthread); \
 	} while (0)
 #else
 #define vm_map_lock_downgrade(map) \
-	lockmgr(&(map)->lock, LK_DOWNGRADE, (void *)0, curthread)
+	lockmgr(&(map)->lock, LK_DOWNGRADE, NULL, curthread)
 #endif
 
 #define vm_map_set_recursive(map) \
 	do { \
-		lwkt_gettoken(&(map)->lock.lk_interlock); \
+		lwkt_tokref ilock; \
+		lwkt_gettoken(&ilock, &(map)->lock.lk_interlock); \
 		(map)->lock.lk_flags |= LK_CANRECURSE; \
-		lwkt_reltoken(&(map)->lock.lk_interlock); \
+		lwkt_reltoken(&ilock); \
 	} while(0)
 #define vm_map_clear_recursive(map) \
 	do { \
-		lwkt_gettoken(&(map)->lock.lk_interlock); \
+		lwkt_tokref ilock; \
+		lwkt_gettoken(&ilock, &(map)->lock.lk_interlock); \
 		(map)->lock.lk_flags &= ~LK_CANRECURSE; \
-		lwkt_reltoken(&(map)->lock.lk_interlock); \
+		lwkt_reltoken(&ilock); \
 	} while(0)
 
 /*
@@ -406,6 +401,8 @@
 #ifdef _KERNEL
 boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t);
 struct pmap;
+struct globaldata;
+void vm_map_entry_reserve_cpu_init(struct globaldata *gd);
 int vm_map_entry_reserve(int);
 int vm_map_entry_kreserve(int);
 void vm_map_entry_release(int);
Index: vm/vm_object.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_object.c,v
retrieving revision 1.12
diff -u -r1.12 vm_object.c
--- vm/vm_object.c	11 Nov 2003 01:35:36 -0000	1.12
+++ vm/vm_object.c	22 Feb 2004 19:08:01 -0000
@@ -200,7 +200,7 @@
 vm_object_init()
 {
 	TAILQ_INIT(&vm_object_list);
-	lwkt_inittoken(&vm_object_list_token);
+	lwkt_token_init(&vm_object_list_token);
 	vm_object_count = 0;
 	
 	kernel_object = &kernel_object_store;
@@ -263,7 +263,8 @@
 
 	object->ref_count++;
 	if (object->type == OBJT_VNODE) {
-		while (vget((struct vnode *) object->handle, LK_RETRY|LK_NOOBJ, curthread)) {
+		while (vget((struct vnode *) object->handle, NULL,
+		    LK_RETRY|LK_NOOBJ, curthread)) {
 			printf("vm_object_reference: delay in getting object\n");
 		}
 	}
@@ -412,6 +413,7 @@
 vm_object_terminate(object)
 	vm_object_t object;
 {
+	lwkt_tokref ilock;
 	vm_page_t p;
 	int s;
 
@@ -486,9 +488,9 @@
 	/*
 	 * Remove the object from the global object list.
 	 */
-	lwkt_gettoken(&vm_object_list_token);
+	lwkt_gettoken(&ilock, &vm_object_list_token);
 	TAILQ_REMOVE(&vm_object_list, object, object_list);
-	lwkt_reltoken(&vm_object_list_token);
+	lwkt_reltoken(&ilock);
 
 	wakeup(object);
 
@@ -528,6 +530,7 @@
 	int clearobjflags;
 	int pagerflags;
 	int curgeneration;
+	lwkt_tokref vlock;
 
 	if (object->type != OBJT_VNODE ||
 		(object->flags & OBJ_MIGHTBEDIRTY) == 0)
@@ -644,9 +647,9 @@
                 if (object->type == OBJT_VNODE &&
                     (vp = (struct vnode *)object->handle) != NULL) {
                         if (vp->v_flag & VOBJDIRTY) {
-                                lwkt_gettoken(&vp->v_interlock);
+                                lwkt_gettoken(&vlock, vp->v_interlock);
                                 vp->v_flag &= ~VOBJDIRTY;
-                                lwkt_reltoken(&vp->v_interlock);
+                                lwkt_reltoken(&vlock);
                         }
                 }
 	}
@@ -1705,14 +1708,15 @@
 vm_object_set_writeable_dirty(vm_object_t object)
 {
 	struct vnode *vp;
+	lwkt_tokref vlock;
 
 	vm_object_set_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
 	if (object->type == OBJT_VNODE &&
 	    (vp = (struct vnode *)object->handle) != NULL) {
 		if ((vp->v_flag & VOBJDIRTY) == 0) {
-			lwkt_gettoken(&vp->v_interlock);
+			lwkt_gettoken(&vlock, vp->v_interlock);
 			vp->v_flag |= VOBJDIRTY;
-			lwkt_reltoken(&vp->v_interlock);
+			lwkt_reltoken(&vlock);
 		}
 	}
 }
Index: vm/vm_pageout.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_pageout.c,v
retrieving revision 1.8
diff -u -r1.8 vm_pageout.c
--- vm/vm_pageout.c	20 Aug 2003 08:03:01 -0000	1.8
+++ vm/vm_pageout.c	22 Feb 2004 06:17:46 -0000
@@ -546,7 +546,7 @@
 	vm_object_t obj, bigobj;
 	int nothingwired;
 
-	if (lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, (void *)0, curthread)) {
+	if (lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, NULL, curthread)) {
 		return;
 	}
 
@@ -768,28 +768,37 @@
 		 * the page being dirty, we have to check for it again.  As 
 		 * far as the VM code knows, any partially dirty pages are 
 		 * fully dirty.
+		 *
+		 * Pages marked PG_WRITEABLE may be mapped into the user
+		 * address space of a process running on another cpu.  A
+		 * user process (without holding the MP lock) running on
+		 * another cpu may be able to touch the page while we are
+		 * trying to remove it.  To prevent this from occuring we
+		 * must call pmap_remove_all() or otherwise make the page
+		 * read-only.  If the race occured pmap_remove_all() is
+		 * responsible for setting m->dirty.
 		 */
 		if (m->dirty == 0) {
 			vm_page_test_dirty(m);
+#if 0
+			if (m->dirty == 0 && (m->flags & PG_WRITEABLE) != 0)
+				pmap_remove_all(m);
+#endif
 		} else {
 			vm_page_dirty(m);
 		}
 
-		/*
-		 * Invalid pages can be easily freed
-		 */
 		if (m->valid == 0) {
+			/*
+			 * Invalid pages can be easily freed
+			 */
 			vm_pageout_page_free(m);
 			mycpu->gd_cnt.v_dfree++;
 			--page_shortage;
-
-		/*
-		 * Clean pages can be placed onto the cache queue.  This
-		 * effectively frees them.
-		 */
 		} else if (m->dirty == 0) {
 			/*
-			 * Clean pages can be immediately freed to the cache.
+			 * Clean pages can be placed onto the cache queue.
+			 * This effectively frees them.
 			 */
 			vm_page_cache(m);
 			--page_shortage;
@@ -868,7 +877,7 @@
 			if (object->type == OBJT_VNODE) {
 				vp = object->handle;
 
-				if (vget(vp, LK_EXCLUSIVE|LK_NOOBJ|LK_TIMELOCK, curthread)) {
+				if (vget(vp, NULL, LK_EXCLUSIVE|LK_NOOBJ|LK_TIMELOCK, curthread)) {
 					++pageout_lock_miss;
 					if (object->flags & OBJ_MIGHTBEDIRTY)
 						    vnodes_skipped++;
Index: vm/vm_swap.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_swap.c,v
retrieving revision 1.9
diff -u -r1.9 vm_swap.c
--- vm/vm_swap.c	23 Sep 2003 05:03:54 -0000	1.9
+++ vm/vm_swap.c	22 Feb 2004 06:02:45 -0000
@@ -264,9 +264,9 @@
 	}
 	return EINVAL;
     found:
-	(void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_OPEN(vp, FREAD | FWRITE, cred, td);
-	(void) VOP_UNLOCK(vp, 0, td);
+	VOP_UNLOCK(vp, NULL, 0, td);
 	if (error)
 		return (error);
 
Index: vm/vm_zone.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_zone.c,v
retrieving revision 1.13
diff -u -r1.13 vm_zone.c
--- vm/vm_zone.c	20 Jan 2004 05:04:08 -0000	1.13
+++ vm/vm_zone.c	22 Feb 2004 07:20:32 -0000
@@ -51,12 +51,13 @@
 zalloc(vm_zone_t z)
 {
 	void *item;
+	lwkt_tokref ilock;
 
 #ifdef INVARIANTS
 	if (z == NULL)
 		zerror(ZONE_ERROR_INVALID);
 #endif
-	lwkt_gettoken(&z->zlock);
+	lwkt_gettoken(&ilock, &z->zlock);
 	if (z->zfreecnt <= z->zfreemin) {
 		item = zget(z);
 		/*
@@ -77,7 +78,7 @@
 		z->zfreecnt--;
 		z->znalloc++;
 	}
-	lwkt_reltoken(&z->zlock);
+	lwkt_reltoken(&ilock);
 	return item;
 }
 
@@ -88,7 +89,9 @@
 void
 zfree(vm_zone_t z, void *item)
 {
-	lwkt_gettoken(&z->zlock);
+	lwkt_tokref ilock;
+
+	lwkt_gettoken(&ilock, &z->zlock);
 	((void **) item)[0] = z->zitems;
 #ifdef INVARIANTS
 	if (((void **) item)[1] == (void *) ZENTRY_FREE)
@@ -97,7 +100,7 @@
 #endif
 	z->zitems = item;
 	z->zfreecnt++;
-	lwkt_reltoken(&z->zlock);
+	lwkt_reltoken(&ilock);
 }
 
 /*
@@ -151,7 +154,7 @@
 
 	if ((z->zflags & ZONE_BOOT) == 0) {
 		z->zsize = (size + ZONE_ROUNDING - 1) & ~(ZONE_ROUNDING - 1);
-		lwkt_inittoken(&z->zlock);
+		lwkt_token_init(&z->zlock);
 		z->zfreecnt = 0;
 		z->ztotal = 0;
 		z->zmax = 0;
@@ -256,7 +259,7 @@
 	z->zpagecount = 0;
 	z->zalloc = 0;
 	z->znalloc = 0;
-	lwkt_inittoken(&z->zlock);
+	lwkt_token_init(&z->zlock);
 
 	bzero(item, nitems * z->zsize);
 	z->zitems = NULL;
@@ -314,9 +317,9 @@
 
 			m = vm_page_alloc(z->zobj, z->zpagecount,
 					  z->zallocflag);
+			/* note: z might be modified due to blocking */
 			if (m == NULL)
 				break;
-			lwkt_regettoken(&z->zlock);
 
 			zkva = z->zkva + z->zpagecount * PAGE_SIZE;
 			pmap_kenter(zkva, VM_PAGE_TO_PHYS(m)); /* YYY */
@@ -331,7 +334,7 @@
 
 		{
 			item = (void *)kmem_alloc3(kernel_map, nbytes, KM_KRESERVE);
-			lwkt_regettoken(&z->zlock);
+			/* note: z might be modified due to blocking */
 			if (item != NULL)
 				zone_kern_pages += z->zalloc;
 		}
Index: vm/vnode_pager.c
===================================================================
RCS file: /cvs/src/sys/vm/vnode_pager.c,v
retrieving revision 1.10
diff -u -r1.10 vnode_pager.c
--- vm/vnode_pager.c	20 Aug 2003 08:03:01 -0000	1.10
+++ vm/vnode_pager.c	22 Feb 2004 06:17:57 -0000
@@ -1050,7 +1050,7 @@
 		if (object->flags & OBJ_DEAD)
 			return NULL;
 
-		while (vget(object->handle,
+		while (vget(object->handle, NULL,
 			LK_NOPAUSE | LK_SHARED | LK_RETRY | LK_CANRECURSE, td)) {
 			if ((object->flags & OBJ_DEAD) ||
 			    (object->type != OBJT_VNODE)) {
