From 41a01a4df889ac2e479e7d4691c3a044d76b0407 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 1 Mar 2004 06:33:24 +0000 Subject: [PATCH] Newtoken commit. Change the token implementation as follows: (1) Obtaining a token no longer enters a critical section. (2) tokens can be held through schedular switches and blocking conditions and are effectively released and reacquired on resume. Thus tokens serialize access only while the thread is actually running. Serialization is not broken by preemptive interrupts. That is, interrupt threads which preempt do no release the preempted thread's tokens. (3) Unlike spl's, tokens will interlock w/ interrupt threads on the same or on a different cpu. The vnode interlock code has been rewritten and the API has changed. The mountlist vnode scanning code has been consolidated and all known races have been fixed. The vnode interlock is now a pool token. The code that frees unreferenced vnodes whos last VM page has been freed has been moved out of the low level vm_page_free() code and moved to the periodic filesystem sycer code in vfs_msycn(). The SMP startup code and the IPI code has been cleaned up considerably. Certain early token interactions on AP cpus have been moved to the BSP. The LWKT rwlock API has been cleaned up and turned on. Major testing by: David Rhodus --- sys/config/LINT | 4 +- sys/ddb/db_ps.c | 90 +- sys/dev/acpica5/Osd/OsdSynch.c | 26 +- sys/dev/acpica5/acpi_ec.c | 18 +- sys/dev/agp/agp.c | 14 +- sys/dev/disk/ccd/ccd.c | 6 +- sys/dev/disk/vn/vn.c | 14 +- sys/dev/drm/drm_os_freebsd.h | 14 +- sys/dev/pccard/pccbb/pccbb.c | 16 +- sys/dev/raid/aac/aacvar.h | 10 +- sys/emulation/43bsd/43bsd_file.c | 6 +- sys/emulation/ibcs2/coff/imgact_coff.c | 6 +- sys/emulation/ibcs2/i386/ibcs2_misc.c | 10 +- .../linux/i386/linprocfs/linprocfs_subr.c | 4 +- .../linux/i386/linprocfs/linprocfs_vnops.c | 6 +- sys/emulation/linux/linux_file.c | 6 +- sys/emulation/linux/linux_getcwd.c | 6 +- sys/emulation/linux/linux_misc.c | 6 +- sys/emulation/svr4/svr4_misc.c | 14 +- sys/i386/apic/mpapic.c | 52 +- sys/i386/apic/mpapic.h | 14 +- sys/i386/conf/LINT | 4 +- sys/i386/i386/machdep.c | 6 +- sys/i386/i386/mp_machdep.c | 81 +- sys/i386/i386/mpapic.c | 52 +- sys/i386/i386/nexus.c | 35 +- sys/i386/i386/pmap.c | 4 +- sys/i386/include/mpapic.h | 14 +- sys/i386/include/smp.h | 7 +- sys/kern/imgact_elf.c | 13 +- sys/kern/init_main.c | 5 +- sys/kern/kern_acct.c | 4 +- sys/kern/kern_acl.c | 10 +- sys/kern/kern_descrip.c | 4 +- sys/kern/kern_exec.c | 6 +- sys/kern/kern_fp.c | 6 +- sys/kern/kern_ktrace.c | 8 +- sys/kern/kern_linker.c | 24 +- sys/kern/kern_lock.c | 31 +- sys/kern/kern_sig.c | 8 +- sys/kern/kern_switch.c | 78 +- sys/kern/link_aout.c | 4 +- sys/kern/link_elf.c | 4 +- sys/kern/lwkt_ipiq.c | 59 +- sys/kern/lwkt_rwlock.c | 38 +- sys/kern/lwkt_thread.c | 118 ++- sys/kern/lwkt_token.c | 532 +++++++--- sys/kern/subr_rman.c | 67 +- sys/kern/tty_tty.c | 14 +- sys/kern/uipc_syscalls.c | 6 +- sys/kern/uipc_usrreq.c | 4 +- sys/kern/vfs_bio.c | 4 +- sys/kern/vfs_cache.c | 16 +- sys/kern/vfs_conf.c | 7 +- sys/kern/vfs_default.c | 34 +- sys/kern/vfs_lookup.c | 28 +- sys/kern/vfs_subr.c | 999 +++++++++++------- sys/kern/vfs_syscalls.c | 152 ++- sys/kern/vfs_vnops.c | 39 +- sys/kern/vnode_if.src | 4 +- sys/netproto/ncp/ncp_conn.c | 34 +- sys/netproto/smb/smb_conn.c | 72 +- sys/netproto/smb/smb_conn.h | 22 +- sys/netproto/smb/smb_iod.c | 110 +- sys/netproto/smb/smb_rq.c | 22 +- sys/netproto/smb/smb_rq.h | 6 +- sys/netproto/smb/smb_subr.c | 10 +- sys/netproto/smb/smb_subr.h | 16 +- sys/platform/pc32/apic/mpapic.c | 52 +- sys/platform/pc32/apic/mpapic.h | 14 +- sys/platform/pc32/i386/machdep.c | 6 +- sys/platform/pc32/i386/mp_machdep.c | 81 +- sys/platform/pc32/i386/mpapic.c | 52 +- sys/platform/pc32/i386/nexus.c | 35 +- sys/platform/pc32/i386/pmap.c | 4 +- sys/platform/pc32/include/mpapic.h | 14 +- sys/platform/pc32/include/smp.h | 7 +- sys/sys/buf2.h | 12 +- sys/sys/globaldata.h | 3 +- sys/sys/kernel.h | 3 +- sys/sys/lock.h | 6 +- sys/sys/mount.h | 7 +- sys/sys/proc.h | 3 +- sys/sys/rman.h | 7 +- sys/sys/thread.h | 77 +- sys/sys/thread2.h | 14 +- sys/sys/vnode.h | 45 +- sys/vfs/coda/coda_subr.c | 6 +- sys/vfs/coda/coda_vfsops.c | 16 +- sys/vfs/coda/coda_vnops.c | 24 +- sys/vfs/deadfs/dead_vnops.c | 5 +- sys/vfs/fdesc/fdesc_vfsops.c | 4 +- sys/vfs/fdesc/fdesc_vnops.c | 14 +- sys/vfs/fifofs/fifo_vnops.c | 20 +- sys/vfs/gnu/ext2fs/ext2_lookup.c | 16 +- sys/vfs/gnu/ext2fs/ext2_vfsops.c | 235 ++-- sys/vfs/gnu/ext2fs/ext2_vnops.c | 24 +- sys/vfs/gnu/ext2fs/fs.h | 6 +- sys/vfs/hpfs/hpfs.h | 10 +- sys/vfs/hpfs/hpfs_hash.c | 74 +- sys/vfs/hpfs/hpfs_vfsops.c | 4 +- sys/vfs/isofs/cd9660/cd9660_lookup.c | 10 +- sys/vfs/isofs/cd9660/cd9660_node.c | 59 +- sys/vfs/isofs/cd9660/cd9660_vfsops.c | 14 +- sys/vfs/mfs/mfs_vnops.c | 4 +- sys/vfs/msdosfs/msdosfs_denode.c | 68 +- sys/vfs/msdosfs/msdosfs_lookup.c | 16 +- sys/vfs/msdosfs/msdosfs_vfsops.c | 124 ++- sys/vfs/msdosfs/msdosfs_vnops.c | 46 +- sys/vfs/nfs/nfs_node.c | 10 +- sys/vfs/nfs/nfs_nqlease.c | 15 +- sys/vfs/nfs/nfs_serv.c | 16 +- sys/vfs/nfs/nfs_subs.c | 10 +- sys/vfs/nfs/nfs_vfsops.c | 8 +- sys/vfs/nfs/nfs_vnops.c | 28 +- sys/vfs/ntfs/ntfs.h | 13 +- sys/vfs/ntfs/ntfs_ihash.c | 26 +- sys/vfs/ntfs/ntfs_subr.c | 25 +- sys/vfs/ntfs/ntfs_vfsops.c | 10 +- sys/vfs/nullfs/null_subr.c | 8 +- sys/vfs/nullfs/null_vfsops.c | 10 +- sys/vfs/nullfs/null_vnops.c | 46 +- sys/vfs/nwfs/nwfs_node.c | 12 +- sys/vfs/nwfs/nwfs_vfsops.c | 10 +- sys/vfs/nwfs/nwfs_vnops.c | 45 +- sys/vfs/portal/portal_vfsops.c | 4 +- sys/vfs/portal/portal_vnops.c | 4 +- sys/vfs/procfs/procfs_subr.c | 4 +- sys/vfs/procfs/procfs_vnops.c | 6 +- sys/vfs/smbfs/smbfs_io.c | 6 +- sys/vfs/smbfs/smbfs_node.c | 20 +- sys/vfs/smbfs/smbfs_vfsops.c | 10 +- sys/vfs/smbfs/smbfs_vnops.c | 39 +- sys/vfs/specfs/spec_vnops.c | 16 +- sys/vfs/ufs/ffs_rawread.c | 10 +- sys/vfs/ufs/ffs_softdep.c | 10 +- sys/vfs/ufs/ffs_vfsops.c | 322 +++--- sys/vfs/ufs/ufs_ihash.c | 79 +- sys/vfs/ufs/ufs_inode.c | 4 +- sys/vfs/ufs/ufs_lookup.c | 28 +- sys/vfs/ufs/ufs_quota.c | 199 ++-- sys/vfs/ufs/ufs_vfsops.c | 4 +- sys/vfs/ufs/ufs_vnops.c | 45 +- sys/vfs/umapfs/umap_subr.c | 4 +- sys/vfs/umapfs/umap_vfsops.c | 6 +- sys/vfs/umapfs/umap_vnops.c | 5 +- sys/vfs/union/union_subr.c | 38 +- sys/vfs/union/union_vfsops.c | 8 +- sys/vfs/union/union_vnops.c | 71 +- sys/vm/vm_contig.c | 8 +- sys/vm/vm_extern.h | 3 +- sys/vm/vm_fault.c | 4 +- sys/vm/vm_glue.c | 4 +- sys/vm/vm_init.c | 3 +- sys/vm/vm_kern.c | 16 +- sys/vm/vm_map.c | 23 +- sys/vm/vm_map.h | 45 +- sys/vm/vm_object.c | 22 +- sys/vm/vm_page.c | 13 +- sys/vm/vm_pageout.c | 33 +- sys/vm/vm_swap.c | 6 +- sys/vm/vm_zone.c | 21 +- sys/vm/vnode_pager.c | 4 +- 163 files changed, 3508 insertions(+), 2335 deletions(-) diff --git a/sys/config/LINT b/sys/config/LINT index bcb713af57..293ecc648e 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/config/LINT,v 1.23 2004/02/27 11:56:12 joerg Exp $ +# $DragonFly: src/sys/config/LINT,v 1.24 2004/03/01 06:33:16 dillon Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -2684,8 +2684,6 @@ device ubsec # Broadcom 5501, 5601, 58xx 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 diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c index 3f5a8c479e..4b31e07cdc 100644 --- a/sys/ddb/db_ps.c +++ b/sys/ddb/db_ps.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ddb/db_ps.c,v 1.20 1999/08/28 00:41:09 peter Exp $ - * $DragonFly: src/sys/ddb/db_ps.c,v 1.8 2003/07/12 17:54:30 dillon Exp $ + * $DragonFly: src/sys/ddb/db_ps.c,v 1.9 2004/03/01 06:32:49 dillon Exp $ */ #include #include @@ -40,7 +40,7 @@ #include -static void +static int db_more(int *nl) { ++*nl; @@ -62,11 +62,14 @@ db_more(int *nl) 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 @@ db_ps(dummy1, dummy2, dummy3, dummy4) 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_ps(dummy1, dummy2, dummy3, dummy4) 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 @@ db_ps(dummy1, dummy2, dummy3, dummy4) * 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 @@ db_ps(dummy1, dummy2, dummy3, dummy4) 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 @@ db_ps(dummy1, dummy2, dummy3, dummy4) 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"); +} + diff --git a/sys/dev/acpica5/Osd/OsdSynch.c b/sys/dev/acpica5/Osd/OsdSynch.c index 9682647ff3..b6b830a27c 100644 --- a/sys/dev/acpica5/Osd/OsdSynch.c +++ b/sys/dev/acpica5/Osd/OsdSynch.c @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/acpica/Osd/OsdSynch.c,v 1.18 2003/09/26 21:22:10 njl Exp $ - * $DragonFly: src/sys/dev/acpica5/Osd/OsdSynch.c,v 1.1 2004/02/21 06:48:09 dillon Exp $ + * $DragonFly: src/sys/dev/acpica5/Osd/OsdSynch.c,v 1.2 2004/03/01 06:33:13 dillon Exp $ */ /* @@ -349,29 +349,27 @@ AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units) 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 @@ AcpiOsDeleteLock (ACPI_HANDLE Handle) 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); } diff --git a/sys/dev/acpica5/acpi_ec.c b/sys/dev/acpica5/acpi_ec.c index f8e5edf7a4..85e15993a1 100644 --- a/sys/dev/acpica5/acpi_ec.c +++ b/sys/dev/acpica5/acpi_ec.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $ - * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.1 2004/02/21 06:48:08 dillon Exp $ + * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $ */ /****************************************************************************** * @@ -138,7 +138,7 @@ *****************************************************************************/ /* * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $ - * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.1 2004/02/21 06:48:08 dillon Exp $ + * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $ * */ @@ -269,7 +269,7 @@ struct acpi_ec_softc { int ec_glk; int ec_glkhandle; - struct lwkt_token ec_token; + struct lwkt_rwlock ec_rwlock; int ec_polldelay; }; @@ -304,13 +304,13 @@ EcLock(struct acpi_ec_softc *sc) 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 @@ EcUnlock(struct acpi_ec_softc *sc) { 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 @@ acpi_ec_probe(device_t dev) 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 @@ acpi_ec_attach(device_t dev) 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); diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c index 4bcfa88687..9b72f20740 100644 --- a/sys/dev/agp/agp.c +++ b/sys/dev/agp/agp.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/pci/agp.c,v 1.3.2.4 2002/08/11 19:58:12 alc Exp $ - * $DragonFly: src/sys/dev/agp/agp.c,v 1.9 2004/01/20 05:04:03 dillon Exp $ + * $DragonFly: src/sys/dev/agp/agp.c,v 1.10 2004/03/01 06:33:13 dillon Exp $ */ #include "opt_bus.h" @@ -278,7 +278,7 @@ agp_generic_detach(device_t dev) { 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 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem, 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 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem, 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 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem, 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 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem) 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 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem) 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; } diff --git a/sys/dev/disk/ccd/ccd.c b/sys/dev/disk/ccd/ccd.c index 726fc1ee4d..f6caf644c1 100644 --- a/sys/dev/disk/ccd/ccd.c +++ b/sys/dev/disk/ccd/ccd.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/dev/ccd/ccd.c,v 1.73.2.1 2001/09/11 09:49:52 kris Exp $ */ -/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.12 2003/09/23 05:03:40 dillon Exp $ */ +/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.13 2004/03/01 06:33:13 dillon Exp $ */ /* $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */ @@ -1578,12 +1578,12 @@ ccdlookup(char *path, struct thread *td, struct vnode **vpp) 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); diff --git a/sys/dev/disk/vn/vn.c b/sys/dev/disk/vn/vn.c index 9e4bcf4538..9ba4064ac1 100644 --- a/sys/dev/disk/vn/vn.c +++ b/sys/dev/disk/vn/vn.c @@ -39,7 +39,7 @@ * * from: @(#)vn.c 8.6 (Berkeley) 4/1/94 * $FreeBSD: src/sys/dev/vn/vn.c,v 1.105.2.4 2001/11/18 07:11:00 dillon Exp $ - * $DragonFly: src/sys/dev/disk/vn/vn.c,v 1.7 2003/09/23 05:03:46 dillon Exp $ + * $DragonFly: src/sys/dev/disk/vn/vn.c,v 1.8 2004/03/01 06:33:14 dillon Exp $ */ /* @@ -387,12 +387,12 @@ vnstrategy(struct buf *bp) 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 @@ vniocattach_file(vn, vio, dev, flag, td) 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 @@ vnsetcred(struct vn_softc *vn, struct ucred *cred) 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); diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h index 451f6c2daa..acfb20b5ef 100644 --- a/sys/dev/drm/drm_os_freebsd.h +++ b/sys/dev/drm/drm_os_freebsd.h @@ -1,6 +1,6 @@ /* * $FreeBSD: src/sys/dev/drm/drm_os_freebsd.h,v 1.10.2.1 2003/04/26 07:05:28 anholt Exp $ - * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.8 2004/02/13 01:23:57 joerg Exp $ + * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.9 2004/03/01 06:33:14 dillon Exp $ */ #include #include @@ -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 diff --git a/sys/dev/pccard/pccbb/pccbb.c b/sys/dev/pccard/pccbb/pccbb.c index dc88a13204..3b729ed4e1 100644 --- a/sys/dev/pccard/pccbb/pccbb.c +++ b/sys/dev/pccard/pccbb/pccbb.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/pccbb/pccbb.c,v 1.64 2002/11/23 23:09:45 imp Exp $ - * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.1 2004/02/10 07:55:47 joerg Exp $ + * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.2 2004/03/01 06:33:14 dillon Exp $ */ /* @@ -719,14 +719,14 @@ cbb_detach(device_t brdev) 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 @@ cbb_event_thread(void *arg) * 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_event_thread(void *arg) 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 @@ cbb_event_thread(void *arg) (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 @@ cbb_intr(void *arg) * 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) { diff --git a/sys/dev/raid/aac/aacvar.h b/sys/dev/raid/aac/aacvar.h index e75987b189..38ebed3b93 100644 --- a/sys/dev/raid/aac/aacvar.h +++ b/sys/dev/raid/aac/aacvar.h @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/aac/aacvar.h,v 1.4.2.7 2003/04/08 13:22:08 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aacvar.h,v 1.5 2004/02/13 01:33:19 joerg Exp $ + * $DragonFly: src/sys/dev/raid/aac/aacvar.h,v 1.6 2004/03/01 06:33:14 dillon Exp $ */ /* @@ -259,10 +259,10 @@ typedef struct mtx aac_lock_t; #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 diff --git a/sys/emulation/43bsd/43bsd_file.c b/sys/emulation/43bsd/43bsd_file.c index 710d83f29f..002f3e529a 100644 --- a/sys/emulation/43bsd/43bsd_file.c +++ b/sys/emulation/43bsd/43bsd_file.c @@ -37,7 +37,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.3 2003/11/11 09:28:15 daver Exp $ + * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.4 2004/03/01 06:33:15 dillon Exp $ * from: DragonFly kern/vfs_syscalls.c,v 1.20 * * These syscalls used to live in kern/vfs_syscalls.c. They are modified @@ -147,7 +147,7 @@ unionread: 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 @@ unionread: } 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) { diff --git a/sys/emulation/ibcs2/coff/imgact_coff.c b/sys/emulation/ibcs2/coff/imgact_coff.c index ecd58841e2..4d824f6d53 100644 --- a/sys/emulation/ibcs2/coff/imgact_coff.c +++ b/sys/emulation/ibcs2/coff/imgact_coff.c @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/i386/ibcs2/imgact_coff.c,v 1.40 1999/12/15 23:01:47 eivind Exp $ - * $DragonFly: src/sys/emulation/ibcs2/coff/Attic/imgact_coff.c,v 1.9 2004/01/20 18:41:49 dillon Exp $ + * $DragonFly: src/sys/emulation/ibcs2/coff/Attic/imgact_coff.c,v 1.10 2004/03/01 06:33:15 dillon Exp $ */ #include @@ -211,7 +211,7 @@ coff_load_file(struct thread *td, char *name) * 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 @@ coff_load_file(struct thread *td, char *name) 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); diff --git a/sys/emulation/ibcs2/i386/ibcs2_misc.c b/sys/emulation/ibcs2/i386/ibcs2_misc.c index 8b5d0d0cf3..1b9cb591fe 100644 --- a/sys/emulation/ibcs2/i386/ibcs2_misc.c +++ b/sys/emulation/ibcs2/i386/ibcs2_misc.c @@ -46,7 +46,7 @@ * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 * * $FreeBSD: src/sys/i386/ibcs2/ibcs2_misc.c,v 1.34 1999/09/29 15:12:09 marcel Exp $ - * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_misc.c,v 1.8 2003/08/20 07:13:25 dillon Exp $ + * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_misc.c,v 1.9 2004/03/01 06:33:15 dillon Exp $ */ /* @@ -330,7 +330,7 @@ ibcs2_getdents(struct ibcs2_getdents_args *uap) 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 @@ eof: 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 @@ ibcs2_read(struct ibcs2_read_args *uap) 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 @@ eof: out: if (cookies) free(cookies, M_TEMP); - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); free(buf, M_TEMP); return (error); } diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c b/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c index 08bc74d02c..dcddd956fd 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c @@ -39,7 +39,7 @@ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_subr.c,v 1.3.2.4 2001/06/25 19:46:47 pirzyk Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.6 2003/08/27 06:30:04 rob Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.7 2004/03/01 06:33:15 dillon Exp $ */ #include @@ -99,7 +99,7 @@ loop: 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); diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c index 0c3744f85e..e5947cf671 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c @@ -39,7 +39,7 @@ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_vnops.c,v 1.3.2.5 2001/08/12 14:29:19 rwatson Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.9 2003/09/23 05:03:51 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.10 2004/03/01 06:33:15 dillon Exp $ */ /* @@ -338,7 +338,7 @@ linprocfs_inactive(ap) { 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 @@ linprocfs_lookup(ap) 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); } diff --git a/sys/emulation/linux/linux_file.c b/sys/emulation/linux/linux_file.c index 8bf958feb2..82551c6877 100644 --- a/sys/emulation/linux/linux_file.c +++ b/sys/emulation/linux/linux_file.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $ - * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.15 2003/11/15 00:40:06 daver Exp $ + * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.16 2004/03/01 06:33:15 dillon Exp $ */ #include "opt_compat.h" @@ -290,7 +290,7 @@ getdents_common(struct linux_getdents64_args *args, int is64bit) 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 @@ out: if (cookies) free(cookies, M_TEMP); - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); free(buf, M_TEMP); return (error); } diff --git a/sys/emulation/linux/linux_getcwd.c b/sys/emulation/linux/linux_getcwd.c index 081c37937a..102ed09725 100644 --- a/sys/emulation/linux/linux_getcwd.c +++ b/sys/emulation/linux/linux_getcwd.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/compat/linux/linux_getcwd.c,v 1.2.2.3 2001/11/05 19:08:22 marcel Exp $ */ -/* $DragonFly: src/sys/emulation/linux/linux_getcwd.c,v 1.13 2003/10/09 22:27:08 dillon Exp $ */ +/* $DragonFly: src/sys/emulation/linux/linux_getcwd.c,v 1.14 2004/03/01 06:33:15 dillon Exp $ */ /* $OpenBSD: linux_getcwd.c,v 1.2 2001/05/16 12:50:21 ho Exp $ */ /* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */ @@ -313,7 +313,7 @@ linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td) * 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 @@ linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td) 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; diff --git a/sys/emulation/linux/linux_misc.c b/sys/emulation/linux/linux_misc.c index 4aa734767a..0df4d71ff0 100644 --- a/sys/emulation/linux/linux_misc.c +++ b/sys/emulation/linux/linux_misc.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $ - * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.18 2004/01/07 10:54:57 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.19 2004/03/01 06:33:15 dillon Exp $ */ #include "opt_compat.h" @@ -326,7 +326,7 @@ linux_uselib(struct linux_uselib_args *args) /* * 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 @@ linux_uselib(struct linux_uselib_args *args) 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) diff --git a/sys/emulation/svr4/svr4_misc.c b/sys/emulation/svr4/svr4_misc.c index c9f32a4354..04e6fd1779 100644 --- a/sys/emulation/svr4/svr4_misc.c +++ b/sys/emulation/svr4/svr4_misc.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/svr4/svr4_misc.c,v 1.13.2.7 2003/01/14 21:33:58 dillon Exp $ - * $DragonFly: src/sys/emulation/svr4/Attic/svr4_misc.c,v 1.20 2004/02/12 23:33:26 joerg Exp $ + * $DragonFly: src/sys/emulation/svr4/Attic/svr4_misc.c,v 1.21 2004/03/01 06:33:15 dillon Exp $ */ /* @@ -286,7 +286,7 @@ svr4_sys_getdents64(struct svr4_sys_getdents64_args *uap) 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 @@ eof: 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 @@ svr4_sys_getdents(struct svr4_sys_getdents_args *uap) 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 @@ again: 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 @@ svr4_sys_fchroot(struct svr4_sys_fchroot_args *uap) 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); diff --git a/sys/i386/apic/mpapic.c b/sys/i386/apic/mpapic.c index 240024b0c6..b7fd1e71d5 100644 --- a/sys/i386/apic/mpapic.c +++ b/sys/i386/apic/mpapic.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $ - * $DragonFly: src/sys/i386/apic/Attic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/i386/apic/Attic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $ */ #include @@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode) 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) /* 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) * 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 */ diff --git a/sys/i386/apic/mpapic.h b/sys/i386/apic/mpapic.h index 11a09c2748..336cf4f58d 100644 --- a/sys/i386/apic/mpapic.h +++ b/sys/i386/apic/mpapic.h @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $ - * $DragonFly: src/sys/i386/apic/Attic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/i386/apic/Attic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $ */ #ifndef _MACHINE_MPAPIC_H_ @@ -63,18 +63,6 @@ enum busTypes { #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 */ diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 5a7ea328bb..67483cb66c 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.23 2004/02/27 11:56:12 joerg Exp $ +# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.24 2004/03/01 06:33:16 dillon Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -2684,8 +2684,6 @@ device ubsec # Broadcom 5501, 5601, 58xx 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 diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 5e9400c56b..a188c2d8e9 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -36,7 +36,7 @@ * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $ - * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.54 2004/02/17 19:38:53 dillon Exp $ + * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.55 2004/03/01 06:33:16 dillon Exp $ */ #include "use_apm.h" @@ -2648,6 +2648,7 @@ init_locks(void) #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 @@ init_locks(void) 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(); } diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 1fd097df6c..3677e42ba3 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $ - * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.23 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.24 2004/03/01 06:33:16 dillon Exp $ */ #include "opt_cpu.h" @@ -280,7 +280,7 @@ struct pcb stoppcbs[MAXCPU]; 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 void install_ap_tramp(u_int boot_addr); 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 @@ restart_cpus(u_int map) * loop for the idlethread. Interrupts are disabled on entry and should * remain disabled at return. */ - void ap_init(void) { @@ -2332,17 +2332,27 @@ ap_init(void) 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 @@ ap_init(void) /* 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 @@ smp_rendezvous(void (* setup_func)(void *), 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 + diff --git a/sys/i386/i386/mpapic.c b/sys/i386/i386/mpapic.c index 0a8d9bc0a4..7b5e6c93db 100644 --- a/sys/i386/i386/mpapic.c +++ b/sys/i386/i386/mpapic.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $ - * $DragonFly: src/sys/i386/i386/Attic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/i386/i386/Attic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $ */ #include @@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode) 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) /* 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) * 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 */ diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c index 697d9b3a75..ae1c770cac 100644 --- a/sys/i386/i386/nexus.c +++ b/sys/i386/i386/nexus.c @@ -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/Attic/nexus.c,v 1.9 2004/02/23 21:23:42 dillon Exp $ + * $DragonFly: src/sys/i386/i386/Attic/nexus.c,v 1.10 2004/03/01 06:33:16 dillon Exp $ */ /* @@ -82,6 +82,7 @@ struct nexus_device { 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 void nexus_delete_resource(device_t, device_t, int, int); 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 @@ static devclass_t nexus_devclass; 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 @@ nexus_attach(device_t dev) 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". diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 4341fea575..367cb49f32 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -40,7 +40,7 @@ * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $ - * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.31 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.32 2004/03/01 06:33:16 dillon Exp $ */ /* @@ -1535,7 +1535,7 @@ pmap_remove_pte(struct pmap *pmap, unsigned *ptq, vm_offset_t va, * 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); diff --git a/sys/i386/include/mpapic.h b/sys/i386/include/mpapic.h index 2745c0c271..8ffac142c8 100644 --- a/sys/i386/include/mpapic.h +++ b/sys/i386/include/mpapic.h @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $ - * $DragonFly: src/sys/i386/include/Attic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/i386/include/Attic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $ */ #ifndef _MACHINE_MPAPIC_H_ @@ -63,18 +63,6 @@ enum busTypes { #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 */ diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h index e473aa0dbc..8f835adc85 100644 --- a/sys/i386/include/smp.h +++ b/sys/i386/include/smp.h @@ -7,7 +7,7 @@ * ---------------------------------------------------------------------------- * * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $ - * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.10 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.11 2004/03/01 06:33:16 dillon Exp $ * */ @@ -128,7 +128,9 @@ void apic_dump (char*); 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 @@ void set_apic_timer (int); 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; diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 05e6f15f5b..a5352c4a17 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $ - * $DragonFly: src/sys/kern/imgact_elf.c,v 1.16 2004/01/20 18:41:51 dillon Exp $ + * $DragonFly: src/sys/kern/imgact_elf.c,v 1.17 2004/03/01 06:33:16 dillon Exp $ */ #include @@ -387,7 +387,7 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) */ 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 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) */ 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 @@ exec_elf_imgact(struct image_params *imgp) const char *interp = NULL; Elf_Brandinfo *brand_info; char *path; + lwkt_tokref ilock; error = 0; @@ -525,9 +526,9 @@ exec_elf_imgact(struct image_params *imgp) * 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 @@ elf_coredump(struct proc *p, struct vnode *vp, off_t limit) 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); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index c1f884c305..29f7579124 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -40,7 +40,7 @@ * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/init_main.c,v 1.134.2.8 2003/06/06 20:21:32 tegge Exp $ - * $DragonFly: src/sys/kern/init_main.c,v 1.27 2004/01/30 05:42:17 dillon Exp $ + * $DragonFly: src/sys/kern/init_main.c,v 1.28 2004/03/01 06:33:16 dillon Exp $ */ #include "opt_init_path.h" @@ -465,7 +465,7 @@ start_init(void *dummy) 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 @@ mi_gdinit(struct globaldata *gd, int cpuid) TAILQ_INIT(&gd->gd_systimerq); gd->gd_cpuid = cpuid; lwkt_gdinit(gd); + vm_map_entry_reserve_cpu_init(gd); } diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index f0ae149c42..40453b8286 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -38,7 +38,7 @@ * * @(#)kern_acct.c 8.1 (Berkeley) 6/14/93 * $FreeBSD: src/sys/kern/kern_acct.c,v 1.23.2.1 2002/07/24 18:33:55 johan Exp $ - * $DragonFly: src/sys/kern/kern_acct.c,v 1.8 2003/09/29 18:52:06 dillon Exp $ + * $DragonFly: src/sys/kern/kern_acct.c,v 1.9 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -136,7 +136,7 @@ acct(uap) 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); diff --git a/sys/kern/kern_acl.c b/sys/kern/kern_acl.c index 3e97090738..9a73fd1bc1 100644 --- a/sys/kern/kern_acl.c +++ b/sys/kern/kern_acl.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_acl.c,v 1.2.2.1 2000/07/28 18:48:16 rwatson Exp $ - * $DragonFly: src/sys/kern/kern_acl.c,v 1.5 2003/09/23 05:03:51 dillon Exp $ + * $DragonFly: src/sys/kern/kern_acl.c,v 1.6 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -80,9 +80,9 @@ vacl_set_acl(struct vnode *vp, acl_type_t type, struct acl *aclp) 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 @@ vacl_delete(struct vnode *vp, acl_type_t type) 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); } diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c672911349..4a00423092 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -37,7 +37,7 @@ * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.17 2003/06/06 20:21:32 tegge Exp $ - * $DragonFly: src/sys/kern/kern_descrip.c,v 1.18 2004/01/17 21:23:38 dillon Exp $ + * $DragonFly: src/sys/kern/kern_descrip.c,v 1.19 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_compat.h" @@ -1353,7 +1353,7 @@ fdcheckstd(struct proc *p) 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); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 3c33c9b007..1d44828799 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $ - * $DragonFly: src/sys/kern/kern_exec.c,v 1.19 2004/01/20 18:41:51 dillon Exp $ + * $DragonFly: src/sys/kern/kern_exec.c,v 1.20 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -186,12 +186,12 @@ interpret: */ 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; diff --git a/sys/kern/kern_fp.c b/sys/kern/kern_fp.c index fa702f3399..5161356fd5 100644 --- a/sys/kern/kern_fp.c +++ b/sys/kern/kern_fp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_fp.c,v 1.4 2003/10/19 23:23:26 dillon Exp $ + * $DragonFly: src/sys/kern/kern_fp.c,v 1.5 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -105,7 +105,7 @@ fp_open(const char *path, int flags, int mode, file_t *fpp) 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 @@ fp_vpopen(struct vnode *vp, int flags, file_t *fpp) if (flags & FWRITE) vp->v_writecount++; done: - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); return (error); } diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 39a6d719f9..f8138b938f 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -32,7 +32,7 @@ * * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.6 2002/07/05 22:36:38 darrenr Exp $ - * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.12 2004/02/14 12:14:30 eirikn Exp $ + * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.13 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_ktrace.h" @@ -268,7 +268,7 @@ ktrace(struct ktrace_args *uap) } 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 @@ ktrwrite(struct vnode *vp, struct ktr_header *kth, struct uio *uio) 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; /* diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index a8c5de05e6..25b2d0b249 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_linker.c,v 1.41.2.3 2001/11/21 17:50:35 luigi Exp $ - * $DragonFly: src/sys/kern/kern_linker.c,v 1.17 2004/01/17 03:24:50 dillon Exp $ + * $DragonFly: src/sys/kern/kern_linker.c,v 1.18 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_ddb.h" @@ -326,14 +326,14 @@ linker_find_file_by_name(const char* filename) 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_find_file_by_id(int fileid) { 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 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops) 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 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops) 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 @@ linker_file_unload(linker_file_t file) 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 @@ linker_file_unload(linker_file_t file) 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 @@ linker_file_unload(linker_file_t file) file->refs--; if (file->refs > 0) { - lockmgr(&lock, LK_RELEASE, 0, curthread); + lockmgr(&lock, LK_RELEASE, NULL, curthread); goto out; } @@ -470,7 +470,7 @@ linker_file_unload(linker_file_t file) } 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 @@ linker_search_path(const char *name) 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); diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 02db658403..6ff5f13b8e 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -39,7 +39,7 @@ * * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95 * $FreeBSD: src/sys/kern/kern_lock.c,v 1.31.2.3 2001/12/25 01:44:44 dillon Exp $ - * $DragonFly: src/sys/kern/kern_lock.c,v 1.9 2003/11/12 22:08:02 dillon Exp $ + * $DragonFly: src/sys/kern/kern_lock.c,v 1.10 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_lint.h" @@ -123,10 +123,9 @@ acquire(struct lock *lkp, int extflags, int wanted) 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 @@ acquire(struct lock *lkp, int extflags, int wanted) */ 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 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp, #endif } - lwkt_gettoken(&lkp->lk_interlock); + lwkt_gettoken(&ilock, &lkp->lk_interlock); if (flags & LK_INTERLOCK) lwkt_reltoken(interlkp); @@ -427,7 +427,7 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp, 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 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp, lkp->lk_flags &= ~LK_WAITDRAIN; wakeup((void *)&lkp->lk_flags); } - lwkt_reltoken(&lkp->lk_interlock); + lwkt_reltoken(&ilock); return (error); } @@ -456,11 +456,10 @@ acquiredrain(struct lock *lkp, int extflags) 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 @@ lockinit(lkp, prio, wmesg, timo, flags) 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 @@ lockinit(lkp, prio, wmesg, timo, flags) 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 @@ lockstatus(struct lock *lkp, struct thread *td) } 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 @@ int 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); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 433f58edb4..8432a0ae69 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -37,7 +37,7 @@ * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 * $FreeBSD: src/sys/kern/kern_sig.c,v 1.72.2.17 2003/05/16 16:34:34 obrien Exp $ - * $DragonFly: src/sys/kern/kern_sig.c,v 1.26 2004/02/12 06:57:48 dillon Exp $ + * $DragonFly: src/sys/kern/kern_sig.c,v 1.27 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_ktrace.h" @@ -1467,7 +1467,7 @@ coredump(struct proc *p) 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 @@ coredump(struct proc *p) } 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) : diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index 0b6ddd81b7..3ad34cb838 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_switch.c,v 1.3.2.1 2000/05/16 06:58:12 dillon Exp $ - * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.17 2004/02/12 06:57:48 dillon Exp $ + * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.18 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -39,6 +39,7 @@ #include #include #include +#include /* * debugging only YYY Remove me! define to schedule user processes only @@ -64,8 +65,8 @@ static struct rq idqueues[NQS]; 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 @@ SYSCTL_INT(_debug, OID_AUTO, choose_affinity, CTLFLAG_RD, &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 @@ rqinit(void *dummy) 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 @@ setrunqueue(struct proc *p) int cpuid; #ifdef SMP int count; - u_int32_t mask; + cpumask_t mask; #endif crit_enter(); @@ -379,6 +378,11 @@ setrunqueue(struct proc *p) * 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 @@ setrunqueue(struct proc *p) } 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 @@ uio_yield(void) } } +#ifdef SMP /* * For SMP systems a user scheduler helper thread is created for each @@ -634,9 +641,6 @@ uio_yield(void) * 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 @@ sched_thread(void *dummy) } } -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 diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c index 962fc0550d..d5fcceade3 100644 --- a/sys/kern/link_aout.c +++ b/sys/kern/link_aout.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/link_aout.c,v 1.26 1999/12/24 15:33:36 bde Exp $ - * $DragonFly: src/sys/kern/link_aout.c,v 1.9 2003/11/13 22:02:42 dillon Exp $ + * $DragonFly: src/sys/kern/link_aout.c,v 1.10 2004/03/01 06:33:17 dillon Exp $ */ #ifndef __alpha__ @@ -285,7 +285,7 @@ link_aout_load_file(const char* filename, linker_file_t* result) *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; diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index cff2ee7d8b..fe88bcda12 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/link_elf.c,v 1.24 1999/12/24 15:33:36 bde Exp $ - * $DragonFly: src/sys/kern/link_elf.c,v 1.11 2004/01/17 03:26:18 dillon Exp $ + * $DragonFly: src/sys/kern/link_elf.c,v 1.12 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -700,7 +700,7 @@ out: 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; diff --git a/sys/kern/lwkt_ipiq.c b/sys/kern/lwkt_ipiq.c index 340bd16d41..95ff667177 100644 --- a/sys/kern/lwkt_ipiq.c +++ b/sys/kern/lwkt_ipiq.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/lwkt_ipiq.c,v 1.3 2004/02/17 19:38:49 dillon Exp $ + * $DragonFly: src/sys/kern/lwkt_ipiq.c,v 1.4 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -147,7 +147,7 @@ lwkt_send_ipiq(globaldata_t target, ipifunc_t func, void *arg) 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(); @@ -165,6 +165,48 @@ lwkt_send_ipiq(globaldata_t target, ipifunc_t func, void *arg) return(ip->ip_windex); } +/* + * 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. */ @@ -217,7 +259,9 @@ lwkt_wait_ipiq(globaldata_t target, int seq) 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 @@ lwkt_wait_ipiq(globaldata_t target, int seq) } } +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 @@ void 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; diff --git a/sys/kern/lwkt_rwlock.c b/sys/kern/lwkt_rwlock.c index 4962e79f1d..008e7f145f 100644 --- a/sys/kern/lwkt_rwlock.c +++ b/sys/kern/lwkt_rwlock.c @@ -25,7 +25,7 @@ * * Implements simple shared/exclusive locks using LWKT. * - * $DragonFly: src/sys/kern/Attic/lwkt_rwlock.c,v 1.4 2003/07/20 01:37:22 dillon Exp $ + * $DragonFly: src/sys/kern/Attic/lwkt_rwlock.c,v 1.5 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -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 @@ lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg) } ++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 @@ lwkt_exunlock(lwkt_rwlock_t lock) 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 diff --git a/sys/kern/lwkt_thread.c b/sys/kern/lwkt_thread.c index f8eb53c260..92285b33b7 100644 --- a/sys/kern/lwkt_thread.c +++ b/sys/kern/lwkt_thread.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.55 2004/02/17 19:38:49 dillon Exp $ + * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.56 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -174,9 +174,12 @@ lwkt_gdinit(struct globaldata *gd) * 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 @@ lwkt_alloc_thread(struct thread *td, int cpu) * 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 @@ lwkt_init_thread_remote(void *arg) 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 @@ lwkt_free_thread(thread_t td) void lwkt_switch(void) { - struct globaldata *gd; + globaldata_t gd; thread_t td = curthread; thread_t ntd; #ifdef SMP @@ -462,9 +469,24 @@ lwkt_switch(void) * * 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 @@ again: 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 @@ lwkt_preempt(thread_t ntd, int critpri) * * 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 @@ lwkt_preempt(thread_t ntd, int critpri) 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 @@ lwkt_schedule_self(void) { 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 @@ void 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 @@ lwkt_schedule(thread_t td) * (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 @@ lwkt_schedule(thread_t td) 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 @@ lwkt_preempted_proc(void) 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 @@ void 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,13 +1090,11 @@ lwkt_signal(lwkt_wait_t w, int count) } 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 * with proc0 - ie: kernel only. diff --git a/sys/kern/lwkt_token.c b/sys/kern/lwkt_token.c index 4e7a5fec94..6b83b779a9 100644 --- a/sys/kern/lwkt_token.c +++ b/sys/kern/lwkt_token.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/lwkt_token.c,v 1.4 2004/02/18 16:31:37 joerg Exp $ + * $DragonFly: src/sys/kern/lwkt_token.c,v 1.5 2004/03/01 06:33:17 dillon Exp $ */ #ifdef _KERNEL @@ -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 @@ SYSCTL_INT(_lwkt, OID_AUTO, token_debug, CTLFLAG_RW, &token_debug, 0, ""); #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. */ +int +lwkt_chktokens(thread_t td) +{ + globaldata_t gd = td->td_gd; /* mycpu */ + lwkt_tokref_t refs; + globaldata_t dgd; + lwkt_token_t tok; + int r = 1; -#ifdef SMP + for (refs = td->td_toks; refs; refs = refs->tr_next) { + tok = refs->tr_tok; + if ((dgd = tok->t_cpu) != gd) { + cpu_mb1(); + r = 0; -static -void -lwkt_gettoken_remote(void *arg) -{ - 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 */ + /* + * 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. - */ + globaldata_t gd = mycpu; + thread_t td = gd->gd_curthread; + lwkt_tokref_t ref; - 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]); + 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 */ + /* - * leave us in a critical section on return. This will be undone - * by lwkt_reltoken(). Bump the generation number. + * 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. */ - return(++tok->t_gen); + 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 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. + */ + 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; - - req.cpu = mycpu; - req.tok = tok; - dcpu = tok->t_cpu; + lwkt_tokref *ref; + lwkt_tokref **pref; + lwkt_token_t tok; + globaldata_t gd; + thread_t td; + + /* + * 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_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_inittoken(lwkt_token_t tok) +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 */ +} diff --git a/sys/kern/subr_rman.c b/sys/kern/subr_rman.c index e0a49af179..ad1d6b0a64 100644 --- a/sys/kern/subr_rman.c +++ b/sys/kern/subr_rman.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/subr_rman.c,v 1.10.2.1 2001/06/05 08:06:08 imp Exp $ - * $DragonFly: src/sys/kern/subr_rman.c,v 1.5 2003/11/15 21:05:43 dillon Exp $ + * $DragonFly: src/sys/kern/subr_rman.c,v 1.6 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -82,11 +82,12 @@ int 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 @@ rman_init(struct rman *rm) 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 @@ int 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 @@ rman_manage_region(struct rman *rm, u_long start, u_long end) 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 @@ rman_manage_region(struct rman *rm, u_long start, u_long end) CIRCLEQ_INSERT_BEFORE(&rm->rm_list, s, r, r_link); } - lwkt_reltoken(rm->rm_slock); + lwkt_reltoken(&ilock); return 0; } @@ -146,11 +148,12 @@ int 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 @@ rman_fini(struct rman *rm) 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 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, u_int want_activate; struct resource *r, *s, *rv; u_long rstart, rend; + lwkt_tokref ilock; rv = 0; @@ -191,7 +196,7 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, 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 @@ out: rv = 0; } } - - lwkt_reltoken(rm->rm_slock); + lwkt_reltoken(&ilock); return (rv); } @@ -441,17 +445,21 @@ rman_activate_resource(struct resource *r) { 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 @@ rman_await_resource(struct resource *r, int slpflags, int timo) 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 @@ rman_await_resource(struct resource *r, int slpflags, int timo) */ 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) 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 @@ out: 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); } diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c index abc1b1db90..84af7f70dd 100644 --- a/sys/kern/tty_tty.c +++ b/sys/kern/tty_tty.c @@ -32,7 +32,7 @@ * * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93 * $FreeBSD: src/sys/kern/tty_tty.c,v 1.30 1999/09/25 18:24:24 phk Exp $ - * $DragonFly: src/sys/kern/tty_tty.c,v 1.6 2003/08/26 21:09:02 rob Exp $ + * $DragonFly: src/sys/kern/tty_tty.c,v 1.7 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -90,7 +90,7 @@ cttyopen(dev_t dev, int flag, int mode, struct thread *td) 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 @@ cttyopen(dev_t dev, int flag, int mode, struct thread *td) 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 @@ cttyread(dev, uio, flag) 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 @@ cttywrite(dev, uio, flag) 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); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index a7408bb9d7..f95d1f8841 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -35,7 +35,7 @@ * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 * $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.17 2003/04/04 17:11:16 tegge Exp $ - * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.23 2003/12/20 05:53:59 dillon Exp $ + * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.24 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_ktrace.h" @@ -1484,11 +1484,11 @@ retry_lookup: 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) { diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 7301b07394..7679c41898 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -32,7 +32,7 @@ * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 * $FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.54.2.10 2003/03/04 17:28:09 nectar Exp $ - * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.10 2003/10/09 22:27:19 dillon Exp $ + * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.11 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -627,7 +627,7 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td) 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); } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 118fef81c5..2d41546481 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -12,7 +12,7 @@ * John S. Dyson. * * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $ - * $DragonFly: src/sys/kern/vfs_bio.c,v 1.18 2004/02/16 19:37:48 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_bio.c,v 1.19 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -351,7 +351,7 @@ bufinit(void) TAILQ_INIT(&bswlist); LIST_INIT(&invalhash); - lwkt_inittoken(&buftimetoken); + lwkt_token_init(&buftimetoken); for (i = 0; i <= bufhashmask; i++) LIST_INIT(&bufhashtbl[i]); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 5132230cf0..876b66c26d 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -37,7 +37,7 @@ * * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95 * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $ - * $DragonFly: src/sys/kern/vfs_cache.c,v 1.12 2003/10/18 05:53:57 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_cache.c,v 1.13 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -792,17 +792,17 @@ vfs_cache_lookup(struct vop_lookup_args *ap) 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 @@ vfs_cache_lookup(struct vop_lookup_args *ap) 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; diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 03f5cd416c..220ed69564 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/vfs_conf.c,v 1.49.2.5 2003/01/07 11:56:53 joerg Exp $ - * $DragonFly: src/sys/kern/vfs_conf.c,v 1.6 2003/08/07 21:17:23 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_conf.c,v 1.7 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -177,6 +177,7 @@ vfs_mountroot_try(char *mountfrom) char *vfsname, *path; int error; char patt[32]; + lwkt_tokref ilock; int s; vfsname = NULL; @@ -235,9 +236,9 @@ done: } 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); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index bd1ad1e99d..88b8d22357 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -37,7 +37,7 @@ * * * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $ - * $DragonFly: src/sys/kern/vfs_default.c,v 1.8 2003/08/26 21:09:02 rob Exp $ + * $DragonFly: src/sys/kern/vfs_default.c,v 1.9 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -241,6 +241,7 @@ int 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 @@ vop_stdlock(ap) 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 @@ int 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 @@ vop_stdunlock(ap) 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 @@ int 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 @@ vop_sharedlock(ap) 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 @@ vop_sharedlock(ap) 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 @@ int 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 @@ vop_nolock(ap) } 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 @@ int 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 @@ retry: 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; } } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 51fb99bb61..17bb8b693b 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -37,7 +37,7 @@ * * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 * $FreeBSD: src/sys/kern/vfs_lookup.c,v 1.38.2.3 2001/08/31 19:36:49 dillon Exp $ - * $DragonFly: src/sys/kern/vfs_lookup.c,v 1.9 2003/11/09 20:29:59 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_lookup.c,v 1.10 2004/03/01 06:33:17 dillon Exp $ */ #include "opt_ktrace.h" @@ -182,7 +182,7 @@ namei(struct nameidata *ndp) 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 @@ lookup(struct nameidata *ndp) 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 @@ dirloop: } 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 @@ dirloop: 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 @@ unionlookup: 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 @@ unionlookup: */ 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 @@ nextname: 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 @@ relookup(dvp, vpp, cnp) 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 @@ relookup(dvp, vpp, cnp) 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 @@ relookup(dvp, vpp, cnp) 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); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 543acee409..97bc3dbfdf 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -37,7 +37,7 @@ * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $ - * $DragonFly: src/sys/kern/vfs_subr.c,v 1.25 2004/02/10 07:34:42 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_subr.c,v 1.26 2004/03/01 06:33:17 dillon Exp $ */ /* @@ -87,9 +87,8 @@ 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, ""); enum vtype iftovt_tab[16] = { @@ -175,6 +174,34 @@ static int vfs_free_netcred (struct radix_node *rn, void *w); static int vfs_hang_addrlist (struct mount *mp, struct netexport *nep, struct export_args *argp); +#define VSHOULDFREE(vp) \ + (!((vp)->v_flag & (VFREE|VDOOMED)) && \ + !(vp)->v_holdcnt && !(vp)->v_usecount && \ + (!(vp)->v_object || \ + !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) + +#define VMIGHTFREE(vp) \ + (((vp)->v_flag & (VFREE|VDOOMED|VXLOCK)) == 0 && \ + cache_leaf_test(vp) == 0 && (vp)->v_usecount == 0) + +#define VSHOULDBUSY(vp) \ + (((vp)->v_flag & VFREE) && \ + ((vp)->v_holdcnt || (vp)->v_usecount)) + +static void vbusy(struct vnode *vp); +static void vfree(struct vnode *vp); +static void vmaybefree(struct vnode *vp); + +/* + * NOTE: the vnode interlock must be held on call. + */ +static __inline void +vmaybefree(struct vnode *vp) +{ + if (VSHOULDFREE(vp)) + vfree(vp); +} + /* * Initialize the vnode management data structures. */ @@ -195,12 +222,12 @@ vntblinit() (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 +242,7 @@ vntblinit() * 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 +250,16 @@ vfs_busy(struct mount *mp, int flags, struct lwkt_token *interlkp, 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 +302,7 @@ vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp) 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 +357,17 @@ vfs_getvfs(fsid) 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 +387,11 @@ vfs_getnewfsid(mp) 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 +404,7 @@ vfs_getnewfsid(mp) } 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 +498,12 @@ static int 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 +518,61 @@ vlrureclaim(struct mount *mp) 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 +588,7 @@ static void vnlru_proc(void) { struct mount *mp, *nmp; + lwkt_tokref ilock; int s; int done; struct thread *td = curthread; @@ -551,18 +606,18 @@ vnlru_proc(void) 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 +649,12 @@ getnewvnode(tag, mp, vops, vpp) 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 +678,114 @@ getnewvnode(tag, mp, vops, vpp) * 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) + if (vp == NULL) 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. */ - vgen = lwkt_gettoken(&vp->v_interlock); - if (lwkt_gentoken(&vnode_free_list_token, &gen) != 0) { - --count; - lwkt_reltoken(&vp->v_interlock); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + + /* + * Skip vnodes that are in the process of being + * held or referenced. Since the act of adding or + * removing a vnode on the freelist requires a token + * and may block, the ref count may be adjusted + * prior to its addition or removal. + */ + if (VSHOULDBUSY(vp)) { 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. + * Obtain the vnode interlock and 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. Note that + * the vnode could be in the middle of being moved + * off the free list (the VSHOULDBUSY() check) and + * must be skipped if so. */ - 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_gettoken(&vlock, vp->v_interlock); + TAILQ_FOREACH_REVERSE(xvp, &vnode_free_list, + freelst, v_freelist) { + if (vp == xvp) + break; + } + if (vp != xvp || VSHOULDBUSY(vp)) { 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 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 (lwkt_gentoken(&vp->v_interlock, &vgen) != 0 || - lwkt_gentoken(&vnode_free_list_token, &gen) != 0) { - --count; + if ((VOP_GETVOBJECT(vp, &object) == 0 && + (object->resident_page_count || object->ref_count)) + ) { + lwkt_reltoken(&vlock); vp = NULL; continue; } - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - KKASSERT(vp->v_flag & VFREE); /* - * 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?) + * 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 (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; - } + KKASSERT(vp->v_flag & VFREE); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + + 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 +808,11 @@ getnewvnode(tag, mp, vops, vpp) 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 +842,9 @@ insmntque(vp, mp) 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 +858,12 @@ insmntque(vp, mp) * 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 +899,7 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td, struct buf *nbp, *blist; int s, error; vm_object_t object; + lwkt_tokref vlock; if (flags & V_SAVE) { s = splbio(); @@ -920,12 +996,12 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td, /* * 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 +1262,9 @@ sched_sync(void) 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 +1592,15 @@ addaliasu(struct vnode *nvp, udev_t nvp_rdev) 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); } /* @@ -1533,50 +1610,58 @@ addalias(struct vnode *nvp, dev_t dev) * when the transition is completed, and an error returned to * indicate that the vnode is no longer usable (possibly having * been changed to a new file system type). + * + * This code is very sensitive. We are depending on the vnode interlock + * to be maintained through to the vn_lock() call, which means that we + * cannot block which means that we cannot call vbusy() until after vn_lock(). + * If the interlock is not maintained, the VXLOCK check will not properly + * interlock against a vclean()'s LK_DRAIN operation on the lock. */ 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. ZZZ it is + * only legal to pass (1) the vnode's interlock and (2) only pass + * NULL w/o LK_INTERLOCK if the vnode is *ALREADY* referenced or + * held. + */ + 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. + * the VXLOCK flag is set. It is possible for the vnode to be + * self-referenced during the cleaning operation. */ if (vp->v_flag & VXLOCK) { - if (vp->v_vxproc == curproc) { + if (vp->v_vxthread == curthread) { #if 0 /* this can now occur in normal operation */ log(LOG_INFO, "VXLOCK interlock avoided\n"); #endif } else { vp->v_flag |= VXWANT; + lwkt_reltoken(vlock); tsleep((caddr_t)vp, 0, "vget", 0); return (ENOENT); } } /* - * Bump v_usecount to prevent the vnode from being cleaned. If the - * vnode gets cleaned unexpectedly we could wind up calling lockmgr - * on a lock embedded in an inode which is then ripped out from - * it. + * Bump v_usecount to prevent the vnode from being recycled. The + * usecount needs to be bumped before we successfully get our lock. */ - vp->v_usecount++; /* XXX MP */ - - if ((flags & LK_INTERLOCK) == 0) { - lwkt_gettoken(&vp->v_interlock); - } - - if (VSHOULDBUSY(vp)) - vbusy(vp); + vp->v_usecount++; 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 +1670,16 @@ vget(vp, flags, td) * 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); + vmaybefree(vp); + lwkt_reltoken(vlock); } return (error); } - lwkt_reltoken(&vp->v_interlock); + if (VSHOULDBUSY(vp)) + vbusy(vp); /* interlock must be held on call */ + lwkt_reltoken(vlock); return (0); } @@ -1613,39 +1697,36 @@ void 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; } if (vp->v_usecount == 1) { vp->v_usecount--; /* - * We must call VOP_INACTIVE with the node locked. - * If we are doing a vpu, the node is already locked, - * but, in the case of vrele, we must explicitly lock - * the vnode before calling VOP_INACTIVE + * We must call VOP_INACTIVE with the node locked and the + * usecount 0. If we are doing a vpu, the node is already + * locked, but, in the case of vrele, we must explicitly lock + * the vnode before calling VOP_INACTIVE. */ - if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0) + if (vn_lock(vp, NULL, LK_EXCLUSIVE, td) == 0) VOP_INACTIVE(vp, td); - if (VSHOULDFREE(vp)) - vfree(vp); - else - vlruvp(vp); + vmaybefree(vp); + lwkt_reltoken(&vlock); } 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 +1735,15 @@ void 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,22 +1754,21 @@ vput(struct vnode *vp) * 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); VOP_INACTIVE(vp, td); - if (VSHOULDFREE(vp)) - vfree(vp); - else - vlruvp(vp); + vmaybefree(vp); + lwkt_reltoken(&vlock); } else { #ifdef DIAGNOSTIC vprint("vput: negative ref count", vp); #endif + lwkt_reltoken(&vlock); panic("vput: negative ref cnt"); } } /* - * Somebody doesn't want the vnode recycled. + * Somebody doesn't want the vnode recycled. ZZZ vnode interlock should + * be held but isn't. */ void vhold(vp) @@ -1698,7 +1779,7 @@ vhold(vp) s = splbio(); vp->v_holdcnt++; if (VSHOULDBUSY(vp)) - vbusy(vp); + vbusy(vp); /* interlock must be held on call */ splx(s); } @@ -1709,15 +1790,86 @@ void vdrop(vp) struct vnode *vp; { - int s; + lwkt_tokref vlock; - s = splbio(); + lwkt_gettoken(&vlock, vp->v_interlock); if (vp->v_holdcnt <= 0) panic("vdrop: holdcnt"); vp->v_holdcnt--; - if (VSHOULDFREE(vp)) - vfree(vp); - splx(s); + vmaybefree(vp); + lwkt_reltoken(&vlock); +} + +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); } /* @@ -1745,6 +1897,14 @@ static int busyprt = 0; /* print out busy vnodes */ 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 +1912,10 @@ vflush(mp, rootrefs, flags) 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 +1928,28 @@ vflush(mp, rootrefs, flags) 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; - } + vflush_info.busy = 0; + vflush_info.flags = flags; + vflush_info.td = td; + vmntvnodescan(mp, NULL, vflush_scan, &vflush_info); - /* - * 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; - } - - /* - * 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,32 +1957,74 @@ loop: } /* - * We do not want to recycle the vnode too quickly. - * - * XXX we can't move vp's around the nvnodelist without really screwing - * up the efficiency of filesystem SYNC and friends. This code is - * disabled until we fix the syncing code's scanning algorithm. + * The scan callback is made with an interlocked vnode. */ -static void -vlruvp(struct vnode *vp) +static int +vflush_scan(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data) { -#if 0 - struct mount *mp; + struct vflush_info *info = data; + struct vattr vattr; - if ((mp = vp->v_mount) != NULL) { - lwkt_gettoken(&mntvnode_token); - TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); - TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); - lwkt_reltoken(&mntvnode_token); + /* + * 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); } /* * 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; @@ -1902,21 +2043,24 @@ vclean(struct vnode *vp, int flags, struct thread *td) if (vp->v_flag & VXLOCK) panic("vclean: deadlock"); vp->v_flag |= VXLOCK; - vp->v_vxproc = curproc; + vp->v_vxthread = curthread; + /* * Even if the count is zero, the VOP_INACTIVE routine may still * have the object locked while it cleans it out. The VOP_LOCK * ensures that the VOP_INACTIVE routine is done with its work. * For active vnodes, it ensures that no other activity can * occur while the underlying object is being cleaned out. + * + * NOTE: we continue to hold the vnode interlock through to the + * end of vclean(). */ - VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td); + VOP_LOCK(vp, NULL, LK_DRAIN, td); /* * Clean out any buffers associated with the vnode. */ vinvalbuf(vp, V_SAVE, td, 0, 0); - VOP_DESTROYVOBJECT(vp); /* @@ -1933,7 +2077,7 @@ vclean(struct vnode *vp, int flags, struct thread *td) * 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 +2090,6 @@ vclean(struct vnode *vp, int flags, struct thread *td) * Inline copy of vrele() since VOP_INACTIVE * has already been called. */ - lwkt_gettoken(&vp->v_interlock); if (--vp->v_usecount <= 0) { #ifdef DIAGNOSTIC if (vp->v_usecount < 0 || vp->v_writecount != 0) { @@ -1956,14 +2099,11 @@ vclean(struct vnode *vp, int flags, struct thread *td) #endif vfree(vp); } - lwkt_reltoken(&vp->v_interlock); } cache_purge(vp); vp->v_vnlock = NULL; - - if (VSHOULDFREE(vp)) - vfree(vp); + vmaybefree(vp); /* * Done with purge, notify sleepers of the grim news. @@ -1972,11 +2112,12 @@ vclean(struct vnode *vp, int flags, struct thread *td) vn_pollgone(vp); vp->v_tag = VT_NON; vp->v_flag &= ~VXLOCK; - vp->v_vxproc = NULL; + vp->v_vxthread = NULL; if (vp->v_flag & VXWANT) { vp->v_flag &= ~VXWANT; wakeup((caddr_t) vp); } + lwkt_reltoken(vlock); } /* @@ -1991,6 +2132,7 @@ vop_revoke(ap) } */ *ap; { struct vnode *vp, *vq; + lwkt_tokref ilock; dev_t dev; KASSERT((ap->a_flags & REVOKEALL) != 0, ("vop_revoke")); @@ -2002,15 +2144,15 @@ vop_revoke(ap) */ 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 +2165,18 @@ vop_revoke(ap) * 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 +2188,19 @@ void 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 +2209,7 @@ vgonel(struct vnode *vp, struct thread *td) */ 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 +2217,8 @@ vgonel(struct vnode *vp, struct thread *td) /* * 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 +2230,10 @@ vgonel(struct vnode *vp, struct thread *td) * 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 +2249,18 @@ vgonel(struct vnode *vp, struct thread *td) */ 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 +2272,18 @@ vfinddev(dev, type, vpp) 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 +2294,15 @@ int 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 +2380,14 @@ vprint(label, vp) 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 +2395,11 @@ DB_SHOW_COMMAND(lockedvnodes, lockedvnodes) 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 +2493,8 @@ sysctl_vnode(SYSCTL_HANDLER_ARGS) 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 +2505,14 @@ sysctl_vnode(SYSCTL_HANDLER_ARGS) 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 +2521,21 @@ again: * 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); } @@ -2711,55 +2858,72 @@ vfs_export_lookup(mp, nep, nam) } /* - * perform msync on all vnodes under a mount point - * the mount point must be locked. + * perform msync on all vnodes under a mount point. The mount point must + * be locked. This code is also responsible for lazy-freeing unreferenced + * vnodes whos VM objects no longer contain pages. + * + * NOTE: MNT_WAIT still skips vnodes in the VXLOCK state. */ +static int vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data); +static int vfs_msync_scan2(struct mount *mp, struct vnode *vp, + lwkt_tokref_t vlock, void *data); + void vfs_msync(struct mount *mp, int flags) { - struct thread *td = curthread; /* XXX */ - struct vnode *vp, *nvp; - struct vm_object *obj; - int tries; - - tries = 5; - lwkt_gettoken(&mntvnode_token); -loop: - for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) { - if (vp->v_mount != mp) { - if (--tries > 0) - goto loop; - break; - } - nvp = TAILQ_NEXT(vp, v_nmntvnodes); + vmntvnodescan(mp, vfs_msync_scan1, vfs_msync_scan2, (void *)flags); +} - if (vp->v_flag & VXLOCK) /* XXX: what if MNT_WAIT? */ - continue; +/* + * scan1 is a fast pre-check. There could be hundreds of thousands of + * vnodes, we cannot afford to do anything heavy weight until we have a + * fairly good indication that there is work to do. + */ +static +int +vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data) +{ + int flags = (int)data; - /* - * There could be hundreds of thousands of vnodes, we cannot - * afford to do anything heavy-weight until we have a fairly - * good indication that there is something to do. - */ - if ((vp->v_flag & VOBJDIRTY) && + if ((vp->v_flag & VXLOCK) == 0) { + if (VSHOULDFREE(vp)) + return(0); + if ((mp->mnt_flag & MNT_RDONLY) == 0 && + (vp->v_flag & VOBJDIRTY) && (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) { - lwkt_reltoken(&mntvnode_token); - if (!vget(vp, - 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; - break; + return(0); + } + } + return(-1); +} + +static +int +vfs_msync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data) +{ + vm_object_t obj; + int error; + int flags = (int)data; + + if (vp->v_flag & VXLOCK) + return(0); + + if ((mp->mnt_flag & MNT_RDONLY) == 0 && + (vp->v_flag & VOBJDIRTY) && + (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) { + error = vget(vp, vlock, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ | LK_INTERLOCK, curthread); + if (error == 0) { + if (VOP_GETVOBJECT(vp, &obj) == 0) { + vm_object_page_clean(obj, 0, 0, + flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC); } + vput(vp); } + return(0); } - lwkt_reltoken(&mntvnode_token); + vmaybefree(vp); + lwkt_reltoken(vlock); + return(0); } /* @@ -2776,43 +2940,56 @@ vfs_object_create(struct vnode *vp, struct thread *td) return (VOP_CREATEVOBJECT(vp, td)); } -void -vfree(vp) - struct vnode *vp; +/* + * NOTE: the vnode interlock must be held during the call. We have to recheck + * the VFREE flag since the vnode may have been removed from the free list + * while we were blocked on vnode_free_list_token. The use or hold count + * must have already been bumped by the caller. + */ +static void +vbusy(struct vnode *vp) { - int s; + lwkt_tokref ilock; - s = splbio(); - lwkt_gettoken(&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); - } else { - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + lwkt_gettoken(&ilock, &vnode_free_list_token); + if ((vp->v_flag & VFREE) != 0) { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; + vp->v_flag &= ~(VFREE|VAGE); } - freevnodes++; - lwkt_reltoken(&vnode_free_list_token); - vp->v_flag &= ~VAGE; - vp->v_flag |= VFREE; - splx(s); + lwkt_reltoken(&ilock); } -void -vbusy(vp) - struct vnode *vp; +/* + * NOTE: the vnode interlock must be held during the call. The use or hold + * count must have already been bumped by the caller. We use a VINFREE to + * interlock against other calls to vfree() which might occur while we + * are blocked. The vnode cannot be reused until it has actually been + * placed on the free list, so there are no other races even though the + * use and hold counts are 0. + */ +static void +vfree(struct vnode *vp) { - int s; + lwkt_tokref ilock; - s = splbio(); - lwkt_gettoken(&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); - vp->v_flag &= ~(VFREE|VAGE); - splx(s); + if ((vp->v_flag & VINFREE) == 0) { + vp->v_flag |= VINFREE; + lwkt_gettoken(&ilock, &vnode_free_list_token); /* can block */ + KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free")); + if (vp->v_flag & VAGE) { + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); + } else { + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + } + freevnodes++; + vp->v_flag &= ~(VAGE|VINFREE); + vp->v_flag |= VFREE; + lwkt_reltoken(&ilock); /* can block */ + } } + /* * Record a process's interest in events which might happen to * a vnode. Because poll uses the historic select-style interface @@ -2824,7 +3001,9 @@ vbusy(vp) 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 +3015,12 @@ vn_pollrecord(struct vnode *vp, struct thread *td, int events) 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 +3035,9 @@ vn_pollevent(vp, events) 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 +3054,7 @@ vn_pollevent(vp, events) vp->v_pollinfo.vpi_revents |= events; selwakeup(&vp->v_pollinfo.vpi_selinfo); } - lwkt_reltoken(&vp->v_pollinfo.vpi_token); + lwkt_reltoken(&ilock); } /* @@ -2885,12 +3066,14 @@ void 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); } @@ -2927,10 +3110,14 @@ VNODEOP_SET(sync_vnodeop_opv_desc); /* * Create a new filesystem syncer vnode for the specified mount point. + * This vnode is placed on the worklist and is responsible for sync'ing + * the filesystem. + * + * NOTE: read-only mounts are also placed on the worklist. The filesystem + * sync code is also responsible for cleaning up vnodes. */ int -vfs_allocate_syncvnode(mp) - struct mount *mp; +vfs_allocate_syncvnode(struct mount *mp) { struct vnode *vp; static long start, incr, next; @@ -2978,6 +3165,7 @@ sync_fsync(ap) struct vnode *syncvp = ap->a_vp; struct mount *mp = syncvp->v_mount; struct thread *td = ap->a_td; + lwkt_tokref ilock; int asyncflag; /* @@ -2993,19 +3181,26 @@ sync_fsync(ap) /* * Walk the list of vnodes pushing all that are dirty and - * not already on the sync list. + * not already on the sync list, and freeing vnodes which have + * no refs and whos VM objects are empty. vfs_msync() handles + * the VM issues and must be called whether the mount is readonly + * or not. */ - 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; - mp->mnt_flag &= ~MNT_ASYNC; - vfs_msync(mp, MNT_NOWAIT); - VFS_SYNC(mp, MNT_LAZY, td); - if (asyncflag) - mp->mnt_flag |= MNT_ASYNC; + if (mp->mnt_flag & MNT_RDONLY) { + vfs_msync(mp, MNT_NOWAIT); + } else { + asyncflag = mp->mnt_flag & MNT_ASYNC; + mp->mnt_flag &= ~MNT_ASYNC; /* ZZZ hack */ + vfs_msync(mp, MNT_NOWAIT); + VFS_SYNC(mp, MNT_LAZY, td); + if (asyncflag) + mp->mnt_flag |= MNT_ASYNC; + } vfs_unbusy(mp, td); return (0); } @@ -3138,7 +3333,7 @@ NDFREE(ndp, flags) 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 +3342,7 @@ NDFREE(ndp, flags) } 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) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 0885ae09c3..104a2ddcb8 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -37,7 +37,7 @@ * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ - * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.28 2003/11/14 19:31:22 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.29 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -108,6 +108,8 @@ mount(struct mount_args *uap) 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 @@ mount(struct mount_args *uap) 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 @@ mount(struct mount_args *uap) 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 @@ mount(struct mount_args *uap) 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 @@ mount(struct mount_args *uap) 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. @@ -291,45 +293,36 @@ update: mp->mnt_flag = flag; mp->mnt_kern_flag = flag2; } - if ((mp->mnt_flag & MNT_RDONLY) == 0) { - if (mp->mnt_syncer == NULL) - error = vfs_allocate_syncvnode(mp); - } else { - if (mp->mnt_syncer != NULL) - vrele(mp->mnt_syncer); - 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); - if ((mp->mnt_flag & MNT_RDONLY) == 0) - error = vfs_allocate_syncvnode(mp); + VOP_UNLOCK(vp, NULL, 0, td); + 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 +436,11 @@ dounmount(struct mount *mp, int flags, struct thread *td) 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 +448,7 @@ dounmount(struct mount *mp, int flags, struct thread *td) 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 +469,14 @@ dounmount(struct mount *mp, int flags, struct thread *td) (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); + if (mp->mnt_syncer == NULL) + 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 +489,7 @@ dounmount(struct mount *mp, int flags, struct thread *td) 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 +511,12 @@ sync(struct sync_args *uap) { 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 +527,11 @@ sync(struct sync_args *uap) 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 +688,15 @@ getfsstat(struct getfsstat_args *uap) 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 +710,7 @@ getfsstat(struct getfsstat_args *uap) 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 +724,11 @@ getfsstat(struct getfsstat_args *uap) 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 +757,13 @@ fchdir(struct fchdir_args *uap) 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 +776,7 @@ fchdir(struct fchdir_args *uap) 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 +915,7 @@ change_dir(struct nameidata *ndp, struct thread *td) if (error) vput(vp); else - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); return (error); } @@ -997,7 +993,7 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res) 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 +1015,7 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res) 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 +1030,13 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res) 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 +1403,7 @@ kern_unlink(struct nameidata *nd) 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 +1814,11 @@ setfflags(struct vnode *vp, int flags) 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 +1873,11 @@ setfmode(struct vnode *vp, int mode) 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 +1965,12 @@ setfown(struct vnode *vp, uid_t uid, gid_t gid) 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 +2071,14 @@ setutimes(struct vnode *vp, const struct timespec *ts, int nullflag) 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 +2207,7 @@ kern_truncate(struct nameidata* nd, off_t length) 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 +2257,7 @@ kern_ftruncate(int fd, off_t length) 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 +2265,7 @@ kern_ftruncate(int fd, off_t length) 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 +2303,14 @@ fsync(struct fsync_args *uap) 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 +2579,12 @@ unionread: 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 +2841,9 @@ fhopen(struct fhopen_args *uap) 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 +2894,7 @@ fhopen(struct fhopen_args *uap) 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 +2912,13 @@ fhopen(struct fhopen_args *uap) 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); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 248b0ea9e9..1cd02eb973 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -37,7 +37,7 @@ * * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/vfs_vnops.c,v 1.87.2.13 2002/12/29 18:19:53 dillon Exp $ - * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.15 2003/10/09 22:27:19 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.16 2004/03/01 06:33:17 dillon Exp $ */ #include @@ -174,9 +174,9 @@ vn_open(ndp, fmode, cmode) } } 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 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td) 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 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td) 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 @@ vn_read(fp, uio, cred, flags, td) 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 @@ vn_read(fp, uio, cred, flags, td) 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 @@ vn_write(fp, uio, cred, flags, td) (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 @@ vn_write(fp, uio, cred, flags, td) 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,33 +626,36 @@ vn_poll(struct file *fp, int events, struct ucred *cred, struct thread *td) */ 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 ((vp->v_flag & VXLOCK) && vp->v_vxproc != curproc) { + if ((flags & LK_INTERLOCK) == 0) { + lwkt_gettoken(&vvlock, vp->v_interlock); + vlock = &vvlock; + } + if ((vp->v_flag & VXLOCK) && vp->v_vxthread != curthread) { vp->v_flag |= VXWANT; - lwkt_reltoken(&vp->v_interlock); + lwkt_reltoken(vlock); tsleep((caddr_t)vp, 0, "vn_lock", 0); error = ENOENT; } else { #if 0 /* this can now occur in normal operation */ - if (vp->v_vxproc != NULL) + if (vp->v_vxthread != NULL) log(LOG_INFO, "VXLOCK interlock avoided in vn_lock\n"); #endif #ifdef DEBUG_LOCKS 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); diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 665a01d81b..fd3af3fbc7 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -32,7 +32,7 @@ # # @(#)vnode_if.src 8.12 (Berkeley) 5/14/95 # $FreeBSD: src/sys/kern/vnode_if.src,v 1.29.2.3 2001/05/18 09:58:45 bp Exp $ -# $DragonFly: src/sys/kern/Attic/vnode_if.src,v 1.5 2003/10/09 22:27:19 dillon Exp $ +# $DragonFly: src/sys/kern/Attic/vnode_if.src,v 1.6 2004/03/01 06:33:17 dillon Exp $ # # @@ -379,6 +379,7 @@ vop_reclaim { # vop_lock { IN struct vnode *vp; + IN struct lwkt_tokref *vlock; IN int flags; IN struct thread *td; }; @@ -388,6 +389,7 @@ vop_lock { # vop_unlock { IN struct vnode *vp; + IN struct lwkt_tokref *vlock; IN int flags; IN struct thread *td; }; diff --git a/sys/netproto/ncp/ncp_conn.c b/sys/netproto/ncp/ncp_conn.c index 6614e56c0e..f453b0f07c 100644 --- a/sys/netproto/ncp/ncp_conn.c +++ b/sys/netproto/ncp/ncp_conn.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * $FreeBSD: src/sys/netncp/ncp_conn.c,v 1.3.2.5 2001/02/22 08:54:11 bp Exp $ - * $DragonFly: src/sys/netproto/ncp/ncp_conn.c,v 1.6 2003/11/10 06:12:14 dillon Exp $ + * $DragonFly: src/sys/netproto/ncp/ncp_conn.c,v 1.7 2004/03/01 06:33:18 dillon Exp $ * * Connection tables */ @@ -80,13 +80,13 @@ ncp_conn_init(void) { 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 @@ ncp_conn_lock_any(struct ncp_conn *conn, struct thread *td, struct ucred *cred) 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 @@ ncp_conn_unlock(struct ncp_conn *conn, struct thread *td) { * 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 @@ ncp_conn_free(struct ncp_conn *ncp) /* * 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 @@ int 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 @@ ncp_conn_gethandle(struct ncp_conn *conn, struct thread *td, struct ncp_handle * 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 @@ int 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 @@ ncp_conn_puthandle(struct ncp_handle *handle, struct thread *td, int force) { 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 @@ int 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 @@ ncp_conn_putprochandles(struct thread *td) { 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 @@ ncp_conn_putprochandles(struct thread *td) { 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; } /* diff --git a/sys/netproto/smb/smb_conn.c b/sys/netproto/smb/smb_conn.c index ff1e81a862..1b21370039 100644 --- a/sys/netproto/smb/smb_conn.c +++ b/sys/netproto/smb/smb_conn.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_conn.c,v 1.1.2.1 2001/05/22 08:32:33 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_conn.c,v 1.6 2003/11/10 06:12:16 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_conn.c,v 1.7 2004/03/01 06:33:18 dillon Exp $ */ /* @@ -82,7 +82,7 @@ smb_sm_init(void) { 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 @@ smb_sm_done(void) 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 @@ smb_co_init(struct smb_connobj *cp, int level, char *objname, struct thread *td) 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 @@ smb_co_gone(struct smb_connobj *cp, struct smb_cred *scred) 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 @@ smb_co_gone(struct smb_connobj *cp, struct smb_cred *scred) 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 @@ smb_co_put(struct smb_connobj *cp, struct smb_cred *scred) { 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 @@ smb_co_put(struct smb_connobj *cp, struct smb_cred *scred) } 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 @@ smb_co_lockstatus(struct smb_connobj *cp, struct thread *td) } 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 @@ smb_co_lock(struct smb_connobj *cp, int flags, struct thread *td) 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 @@ smb_vc_rele(struct smb_vc *vcp, struct smb_cred *scred) 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 @@ smb_vc_put(struct smb_vc *vcp, struct smb_cred *scred) 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 @@ u_short 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 @@ smb_share_rele(struct smb_share *ssp, struct smb_cred *scred) 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 @@ smb_share_put(struct smb_share *ssp, struct smb_cred *scred) 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 diff --git a/sys/netproto/smb/smb_conn.h b/sys/netproto/smb/smb_conn.h index e5c6ce7094..65ab0f974c 100644 --- a/sys/netproto/smb/smb_conn.h +++ b/sys/netproto/smb/smb_conn.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_conn.h,v 1.1.2.3 2002/04/23 03:45:01 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_conn.h,v 1.4 2003/08/07 21:17:38 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_conn.h,v 1.5 2004/03/01 06:33:18 dillon Exp $ */ #ifndef _NETINET_IN_H_ #include @@ -199,8 +199,8 @@ struct smb_connobj; 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 @@ struct smb_connobj { /* * 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 @@ struct smb_vc { /* * 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 @@ int smb_sm_lookup(struct smb_vcspec *vcspec, */ 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 diff --git a/sys/netproto/smb/smb_iod.c b/sys/netproto/smb/smb_iod.c index 8f8ac0e869..87396bb63c 100644 --- a/sys/netproto/smb/smb_iod.c +++ b/sys/netproto/smb/smb_iod.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_iod.c,v 1.1.2.2 2002/04/23 03:45:01 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_iod.c,v 1.7 2003/08/07 21:17:39 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_iod.c,v 1.8 2004/03/01 06:33:18 dillon Exp $ */ #include @@ -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 void smb_iod_thread(void *); 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 @@ static int 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 @@ smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp) 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 @@ smb_iod_recvall(struct smbiod *iod) 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 @@ smb_iod_recvall(struct smbiod *iod) } 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 @@ smb_iod_recvall(struct smbiod *iod) /* * 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 @@ smb_iod_request(struct smbiod *iod, int event, void *ident) { 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 @@ smb_iod_addrq(struct smb_rq *rqp) { 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 @@ smb_iod_addrq(struct smb_rq *rqp) break; } - SMB_IOD_RQLOCK(iod); + SMB_IOD_RQLOCK(&ilock, iod); for (;;) { if (vcp->vc_maxmux == 0) { SMBERROR("maxmux == 0\n"); @@ -443,12 +454,11 @@ smb_iod_addrq(struct smb_rq *rqp) 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 @@ smb_iod_removerq(struct smb_rq *rqp) { 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 @@ smb_iod_removerq(struct smb_rq *rqp) iod->iod_muxwant--; wakeup(&iod->iod_muxwant); } - SMB_IOD_RQUNLOCK(iod); + SMB_IOD_RQUNLOCK(&ilock); return 0; } @@ -485,6 +496,7 @@ int 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 @@ smb_iod_waitrq(struct smb_rq *rqp) 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 @@ smb_iod_sendall(struct smbiod *iod) 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 @@ smb_iod_sendall(struct smbiod *iod) if (herror) break; } - SMB_IOD_RQUNLOCK(iod); + SMB_IOD_RQUNLOCK(&ilock); if (herror == ENOTCONN) smb_iod_dead(iod); return 0; @@ -577,6 +590,7 @@ smb_iod_main(struct smbiod *iod) struct smbiod_event *evp; /* struct timespec tsnow;*/ int error; + smb_ilock ilock; SMBIODEBUG("\n"); error = 0; @@ -585,15 +599,15 @@ smb_iod_main(struct smbiod *iod) * 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 @@ smb_iod_main(struct smbiod *iod) 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); } diff --git a/sys/netproto/smb/smb_rq.c b/sys/netproto/smb/smb_rq.c index fc58587081..afba5f526c 100644 --- a/sys/netproto/smb/smb_rq.c +++ b/sys/netproto/smb/smb_rq.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_rq.c,v 1.1.2.2 2002/04/23 03:45:01 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_rq.c,v 1.6 2003/08/07 21:17:39 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_rq.c,v 1.7 2004/03/01 06:33:18 dillon Exp $ */ #include #include @@ -172,23 +172,24 @@ smb_rq_enqueue(struct smb_rq *rqp) { 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 @@ smb_t2_reply(struct smb_t2rq *t2p) 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 @@ smb_t2_reply(struct smb_t2rq *t2p) /* * 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 @@ smb_t2_reply(struct smb_t2rq *t2p) /* * 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; diff --git a/sys/netproto/smb/smb_rq.h b/sys/netproto/smb/smb_rq.h index 9523ff0283..245c974c5b 100644 --- a/sys/netproto/smb/smb_rq.h +++ b/sys/netproto/smb/smb_rq.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_rq.h,v 1.1.2.2 2002/04/23 03:45:01 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_rq.h,v 1.2 2003/06/17 04:28:54 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_rq.h,v 1.3 2004/03/01 06:33:18 dillon Exp $ */ #ifndef _NETSMB_SMB_RQ_H_ #define _NETSMB_SMB_RQ_H_ @@ -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) diff --git a/sys/netproto/smb/smb_subr.c b/sys/netproto/smb/smb_subr.c index d315f08167..e6eac078fb 100644 --- a/sys/netproto/smb/smb_subr.c +++ b/sys/netproto/smb/smb_subr.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_subr.c,v 1.1.2.2 2001/09/03 08:55:11 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_subr.c,v 1.9 2003/11/09 02:22:37 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_subr.c,v 1.10 2004/03/01 06:33:18 dillon Exp $ */ #include #include @@ -429,15 +429,13 @@ kthread_create2(void (*func)(void *), void *arg, * 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; } diff --git a/sys/netproto/smb/smb_subr.h b/sys/netproto/smb/smb_subr.h index b48af387bd..4e12afeec7 100644 --- a/sys/netproto/smb/smb_subr.h +++ b/sys/netproto/smb/smb_subr.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_subr.h,v 1.1.2.1 2001/05/22 08:32:34 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_subr.h,v 1.7 2003/11/15 21:05:43 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_subr.h,v 1.8 2004/03/01 06:33:18 dillon Exp $ */ #ifndef _NETSMB_SMB_SUBR_H_ #define _NETSMB_SMB_SUBR_H_ @@ -80,10 +80,11 @@ void m_dumpm(struct mbuf *m); #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 @@ extern smb_unichar smb_unieol; 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 smb_checksmp(void); */ 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_ */ diff --git a/sys/platform/pc32/apic/mpapic.c b/sys/platform/pc32/apic/mpapic.c index 46bdd1eb95..7ca89380fa 100644 --- a/sys/platform/pc32/apic/mpapic.c +++ b/sys/platform/pc32/apic/mpapic.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $ - * $DragonFly: src/sys/platform/pc32/apic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/platform/pc32/apic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $ */ #include @@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode) 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) /* 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) * 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 */ diff --git a/sys/platform/pc32/apic/mpapic.h b/sys/platform/pc32/apic/mpapic.h index 07059400eb..76cb15a913 100644 --- a/sys/platform/pc32/apic/mpapic.h +++ b/sys/platform/pc32/apic/mpapic.h @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $ - * $DragonFly: src/sys/platform/pc32/apic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/apic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $ */ #ifndef _MACHINE_MPAPIC_H_ @@ -63,18 +63,6 @@ enum busTypes { #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 */ diff --git a/sys/platform/pc32/i386/machdep.c b/sys/platform/pc32/i386/machdep.c index 94404fe6a4..760288f95e 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -36,7 +36,7 @@ * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $ - * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.54 2004/02/17 19:38:53 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.55 2004/03/01 06:33:16 dillon Exp $ */ #include "use_apm.h" @@ -2648,6 +2648,7 @@ init_locks(void) #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 @@ init_locks(void) 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(); } diff --git a/sys/platform/pc32/i386/mp_machdep.c b/sys/platform/pc32/i386/mp_machdep.c index ab0c5f2c03..cf2c49a1b7 100644 --- a/sys/platform/pc32/i386/mp_machdep.c +++ b/sys/platform/pc32/i386/mp_machdep.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $ - * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.23 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.24 2004/03/01 06:33:16 dillon Exp $ */ #include "opt_cpu.h" @@ -280,7 +280,7 @@ struct pcb stoppcbs[MAXCPU]; 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 void install_ap_tramp(u_int boot_addr); 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 @@ restart_cpus(u_int map) * loop for the idlethread. Interrupts are disabled on entry and should * remain disabled at return. */ - void ap_init(void) { @@ -2332,17 +2332,27 @@ ap_init(void) 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 @@ ap_init(void) /* 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 @@ smp_rendezvous(void (* setup_func)(void *), 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 + diff --git a/sys/platform/pc32/i386/mpapic.c b/sys/platform/pc32/i386/mpapic.c index c62cd5e69b..46c2d1377a 100644 --- a/sys/platform/pc32/i386/mpapic.c +++ b/sys/platform/pc32/i386/mpapic.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $ - * $DragonFly: src/sys/platform/pc32/i386/Attic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/platform/pc32/i386/Attic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $ */ #include @@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode) 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) /* 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 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode) * 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 */ diff --git a/sys/platform/pc32/i386/nexus.c b/sys/platform/pc32/i386/nexus.c index b7622835b9..ce9f826ea1 100644 --- a/sys/platform/pc32/i386/nexus.c +++ b/sys/platform/pc32/i386/nexus.c @@ -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/platform/pc32/i386/nexus.c,v 1.9 2004/02/23 21:23:42 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/nexus.c,v 1.10 2004/03/01 06:33:16 dillon Exp $ */ /* @@ -82,6 +82,7 @@ struct nexus_device { 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 void nexus_delete_resource(device_t, device_t, int, int); 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 @@ static devclass_t nexus_devclass; 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 @@ nexus_attach(device_t dev) 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". diff --git a/sys/platform/pc32/i386/pmap.c b/sys/platform/pc32/i386/pmap.c index fb236fb3fb..53732a3759 100644 --- a/sys/platform/pc32/i386/pmap.c +++ b/sys/platform/pc32/i386/pmap.c @@ -40,7 +40,7 @@ * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $ - * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.31 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.32 2004/03/01 06:33:16 dillon Exp $ */ /* @@ -1535,7 +1535,7 @@ pmap_remove_pte(struct pmap *pmap, unsigned *ptq, vm_offset_t va, * 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); diff --git a/sys/platform/pc32/include/mpapic.h b/sys/platform/pc32/include/mpapic.h index 41d00a630e..9578c64fe0 100644 --- a/sys/platform/pc32/include/mpapic.h +++ b/sys/platform/pc32/include/mpapic.h @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $ - * $DragonFly: src/sys/platform/pc32/include/Attic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/include/Attic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $ */ #ifndef _MACHINE_MPAPIC_H_ @@ -63,18 +63,6 @@ enum busTypes { #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 */ diff --git a/sys/platform/pc32/include/smp.h b/sys/platform/pc32/include/smp.h index 225556d54b..6ddabd1b5d 100644 --- a/sys/platform/pc32/include/smp.h +++ b/sys/platform/pc32/include/smp.h @@ -7,7 +7,7 @@ * ---------------------------------------------------------------------------- * * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $ - * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.10 2004/02/21 06:37:07 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.11 2004/03/01 06:33:16 dillon Exp $ * */ @@ -128,7 +128,9 @@ void apic_dump (char*); 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 @@ void set_apic_timer (int); 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; diff --git a/sys/sys/buf2.h b/sys/sys/buf2.h index deda22326c..317e254234 100644 --- a/sys/sys/buf2.h +++ b/sys/sys/buf2.h @@ -37,7 +37,7 @@ * * @(#)buf.h 8.9 (Berkeley) 3/30/95 * $FreeBSD: src/sys/sys/buf.h,v 1.88.2.10 2003/01/25 19:02:23 dillon Exp $ - * $DragonFly: src/sys/sys/buf2.h,v 1.6 2003/08/20 07:31:21 rob Exp $ + * $DragonFly: src/sys/sys/buf2.h,v 1.7 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_BUF2_H_ @@ -63,15 +63,16 @@ static __inline int BUF_LOCK (struct buf *, int); 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 *, int, char *, int, int); 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; } diff --git a/sys/sys/globaldata.h b/sys/sys/globaldata.h index 9f9d61c304..2d565cf534 100644 --- a/sys/sys/globaldata.h +++ b/sys/sys/globaldata.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/globaldata.h,v 1.11.2.1 2000/05/16 06:58:10 dillon Exp $ - * $DragonFly: src/sys/sys/globaldata.h,v 1.26 2004/02/20 17:11:08 dillon Exp $ + * $DragonFly: src/sys/sys/globaldata.h,v 1.27 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_GLOBALDATA_H_ @@ -119,6 +119,7 @@ struct globaldata { struct pipe *gd_pipeq; /* cache pipe structures */ int gd_pipeqcount; /* number of structures */ + lwkt_tokref_t gd_tokreqbase; /* requests from other cpus */ /* extended by */ }; diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 7543abdcd9..f5b4e25ae2 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -40,7 +40,7 @@ * * @(#)kernel.h 8.3 (Berkeley) 1/21/94 * $FreeBSD: src/sys/sys/kernel.h,v 1.63.2.9 2002/07/02 23:00:30 archie Exp $ - * $DragonFly: src/sys/sys/kernel.h,v 1.9 2004/02/25 17:38:51 joerg Exp $ + * $DragonFly: src/sys/sys/kernel.h,v 1.10 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_KERNEL_H_ @@ -128,6 +128,7 @@ enum sysinit_sub_id { 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*/ diff --git a/sys/sys/lock.h b/sys/sys/lock.h index 20000c9bab..9e91234d20 100644 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -36,7 +36,7 @@ * * @(#)lock.h 8.12 (Berkeley) 5/19/95 * $FreeBSD: src/sys/sys/lock.h,v 1.17.2.3 2001/12/25 01:44:44 dillon Exp $ - * $DragonFly: src/sys/sys/lock.h,v 1.7 2003/11/21 22:46:13 dillon Exp $ + * $DragonFly: src/sys/sys/lock.h,v 1.8 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_LOCK_H_ @@ -193,7 +193,7 @@ void lockinit (struct lock *, int prio, char *wmesg, int timo, 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 @@ int debuglockmgr (struct lock *, u_int flags, "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 *); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index db1ee71677..0f749f6164 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -32,7 +32,7 @@ * * @(#)mount.h 8.21 (Berkeley) 5/20/95 * $FreeBSD: src/sys/sys/mount.h,v 1.89.2.7 2003/04/04 20:35:57 tegge Exp $ - * $DragonFly: src/sys/sys/mount.h,v 1.8 2004/02/02 05:43:15 dillon Exp $ + * $DragonFly: src/sys/sys/mount.h,v 1.9 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_MOUNT_H_ @@ -111,6 +111,9 @@ struct statfs { * 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_setpublicfs /* set publicly exported fs */ 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 */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 810c0f85bf..09f3f50483 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -37,7 +37,7 @@ * * @(#)proc.h 8.15 (Berkeley) 5/19/95 * $FreeBSD: src/sys/sys/proc.h,v 1.99.2.9 2003/06/06 20:21:32 tegge Exp $ - * $DragonFly: src/sys/sys/proc.h,v 1.42 2004/01/30 05:42:18 dillon Exp $ + * $DragonFly: src/sys/sys/proc.h,v 1.43 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_PROC_H_ @@ -449,7 +449,6 @@ void cpu_thread_wait (struct thread *); 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); diff --git a/sys/sys/rman.h b/sys/sys/rman.h index 9ea29aba98..67db79cbbb 100644 --- a/sys/sys/rman.h +++ b/sys/sys/rman.h @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/sys/rman.h,v 1.5.2.1 2001/06/05 08:06:07 imp Exp $ - * $DragonFly: src/sys/sys/rman.h,v 1.6 2004/02/21 09:17:10 dillon Exp $ + * $DragonFly: src/sys/sys/rman.h,v 1.7 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_RMAN_H_ @@ -77,6 +77,9 @@ struct resource { 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 @@ TAILQ_HEAD(rman_head, rman); #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); diff --git a/sys/sys/thread.h b/sys/sys/thread.h index ad9338ff6f..63f17d92cd 100644 --- a/sys/sys/thread.h +++ b/sys/sys/thread.h @@ -7,7 +7,7 @@ * Types which must already be defined when this header is included by * userland: struct md_thread * - * $DragonFly: src/sys/sys/thread.h,v 1.46 2004/02/17 19:38:50 dillon Exp $ + * $DragonFly: src/sys/sys/thread.h,v 1.47 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_THREAD_H_ @@ -31,6 +31,7 @@ struct proc; 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 @@ union sysunion; 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 @@ struct intrframe; #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 @@ typedef struct lwkt_wait { #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 @@ struct thread { 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_init_thread(struct thread *td, void *stack, int flags, 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_deschedule_self(void); 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); diff --git a/sys/sys/thread2.h b/sys/sys/thread2.h index 48f763bc8e..84f9328037 100644 --- a/sys/sys/thread2.h +++ b/sys/sys/thread2.h @@ -8,7 +8,7 @@ * on a different cpu will not be immediately scheduled by a yield() on * this cpu. * - * $DragonFly: src/sys/sys/thread2.h,v 1.12 2004/02/10 07:34:43 dillon Exp $ + * $DragonFly: src/sys/sys/thread2.h,v 1.13 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_THREAD2_H_ @@ -102,10 +102,16 @@ crit_panic_restore(int cpri) 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; } /* diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 9b7bc4a0b8..1799370969 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -32,7 +32,7 @@ * * @(#)vnode.h 8.7 (Berkeley) 2/4/94 * $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $ - * $DragonFly: src/sys/sys/vnode.h,v 1.9 2004/01/20 18:41:51 dillon Exp $ + * $DragonFly: src/sys/sys/vnode.h,v 1.10 2004/03/01 06:33:19 dillon Exp $ */ #ifndef _SYS_VNODE_H_ @@ -116,7 +116,7 @@ struct vnode { 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 */ @@ -134,7 +134,7 @@ struct vnode { short vpi_events; /* what they are looking for */ short vpi_revents; /* what has happened */ } v_pollinfo; - struct proc *v_vxproc; /* proc owning VXLOCK */ + struct thread *v_vxthread; /* thread owning VXLOCK */ struct vmresident *v_resident; /* optional vmresident */ #ifdef DEBUG_LOCKS const char *filename; /* Source file doing locking */ @@ -172,9 +172,11 @@ struct vnode { #define VOWANT 0x20000 /* a process is waiting for VOLOCK */ #define VDOOMED 0x40000 /* This vnode is being recycled */ #define VFREE 0x80000 /* This vnode is on the freelist */ +#define VINFREE 0x100000 /* This vnode is in the midst of being freed */ #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 @@ -311,22 +313,8 @@ extern int vfs_ioopt; extern void (*lease_updatetime) (int deltat); -#define VSHOULDFREE(vp) \ - (!((vp)->v_flag & (VFREE|VDOOMED)) && \ - !(vp)->v_holdcnt && !(vp)->v_usecount && \ - (!(vp)->v_object || \ - !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) - -#define VMIGHTFREE(vp) \ - (((vp)->v_flag & (VFREE|VDOOMED|VXLOCK)) == 0 && \ - cache_leaf_test(vp) == 0 && (vp)->v_usecount == 0) - -#define VSHOULDBUSY(vp) \ - (((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 +564,29 @@ int vfinddev (dev_t dev, enum vtype type, struct vnode **vpp); 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); @@ -633,11 +626,9 @@ int vop_stdcreatevobject (struct vop_createvobject_args *ap); int vop_stddestroyvobject (struct vop_destroyvobject_args *ap); int vop_stdgetvobject (struct vop_getvobject_args *ap); -void vfree (struct vnode *vp); void vput (struct vnode *vp); void vrele (struct vnode *vp); void vref (struct vnode *vp); -void vbusy (struct vnode *vp); extern vop_t **default_vnodeop_p; extern vop_t **spec_vnodeop_p; diff --git a/sys/vfs/coda/coda_subr.c b/sys/vfs/coda/coda_subr.c index 9ddcb9919c..29eb158338 100644 --- a/sys/vfs/coda/coda_subr.c +++ b/sys/vfs/coda/coda_subr.c @@ -28,7 +28,7 @@ * * @(#) src/sys/coda/coda_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ * $FreeBSD: src/sys/coda/coda_subr.c,v 1.11.2.1 2001/10/25 19:18:51 dillon Exp $ - * $DragonFly: src/sys/vfs/coda/Attic/coda_subr.c,v 1.5 2003/11/12 22:08:09 dillon Exp $ + * $DragonFly: src/sys/vfs/coda/Attic/coda_subr.c,v 1.6 2004/03/01 06:33:19 dillon Exp $ * */ @@ -315,9 +315,11 @@ coda_checkunmounting(mp) 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)) { diff --git a/sys/vfs/coda/coda_vfsops.c b/sys/vfs/coda/coda_vfsops.c index d5eb9a044c..c971785c9d 100644 --- a/sys/vfs/coda/coda_vfsops.c +++ b/sys/vfs/coda/coda_vfsops.c @@ -28,7 +28,7 @@ * * @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ * $FreeBSD: src/sys/coda/coda_vfsops.c,v 1.24.2.1 2001/07/26 20:36:45 iedowse Exp $ - * $DragonFly: src/sys/vfs/coda/Attic/coda_vfsops.c,v 1.10 2003/09/23 05:03:52 dillon Exp $ + * $DragonFly: src/sys/vfs/coda/Attic/coda_vfsops.c,v 1.11 2004/03/01 06:33:19 dillon Exp $ * */ @@ -314,11 +314,11 @@ coda_root(vfsp, vpp) { /* 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 @@ coda_root(vfsp, vpp) *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 @@ coda_root(vfsp, vpp) *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); diff --git a/sys/vfs/coda/coda_vnops.c b/sys/vfs/coda/coda_vnops.c index f96be8b3f9..64fbbd5538 100644 --- a/sys/vfs/coda/coda_vnops.c +++ b/sys/vfs/coda/coda_vnops.c @@ -28,7 +28,7 @@ * * @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ * $FreeBSD: src/sys/coda/coda_vnops.c,v 1.22.2.1 2001/06/29 16:26:22 shafeeq Exp $ - * $DragonFly: src/sys/vfs/coda/Attic/coda_vnops.c,v 1.13 2004/02/16 19:56:26 dillon Exp $ + * $DragonFly: src/sys/vfs/coda/Attic/coda_vnops.c,v 1.14 2004/03/01 06:33:19 dillon Exp $ * */ @@ -272,7 +272,7 @@ coda_open(v) 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 @@ coda_rdwr(vp, uiop, rw, ioflag, cred, td) * 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 @@ coda_inactive(v) 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 @@ coda_inactive(v) panic("coda_inactive: cp->ovp != NULL"); } #endif - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); vgone(vp); } @@ -1072,7 +1072,7 @@ coda_lookup(v) */ 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 @@ coda_lookup(v) * 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 @@ coda_lookup(v) /* 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 @@ coda_create(v) 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 @@ coda_lock(v) } #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 @@ coda_unlock(v) 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 diff --git a/sys/vfs/deadfs/dead_vnops.c b/sys/vfs/deadfs/dead_vnops.c index 06bd7e96ef..3c146e6776 100644 --- a/sys/vfs/deadfs/dead_vnops.c +++ b/sys/vfs/deadfs/dead_vnops.c @@ -32,7 +32,7 @@ * * @(#)dead_vnops.c 8.1 (Berkeley) 6/10/93 * $FreeBSD: src/sys/miscfs/deadfs/dead_vnops.c,v 1.26 1999/08/28 00:46:42 peter Exp $ - * $DragonFly: src/sys/vfs/deadfs/dead_vnops.c,v 1.6 2003/08/20 09:56:31 rob Exp $ + * $DragonFly: src/sys/vfs/deadfs/dead_vnops.c,v 1.7 2004/03/01 06:33:20 dillon Exp $ */ #include @@ -201,6 +201,7 @@ static int 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 @@ dead_lock(ap) * 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)) diff --git a/sys/vfs/fdesc/fdesc_vfsops.c b/sys/vfs/fdesc/fdesc_vfsops.c index 18a9de6a9c..fab2436c68 100644 --- a/sys/vfs/fdesc/fdesc_vfsops.c +++ b/sys/vfs/fdesc/fdesc_vfsops.c @@ -36,7 +36,7 @@ * @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94 * * $FreeBSD: src/sys/miscfs/fdesc/fdesc_vfsops.c,v 1.22.2.3 2002/08/23 17:42:39 njl Exp $ - * $DragonFly: src/sys/vfs/fdesc/fdesc_vfsops.c,v 1.5 2003/08/20 09:56:31 rob Exp $ + * $DragonFly: src/sys/vfs/fdesc/fdesc_vfsops.c,v 1.6 2004/03/01 06:33:20 dillon Exp $ */ /* @@ -149,7 +149,7 @@ fdesc_root(struct mount *mp, struct vnode **vpp) */ 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); } diff --git a/sys/vfs/fdesc/fdesc_vnops.c b/sys/vfs/fdesc/fdesc_vnops.c index 01b8b8d673..42bd720f95 100644 --- a/sys/vfs/fdesc/fdesc_vnops.c +++ b/sys/vfs/fdesc/fdesc_vnops.c @@ -36,7 +36,7 @@ * @(#)fdesc_vnops.c 8.9 (Berkeley) 1/21/94 * * $FreeBSD: src/sys/miscfs/fdesc/fdesc_vnops.c,v 1.47.2.1 2001/10/22 22:49:26 chris Exp $ - * $DragonFly: src/sys/vfs/fdesc/fdesc_vnops.c,v 1.8 2003/09/23 05:03:52 dillon Exp $ + * $DragonFly: src/sys/vfs/fdesc/fdesc_vnops.c,v 1.9 2004/03/01 06:33:20 dillon Exp $ */ /* @@ -112,7 +112,7 @@ fdesc_allocvp(ftype, ix, mp, vpp, td) 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 @@ fdesc_lookup(ap) 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 @@ fdesc_lookup(ap) 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 @@ fdesc_inactive(ap) * 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); } diff --git a/sys/vfs/fifofs/fifo_vnops.c b/sys/vfs/fifofs/fifo_vnops.c index 754a2e1583..3883d69922 100644 --- a/sys/vfs/fifofs/fifo_vnops.c +++ b/sys/vfs/fifofs/fifo_vnops.c @@ -32,7 +32,7 @@ * * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 * $FreeBSD: src/sys/miscfs/fifofs/fifo_vnops.c,v 1.45.2.4 2003/04/22 10:11:24 bde Exp $ - * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.12 2003/09/04 23:46:59 hmp Exp $ + * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.13 2004/03/01 06:33:20 dillon Exp $ */ #include @@ -225,10 +225,10 @@ fifo_open(ap) } 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 @@ fifo_open(ap) } } 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 @@ fifo_read(ap) 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 @@ fifo_write(ap) #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 @@ fifo_inactive(ap) 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); } diff --git a/sys/vfs/gnu/ext2fs/ext2_lookup.c b/sys/vfs/gnu/ext2fs/ext2_lookup.c index bb161f4645..7b9d8665aa 100644 --- a/sys/vfs/gnu/ext2fs/ext2_lookup.c +++ b/sys/vfs/gnu/ext2fs/ext2_lookup.c @@ -5,7 +5,7 @@ * University of Utah, Department of Computer Science * * $FreeBSD: src/sys/gnu/ext2fs/ext2_lookup.c,v 1.21.2.3 2002/11/17 02:02:42 bde Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v 1.8 2003/10/09 22:27:22 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v 1.9 2004/03/01 06:33:20 dillon Exp $ */ /* * Copyright (c) 1989, 1993 @@ -539,7 +539,7 @@ searchloop: */ cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) - VOP_UNLOCK(vdp, 0, td); + VOP_UNLOCK(vdp, NULL, 0, td); return (EJUSTRETURN); } /* @@ -617,7 +617,7 @@ found: } *vpp = tdp; if (!lockparent) - VOP_UNLOCK(vdp, 0, td); + VOP_UNLOCK(vdp, NULL, 0, td); return (0); } @@ -642,7 +642,7 @@ found: *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 @@ found: */ 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 @@ found: 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; } diff --git a/sys/vfs/gnu/ext2fs/ext2_vfsops.c b/sys/vfs/gnu/ext2fs/ext2_vfsops.c index 550bacaa01..2127391d59 100644 --- a/sys/vfs/gnu/ext2fs/ext2_vfsops.c +++ b/sys/vfs/gnu/ext2fs/ext2_vfsops.c @@ -38,7 +38,7 @@ * * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 * $FreeBSD: src/sys/gnu/ext2fs/ext2_vfsops.c,v 1.63.2.7 2002/07/01 00:18:51 iedowse Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.11 2003/09/23 05:03:52 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.12 2004/03/01 06:33:20 dillon Exp $ */ #include "opt_quota.h" @@ -211,7 +211,7 @@ ext2_mount(mp, path, data, ndp, td) 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 @@ ext2_mount(mp, path, data, ndp, td) * 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 @@ ext2_mount(mp, path, data, ndp, td) 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 @@ static int compute_sb_data(devvp, es, fs) * 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 @@ ext2_reload(mountp, cred, td) #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 @@ ext2_mountfs(devvp, mp, td) #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 @@ ext2_statfs(mp, sbp, td) * * 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 @@ loop: 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); + } + error = vget(vp, vlock, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, info->td); + if (error) { + if (error == ENOENT) + info->rescan = 1; + return(0); } - return (allerror); + if ((error = VOP_FSYNC(vp, info->waitfor, info->td)) != 0) + info->allerror = error; + VOP_UNLOCK(vp, NULL, 0, info->td); + vrele(vp); + return(0); } /* diff --git a/sys/vfs/gnu/ext2fs/ext2_vnops.c b/sys/vfs/gnu/ext2fs/ext2_vnops.c index f76d6aacd4..952a420e9e 100644 --- a/sys/vfs/gnu/ext2fs/ext2_vnops.c +++ b/sys/vfs/gnu/ext2fs/ext2_vnops.c @@ -44,7 +44,7 @@ * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 * @(#)ext2_vnops.c 8.7 (Berkeley) 2/3/94 * $FreeBSD: src/sys/gnu/ext2fs/ext2_vnops.c,v 1.51.2.2 2003/01/02 17:26:18 bde Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v 1.9 2003/09/23 05:03:52 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v 1.10 2004/03/01 06:33:20 dillon Exp $ */ #include "opt_quota.h" @@ -352,7 +352,7 @@ ext2_link(ap) 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 @@ ext2_link(ap) } out1: if (tdvp != vp) - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); out2: return (error); } @@ -447,18 +447,18 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: * 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 @@ bad: 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 @@ ext2_rmdir(ap) 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 @@ ext2_rmdir(ap) 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); } diff --git a/sys/vfs/gnu/ext2fs/fs.h b/sys/vfs/gnu/ext2fs/fs.h index 7b9f4d8351..4a2c7c6814 100644 --- a/sys/vfs/gnu/ext2fs/fs.h +++ b/sys/vfs/gnu/ext2fs/fs.h @@ -38,7 +38,7 @@ * * @(#)fs.h 8.7 (Berkeley) 4/19/94 * $FreeBSD: src/sys/gnu/ext2fs/fs.h,v 1.5.2.1 2000/11/11 13:12:45 bde Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/fs.h,v 1.3 2003/06/26 20:27:51 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/fs.h,v 1.4 2004/03/01 06:33:20 dillon Exp $ */ /* @@ -154,8 +154,8 @@ extern u_char *fragtbl[]; * 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, diff --git a/sys/vfs/hpfs/hpfs.h b/sys/vfs/hpfs/hpfs.h index fc10b0bd16..73052bc814 100644 --- a/sys/vfs/hpfs/hpfs.h +++ b/sys/vfs/hpfs/hpfs.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/hpfs/hpfs.h,v 1.1 1999/12/09 19:09:58 semenu Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs.h,v 1.9 2004/02/05 21:03:37 rob Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs.h,v 1.10 2004/03/01 06:33:20 dillon Exp $ */ /*#define HPFS_DEBUG 10*/ @@ -399,10 +399,10 @@ typedef int (vop_t) (void *); #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 diff --git a/sys/vfs/hpfs/hpfs_hash.c b/sys/vfs/hpfs/hpfs_hash.c index c997d7d858..ccf4518440 100644 --- a/sys/vfs/hpfs/hpfs_hash.c +++ b/sys/vfs/hpfs/hpfs_hash.c @@ -32,7 +32,7 @@ * * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 * $FreeBSD: src/sys/fs/hpfs/hpfs_hash.c,v 1.1 1999/12/09 19:09:58 semenu Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs_hash.c,v 1.9 2003/10/19 21:24:55 hmp Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_hash.c,v 1.10 2004/03/01 06:33:20 dillon Exp $ */ #include @@ -69,7 +69,7 @@ hpfs_hphashinit() 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 @@ hpfs_hphashinit() 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 @@ hpfs_hphashlookup(dev, ino) 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 @@ hpfs_hphashvget(dev, ino, td) 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 @@ hpfs_hphashins(hp) 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 @@ void 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 @@ hpfs_hphashrem(hp) hp->h_hash.le_prev = NULL; #endif } - lwkt_reltoken(&hpfs_hphash_token); + lwkt_reltoken(&ilock); } diff --git a/sys/vfs/hpfs/hpfs_vfsops.c b/sys/vfs/hpfs/hpfs_vfsops.c index 4c45dfc43f..96ee555b38 100644 --- a/sys/vfs/hpfs/hpfs_vfsops.c +++ b/sys/vfs/hpfs/hpfs_vfsops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/hpfs/hpfs_vfsops.c,v 1.3.2.2 2001/12/25 01:44:45 dillon Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.12 2004/02/05 21:03:37 rob Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.13 2004/03/01 06:33:20 dillon Exp $ */ @@ -668,7 +668,7 @@ hpfs_vget( 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; diff --git a/sys/vfs/isofs/cd9660/cd9660_lookup.c b/sys/vfs/isofs/cd9660/cd9660_lookup.c index 19f153445c..ffe686224a 100644 --- a/sys/vfs/isofs/cd9660/cd9660_lookup.c +++ b/sys/vfs/isofs/cd9660/cd9660_lookup.c @@ -39,7 +39,7 @@ * * @(#)cd9660_lookup.c 8.2 (Berkeley) 1/23/94 * $FreeBSD: src/sys/isofs/cd9660/cd9660_lookup.c,v 1.23.2.2 2001/11/04 06:19:47 dillon Exp $ - * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_lookup.c,v 1.8 2003/10/09 22:27:24 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_lookup.c,v 1.9 2004/03/01 06:33:21 dillon Exp $ */ #include @@ -352,16 +352,16 @@ found: * 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 @@ found: 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; } diff --git a/sys/vfs/isofs/cd9660/cd9660_node.c b/sys/vfs/isofs/cd9660/cd9660_node.c index 5b93e97205..19cf6c822f 100644 --- a/sys/vfs/isofs/cd9660/cd9660_node.c +++ b/sys/vfs/isofs/cd9660/cd9660_node.c @@ -37,7 +37,7 @@ * * @(#)cd9660_node.c 8.2 (Berkeley) 1/23/94 * $FreeBSD: src/sys/isofs/cd9660/cd9660_node.c,v 1.29.2.1 2000/07/08 14:35:56 bp Exp $ - * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_node.c,v 1.8 2003/10/18 20:15:06 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_node.c,v 1.9 2004/03/01 06:33:21 dillon Exp $ */ #include @@ -75,7 +75,7 @@ cd9660_init(vfsp) { isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash); - lwkt_inittoken(&cd9660_ihash_token); + lwkt_token_init(&cd9660_ihash_token); return (0); } @@ -101,32 +101,35 @@ cd9660_ihashget(dev, inum) { 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 @@ cd9660_ihashins(struct iso_node *ip) { 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 @@ cd9660_ihashrem(ip) 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 @@ cd9660_ihashrem(ip) ip->i_next = NULL; ip->i_prev = NULL; #endif - lwkt_reltoken(&cd9660_ihash_token); + lwkt_reltoken(&ilock); } /* @@ -191,7 +196,7 @@ cd9660_inactive(ap) 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. diff --git a/sys/vfs/isofs/cd9660/cd9660_vfsops.c b/sys/vfs/isofs/cd9660/cd9660_vfsops.c index ea0dcab0cc..a4e247a9e7 100644 --- a/sys/vfs/isofs/cd9660/cd9660_vfsops.c +++ b/sys/vfs/isofs/cd9660/cd9660_vfsops.c @@ -37,7 +37,7 @@ * * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vfsops.c,v 1.74.2.7 2002/04/08 09:39:29 bde Exp $ - * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.11 2003/09/23 05:03:52 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.12 2004/03/01 06:33:21 dillon Exp $ */ #include @@ -150,9 +150,9 @@ iso_mountroot(struct mount *mp, struct thread *td) } 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 @@ cd9660_mount(mp, path, data, ndp, td) * 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 @@ cd9660_mount(mp, path, data, ndp, td) 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 @@ iso_mountfs( 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) diff --git a/sys/vfs/mfs/mfs_vnops.c b/sys/vfs/mfs/mfs_vnops.c index bd4e7ef974..ab6e3b758e 100644 --- a/sys/vfs/mfs/mfs_vnops.c +++ b/sys/vfs/mfs/mfs_vnops.c @@ -32,7 +32,7 @@ * * @(#)mfs_vnops.c 8.11 (Berkeley) 5/22/95 * $FreeBSD: src/sys/ufs/mfs/mfs_vnops.c,v 1.47.2.1 2001/05/22 02:06:43 bp Exp $ - * $DragonFly: src/sys/vfs/mfs/mfs_vnops.c,v 1.10 2003/08/20 09:56:32 rob Exp $ + * $DragonFly: src/sys/vfs/mfs/mfs_vnops.c,v 1.11 2004/03/01 06:33:21 dillon Exp $ */ #include @@ -374,7 +374,7 @@ mfs_inactive(ap) 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); } diff --git a/sys/vfs/msdosfs/msdosfs_denode.c b/sys/vfs/msdosfs/msdosfs_denode.c index b4e7c43a90..2374a525f6 100644 --- a/sys/vfs/msdosfs/msdosfs_denode.c +++ b/sys/vfs/msdosfs/msdosfs_denode.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_denode.c,v 1.47.2.3 2002/08/22 16:20:15 trhodes Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.9 2003/10/18 20:15:08 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.10 2004/03/01 06:33:21 dillon Exp $ */ /* $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $ */ /*- @@ -104,7 +104,7 @@ msdosfs_init(vfsp) 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 @@ msdosfs_hashget(dev, dirclust, diroff) { 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 @@ msdosfs_hashins(dep) 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 @@ msdosfs_hashins(dep) dep->de_next = deq; dep->de_prev = depp; *depp = dep; - lwkt_reltoken(&dehash_token); + lwkt_reltoken(&ilock); } static void @@ -180,8 +189,9 @@ msdosfs_hashrem(dep) 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 @@ msdosfs_hashrem(dep) dep->de_next = NULL; dep->de_prev = NULL; #endif - lwkt_reltoken(&dehash_token); + lwkt_reltoken(&ilock); } /* @@ -723,7 +733,7 @@ msdosfs_inactive(ap) 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. diff --git a/sys/vfs/msdosfs/msdosfs_lookup.c b/sys/vfs/msdosfs/msdosfs_lookup.c index 27d70a4425..386779966f 100644 --- a/sys/vfs/msdosfs/msdosfs_lookup.c +++ b/sys/vfs/msdosfs/msdosfs_lookup.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_lookup.c,v 1.30.2.1 2000/11/03 15:55:39 bp Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_lookup.c,v 1.7 2003/10/09 22:27:26 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_lookup.c,v 1.8 2004/03/01 06:33:21 dillon Exp $ */ /* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ /*- @@ -366,7 +366,7 @@ notfound: */ 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 @@ foundroot: 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 @@ foundroot: *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 @@ foundroot: */ 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 @@ foundroot: 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); diff --git a/sys/vfs/msdosfs/msdosfs_vfsops.c b/sys/vfs/msdosfs/msdosfs_vfsops.c index 02392e21b6..30df423d98 100644 --- a/sys/vfs/msdosfs/msdosfs_vfsops.c +++ b/sys/vfs/msdosfs/msdosfs_vfsops.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_vfsops.c,v 1.60.2.6 2002/09/12 21:33:38 trhodes Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.10 2004/02/05 21:03:37 rob Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.11 2004/03/01 06:33:21 dillon Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */ /*- @@ -271,14 +271,14 @@ msdosfs_mount(mp, path, data, ndp, td) */ 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 @@ msdosfs_mount(mp, path, data, ndp, td) 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 @@ mountmsdosfs(devvp, mp, td, argp) 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 @@ msdosfs_statfs(mp, sbp, td) 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 @@ msdosfs_sync(mp, waitfor, td) } /* * 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 (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); } - return (allerror); + 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 diff --git a/sys/vfs/msdosfs/msdosfs_vnops.c b/sys/vfs/msdosfs/msdosfs_vnops.c index f8d27d5af1..a7d4df2253 100644 --- a/sys/vfs/msdosfs/msdosfs_vnops.c +++ b/sys/vfs/msdosfs/msdosfs_vnops.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_vnops.c,v 1.95.2.4 2003/06/13 15:05:47 trhodes Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.12 2003/09/23 05:03:52 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.13 2004/03/01 06:33:21 dillon Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -233,16 +233,16 @@ msdosfs_close(ap) 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 @@ abortit: 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 @@ abortit: (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 @@ abortit: * 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: } reinsert(ip); if (newparent) - VOP_UNLOCK(fdvp, 0, td); + VOP_UNLOCK(fdvp, NULL, 0, td); } /* @@ -1275,7 +1275,7 @@ abortit: 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 @@ abortit: 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 @@ msdosfs_rmdir(ap) * 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); } diff --git a/sys/vfs/nfs/nfs_node.c b/sys/vfs/nfs/nfs_node.c index ac1ae64c6f..3a877a0c7c 100644 --- a/sys/vfs/nfs/nfs_node.c +++ b/sys/vfs/nfs/nfs_node.c @@ -35,7 +35,7 @@ * * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 * $FreeBSD: src/sys/nfs/nfs_node.c,v 1.36.2.3 2002/01/05 22:25:04 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_node.c,v 1.8 2003/10/10 22:01:13 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_node.c,v 1.9 2004/03/01 06:33:21 dillon Exp $ */ @@ -112,7 +112,7 @@ loop: 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 @@ loop: /* * 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 @@ nfs_inactive(ap) */ 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 @@ nfs_inactive(ap) } 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); } diff --git a/sys/vfs/nfs/nfs_nqlease.c b/sys/vfs/nfs/nfs_nqlease.c index 7f3a4b79da..ff5ee86c42 100644 --- a/sys/vfs/nfs/nfs_nqlease.c +++ b/sys/vfs/nfs/nfs_nqlease.c @@ -35,7 +35,7 @@ * * @(#)nfs_nqlease.c 8.9 (Berkeley) 5/20/95 * $FreeBSD: src/sys/nfs/nfs_nqlease.c,v 1.50 2000/02/13 03:32:05 peter Exp $ - * $DragonFly: src/sys/vfs/nfs/Attic/nfs_nqlease.c,v 1.13 2003/11/15 21:05:44 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/Attic/nfs_nqlease.c,v 1.14 2004/03/01 06:33:21 dillon Exp $ */ @@ -1081,7 +1081,7 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, td) 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 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, td) 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 @@ nqnfs_lease_updatetime(int deltat) struct nfsnode *np; struct mount *mp, *nxtmp; struct nfsmount *nmp; + lwkt_tokref ilock; int s; if (nqnfsstarttime != 0) @@ -1190,9 +1191,9 @@ nqnfs_lease_updatetime(int deltat) * 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 @@ nqnfs_lease_updatetime(int deltat) } } } - 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 diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index 4867450cb8..a281ed58b8 100644 --- a/sys/vfs/nfs/nfs_serv.c +++ b/sys/vfs/nfs/nfs_serv.c @@ -35,7 +35,7 @@ * * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95 * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.12 2004/01/30 06:18:28 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.13 2004/03/01 06:33:21 dillon Exp $ */ /* @@ -529,7 +529,7 @@ nfsrv_lookup(nfsd, slp, td, mrq) * 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 @@ nfsrv_readdir(nfsd, slp, td, mrq) 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 @@ again: 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 @@ again: 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 @@ nfsrv_readdirplus(nfsd, slp, td, mrq) 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 @@ again: 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 @@ again: 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) diff --git a/sys/vfs/nfs/nfs_subs.c b/sys/vfs/nfs/nfs_subs.c index 11ca2d3837..86eb4d05d5 100644 --- a/sys/vfs/nfs/nfs_subs.c +++ b/sys/vfs/nfs/nfs_subs.c @@ -35,7 +35,7 @@ * * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 * $FreeBSD: src/sys/nfs/nfs_subs.c,v 1.90.2.2 2001/10/25 19:18:53 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.11 2003/12/21 12:34:08 eirikn Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.12 2004/03/01 06:33:21 dillon Exp $ */ /* @@ -1651,7 +1651,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag) * 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_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag) nfsrv_object_create(*vpp); if (!lockflag) - VOP_UNLOCK(*vpp, 0, td); + VOP_UNLOCK(*vpp, NULL, 0, td); return (0); } @@ -2143,9 +2143,11 @@ nfs_clearcommit(mp) 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 && diff --git a/sys/vfs/nfs/nfs_vfsops.c b/sys/vfs/nfs/nfs_vfsops.c index 2e7b121758..a7d1ce8c5b 100644 --- a/sys/vfs/nfs/nfs_vfsops.c +++ b/sys/vfs/nfs/nfs_vfsops.c @@ -35,7 +35,7 @@ * * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 * $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.12 2004/02/24 19:22:38 joerg Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.13 2004/03/01 06:33:21 dillon Exp $ */ #include "opt_bootp.h" @@ -945,7 +945,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, /* * 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 @@ loop: 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 @@ loop: 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) diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index a15cba7c20..feae810dd6 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -35,7 +35,7 @@ * * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.18 2004/02/08 05:27:42 hmp Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.19 2004/03/01 06:33:21 dillon Exp $ */ @@ -888,14 +888,14 @@ nfs_lookup(ap) 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 @@ nfs_lookup(ap) } 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 @@ nfs_lookup(ap) 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 @@ nfs_lookup(ap) 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 @@ nfsmout: 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 diff --git a/sys/vfs/ntfs/ntfs.h b/sys/vfs/ntfs/ntfs.h index b4403ba3f4..e155cd1ae6 100644 --- a/sys/vfs/ntfs/ntfs.h +++ b/sys/vfs/ntfs/ntfs.h @@ -26,13 +26,16 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs.h,v 1.8.2.2 2001/10/12 22:08:49 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs.h,v 1.3 2003/08/20 09:56:33 rob Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs.h,v 1.4 2004/03/01 06:33:22 dillon Exp $ */ /*#define NTFS_DEBUG 1*/ #if defined(__NetBSD__) && defined(_KERNEL) && !defined(_LKM) #include "opt_ntfs.h" #endif +#if defined(__DragonFly__) +#include +#endif typedef u_int64_t cn_t; typedef u_int16_t wchar; @@ -314,10 +317,10 @@ typedef int (vop_t) (void *); #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 LOCKMGR(a, b, c) lockmgr((a), (b), (c), NULL) +#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), curthread) #endif /* NetBSD */ diff --git a/sys/vfs/ntfs/ntfs_ihash.c b/sys/vfs/ntfs/ntfs_ihash.c index 805e712ae2..47a9f2a256 100644 --- a/sys/vfs/ntfs/ntfs_ihash.c +++ b/sys/vfs/ntfs/ntfs_ihash.c @@ -34,7 +34,7 @@ * * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 * $FreeBSD: src/sys/ntfs/ntfs_ihash.c,v 1.7 1999/12/03 20:37:39 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_ihash.c,v 1.7 2003/12/29 18:04:59 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_ihash.c,v 1.8 2004/03/01 06:33:22 dillon Exp $ */ #include @@ -70,7 +70,7 @@ ntfs_nthashinit() 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 @@ ntfs_nthashinit() 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 @@ ntfs_nthashlookup(dev, inum) 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 @@ ntfs_nthashins(ip) 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 @@ void 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 @@ ntfs_nthashrem(ip) ip->i_hash.le_prev = NULL; #endif } - lwkt_reltoken(&ntfs_nthash_slock); + lwkt_reltoken(&ilock); } diff --git a/sys/vfs/ntfs/ntfs_subr.c b/sys/vfs/ntfs/ntfs_subr.c index 3e059a4d63..8311c7734a 100644 --- a/sys/vfs/ntfs/ntfs_subr.c +++ b/sys/vfs/ntfs/ntfs_subr.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_subr.c,v 1.7.2.4 2001/10/12 22:08:49 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_subr.c,v 1.10 2004/02/05 21:03:37 rob Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_subr.c,v 1.11 2004/03/01 06:33:22 dillon Exp $ */ #include @@ -356,12 +356,14 @@ int 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 @@ ntfs_ntlookup( /* 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 @@ ntfs_ntput(ip) 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 @@ ntfs_ntput(ip) #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 @@ ntfs_ntput(ip) 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 @@ void 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); } /* diff --git a/sys/vfs/ntfs/ntfs_vfsops.c b/sys/vfs/ntfs/ntfs_vfsops.c index fd60cc05c3..c1bc063d15 100644 --- a/sys/vfs/ntfs/ntfs_vfsops.c +++ b/sys/vfs/ntfs/ntfs_vfsops.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_vfsops.c,v 1.20.2.5 2001/12/25 01:44:45 dillon Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.12 2004/02/05 21:03:37 rob Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.13 2004/03/01 06:33:22 dillon Exp $ */ @@ -167,8 +167,9 @@ ntfs_mountroot() 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 @@ ntfs_mountroot() 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_vgetex( ntfs_ntput(ip); if (lkflags & LK_TYPE_MASK) { + KKASSERT((lkflags & LK_INTERLOCK) == 0); error = VN_LOCK(vp, lkflags, td); if (error) { vput(vp); diff --git a/sys/vfs/nullfs/null_subr.c b/sys/vfs/nullfs/null_subr.c index 5fd840a946..6495f8d7f8 100644 --- a/sys/vfs/nullfs/null_subr.c +++ b/sys/vfs/nullfs/null_subr.c @@ -36,7 +36,7 @@ * @(#)null_subr.c 8.7 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/miscfs/nullfs/null_subr.c,v 1.21.2.4 2001/06/26 04:20:09 bp Exp $ - * $DragonFly: src/sys/vfs/nullfs/Attic/null_subr.c,v 1.6 2003/08/28 02:03:18 hmp Exp $ + * $DragonFly: src/sys/vfs/nullfs/Attic/null_subr.c,v 1.7 2004/03/01 06:33:22 dillon Exp $ */ #include @@ -131,11 +131,11 @@ loop: * 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 @@ null_node_alloc(mp, lowervp, vpp) 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"); diff --git a/sys/vfs/nullfs/null_vfsops.c b/sys/vfs/nullfs/null_vfsops.c index 7e0e72889e..f1dbaf8547 100644 --- a/sys/vfs/nullfs/null_vfsops.c +++ b/sys/vfs/nullfs/null_vfsops.c @@ -37,7 +37,7 @@ * * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 * $FreeBSD: src/sys/miscfs/nullfs/null_vfsops.c,v 1.35.2.3 2001/07/26 20:37:11 iedowse Exp $ - * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.6 2003/09/23 05:03:53 dillon Exp $ + * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.7 2004/03/01 06:33:22 dillon Exp $ */ /* @@ -118,7 +118,7 @@ nullfs_mount(mp, path, data, ndp, td) */ 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 @@ nullfs_mount(mp, path, data, ndp, td) * 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 @@ nullfs_mount(mp, path, data, ndp, td) /* * 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 @@ nullfs_root(struct mount *mp, struct vnode **vpp) return (EDEADLK); } #endif - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); *vpp = vp; return 0; } diff --git a/sys/vfs/nullfs/null_vnops.c b/sys/vfs/nullfs/null_vnops.c index bcb5fe3dd1..aafb3af197 100644 --- a/sys/vfs/nullfs/null_vnops.c +++ b/sys/vfs/nullfs/null_vnops.c @@ -38,7 +38,7 @@ * Ancestors: * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92 * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $ - * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.8 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.9 2004/03/01 06:33:22 dillon Exp $ * ...and... * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project * @@ -315,7 +315,7 @@ null_bypass(ap) *(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 @@ null_lookup(ap) * 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 @@ static int 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 @@ null_lock(ap) 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 @@ null_lock(ap) 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 @@ null_lock(ap) */ 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 @@ static int 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 @@ null_unlock(ap) 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 @@ null_inactive(ap) 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); /* diff --git a/sys/vfs/nwfs/nwfs_node.c b/sys/vfs/nwfs/nwfs_node.c index 9ec0bcd19b..7caf4c2022 100644 --- a/sys/vfs/nwfs/nwfs_node.c +++ b/sys/vfs/nwfs/nwfs_node.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/nwfs/nwfs_node.c,v 1.3.2.8 2001/12/25 01:44:45 dillon Exp $ - * $DragonFly: src/sys/vfs/nwfs/nwfs_node.c,v 1.9 2003/11/10 06:12:17 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_node.c,v 1.10 2004/03/01 06:33:22 dillon Exp $ */ #include #include @@ -140,17 +140,17 @@ nwfs_allocvp(struct mount *mp, ncpfid fid, struct vnode **vpp) 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 @@ rescan: 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 @@ nwfs_inactive(ap) 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); diff --git a/sys/vfs/nwfs/nwfs_vfsops.c b/sys/vfs/nwfs/nwfs_vfsops.c index 17bcb5210d..867e1ebf72 100644 --- a/sys/vfs/nwfs/nwfs_vfsops.c +++ b/sys/vfs/nwfs/nwfs_vfsops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/nwfs/nwfs_vfsops.c,v 1.6.2.6 2001/10/25 19:18:54 dillon Exp $ - * $DragonFly: src/sys/vfs/nwfs/nwfs_vfsops.c,v 1.8 2004/01/20 05:04:07 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_vfsops.c,v 1.9 2004/03/01 06:33:22 dillon Exp $ */ #include "opt_ncp.h" #ifndef NCP @@ -224,7 +224,7 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, /* * 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 @@ nwfs_root(struct mount *mp, struct vnode **vpp) { 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 @@ loop: 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 @@ loop: 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) diff --git a/sys/vfs/nwfs/nwfs_vnops.c b/sys/vfs/nwfs/nwfs_vnops.c index 3285cba695..5c937f3643 100644 --- a/sys/vfs/nwfs/nwfs_vnops.c +++ b/sys/vfs/nwfs/nwfs_vnops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/nwfs/nwfs_vnops.c,v 1.6.2.3 2001/03/14 11:26:59 bp Exp $ - * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.9 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.10 2004/03/01 06:33:22 dillon Exp $ */ #include #include @@ -242,30 +242,31 @@ nwfs_close(ap) { 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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD 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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD } 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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD 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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD 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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD *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 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISD *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; diff --git a/sys/vfs/portal/portal_vfsops.c b/sys/vfs/portal/portal_vfsops.c index 3d5c296971..8a3381b7e7 100644 --- a/sys/vfs/portal/portal_vfsops.c +++ b/sys/vfs/portal/portal_vfsops.c @@ -36,7 +36,7 @@ * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/miscfs/portal/portal_vfsops.c,v 1.26.2.2 2001/07/26 20:37:16 iedowse Exp $ - * $DragonFly: src/sys/vfs/portal/portal_vfsops.c,v 1.5 2003/08/20 09:56:33 rob Exp $ + * $DragonFly: src/sys/vfs/portal/portal_vfsops.c,v 1.6 2004/03/01 06:33:22 dillon Exp $ */ /* @@ -210,7 +210,7 @@ portal_root(mp, vpp) */ 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); } diff --git a/sys/vfs/portal/portal_vnops.c b/sys/vfs/portal/portal_vnops.c index 399f5e1088..ab5e24bc3c 100644 --- a/sys/vfs/portal/portal_vnops.c +++ b/sys/vfs/portal/portal_vnops.c @@ -36,7 +36,7 @@ * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/miscfs/portal/portal_vnops.c,v 1.38 1999/12/21 06:29:00 chris Exp $ - * $DragonFly: src/sys/vfs/portal/portal_vnops.c,v 1.8 2003/09/23 05:03:53 dillon Exp $ + * $DragonFly: src/sys/vfs/portal/portal_vnops.c,v 1.9 2004/03/01 06:33:22 dillon Exp $ */ /* @@ -537,7 +537,7 @@ portal_inactive(ap) } */ *ap; { - VOP_UNLOCK(ap->a_vp, 0, ap->a_td); + VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } diff --git a/sys/vfs/procfs/procfs_subr.c b/sys/vfs/procfs/procfs_subr.c index ac40db882c..dade967886 100644 --- a/sys/vfs/procfs/procfs_subr.c +++ b/sys/vfs/procfs/procfs_subr.c @@ -37,7 +37,7 @@ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/miscfs/procfs/procfs_subr.c,v 1.26.2.3 2002/02/18 21:28:04 des Exp $ - * $DragonFly: src/sys/vfs/procfs/procfs_subr.c,v 1.5 2003/08/07 21:17:43 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_subr.c,v 1.6 2004/03/01 06:33:22 dillon Exp $ */ #include @@ -98,7 +98,7 @@ loop: 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); diff --git a/sys/vfs/procfs/procfs_vnops.c b/sys/vfs/procfs/procfs_vnops.c index 8189db92e6..8ce7325640 100644 --- a/sys/vfs/procfs/procfs_vnops.c +++ b/sys/vfs/procfs/procfs_vnops.c @@ -37,7 +37,7 @@ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/miscfs/procfs/procfs_vnops.c,v 1.76.2.7 2002/01/22 17:22:59 nectar Exp $ - * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.10 2003/09/23 05:03:53 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.11 2004/03/01 06:33:22 dillon Exp $ */ /* @@ -363,7 +363,7 @@ procfs_inactive(ap) { 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 @@ procfs_lookup(ap) 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); } diff --git a/sys/vfs/smbfs/smbfs_io.c b/sys/vfs/smbfs/smbfs_io.c index d9a47e8745..a597526ed5 100644 --- a/sys/vfs/smbfs/smbfs_io.c +++ b/sys/vfs/smbfs/smbfs_io.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/smbfs/smbfs_io.c,v 1.3.2.3 2003/01/17 08:20:26 tjr Exp $ - * $DragonFly: src/sys/vfs/smbfs/smbfs_io.c,v 1.9 2003/11/10 06:12:17 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_io.c,v 1.10 2004/03/01 06:33:22 dillon Exp $ * */ #include @@ -205,10 +205,10 @@ smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred) 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; } diff --git a/sys/vfs/smbfs/smbfs_node.c b/sys/vfs/smbfs/smbfs_node.c index 5e15ee1824..15f2726362 100644 --- a/sys/vfs/smbfs/smbfs_node.c +++ b/sys/vfs/smbfs/smbfs_node.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/smbfs/smbfs_node.c,v 1.2.2.3 2003/01/17 08:20:26 tjr Exp $ - * $DragonFly: src/sys/vfs/smbfs/smbfs_node.c,v 1.8 2003/11/10 06:12:17 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_node.c,v 1.9 2004/03/01 06:33:23 dillon Exp $ */ #include #include @@ -169,6 +169,7 @@ smbfs_node_alloc(struct mount *mp, struct vnode *dvp, struct smbnode *np, *np2, *dnp; struct vnode *vp; u_long hashval; + lwkt_tokref vlock; int error; *vpp = NULL; @@ -180,7 +181,7 @@ smbfs_node_alloc(struct mount *mp, struct vnode *dvp, 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 @@ loop: 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 @@ loop: 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 @@ smbfs_reclaim(ap) 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_reclaim(ap) 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 @@ smbfs_reclaim(ap) */ smp->sm_didrele = 1; } else { - VI_UNLOCK(dvp); + VI_UNLOCK(&vlock, dvp); SMBERROR("BUG: negative use count for parent!\n"); } } @@ -358,7 +360,7 @@ smbfs_inactive(ap) &np->n_mtime, &scred); np->n_opencount = 0; } - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); return (0); } /* diff --git a/sys/vfs/smbfs/smbfs_vfsops.c b/sys/vfs/smbfs/smbfs_vfsops.c index 785b2b2d7a..eed4c2445d 100644 --- a/sys/vfs/smbfs/smbfs_vfsops.c +++ b/sys/vfs/smbfs/smbfs_vfsops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/smbfs/smbfs_vfsops.c,v 1.2.2.5 2003/01/17 08:20:26 tjr Exp $ - * $DragonFly: src/sys/vfs/smbfs/smbfs_vfsops.c,v 1.9 2004/02/12 23:36:28 joerg Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_vfsops.c,v 1.10 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_netsmb.h" #ifndef NETSMB @@ -224,7 +224,7 @@ smbfs_mount(struct mount *mp, char *path, caddr_t data, 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 @@ smbfs_root(struct mount *mp, struct vnode **vpp) } 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 @@ loop: 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 @@ loop: 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) diff --git a/sys/vfs/smbfs/smbfs_vnops.c b/sys/vfs/smbfs/smbfs_vnops.c index c2f062f293..20628f6ee6 100644 --- a/sys/vfs/smbfs/smbfs_vnops.c +++ b/sys/vfs/smbfs/smbfs_vnops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/smbfs/smbfs_vnops.c,v 1.2.2.8 2003/04/04 08:57:23 tjr Exp $ - * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.10 2003/12/22 17:41:08 hsu Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.11 2004/03/01 06:33:23 dillon Exp $ */ #include #include @@ -289,16 +289,17 @@ smbfs_close(ap) 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 @@ smbfs_lookup(ap) 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 @@ smbfs_lookup(ap) } 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 @@ smbfs_lookup(ap) 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 @@ smbfs_lookup(ap) *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 @@ smbfs_lookup(ap) *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 @@ smbfs_lookup(ap) *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; } } diff --git a/sys/vfs/specfs/spec_vnops.c b/sys/vfs/specfs/spec_vnops.c index 6feff51e83..e27ae0d32a 100644 --- a/sys/vfs/specfs/spec_vnops.c +++ b/sys/vfs/specfs/spec_vnops.c @@ -32,7 +32,7 @@ * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 * $FreeBSD: src/sys/miscfs/specfs/spec_vnops.c,v 1.131.2.4 2001/02/26 04:23:20 jlemon Exp $ - * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.12 2003/08/20 09:56:33 rob Exp $ + * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.13 2004/03/01 06:33:23 dillon Exp $ */ #include @@ -190,9 +190,9 @@ spec_open(ap) 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 @@ spec_read(ap) 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 @@ spec_write(ap) 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 @@ spec_inactive(ap) } */ *ap; { - VOP_UNLOCK(ap->a_vp, 0, ap->a_td); + VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } diff --git a/sys/vfs/ufs/ffs_rawread.c b/sys/vfs/ufs/ffs_rawread.c index 57df545b0e..330260ca05 100644 --- a/sys/vfs/ufs/ffs_rawread.c +++ b/sys/vfs/ufs/ffs_rawread.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ufs/ffs/ffs_rawread.c,v 1.3.2.2 2003/05/29 06:15:35 alc Exp $ - * $DragonFly: src/sys/vfs/ufs/ffs_rawread.c,v 1.6 2003/09/08 18:26:39 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_rawread.c,v 1.7 2004/03/01 06:33:23 dillon Exp $ */ #include @@ -105,7 +105,7 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) 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 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) 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 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) 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 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) } splx(spl); if (upgraded != 0) - VOP_LOCK(vp, LK_DOWNGRADE, td); + VOP_LOCK(vp, NULL, LK_DOWNGRADE, td); } else { splx(spl); } diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c index 9f80fae953..87d219952c 100644 --- a/sys/vfs/ufs/ffs_softdep.c +++ b/sys/vfs/ufs/ffs_softdep.c @@ -37,7 +37,7 @@ * * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00 * $FreeBSD: src/sys/ufs/ffs/ffs_softdep.c,v 1.57.2.11 2002/02/05 18:46:53 dillon Exp $ - * $DragonFly: src/sys/vfs/ufs/ffs_softdep.c,v 1.12 2004/02/16 19:48:51 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_softdep.c,v 1.13 2004/03/01 06:33:23 dillon Exp $ */ /* @@ -820,9 +820,9 @@ softdep_flushfiles(struct mount *oldmnt, int flags, struct thread *td) 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 @@ softdep_fsync(vp) * 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) { diff --git a/sys/vfs/ufs/ffs_vfsops.c b/sys/vfs/ufs/ffs_vfsops.c index 6133165775..5c147c3d04 100644 --- a/sys/vfs/ufs/ffs_vfsops.c +++ b/sys/vfs/ufs/ffs_vfsops.c @@ -32,7 +32,7 @@ * * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $ - * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.13 2004/02/08 05:56:10 hmp Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.14 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_quota.h" @@ -224,13 +224,13 @@ ffs_mount( mp, path, data, ndp, td) * 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 @@ ffs_mount( mp, path, data, ndp, td) 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 @@ success: * 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 @@ ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td) * 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 @@ ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td) * 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 @@ ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td) *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 @@ ffs_mountfs(devvp, mp, td, malloctype) 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 @@ ffs_mountfs(devvp, mp, td, malloctype) 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 @@ ffs_mountfs(devvp, mp, td, malloctype) * 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 @@ ffs_flushfiles(struct mount *mp, int flags, struct thread *td) /* * 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 @@ ffs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) * * 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 @@ loop: * 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); } /* diff --git a/sys/vfs/ufs/ufs_ihash.c b/sys/vfs/ufs/ufs_ihash.c index 58d2004ef3..8f6261d822 100644 --- a/sys/vfs/ufs/ufs_ihash.c +++ b/sys/vfs/ufs/ufs_ihash.c @@ -32,7 +32,7 @@ * * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 * $FreeBSD: src/sys/ufs/ufs/ufs_ihash.c,v 1.20 1999/08/28 00:52:29 peter Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.10 2004/01/15 20:17:36 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.11 2004/03/01 06:33:23 dillon Exp $ */ #include @@ -63,7 +63,7 @@ void ufs_ihashinit() { ihashtbl = hashinit(desiredvnodes, M_UFSIHASH, &ihash); - lwkt_inittoken(&ufs_ihash_token); + lwkt_token_init(&ufs_ihash_token); } /* @@ -76,13 +76,14 @@ ufs_ihashlookup(dev, inum) 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 @@ ufs_ihashlookup(dev, inum) * 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 @@ ufs_ihashins(struct inode *ip) { 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 @@ void 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 @@ ufs_ihashrem(ip) ip->i_hash.le_prev = NULL; #endif } - lwkt_reltoken(&ufs_ihash_token); + lwkt_reltoken(&ilock); } diff --git a/sys/vfs/ufs/ufs_inode.c b/sys/vfs/ufs/ufs_inode.c index cdb0f273dc..cb62aaedb4 100644 --- a/sys/vfs/ufs/ufs_inode.c +++ b/sys/vfs/ufs/ufs_inode.c @@ -37,7 +37,7 @@ * * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95 * $FreeBSD: src/sys/ufs/ufs/ufs_inode.c,v 1.25.2.3 2002/07/05 22:42:31 dillon Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_inode.c,v 1.6 2003/08/07 21:17:44 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_inode.c,v 1.7 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_quota.h" @@ -97,7 +97,7 @@ ufs_inactive(ap) 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. diff --git a/sys/vfs/ufs/ufs_lookup.c b/sys/vfs/ufs/ufs_lookup.c index 323353a9c6..16f09dc13a 100644 --- a/sys/vfs/ufs/ufs_lookup.c +++ b/sys/vfs/ufs/ufs_lookup.c @@ -37,7 +37,7 @@ * * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95 * $FreeBSD: src/sys/ufs/ufs/ufs_lookup.c,v 1.33.2.7 2001/09/22 19:22:13 iedowse Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_lookup.c,v 1.8 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_lookup.c,v 1.9 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_ufs.h" @@ -443,7 +443,7 @@ notfound: */ 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 @@ found: 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 @@ found: } *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 @@ found: 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 @@ found: *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 @@ found: */ 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 @@ found: 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 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp) */ 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); } diff --git a/sys/vfs/ufs/ufs_quota.c b/sys/vfs/ufs/ufs_quota.c index fafcc94122..e031d425b1 100644 --- a/sys/vfs/ufs/ufs_quota.c +++ b/sys/vfs/ufs/ufs_quota.c @@ -35,7 +35,7 @@ * * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 * $FreeBSD: src/sys/ufs/ufs/ufs_quota.c,v 1.27.2.3 2002/01/15 10:33:32 phk Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_quota.c,v 1.11 2003/09/23 05:03:53 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_quota.c,v 1.12 2004/03/01 06:33:23 dillon Exp $ */ #include @@ -380,9 +380,18 @@ chkdquot(ip) * 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 @@ quotaon(td, mp, type, fname) { 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 @@ quotaon(td, mp, type, fname) 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 @@ quotaon(td, mp, type, fname) * 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 @@ again: 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 @@ quotaoff(struct thread *td, struct mount *mp, int type) 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 @@ again: 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 @@ setuse(mp, id, type, addr) /* * 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 @@ qsync(struct mount *mp) * 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 @@ dqget(vp, id, ump, type, dqp) * 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 @@ dqget(vp, id, ump, type, dqp) 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 @@ dqsync(struct vnode *vp, struct dquot *dq) 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 @@ dqsync(struct vnode *vp, struct dquot *dq) 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); } diff --git a/sys/vfs/ufs/ufs_vfsops.c b/sys/vfs/ufs/ufs_vfsops.c index 75b915dce6..b8bff2a7c6 100644 --- a/sys/vfs/ufs/ufs_vfsops.c +++ b/sys/vfs/ufs/ufs_vfsops.c @@ -37,7 +37,7 @@ * * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95 * $FreeBSD: src/sys/ufs/ufs/ufs_vfsops.c,v 1.17.2.3 2001/10/14 19:08:16 iedowse Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_vfsops.c,v 1.5 2003/08/07 21:17:44 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_vfsops.c,v 1.6 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_quota.h" @@ -123,7 +123,7 @@ ufs_quotactl(mp, cmds, uid, arg, td) 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) { diff --git a/sys/vfs/ufs/ufs_vnops.c b/sys/vfs/ufs/ufs_vnops.c index a72b09b8f2..9d4df89089 100644 --- a/sys/vfs/ufs/ufs_vnops.c +++ b/sys/vfs/ufs/ufs_vnops.c @@ -37,7 +37,7 @@ * * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.131.2.8 2003/01/02 17:26:19 bde Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.10 2003/09/23 05:03:53 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.11 2004/03/01 06:33:23 dillon Exp $ */ #include "opt_quota.h" @@ -293,11 +293,12 @@ ufs_close(ap) } */ *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 @@ ufs_link(ap) 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 @@ ufs_link(ap) } 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: 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 @@ abortit: * 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 @@ bad: 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 @@ ufsspec_close(ap) } */ *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 @@ ufsfifo_close(ap) } */ *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 @@ ufs_kqfilter(ap) { 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 @@ ufs_kqfilter(ap) 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 @@ static void 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*/ diff --git a/sys/vfs/umapfs/umap_subr.c b/sys/vfs/umapfs/umap_subr.c index b7b061250d..bab5842acc 100644 --- a/sys/vfs/umapfs/umap_subr.c +++ b/sys/vfs/umapfs/umap_subr.c @@ -36,7 +36,7 @@ * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/miscfs/umapfs/umap_subr.c,v 1.19 1999/09/04 11:51:41 bde Exp $ - * $DragonFly: src/sys/vfs/umapfs/Attic/umap_subr.c,v 1.5 2003/08/20 09:56:34 rob Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_subr.c,v 1.6 2004/03/01 06:33:23 dillon Exp $ */ #include @@ -168,7 +168,7 @@ loop: * 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 diff --git a/sys/vfs/umapfs/umap_vfsops.c b/sys/vfs/umapfs/umap_vfsops.c index ef2385ace0..65954b2346 100644 --- a/sys/vfs/umapfs/umap_vfsops.c +++ b/sys/vfs/umapfs/umap_vfsops.c @@ -36,7 +36,7 @@ * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/miscfs/umapfs/umap_vfsops.c,v 1.31.2.2 2001/09/11 09:49:53 kris Exp $ - * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vfsops.c,v 1.8 2003/09/23 05:03:54 dillon Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vfsops.c,v 1.9 2004/03/01 06:33:23 dillon Exp $ */ /* @@ -204,7 +204,7 @@ umapfs_mount(struct mount *mp, char *path, caddr_t data, /* * 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 @@ umapfs_root(struct mount *mp, struct vnode **vpp) */ 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); } diff --git a/sys/vfs/umapfs/umap_vnops.c b/sys/vfs/umapfs/umap_vnops.c index 7a890e094f..c1f7f026dd 100644 --- a/sys/vfs/umapfs/umap_vnops.c +++ b/sys/vfs/umapfs/umap_vnops.c @@ -35,7 +35,7 @@ * * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95 * $FreeBSD: src/sys/miscfs/umapfs/umap_vnops.c,v 1.30 1999/08/30 07:08:04 bde Exp $ - * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vnops.c,v 1.5 2003/08/20 09:56:34 rob Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vnops.c,v 1.6 2004/03/01 06:33:23 dillon Exp $ */ /* @@ -359,6 +359,7 @@ static int 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 @@ umap_inactive(ap) * */ 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); } diff --git a/sys/vfs/union/union_subr.c b/sys/vfs/union/union_subr.c index 5925e189df..ab9a0839d0 100644 --- a/sys/vfs/union/union_subr.c +++ b/sys/vfs/union/union_subr.c @@ -36,7 +36,7 @@ * * @(#)union_subr.c 8.20 (Berkeley) 5/20/95 * $FreeBSD: src/sys/miscfs/union/union_subr.c,v 1.43.2.2 2001/12/25 01:44:45 dillon Exp $ - * $DragonFly: src/sys/vfs/union/union_subr.c,v 1.9 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_subr.c,v 1.10 2004/03/01 06:33:24 dillon Exp $ */ #include @@ -403,7 +403,7 @@ loop: (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 @@ loop: * 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 @@ loop: 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 @@ union_copyup(un, docopy, cred, td) * 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 @@ union_copyup(un, docopy, cred, td) * 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 @@ union_relookup(um, dvp, vpp, cnp, cn, path, pathlen) 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 @@ union_relookup(um, dvp, vpp, cnp, cn, path, pathlen) */ 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 @@ union_dircache(struct vnode *vp, struct thread *td) 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 @@ union_dircache(struct vnode *vp, struct thread *td) 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 @@ union_dircache(struct vnode *vp, struct thread *td) un->un_dircache = dircache; out: - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); return (nvp); } @@ -1335,7 +1335,7 @@ union_dircheck(struct thread *td, struct vnode **vp, struct file *fp) 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); diff --git a/sys/vfs/union/union_vfsops.c b/sys/vfs/union/union_vfsops.c index a50195f668..3f845e4b6b 100644 --- a/sys/vfs/union/union_vfsops.c +++ b/sys/vfs/union/union_vfsops.c @@ -36,7 +36,7 @@ * * @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95 * $FreeBSD: src/sys/miscfs/union/union_vfsops.c,v 1.39.2.2 2001/10/25 19:18:53 dillon Exp $ - * $DragonFly: src/sys/vfs/union/union_vfsops.c,v 1.7 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_vfsops.c,v 1.8 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -129,7 +129,7 @@ union_mount(mp, path, data, ndp, td) * 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 @@ union_mount(mp, path, data, ndp, td) #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 @@ union_unmount(mp, mntflags, td) 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++; } diff --git a/sys/vfs/union/union_vnops.c b/sys/vfs/union/union_vnops.c index 382da6990e..ab202ef89e 100644 --- a/sys/vfs/union/union_vnops.c +++ b/sys/vfs/union/union_vnops.c @@ -36,7 +36,7 @@ * * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95 * $FreeBSD: src/sys/miscfs/union/union_vnops.c,v 1.72 1999/12/15 23:02:14 eivind Exp $ - * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.9 2003/10/09 22:27:27 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.10 2004/03/01 06:33:24 dillon Exp $ */ #include @@ -116,7 +116,7 @@ union_lock_upper(struct union_node *un, struct thread *td) 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 @@ union_lock_other(struct union_node *un, struct thread *td) 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 @@ union_lookup1(udvp, pdvp, vpp, cnp) 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 @@ union_lookup1(udvp, pdvp, vpp, cnp) 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 @@ union_lookup1(udvp, pdvp, vpp, cnp) ) { 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 @@ union_lookup1(udvp, pdvp, vpp, cnp) 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 @@ union_lookup(ap) * 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 @@ union_lookup(ap) 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 @@ union_lookup(ap) */ 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 @@ out: 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 @@ union_create(ap) 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 @@ union_open(ap) } 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 @@ union_access(ap) } 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 @@ union_access(ap) error = VCALL(vp, VOFFSET(vop_access), ap); } } - VOP_UNLOCK(vp, 0, td); + VOP_UNLOCK(vp, NULL, 0, td); } return(error); } @@ -1317,24 +1317,24 @@ union_link(ap) 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 @@ union_link(ap) 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 @@ union_rename(ap) 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 @@ union_rename(ap) #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_mkdir(ap) 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 @@ union_inactive(ap) #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 @@ union_lock(ap) 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 @@ static int 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 @@ union_unlock(ap) 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); diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 6ee4ac6912..f46f123f0c 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $DragonFly: src/sys/vm/vm_contig.c,v 1.5 2004/02/18 16:28:21 joerg Exp $ + * $DragonFly: src/sys/vm/vm_contig.c,v 1.6 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -126,10 +126,10 @@ vm_contig_pg_clean(int queue) 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) { diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index fcaa95273f..6d105c21fd 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -32,7 +32,7 @@ * * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 * $FreeBSD: src/sys/vm/vm_extern.h,v 1.46.2.3 2003/01/13 22:51:17 dillon Exp $ - * $DragonFly: src/sys/vm/vm_extern.h,v 1.9 2004/01/20 18:41:52 dillon Exp $ + * $DragonFly: src/sys/vm/vm_extern.h,v 1.10 2004/03/01 06:33:24 dillon Exp $ */ #ifndef _VM_EXTERN_H_ @@ -70,7 +70,6 @@ vm_offset_t kmem_alloc_wait (vm_map_t, vm_size_t); 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); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 2604298919..f6382fe31d 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -67,7 +67,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_fault.c,v 1.108.2.8 2002/02/26 05:49:27 silby Exp $ - * $DragonFly: src/sys/vm/vm_fault.c,v 1.10 2004/01/20 05:04:08 dillon Exp $ + * $DragonFly: src/sys/vm/vm_fault.c,v 1.11 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -649,7 +649,7 @@ readrest: * 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; diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index a21fb8b11f..145397e70e 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -60,7 +60,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_glue.c,v 1.94.2.4 2003/01/13 22:51:17 dillon Exp $ - * $DragonFly: src/sys/vm/vm_glue.c,v 1.19 2004/01/14 23:26:14 dillon Exp $ + * $DragonFly: src/sys/vm/vm_glue.c,v 1.20 2004/03/01 06:33:24 dillon Exp $ */ #include "opt_vm.h" @@ -498,7 +498,7 @@ retry: */ if (lockmgr(&vm->vm_map.lock, LK_EXCLUSIVE | LK_NOWAIT, - (void *)0, curthread)) { + NULL, curthread)) { vmspace_free(vm); continue; } diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c index e8bc206cdf..d52a4b9ff9 100644 --- a/sys/vm/vm_init.c +++ b/sys/vm/vm_init.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_init.c,v 1.20 1999/10/29 18:09:29 phk Exp $ - * $DragonFly: src/sys/vm/vm_init.c,v 1.4 2003/08/27 01:43:08 dillon Exp $ + * $DragonFly: src/sys/vm/vm_init.c,v 1.5 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -113,7 +113,6 @@ vm_mem_init(dummy) vm_object_init(); vm_map_startup(); kmem_init(virtual_avail, virtual_end); - kmem_cpu_init(); pmap_init(avail_start, avail_end); vm_pager_init(); } diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index e322b81b5f..470a863200 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_kern.c,v 1.61.2.2 2002/03/12 18:25:26 tegge Exp $ - * $DragonFly: src/sys/vm/vm_kern.c,v 1.14 2004/01/20 05:04:08 dillon Exp $ + * $DragonFly: src/sys/vm/vm_kern.c,v 1.15 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -536,17 +536,3 @@ kmem_init(vm_offset_t start, vm_offset_t end) 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); -} - diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 91b7c205bf..ca3759d7bb 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_map.c,v 1.187.2.19 2003/05/27 00:47:02 alc Exp $ - * $DragonFly: src/sys/vm/vm_map.c,v 1.21 2004/01/20 18:41:52 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.c,v 1.22 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -329,6 +329,22 @@ vm_map_init(struct vm_map *map, vm_offset_t min, vm_offset_t max) lockinit(&map->lock, 0, "thrd_sleep", 0, LK_NOPAUSE); } +/* + * 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: * @@ -2188,14 +2204,15 @@ vm_map_clean(map, start, end, syncio, invalidate) 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 && diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 1c559fa373..1e3ddc3d46 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_map.h,v 1.54.2.5 2003/01/13 22:51:17 dillon Exp $ - * $DragonFly: src/sys/vm/vm_map.h,v 1.11 2004/01/20 18:41:52 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.h,v 1.12 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -257,20 +257,13 @@ struct vmresident { * 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 @@ struct vmresident { #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 @@ struct vmresident { #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 @@ struct vmresident { #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 @@ _vm_map_lock_upgrade(vm_map_t map, struct thread *td) { #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 @@ _vm_map_lock_upgrade(vm_map_t map, struct thread *td) { #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 @@ vmspace_resident_count(struct vmspace *vmspace) #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); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index c5ad40a9b3..911675fa79 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_object.c,v 1.171.2.8 2003/05/26 19:17:56 alc Exp $ - * $DragonFly: src/sys/vm/vm_object.c,v 1.12 2003/11/11 01:35:36 dillon Exp $ + * $DragonFly: src/sys/vm/vm_object.c,v 1.13 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -200,7 +200,7 @@ void 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 @@ vm_object_reference(object) 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 @@ void vm_object_terminate(object) vm_object_t object; { + lwkt_tokref ilock; vm_page_t p; int s; @@ -486,9 +488,9 @@ vm_object_terminate(object) /* * 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 @@ vm_object_page_clean(object, start, end, flags) int clearobjflags; int pagerflags; int curgeneration; + lwkt_tokref vlock; if (object->type != OBJT_VNODE || (object->flags & OBJ_MIGHTBEDIRTY) == 0) @@ -644,9 +647,9 @@ vm_object_page_clean(object, start, end, flags) 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 @@ void 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); } } } diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 0cbecd9464..9e4c2b3640 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -35,7 +35,7 @@ * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 * $FreeBSD: src/sys/vm/vm_page.c,v 1.147.2.18 2002/03/10 05:03:19 alc Exp $ - * $DragonFly: src/sys/vm/vm_page.c,v 1.16 2004/01/20 05:04:08 dillon Exp $ + * $DragonFly: src/sys/vm/vm_page.c,v 1.17 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -1057,19 +1057,22 @@ vm_page_free_toq(vm_page_t m) } /* - * If we've exhausted the object's resident pages we want to free - * it up. + * We used to free the underlying vnode if the object was empty, + * but we no longer do that because it can block. Instead, the + * sync code is made responsible for the cleanup. */ - +#if 0 if (object && (object->type == OBJT_VNODE) && - ((object->flags & OBJ_DEAD) == 0) + ((object->flags & OBJ_DEAD) == 0) && + object->handle != NULL ) { struct vnode *vp = (struct vnode *)object->handle; if (vp && VSHOULDFREE(vp)) vfree(vp); } +#endif /* * Clear the UNMANAGED flag when freeing an unmanaged page. diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 33c3cd4309..ccf6a3852d 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -66,7 +66,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_pageout.c,v 1.151.2.15 2002/12/29 18:21:04 dillon Exp $ - * $DragonFly: src/sys/vm/vm_pageout.c,v 1.8 2003/08/20 08:03:01 rob Exp $ + * $DragonFly: src/sys/vm/vm_pageout.c,v 1.9 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -546,7 +546,7 @@ vm_pageout_map_deactivate_pages(map, desired) 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 @@ rescan0: * 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 @@ rescan0: 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++; diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c index 12df4c42b8..2ba3c64371 100644 --- a/sys/vm/vm_swap.c +++ b/sys/vm/vm_swap.c @@ -32,7 +32,7 @@ * * @(#)vm_swap.c 8.5 (Berkeley) 2/17/94 * $FreeBSD: src/sys/vm/vm_swap.c,v 1.96.2.2 2001/10/14 18:46:47 iedowse Exp $ - * $DragonFly: src/sys/vm/vm_swap.c,v 1.9 2003/09/23 05:03:54 dillon Exp $ + * $DragonFly: src/sys/vm/vm_swap.c,v 1.10 2004/03/01 06:33:24 dillon Exp $ */ #include "opt_swap.h" @@ -264,9 +264,9 @@ swaponvp(struct thread *td, struct vnode *vp, dev_t dev, u_long nblks) } 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); diff --git a/sys/vm/vm_zone.c b/sys/vm/vm_zone.c index 46ef11556e..be726b7002 100644 --- a/sys/vm/vm_zone.c +++ b/sys/vm/vm_zone.c @@ -12,7 +12,7 @@ * John S. Dyson. * * $FreeBSD: src/sys/vm/vm_zone.c,v 1.30.2.6 2002/10/10 19:50:16 dillon Exp $ - * $DragonFly: src/sys/vm/vm_zone.c,v 1.13 2004/01/20 05:04:08 dillon Exp $ + * $DragonFly: src/sys/vm/vm_zone.c,v 1.14 2004/03/01 06:33:24 dillon Exp $ */ #include @@ -51,12 +51,13 @@ void * 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 @@ zalloc(vm_zone_t z) z->zfreecnt--; z->znalloc++; } - lwkt_reltoken(&z->zlock); + lwkt_reltoken(&ilock); return item; } @@ -88,7 +89,9 @@ zalloc(vm_zone_t z) 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 @@ zfree(vm_zone_t z, void *item) #endif z->zitems = item; z->zfreecnt++; - lwkt_reltoken(&z->zlock); + lwkt_reltoken(&ilock); } /* @@ -151,7 +154,7 @@ zinitna(vm_zone_t z, vm_object_t obj, char *name, int size, 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 @@ zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) 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 @@ zget(vm_zone_t z) 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 @@ zget(vm_zone_t z) { 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; } diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 0bdaf07c1f..81ccd0c1be 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -39,7 +39,7 @@ * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 * $FreeBSD: src/sys/vm/vnode_pager.c,v 1.116.2.7 2002/12/31 09:34:51 dillon Exp $ - * $DragonFly: src/sys/vm/vnode_pager.c,v 1.10 2003/08/20 08:03:01 rob Exp $ + * $DragonFly: src/sys/vm/vnode_pager.c,v 1.11 2004/03/01 06:33:24 dillon Exp $ */ /* @@ -1050,7 +1050,7 @@ vnode_pager_lock(vm_object_t object) 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)) { -- 2.41.0