From 5fd012e050d93d63bb14aa95206eeac67bf0e87e Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 12 Oct 2004 19:21:16 +0000 Subject: [PATCH] VFS messaging/interfacing work stage 8/99: Major reworking of the vnode interlock and other miscellanious things. This patch also fixes FS corruption due to prior vfs work in head. In particular, prior to this patch the namecache locking could introduce blocking conditions that confuse the old vnode deactivation and reclamation code paths. With this patch there appear to be no serious problems even after two days of continuous testing. * VX lock all VOP_CLOSE operations. * Fix two NFS issues. There was an incorrect assertion (found by David Rhodus), and the nfs_rename() code was not properly purging the target file from the cache, resulting in Stale file handle errors during, e.g. a buildworld with an NFS-mounted /usr/obj. * Fix a TTY session issue. Programs which open("/dev/tty" ,...) and then run the TIOCNOTTY ioctl were causing the system to lose track of the open count, preventing the tty from properly detaching. This is actually a very old BSD bug, but it came out of the woodwork in DragonFly because I am now attempting to track device opens explicitly. * Gets rid of the vnode interlock. The lockmgr interlock remains. * Introduced VX locks, which are mandatory vp->v_lock based locks. * Rewrites the locking semantics for deactivation and reclamation. (A ref'd VX lock'd vnode is now required for vgone(), VOP_INACTIVE, and VOP_RECLAIM). New guarentees emplaced with regard to vnode ripouts. * Recodes the mountlist scanning routines to close timing races. * Recodes getnewvnode to close timing races (it now returns a VX locked and refd vnode rather then a refd but unlocked vnode). * Recodes VOP_REVOKE- a locked vnode is now mandatory. * Recodes all VFS inode hash routines to close timing holes. * Removes cache_leaf_test() - vnodes representing intermediate directories are now held so the leaf test should no longer be necessary. * Splits the over-large vfs_subr.c into three additional source files, broken down by major function (locking, mount related, filesystem syncer). * Changes splvm() protection to a critical-section in a number of places (bleedover from another patch set which is also about to be committed). Known issues not yet resolved: * Possible vnode/namecache deadlocks. * While most filesystems now use vp->v_lock, I haven't done a final pass to make vp->v_lock mandatory and to clean up the few remaining inode based locks (nwfs I think and other obscure filesystems). * NullFS gets confused when you hit a mount point in the underlying filesystem. * Only UFS and NFS have been well tested * NFS is not properly timing out namecache entries, causing changes made on the server to not be properly detected on the client if the client already has a negative-cache hit for the filename in question. Testing-by: David Rhodus , Peter Kadau , walt , others --- sys/conf/files | 5 +- sys/dev/disk/ccd/ccd.c | 6 +- sys/dev/disk/vn/vn.c | 14 +- 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 | 6 +- .../linux/i386/linprocfs/linprocfs_vnops.c | 16 +- sys/emulation/linux/linux_file.c | 6 +- sys/emulation/linux/linux_getcwd.c | 6 +- sys/emulation/linux/linux_misc.c | 6 +- sys/emulation/ndis/subr_ndis.c | 4 +- sys/emulation/svr4/svr4_fcntl.c | 7 +- sys/emulation/svr4/svr4_misc.c | 14 +- sys/kern/imgact_elf.c | 13 +- sys/kern/imgact_resident.c | 4 +- sys/kern/init_main.c | 6 +- sys/kern/kern_acct.c | 4 +- sys/kern/kern_acl.c | 10 +- sys/kern/kern_descrip.c | 4 +- sys/kern/kern_exec.c | 21 +- sys/kern/kern_exit.c | 22 +- sys/kern/kern_fork.c | 7 +- sys/kern/kern_fp.c | 6 +- sys/kern/kern_ktrace.c | 8 +- sys/kern/kern_linker.c | 4 +- sys/kern/kern_sig.c | 24 +- sys/kern/link_aout.c | 4 +- sys/kern/link_elf.c | 4 +- sys/kern/tty.c | 27 +- sys/kern/tty_tty.c | 42 +- sys/kern/uipc_syscalls.c | 41 +- sys/kern/uipc_usrreq.c | 4 +- sys/kern/vfs_cache.c | 60 +- sys/kern/vfs_default.c | 21 +- sys/kern/vfs_init.c | 22 +- sys/kern/vfs_lock.c | 517 +++++ sys/kern/vfs_lookup.c | 26 +- sys/kern/vfs_mount.c | 784 +++++++ sys/kern/vfs_subr.c | 1861 ++--------------- sys/kern/vfs_sync.c | 476 +++++ sys/kern/vfs_syscalls.c | 101 +- sys/kern/vfs_vnops.c | 68 +- sys/kern/vfs_vopops.c | 10 +- sys/sys/namecache.h | 6 +- sys/sys/systm.h | 3 +- sys/sys/tty.h | 3 +- sys/sys/vfsops.h | 16 +- sys/sys/vnode.h | 83 +- sys/vfs/coda/coda_vfsops.c | 23 +- sys/vfs/coda/coda_vnops.c | 27 +- sys/vfs/deadfs/dead_vnops.c | 49 +- sys/vfs/fdesc/fdesc_vfsops.c | 4 +- sys/vfs/fdesc/fdesc_vnops.c | 14 +- sys/vfs/fifofs/fifo_vnops.c | 31 +- sys/vfs/gnu/ext2fs/ext2_lookup.c | 16 +- sys/vfs/gnu/ext2fs/ext2_vfsops.c | 84 +- sys/vfs/gnu/ext2fs/ext2_vnops.c | 26 +- sys/vfs/gnu/ext2fs/fs.h | 6 +- sys/vfs/hpfs/hpfs.h | 10 +- sys/vfs/hpfs/hpfs_hash.c | 10 +- sys/vfs/hpfs/hpfs_vfsops.c | 15 +- sys/vfs/hpfs/hpfs_vnops.c | 8 +- sys/vfs/isofs/cd9660/cd9660_lookup.c | 10 +- sys/vfs/isofs/cd9660/cd9660_node.c | 16 +- sys/vfs/isofs/cd9660/cd9660_vfsops.c | 32 +- sys/vfs/mfs/mfs_vfsops.c | 3 +- sys/vfs/mfs/mfs_vnops.c | 3 +- sys/vfs/msdosfs/msdosfs_denode.c | 35 +- sys/vfs/msdosfs/msdosfs_lookup.c | 16 +- sys/vfs/msdosfs/msdosfs_vfsops.c | 41 +- sys/vfs/msdosfs/msdosfs_vnops.c | 43 +- sys/vfs/nfs/nfs_bio.c | 5 +- sys/vfs/nfs/nfs_node.c | 44 +- sys/vfs/nfs/nfs_nqlease.c | 6 +- sys/vfs/nfs/nfs_serv.c | 16 +- sys/vfs/nfs/nfs_subs.c | 6 +- sys/vfs/nfs/nfs_vfsops.c | 15 +- sys/vfs/nfs/nfs_vnops.c | 33 +- sys/vfs/ntfs/ntfs.h | 8 +- sys/vfs/ntfs/ntfs_vfsops.c | 14 +- sys/vfs/ntfs/ntfs_vnops.c | 10 +- sys/vfs/nullfs/null_subr.c | 12 +- sys/vfs/nullfs/null_vfsops.c | 10 +- sys/vfs/nullfs/null_vnops.c | 62 +- sys/vfs/nwfs/nwfs_io.c | 4 +- sys/vfs/nwfs/nwfs_node.c | 16 +- sys/vfs/nwfs/nwfs_vfsops.c | 9 +- sys/vfs/nwfs/nwfs_vnops.c | 41 +- sys/vfs/portal/portal_vfsops.c | 5 +- sys/vfs/portal/portal_vnops.c | 4 +- sys/vfs/procfs/procfs_subr.c | 25 +- sys/vfs/procfs/procfs_vnops.c | 8 +- sys/vfs/smbfs/smbfs_io.c | 8 +- sys/vfs/smbfs/smbfs_node.c | 51 +- sys/vfs/smbfs/smbfs_vfsops.c | 8 +- sys/vfs/smbfs/smbfs_vnops.c | 62 +- sys/vfs/specfs/spec_vnops.c | 19 +- sys/vfs/udf/udf_vfsops.c | 13 +- sys/vfs/udf/udf_vnops.c | 29 +- sys/vfs/ufs/ffs_rawread.c | 10 +- sys/vfs/ufs/ffs_softdep.c | 12 +- sys/vfs/ufs/ffs_vfsops.c | 117 +- sys/vfs/ufs/ufs_ihash.c | 10 +- sys/vfs/ufs/ufs_inode.c | 6 +- sys/vfs/ufs/ufs_lookup.c | 28 +- sys/vfs/ufs/ufs_quota.c | 73 +- sys/vfs/ufs/ufs_vnops.c | 31 +- sys/vfs/umapfs/umap_subr.c | 6 +- sys/vfs/umapfs/umap_vfsops.c | 6 +- sys/vfs/umapfs/umap_vnops.c | 14 +- sys/vfs/union/union.h | 7 +- sys/vfs/union/union_subr.c | 43 +- sys/vfs/union/union_vfsops.c | 6 +- sys/vfs/union/union_vnops.c | 88 +- sys/vm/vm_contig.c | 34 +- sys/vm/vm_map.c | 39 +- sys/vm/vm_object.c | 86 +- sys/vm/vm_pageout.c | 61 +- sys/vm/vm_swap.c | 7 +- sys/vm/vnode_pager.c | 23 +- 121 files changed, 3146 insertions(+), 3050 deletions(-) create mode 100644 sys/kern/vfs_lock.c create mode 100644 sys/kern/vfs_mount.c create mode 100644 sys/kern/vfs_sync.c diff --git a/sys/conf/files b/sys/conf/files index 0468751856..fd3a460b9f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.76 2004/09/28 00:25:25 dillon Exp $ +# $DragonFly: src/sys/conf/files,v 1.77 2004/10/12 19:20:26 dillon Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -725,6 +725,9 @@ kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_nlookup.c standard kern/vfs_subr.c standard +kern/vfs_lock.c standard +kern/vfs_mount.c standard +kern/vfs_sync.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard kern/vfs_vopops.c standard diff --git a/sys/dev/disk/ccd/ccd.c b/sys/dev/disk/ccd/ccd.c index 2fe21024a3..7ae15a4f01 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.16 2004/05/19 22:52:41 dillon Exp $ */ +/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.17 2004/10/12 19:20:30 dillon Exp $ */ /* $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */ @@ -1567,12 +1567,12 @@ ccdlookup(char *path, struct thread *td, struct vnode **vpp) vprint("ccdlookup: vnode info", vp); #endif - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); NDFREE(&nd, NDF_ONLY_PNBUF); *vpp = vp; return (0); bad: - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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 4ddd919ffb..f40b4446a6 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.11 2004/05/26 01:14:36 dillon Exp $ + * $DragonFly: src/sys/dev/disk/vn/vn.c,v 1.12 2004/10/12 19:20:32 dillon Exp $ */ /* @@ -390,12 +390,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, NULL, LK_EXCLUSIVE | LK_RETRY, curthread); + vn_lock(vn->sc_vp, 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, NULL, 0, curthread); + VOP_UNLOCK(vn->sc_vp, 0, curthread); bp->b_resid = auio.uio_resid; if (error) { @@ -563,11 +563,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, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); (void) vn_close(nd.ni_vp, flags, td); return (error ? error : EINVAL); } - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); vn->sc_secsize = DEV_BSIZE; vn->sc_vp = nd.ni_vp; @@ -718,9 +718,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, NULL, LK_EXCLUSIVE | LK_RETRY, curthread); + vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curthread); error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred); - VOP_UNLOCK(vn->sc_vp, NULL, 0, curthread); + VOP_UNLOCK(vn->sc_vp, 0, curthread); free(tmpbuf, M_TEMP); } return (error); diff --git a/sys/emulation/43bsd/43bsd_file.c b/sys/emulation/43bsd/43bsd_file.c index 747d963f53..7a82c9a350 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.5 2004/04/24 04:32:02 drhodus Exp $ + * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.6 2004/10/12 19:20:33 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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 e46cac2d4e..aac6ba6829 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.11 2004/06/21 05:58:01 dillon Exp $ + * $DragonFly: src/sys/emulation/ibcs2/coff/Attic/imgact_coff.c,v 1.12 2004/10/12 19:20:34 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, NULL, 0, td); + VOP_UNLOCK(vp, 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("%s: vm_map_remove failed", __FUNCTION__); fail: - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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 1b9cb591fe..72d8c35bc9 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.9 2004/03/01 06:33:15 dillon Exp $ + * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_misc.c,v 1.10 2004/10/12 19:20:36 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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 e1cb325058..609229b729 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.12 2004/08/28 19:02:04 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.13 2004/10/12 19:20:38 dillon Exp $ */ #include @@ -100,7 +100,7 @@ loop: if (pfs->pfs_pid == pid && pfs->pfs_type == pfs_type && vp->v_mount == mp) { - if (vget(vp, NULL, 0, td)) + if (vget(vp, LK_EXCLUSIVE|LK_SLEEPFAIL, td)) goto loop; *vpp = vp; return (0); @@ -203,6 +203,8 @@ loop: continue; *pp = pfs; + vx_unlock(vp); /* vnode ready to roll! */ + out: pfsvplock &= ~PROCFS_LOCKED; diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c index 180b377235..9905f5ab7f 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.17 2004/09/09 20:52:21 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.18 2004/10/12 19:20:38 dillon Exp $ */ /* @@ -323,12 +323,13 @@ linprocfs_bmap(ap) /* * linprocfs_inactive is called when the pfsnode - * is vrele'd and the reference count goes - * to zero. (vp) will be on the vnode free + * is vrele'd and the reference count is about + * to go to zero. (vp) will be on the vnode free * list, so to get it back vget() must be * used. * - * (vp) is locked on entry, but must be unlocked on exit. + * (vp) is locked on entry and must remain locked + * on exit. */ static int linprocfs_inactive(ap) @@ -336,9 +337,7 @@ linprocfs_inactive(ap) struct vnode *a_vp; } */ *ap; { - struct vnode *vp = ap->a_vp; - - VOP_UNLOCK(vp, NULL, 0, ap->a_td); + /*struct vnode *vp = ap->a_vp;*/ return (0); } @@ -356,7 +355,6 @@ linprocfs_reclaim(ap) struct vnode *a_vp; } */ *ap; { - return (linprocfs_freevp(ap->a_vp)); } @@ -758,7 +756,7 @@ out: if (error == 0) { if (*vpp != dvp && (cnp->cn_flags & CNP_LOCKPARENT) == 0) { cnp->cn_flags |= CNP_PDIRUNLOCK; - VOP_UNLOCK(dvp, NULL, 0, cnp->cn_td); + VOP_UNLOCK(dvp, 0, cnp->cn_td); } } return (error); diff --git a/sys/emulation/linux/linux_file.c b/sys/emulation/linux/linux_file.c index 776ea656cc..29469ff880 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.17 2004/09/30 18:59:38 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.18 2004/10/12 19:20:37 dillon Exp $ */ #include "opt_compat.h" @@ -291,7 +291,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); again: aiov.iov_base = buf; @@ -430,7 +430,7 @@ out: if (cookies) free(cookies, M_TEMP); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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 18738666d5..f6f2db7ad3 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.16 2004/09/26 06:00:07 dillon Exp $ */ +/* $DragonFly: src/sys/emulation/linux/linux_getcwd.c,v 1.17 2004/10/12 19:20:37 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + error = vn_lock(lvp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + error = vn_lock(lvp, 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 ea3bf961f3..006dd508ae 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.20 2004/09/17 01:29:45 joerg Exp $ + * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.21 2004/10/12 19:20:37 dillon Exp $ */ #include "opt_compat.h" @@ -326,7 +326,7 @@ linux_uselib(struct linux_uselib_args *args) /* * Lock no longer needed */ - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* Release the kernel mapping. */ if (a_out) diff --git a/sys/emulation/ndis/subr_ndis.c b/sys/emulation/ndis/subr_ndis.c index 66aaeb7488..323a6078e0 100644 --- a/sys/emulation/ndis/subr_ndis.c +++ b/sys/emulation/ndis/subr_ndis.c @@ -30,7 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.62 2004/07/11 00:19:30 wpaul Exp $ - * $DragonFly: src/sys/emulation/ndis/subr_ndis.c,v 1.4 2004/09/20 06:32:41 dillon Exp $ + * $DragonFly: src/sys/emulation/ndis/subr_ndis.c,v 1.5 2004/10/12 19:20:40 dillon Exp $ */ /* @@ -2577,7 +2577,7 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr) /* Get the file size. */ VOP_GETATTR(nd.ni_vp, vap, td); - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); fh->nf_vp = nd.ni_vp; fh->nf_map = NULL; diff --git a/sys/emulation/svr4/svr4_fcntl.c b/sys/emulation/svr4/svr4_fcntl.c index 2e3799aaae..4ff1640446 100644 --- a/sys/emulation/svr4/svr4_fcntl.c +++ b/sys/emulation/svr4/svr4_fcntl.c @@ -29,7 +29,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/svr4/svr4_fcntl.c,v 1.7 1999/12/12 10:27:04 newton Exp $ - * $DragonFly: src/sys/emulation/svr4/Attic/svr4_fcntl.c,v 1.14 2003/08/27 06:07:10 rob Exp $ + * $DragonFly: src/sys/emulation/svr4/Attic/svr4_fcntl.c,v 1.15 2004/10/12 19:20:42 dillon Exp $ */ #include #include @@ -263,6 +263,9 @@ fd_revoke(struct thread *td, int fd) vp = (struct vnode *) fp->f_data; + if ((error = vx_get(vp)) != 0) + return (error); + if (vp->v_type != VCHR && vp->v_type != VBLK) { error = EINVAL; goto out; @@ -278,7 +281,7 @@ fd_revoke(struct thread *td, int fd) if (vcount(vp) > 1) VOP_REVOKE(vp, REVOKEALL); out: - vrele(vp); + vx_put(vp); return error; } diff --git a/sys/emulation/svr4/svr4_misc.c b/sys/emulation/svr4/svr4_misc.c index 683046c3ef..a53102eeb8 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.24 2004/09/30 18:59:43 dillon Exp $ + * $DragonFly: src/sys/emulation/svr4/Attic/svr4_misc.c,v 1.25 2004/10/12 19:20:42 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type != VDIR || fp->f_ncp == NULL) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, cred, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (error) return error; vref(vp); diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 206a9eb0b3..8cc245adb4 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.21 2004/07/24 20:21:35 dillon Exp $ + * $DragonFly: src/sys/kern/imgact_elf.c,v 1.22 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -381,7 +381,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, NULL, 0, td); + VOP_UNLOCK(nd->ni_vp, 0, td); goto fail; } @@ -392,7 +392,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, NULL, 0, td); + VOP_UNLOCK(nd->ni_vp, 0, td); if (error) goto fail; @@ -484,7 +484,6 @@ exec_elf_imgact(struct image_params *imgp) const char *interp = NULL; Elf_Brandinfo *brand_info; char *path; - lwkt_tokref ilock; error = 0; @@ -518,9 +517,7 @@ 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(&ilock, imgp->vp->v_interlock); - imgp->vp->v_flag |= VTEXT; - lwkt_reltoken(&ilock); + vsetflags(imgp->vp, VTEXT); vmspace = imgp->proc->p_vmspace; @@ -808,7 +805,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, NULL, 0, p->p_thread); + VOP_UNLOCK(vp, 0, p->p_thread); error = generic_elf_coredump(p, fp, limit); diff --git a/sys/kern/imgact_resident.c b/sys/kern/imgact_resident.c index 2bef4a3ffb..ff2892ea40 100644 --- a/sys/kern/imgact_resident.c +++ b/sys/kern/imgact_resident.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/imgact_resident.c,v 1.5 2004/07/16 05:51:09 dillon Exp $ + * $DragonFly: src/sys/kern/imgact_resident.c,v 1.6 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -101,7 +101,7 @@ fill_xresident(struct vmresident *vr, struct xresident *in, struct thread *td) } /* indicate that we are using the vnode */ - error = vget(vrtmp, NULL, LK_EXCLUSIVE, td); + error = vget(vrtmp, LK_EXCLUSIVE, td); if (error) goto done; diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 8ce23aa7f5..627261a0ec 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.39 2004/10/04 09:20:40 dillon Exp $ + * $DragonFly: src/sys/kern/init_main.c,v 1.40 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_init_path.h" @@ -464,7 +464,7 @@ start_init(void *dummy) if (VFS_ROOT(mp, &vp)) panic("cannot find root vnode"); if (mp->mnt_ncp == NULL) { - mp->mnt_ncp = cache_allocroot(vp); + mp->mnt_ncp = cache_allocroot(mp, vp); cache_unlock(mp->mnt_ncp); /* leave ref intact */ } p->p_fd->fd_cdir = vp; @@ -472,7 +472,7 @@ start_init(void *dummy) p->p_fd->fd_rdir = vp; vref(p->p_fd->fd_rdir); vfs_cache_setroot(vp, cache_hold(mp->mnt_ncp)); - VOP_UNLOCK(vp, NULL, 0, curthread); /* leave ref intact */ + VOP_UNLOCK(vp, 0, curthread); /* leave ref intact */ p->p_fd->fd_ncdir = cache_hold(mp->mnt_ncp); p->p_fd->fd_nrdir = cache_hold(mp->mnt_ncp); diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index 1d7d682871..110333885e 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.14 2004/09/17 17:06:59 dillon Exp $ + * $DragonFly: src/sys/kern/kern_acct.c,v 1.15 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -142,7 +142,7 @@ acct(uap) if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 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 9a73fd1bc1..4e7dc33463 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.6 2004/03/01 06:33:17 dillon Exp $ + * $DragonFly: src/sys/kern/kern_acl.c,v 1.7 2004/10/12 19:20:46 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_SETACL(vp, type, &inkernacl, ucred, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_SETACL(vp, ACL_TYPE_DEFAULT, 0, ucred, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index afd79cda84..098616d279 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.19 2004/02/28 00:43:31 tegge Exp $ - * $DragonFly: src/sys/kern/kern_descrip.c,v 1.29 2004/09/30 18:59:48 dillon Exp $ + * $DragonFly: src/sys/kern/kern_descrip.c,v 1.30 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_compat.h" @@ -1366,7 +1366,7 @@ fdcheckstd(struct proc *p) fp->f_flag = flags; fp->f_ops = &vnops; fp->f_type = DTYPE_VNODE; - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 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 d4bd73c234..4ffc0e3084 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.27 2004/05/13 17:40:15 dillon Exp $ + * $DragonFly: src/sys/kern/kern_exec.c,v 1.28 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -67,6 +67,8 @@ #include #include +#include + MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); static register_t *exec_copyout_strings (struct image_params *); @@ -175,12 +177,12 @@ interpret: */ error = exec_check_permissions(imgp); if (error) { - VOP_UNLOCK(imgp->vp, NULL, 0, td); + VOP_UNLOCK(imgp->vp, 0, td); goto exec_fail_dealloc; } error = exec_map_first_page(imgp); - VOP_UNLOCK(imgp->vp, NULL, 0, td); + VOP_UNLOCK(imgp->vp, 0, td); if (error) goto exec_fail_dealloc; @@ -490,7 +492,7 @@ execve(struct execve_args *uap) int exec_map_first_page(struct image_params *imgp) { - int s, rv, i; + int rv, i; int initial_pagein; vm_page_t ma[VM_INITIAL_PAGEIN]; vm_page_t m; @@ -506,7 +508,7 @@ exec_map_first_page(struct image_params *imgp) * need it for the lookup loop below (lookup/busy race), since * an interrupt can unbusy and free the page before our busy check. */ - s = splvm(); + crit_enter(); m = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) { @@ -542,13 +544,13 @@ exec_map_first_page(struct image_params *imgp) vm_page_protect(m, VM_PROT_NONE); vm_page_free(m); } - splx(s); + crit_exit(); return EIO; } } vm_page_hold(m); vm_page_wakeup(m); /* unbusy the page */ - splx(s); + crit_exit(); imgp->firstpage = sf_buf_alloc(m, SFBA_QUICK); imgp->image_header = (void *)sf_buf_kva(imgp->firstpage); @@ -561,9 +563,8 @@ exec_unmap_first_page(imgp) struct image_params *imgp; { vm_page_t m; - int s; - s = splvm(); + crit_enter(); if (imgp->firstpage != NULL) { m = sf_buf_page(imgp->firstpage); sf_buf_free(imgp->firstpage); @@ -571,7 +572,7 @@ exec_unmap_first_page(imgp) imgp->image_header = NULL; vm_page_unhold(m); } - splx(s); + crit_exit(); } /* diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 55330489e6..5eeed446ea 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -37,7 +37,7 @@ * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 * $FreeBSD: src/sys/kern/kern_exit.c,v 1.92.2.11 2003/01/13 22:51:16 dillon Exp $ - * $DragonFly: src/sys/kern/kern_exit.c,v 1.38 2004/09/17 01:29:45 joerg Exp $ + * $DragonFly: src/sys/kern/kern_exit.c,v 1.39 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_compat.h" @@ -260,15 +260,21 @@ exit1(int rv) * if we blocked. */ if ((vp = sp->s_ttyvp) != NULL) { - sp->s_ttyvp = NULL; - VOP_REVOKE(vp, REVOKEALL); - vrele(vp); + ttyclosesession(sp, 0); + if (vx_lock(vp) == 0) { + VOP_REVOKE(vp, REVOKEALL); + vx_unlock(vp); + } + vrele(vp); /* s_ttyvp ref */ } } - if ((vp = sp->s_ttyvp) != NULL) { - sp->s_ttyvp = NULL; - vrele(vp); - } + /* + * Release the tty. If someone has it open via + * /dev/tty then close it (since they no longer can + * once we've NULL'd it out). + */ + if (sp->s_ttyvp) + ttyclosesession(sp, 1); /* * s_ttyp is not zero'd; we use this to indicate * that the session once had a controlling terminal. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 0877dd743b..396e76b94c 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -37,7 +37,7 @@ * * @(#)kern_fork.c 8.6 (Berkeley) 4/8/94 * $FreeBSD: src/sys/kern/kern_fork.c,v 1.72.2.14 2003/06/26 04:15:10 silby Exp $ - * $DragonFly: src/sys/kern/kern_fork.c,v 1.29 2004/09/17 01:29:45 joerg Exp $ + * $DragonFly: src/sys/kern/kern_fork.c,v 1.30 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_ktrace.h" @@ -473,6 +473,11 @@ again: if (flags & RFPPWAIT) p2->p_flag |= P_PPWAIT; + /* + * Once we are on a pglist we may receive signals. XXX we might + * race a ^C being sent to the process group by not receiving it + * at all prior to this line. + */ LIST_INSERT_AFTER(p1, p2, p_pglist); /* diff --git a/sys/kern/kern_fp.c b/sys/kern/kern_fp.c index 1c56d99a93..79856b3c4e 100644 --- a/sys/kern/kern_fp.c +++ b/sys/kern/kern_fp.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_fp.c,v 1.7 2004/07/29 20:32:59 dillon Exp $ + * $DragonFly: src/sys/kern/kern_fp.c,v 1.8 2004/10/12 19:20:46 dillon Exp $ */ /* @@ -119,7 +119,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, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); } else { fdrop(fp, td); *fpp = NULL; @@ -205,7 +205,7 @@ fp_vpopen(struct vnode *vp, int flags, file_t *fpp) if (flags & FWRITE) vp->v_writecount++; done: - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 172c6ffa68..b83585e082 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.15 2004/05/21 15:41:23 drhodus Exp $ + * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.16 2004/10/12 19:20:46 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, td); curp->p_traceflag &= ~KTRFAC_ACTIVE; @@ -488,13 +488,13 @@ ktrwrite(struct vnode *vp, struct ktr_header *kth, struct uio *uio) kth->ktr_len += uio->uio_resid; } VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred); if (error == 0 && uio != NULL) { VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred); } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (!error) return; /* diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 25b2d0b249..de28449bcd 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.18 2004/03/01 06:33:17 dillon Exp $ + * $DragonFly: src/sys/kern/kern_linker.c,v 1.19 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_ddb.h" @@ -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, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td); if (type == VREG) return(result); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 89efe8dbcf..ea0a838570 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.30 2004/04/15 00:51:32 dillon Exp $ + * $DragonFly: src/sys/kern/kern_sig.c,v 1.31 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_ktrace.h" @@ -959,6 +959,9 @@ psignal(struct proc *p, int sig) * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. * + * Note that p_thread may be NULL or may not be completely + * initialized if the process is in the SIDL or SZOMB state. + * * For SMP we may have to forward the request to another cpu. * YYY the MP lock prevents the target process from moving * to another cpu, see kern/kern_switch.c @@ -970,9 +973,13 @@ psignal(struct proc *p, int sig) #ifdef SMP if (p == lwkt_preempted_proc()) { signotify(); - } else { + } else if (p->p_stat == SRUN) { struct thread *td = p->p_thread; + KASSERT(td != NULL, + ("pid %d NULL p_thread stat %d flags %08x", + p->p_pid, p->p_stat, p->p_flag)); + if (td->td_gd != mycpu) lwkt_send_ipiq(td->td_gd, signotify_remote, p); else if (td->td_msgport.mp_flags & MSGPORTF_WAITING) @@ -981,8 +988,13 @@ psignal(struct proc *p, int sig) #else if (p == lwkt_preempted_proc()) { signotify(); - } else { + } else if (p->p_stat == SRUN) { struct thread *td = p->p_thread; + + KASSERT(td != NULL, + ("pid %d NULL p_thread stat %d flags %08x", + p->p_pid, p->p_stat, p->p_flag)); + if (td->td_msgport.mp_flags & MSGPORTF_WAITING) lwkt_schedule(td); } @@ -1473,7 +1485,7 @@ coredump(struct proc *p) NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; @@ -1490,12 +1502,12 @@ coredump(struct proc *p) } VATTR_NULL(&vattr); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); error = p->p_sysent->sv_coredump ? p->p_sysent->sv_coredump(p, vp, limit) : diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c index 7f9bfa82b7..af5e8243a2 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.11 2004/05/21 15:41:23 drhodus Exp $ + * $DragonFly: src/sys/kern/link_aout.c,v 1.12 2004/10/12 19:20:46 dillon Exp $ */ #ifndef __alpha__ @@ -286,7 +286,7 @@ link_aout_load_file(const char* filename, linker_file_t* result) *result = lf; out: - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 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 58cfbe4130..4169675874 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.13 2004/03/20 16:27:41 drhodus Exp $ + * $DragonFly: src/sys/kern/link_elf.c,v 1.14 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -696,7 +696,7 @@ out: free(shdr, M_LINKER); if (firstpage) free(firstpage, M_LINKER); - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td); return error; diff --git a/sys/kern/tty.c b/sys/kern/tty.c index baeda44811..2bd19d8fd8 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -37,7 +37,7 @@ * * @(#)tty.c 8.8 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/tty.c,v 1.129.2.5 2002/03/11 01:32:31 dd Exp $ - * $DragonFly: src/sys/kern/tty.c,v 1.13 2004/10/07 01:32:03 dillon Exp $ + * $DragonFly: src/sys/kern/tty.c,v 1.14 2004/10/12 19:20:46 dillon Exp $ */ /*- @@ -289,6 +289,31 @@ ttyclearsession(struct tty *tp) } } +/* + * Terminate the tty vnode association for a session. This is the + * 'other half' of the close. + */ +void +ttyclosesession(struct session *sp, int dorele) +{ + struct vnode *vp; + struct thread *td = curthread; + + if ((vp = sp->s_ttyvp) == NULL) + return; + sp->s_ttyvp = NULL; + if (vp->v_flag & VCTTYISOPEN) { + if (vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td) == 0) { + vclrflags(vp, VCTTYISOPEN); + VOP_CLOSE(vp, 0, td); + VOP_UNLOCK(vp, 0, td); + } + } + if (dorele) + vrele(vp); +} + + #define FLUSHQ(q) { \ if ((q)->c_cc) \ ndflush(q, (q)->c_cc); \ diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c index 15eacbe19a..9070030df2 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.9 2004/05/19 22:52:58 dillon Exp $ + * $DragonFly: src/sys/kern/tty_tty.c,v 1.10 2004/10/12 19:20:46 dillon Exp $ */ /* @@ -89,9 +89,14 @@ cttyopen(dev_t dev, int flag, int mode, struct thread *td) KKASSERT(p); ttyvp = cttyvp(p); if (ttyvp) { - vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_OPEN(ttyvp, flag, NOCRED, td); - VOP_UNLOCK(ttyvp, NULL, 0, td); + if (ttyvp->v_flag & VCTTYISOPEN) { + error = 0; + } else { + vsetflags(ttyvp, VCTTYISOPEN); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); + error = VOP_OPEN(ttyvp, flag, NOCRED, td); + VOP_UNLOCK(ttyvp, 0, td); + } } else { error = ENXIO; } @@ -107,10 +112,23 @@ cttyclose(dev_t dev, int fflag, int devtype, struct thread *td) KKASSERT(p); ttyvp = cttyvp(p); - if (ttyvp == NULL) - error = EIO; - else - error = VOP_CLOSE(ttyvp, fflag, td); + if (ttyvp == NULL) { + /* + * The tty may have been TIOCNOTTY'd, don't return an + * error on close. We just have nothing to do. + */ + /* error = EIO; */ + error = 0; + } else if (ttyvp->v_flag & VCTTYISOPEN) { + vclrflags(ttyvp, VCTTYISOPEN); + error = vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error == 0) { + error = VOP_CLOSE(ttyvp, fflag, td); + VOP_UNLOCK(ttyvp, 0, td); + } + } else { + error = 0; + } return(error); } @@ -130,9 +148,9 @@ cttyread(dev, uio, flag) ttyvp = cttyvp(p); if (ttyvp == NULL) return (EIO); - vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_READ(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp, NULL, 0, td); + VOP_UNLOCK(ttyvp, 0, td); return (error); } @@ -152,9 +170,9 @@ cttywrite(dev, uio, flag) ttyvp = cttyvp(p); if (ttyvp == NULL) return (EIO); - vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_WRITE(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp, NULL, 0, td); + VOP_UNLOCK(ttyvp, 0, td); return (error); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 85a68f84ca..ca7da9e1b7 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.41 2004/08/24 21:53:38 dillon Exp $ + * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.42 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_ktrace.h" @@ -1299,17 +1299,16 @@ sf_buf_mfree(void *arg) { struct sfbuf_mref *sfm = arg; vm_page_t m; - int s; KKASSERT(sfm->mref_count > 0); if (--sfm->mref_count == 0) { m = sf_buf_page(sfm->sf); sf_buf_free(sfm->sf); - s = splvm(); + crit_enter(); vm_page_unwire(m, 0); if (m->wire_count == 0 && m->object == NULL) vm_page_free(m); - splx(s); + crit_exit(); free(sfm, M_SENDFILE); } } @@ -1449,7 +1448,6 @@ kern_sendfile(struct vnode *vp, int sfd, off_t offset, size_t nbytes, off_t off, xfsize; off_t hbytes = 0; int error = 0; - int s; if (vp->v_type != VREG || VOP_GETVOBJECT(vp, &obj) != 0) { error = EINVAL; @@ -1520,26 +1518,27 @@ retry_lookup: * Attempt to look up the page. * * Allocate if not found, wait and loop if busy, then - * wire the page. splvm() protection is required to - * maintain the object association (an interrupt can - * free the page) through to the vm_page_wire() call. + * wire the page. critical section protection is + * required to maintain the object association (an + * interrupt can free the page) through to the + * vm_page_wire() call. */ - s = splvm(); + crit_enter(); pg = vm_page_lookup(obj, pindex); if (pg == NULL) { pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL); if (pg == NULL) { vm_wait(); - splx(s); + crit_exit(); goto retry_lookup; } vm_page_wakeup(pg); } else if (vm_page_sleep_busy(pg, TRUE, "sfpbsy")) { - splx(s); + crit_exit(); goto retry_lookup; } vm_page_wire(pg); - splx(s); + crit_exit(); /* * If page is not valid for what we need, initiate I/O @@ -1569,11 +1568,11 @@ retry_lookup: auio.uio_segflg = UIO_NOCOPY; auio.uio_rw = UIO_READ; auio.uio_td = td; - vn_lock(vp, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td); error = VOP_READ(vp, &auio, IO_VMIO | ((MAXBSIZE / bsize) << 16), p->p_ucred); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); vm_page_flag_clear(pg, PG_ZERO); vm_page_io_finish(pg); if (error) { @@ -1599,11 +1598,11 @@ retry_lookup: * but this wait can be interrupted. */ if ((sf = sf_buf_alloc(pg, SFBA_PCATCH)) == NULL) { - s = splvm(); + crit_enter(); vm_page_unwire(pg, 0); if (pg->wire_count == 0 && pg->object == NULL) vm_page_free(pg); - splx(s); + crit_exit(); sbunlock(&so->so_snd); error = EINTR; goto done; @@ -1649,7 +1648,7 @@ retry_lookup: /* * Add the buffer to the socket buffer chain. */ - s = splnet(); + crit_enter(); retry_space: /* * Make sure that the socket is still able to take more data. @@ -1671,7 +1670,7 @@ retry_space: } m_freem(m); sbunlock(&so->so_snd); - splx(s); + crit_exit(); goto done; } /* @@ -1683,7 +1682,7 @@ retry_space: if (so->so_state & SS_NBIO) { m_freem(m); sbunlock(&so->so_snd); - splx(s); + crit_exit(); error = EAGAIN; goto done; } @@ -1696,13 +1695,13 @@ retry_space: if (error) { m_freem(m); sbunlock(&so->so_snd); - splx(s); + crit_exit(); goto done; } goto retry_space; } error = so_pru_send(so, 0, m, NULL, NULL, td); - splx(s); + crit_exit(); if (error) { sbunlock(&so->so_snd); goto done; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 30f0ce5335..3d12d11657 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.15 2004/06/06 19:16:06 dillon Exp $ + * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.16 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -626,7 +626,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); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (0); } diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 2496bf6327..1208393300 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -67,7 +67,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.37 2004/10/07 20:18:33 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_cache.c,v 1.38 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -356,12 +356,16 @@ cache_lock(struct namecache *ncp) } ncp->nc_flag |= NCF_LOCKREQ; if (tsleep(ncp, 0, "clock", hz) == EWOULDBLOCK) { - if (didwarn == 0) { - didwarn = 1; - printf("[diagnostic] cache_lock: blocked on %*.*s\n", - ncp->nc_nlen, ncp->nc_nlen, - ncp->nc_name); - } + if (didwarn) + continue; + didwarn = 1; + printf("[diagnostic] cache_lock: blocked on %p", ncp); + if ((ncp->nc_flag & NCF_MOUNTPT) && ncp->nc_mount) + printf(" [MOUNTPT %s]\n", ncp->nc_mount->mnt_stat.f_mntonname); + else + printf(" \"%*.*s\"\n", + ncp->nc_nlen, ncp->nc_nlen, + ncp->nc_name); } } @@ -638,7 +642,7 @@ again: error = 0; } if (error == 0 && (vp = ncp->nc_vp) != NULL) { - error = vget(vp, NULL, lk_type, curthread); + error = vget(vp, lk_type, curthread); if (error) { if (vp != ncp->nc_vp) /* handle cache_zap race */ goto again; @@ -1438,11 +1442,12 @@ nchinit(void) * a referenced, unlocked namecache record. */ struct namecache * -cache_allocroot(struct vnode *vp) +cache_allocroot(struct mount *mp, struct vnode *vp) { struct namecache *ncp = cache_alloc(0); ncp->nc_flag |= NCF_MOUNTPT | NCF_ROOT; + ncp->nc_mount = mp; cache_setvp(ncp, vp); return(ncp); } @@ -1546,29 +1551,6 @@ cache_purgevfs(struct mount *mp) } } -/* - * cache_leaf_test() - * - * Test whether the vnode is at a leaf in the nameicache tree. - * - * Returns 0 if it is a leaf, -1 if it isn't. - */ -int -cache_leaf_test(struct vnode *vp) -{ - struct namecache *scan; - struct namecache *ncp; - - TAILQ_FOREACH(scan, &vp->v_namecache, nc_vnode) { - TAILQ_FOREACH(ncp, &scan->nc_list, nc_entry) { - /* YYY && ncp->nc_vp->v_type == VDIR ? */ - if (ncp->nc_vp != NULL) - return(-1); - } - } - return(0); -} - /* * Perform canonical checks and cache lookup and pass on to filesystem * through the vop_cachedlookup only if needed. @@ -1627,19 +1609,19 @@ vfs_cache_lookup(struct vop_lookup_args *ap) /* already ref'd from cache_lookup() */ error = 0; } else if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; - error = vget(vp, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!error && lockparent && (flags & CNP_ISLASTCN)) { - if ((error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td)) == 0) + if ((error = vn_lock(dvp, LK_EXCLUSIVE, td)) == 0) cnp->cn_flags &= ~CNP_PDIRUNLOCK; } } else { - error = vget(vp, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!lockparent || error || !(flags & CNP_ISLASTCN)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } @@ -1652,12 +1634,12 @@ vfs_cache_lookup(struct vop_lookup_args *ap) return (0); vput(vp); if (lockparent && dvp != vp && (flags & CNP_ISLASTCN)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } if (cnp->cn_flags & CNP_PDIRUNLOCK) { - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error) return (error); cnp->cn_flags &= ~CNP_PDIRUNLOCK; diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index b9fafbc826..20ac585957 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.20 2004/10/07 10:03:02 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_default.c,v 1.21 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -191,7 +191,7 @@ vop_noresolve(struct vop_resolve_args *ap) if ((dvp = ncp->nc_parent->nc_vp) == NULL) return(EPERM); - if ((error = vget(dvp, NULL, LK_EXCLUSIVE, curthread)) != 0) { + if ((error = vget(dvp, LK_EXCLUSIVE, curthread)) != 0) { printf("[diagnostic] vop_noresolve: EAGAIN on ncp %p %*.*s\n", ncp, ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name); return(EAGAIN); @@ -211,9 +211,9 @@ vop_noresolve(struct vop_resolve_args *ap) */ error = vop_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); if (error == 0) - VOP_UNLOCK(vp, NULL, 0, curthread); + VOP_UNLOCK(vp, 0, curthread); if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) - VOP_UNLOCK(dvp, NULL, 0, curthread); + VOP_UNLOCK(dvp, 0, curthread); if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) { /* was resolved by another process while we were unlocked */ if (error == 0) @@ -373,7 +373,6 @@ 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; @@ -381,11 +380,10 @@ vop_stdlock(ap) int error; #ifndef DEBUG_LOCKS - error = lockmgr(&ap->a_vp->v_lock, ap->a_flags, - ap->a_vlock, ap->a_td); + error = lockmgr(&ap->a_vp->v_lock, ap->a_flags, NULL, ap->a_td); #else error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags, - ap->a_vlock, ap->a_td, + NULL, ap->a_td, "vop_stdlock", ap->a_vp->filename, ap->a_vp->line); #endif return(error); @@ -395,7 +393,6 @@ 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; @@ -403,7 +400,7 @@ vop_stdunlock(ap) int error; error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE, - ap->a_vlock, ap->a_td); + NULL, ap->a_td); return(error); } @@ -508,9 +505,9 @@ retry: vp->v_usecount--; } else { if (object->flags & OBJ_DEAD) { - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); tsleep(object, 0, "vodead", 0); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); goto retry; } } diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 0e760a77cd..f89f47c11d 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -70,7 +70,7 @@ * * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 * $FreeBSD: src/sys/kern/vfs_init.c,v 1.59 2002/04/30 18:44:32 dillon Exp $ - * $DragonFly: src/sys/kern/vfs_init.c,v 1.6 2004/08/17 18:57:32 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_init.c,v 1.7 2004/10/12 19:20:46 dillon Exp $ */ /* * Manage vnode VOP operations vectors @@ -84,7 +84,7 @@ #include #include -MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); +static MALLOC_DEFINE(M_VNODEOP, "vnodeops", "vnode operations vectors"); /* * Zone for namei @@ -129,9 +129,10 @@ vfs_add_vnodeops(struct vop_ops **vops_pp, struct vnodeopv_entry_desc *descs) struct vnodeopv_node *node; struct vop_ops *ops; - node = malloc(sizeof(*node), M_VNODE, M_ZERO|M_WAITOK); + node = malloc(sizeof(*node), M_VNODEOP, M_ZERO|M_WAITOK); if ((ops = *vops_pp) == NULL) { - ops = malloc(sizeof(struct vop_ops), M_VNODE, M_ZERO|M_WAITOK); + ops = malloc(sizeof(struct vop_ops), + M_VNODEOP, M_ZERO|M_WAITOK); *vops_pp = ops; } node->ops = ops; @@ -159,11 +160,11 @@ vfs_rm_vnodeops(struct vop_ops **vops_pp) return; } TAILQ_REMOVE(&vnodeopv_list, node, entry); - free(node, M_VNODE); + free(node, M_VNODEOP); KKASSERT(ops != NULL && ops->vv_refs > 0); if (--ops->vv_refs == 0) { *vops_pp = NULL; - free(ops, M_VNODE); + free(ops, M_VNODEOP); } vfs_recalc_vnodeops(); } @@ -191,7 +192,7 @@ vfs_recalc_vnodeops(void) ops = node->ops; if ((vnew = ops->vv_new) == NULL) { vnew = malloc(sizeof(struct vop_ops), - M_VNODE, M_ZERO|M_WAITOK); + M_VNODEOP, M_ZERO|M_WAITOK); ops->vv_new = vnew; vnew->vop_default = vop_eopnotsupp; } @@ -224,7 +225,7 @@ vfs_recalc_vnodeops(void) *(void **)((char *)vnew + off); } ops->vv_new = NULL; - free(vnew, M_VNODE); + free(vnew, M_VNODEOP); } } @@ -246,7 +247,10 @@ vfsinit(void *dummy) /* * Initialize the vnode table */ - vntblinit(); + vfs_subr_init(); + vfs_mount_init(); + vfs_lock_init(); + vfs_sync_init(); /* * Initialize the vnode name cache */ diff --git a/sys/kern/vfs_lock.c b/sys/kern/vfs_lock.c new file mode 100644 index 0000000000..7946ba2cd6 --- /dev/null +++ b/sys/kern/vfs_lock.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2004 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/kern/vfs_lock.c,v 1.1 2004/10/12 19:20:46 dillon Exp $ + */ + +/* + * External virtual filesystem routines + */ +#include "opt_ddb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + + +static MALLOC_DEFINE(M_VNODE, "vnodes", "vnode structures"); + +static TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ + +int freevnodes = 0; +SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, + &freevnodes, 0, ""); +static int wantfreevnodes = 25; +SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, + &wantfreevnodes, 0, ""); +static int minvnodes; +SYSCTL_INT(_kern, OID_AUTO, minvnodes, CTLFLAG_RW, + &minvnodes, 0, "Minimum number of vnodes"); + +/* + * Called from vfsinit() + */ +void +vfs_lock_init(void) +{ + minvnodes = desiredvnodes / 4; + + TAILQ_INIT(&vnode_free_list); +} + +/* + * Inline helper functions. vbusy() and vfree() must be called while in a + * critical section. + */ +static __inline +void +__vbusy(struct vnode *vp) +{ + KKASSERT(vp->v_flag & VFREE); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; + vp->v_flag &= ~(VFREE|VAGE); +} + +static __inline +void +__vfree(struct vnode *vp) +{ + KKASSERT((vp->v_flag & VFREE) == 0); + if (vp->v_flag & (VAGE|VRECLAIMED)) + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); + else + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + freevnodes++; + vp->v_flag &= ~VAGE; + vp->v_flag |= VFREE; +} + +/* + * Return 1 if we can immediately place the vnode on the freelist. + */ +static __inline int +vshouldfree(struct vnode *vp, int usecount) +{ + if (vp->v_holdcnt != 0 || vp->v_usecount != usecount) + return (0); /* other holderse */ + if (vp->v_object && + (vp->v_object->ref_count || vp->v_object->resident_page_count)) { + return (0); + } + return (1); +} + +/* + * Reference a vnode or release the reference on a vnode. The vnode will + * be taken off the freelist if it is on it and cannot be recycled or + * deactivated while refd. The last release of a vnode will deactivate the + * vnode via VOP_INACTIVE(). + * + * Special cases: refing a vnode does not clear VINACTIVE, you have to vget() + * the vnode shared or exclusive to do that. + */ +static __inline +void +__vref(struct vnode *vp) +{ + ++vp->v_usecount; + if (vp->v_flag & VFREE) + __vbusy(vp); +} + +void +vref(struct vnode *vp) +{ + crit_enter(); + __vref(vp); + crit_exit(); +} + +void +vrele(struct vnode *vp) +{ + thread_t td = curthread; + + crit_enter(); + if (vp->v_usecount == 1) { + KKASSERT(lockcount(&vp->v_lock) == 0); + + /* + * Deactivation requires an exclusive v_lock (vx_lock()), and + * only occurs if the usecount is still 1 after locking. + */ + if ((vp->v_flag & VINACTIVE) == 0) { + if (vx_lock(vp) == 0) { + if ((vp->v_flag & VINACTIVE) == 0 && + vp->v_usecount == 1) { + vp->v_flag |= VINACTIVE; + VOP_INACTIVE(vp, td); + } + vx_unlock(vp); + } + } + if (vshouldfree(vp, 1)) + __vfree(vp); + } else { + KKASSERT(vp->v_usecount > 0); + } + --vp->v_usecount; + crit_exit(); +} + +/* + * Hold a vnode or drop the hold on a vnode. The vnode will be taken off + * the freelist if it is on it and cannot be recycled. However, the + * vnode can be deactivated and reactivated while held. + * + * Special cases: The last drop of a vnode does nothing special, allowing it + * to be called from an interrupt. vrele() on the otherhand cannot be called + * from an interrupt. + */ +void +vhold(struct vnode *vp) +{ + crit_enter(); + ++vp->v_holdcnt; + if (vp->v_flag & VFREE) + __vbusy(vp); + crit_exit(); +} + +void +vdrop(struct vnode *vp) +{ + crit_enter(); + if (vp->v_holdcnt == 1) { + --vp->v_holdcnt; + if (vshouldfree(vp, 0)) + __vfree(vp); + } else { + --vp->v_holdcnt; + KKASSERT(vp->v_holdcnt > 0); + } + crit_exit(); +} + +/**************************************************************** + * VX LOCKING FUNCTIONS * + **************************************************************** + * + * These functions lock vnodes for reclamation and deactivation ops. + * Only vp->v_lock, the top layer of the VFS, is locked. You must be + * holding a normal reference in order to be able to safely call vx_lock() + * and vx_unlock(). vx_get() and vx_put() are combination functions which + * vref+vx_lock and vrele+vx_unlock. + */ + +#define VXLOCKFLAGS (LK_EXCLUSIVE|LK_RETRY) +#define VXLOCKFLAGS_NB (LK_EXCLUSIVE|LK_NOWAIT) + +static int +__vxlock(struct vnode *vp, int flags) +{ + return(lockmgr(&vp->v_lock, flags, NULL, curthread)); +} + +static void +__vxunlock(struct vnode *vp) +{ + lockmgr(&vp->v_lock, LK_RELEASE, NULL, curthread); +} + +int +vx_lock(struct vnode *vp) +{ + return(__vxlock(vp, VXLOCKFLAGS)); +} + +void +vx_unlock(struct vnode *vp) +{ + __vxunlock(vp); +} + +int +vx_get(struct vnode *vp) +{ + int error; + + vref(vp); + if ((error = __vxlock(vp, VXLOCKFLAGS)) != 0) + vrele(vp); + return(error); +} + +int +vx_get_nonblock(struct vnode *vp) +{ + int error; + + vref(vp); + if ((error = __vxlock(vp, VXLOCKFLAGS_NB)) != 0) + vrele(vp); + return(error); +} + +void +vx_put(struct vnode *vp) +{ + __vxunlock(vp); + vrele(vp); +} + +/**************************************************************** + * VNODE ACQUISITION FUNCTIONS * + **************************************************************** + * + * vget() and vput() access a vnode for the intent of executing an + * operation other then a reclamation or deactivation. vget() will ref + * and lock the vnode, vput() will unlock and deref the vnode. + * The VOP_*() locking functions are used. + * + * Special cases: If vget()'s locking operation fails the vrele() call may + * cause the vnode to be deactivated (VOP_INACTIVE called). However, this + * never occurs if the vnode is in a reclaimed state. Vnodes in reclaimed + * states always return an error code of ENOENT. + * + * Special cases: vput() will unlock and, if it is the last reference, + * deactivate the vnode. The deactivation uses a separate non-layered + * VX lock after the normal unlock. XXX make it more efficient. + */ +int +vget(struct vnode *vp, int flags, thread_t td) +{ + int error; + + crit_enter(); + __vref(vp); + if (flags & LK_TYPE_MASK) { + if ((error = vn_lock(vp, flags, td)) != 0) { + vrele(vp); + } else if (vp->v_flag & VRECLAIMED) { + VOP_UNLOCK(vp, 0, td); + vrele(vp); + error = ENOENT; + } else { + vp->v_flag &= ~VINACTIVE; + error = 0; + } + } else { + panic("vget() called with no lock specified!"); + error = ENOENT; /* not reached, compiler opt */ + } + crit_exit(); + return(error); +} + +void +vput(struct vnode *vp) +{ + VOP_UNLOCK(vp, 0, curthread); + vrele(vp); +} + +void +vsetflags(struct vnode *vp, int flags) +{ + crit_enter(); + vp->v_flag |= flags; + crit_exit(); +} + +void +vclrflags(struct vnode *vp, int flags) +{ + crit_enter(); + vp->v_flag &= ~flags; + crit_exit(); +} + +/* + * Obtain a new vnode from the freelist, allocating more if necessary. + * The returned vnode is VX locked & refd. + */ +struct vnode * +allocvnode(int lktimeout, int lkflags) +{ + struct thread *td; + struct vnode *vp; + + /* + * Try to reuse vnodes if we hit the max. This situation only + * occurs in certain large-memory (2G+) situations. We cannot + * attempt to directly reclaim vnodes due to nasty recursion + * problems. + */ + while (numvnodes - freevnodes > desiredvnodes) + vnlru_proc_wait(); + + td = curthread; + vp = NULL; + + /* + * Attempt to reuse a vnode already on the free list, allocating + * a new vnode if we can't find one or if we have not reached a + * good minimum for good LRU performance. + */ + 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) + panic("getnewvnode: free vnode isn't"); + + /* + * Note the lack of a critical section. We vx_get() + * the vnode before we check it for validity, reducing + * the number of checks we have to make. The vx_get() + * will pull it off the freelist. + */ + if (vx_get(vp)) { + vp = NULL; + continue; + } + + /* + * Can this vnode be recycled? It must be in a + * VINACTIVE state with only our reference to it. + * (vx_get(), unlike vget(), does not reactivate + * the vnode). vx_put() will recycle it onto the + * end of the freelist. + */ + if ((vp->v_flag & VINACTIVE) == 0 || + vp->v_holdcnt || vp->v_usecount != 1) { + vx_put(vp); + vp = NULL; + continue; + } + + /* + * Ok, we can reclaim the vnode if it isn't already + * in a reclaimed state. If the reclamation fails, + * or if someone else is referencing the vnode after + * we have vgone()'d it, we recycle the vnode on the + * freelist or hold it (by calling vx_put()). + */ + if ((vp->v_flag & VRECLAIMED) == 0) { + vgone(vp); + if ((vp->v_flag & VRECLAIMED) == 0 || + vp->v_holdcnt || vp->v_usecount != 1) { + vx_put(vp); + vp = NULL; + continue; + } + } + KKASSERT(vp->v_flag & VINACTIVE); + + /* + * We have a vnode! + */ + break; + } + } + + /* + * If we have a vp it will be refd and VX locked. + */ + if (vp) { + vp->v_lease = NULL; + +#ifdef INVARIANTS + if (vp->v_data) + panic("cleaned vnode isn't"); + if (vp->v_numoutput) + panic("Clean vnode has pending I/O's"); + KKASSERT(vp->v_mount == NULL); +#endif + vp->v_flag = 0; + vp->v_lastw = 0; + vp->v_lasta = 0; + vp->v_cstart = 0; + vp->v_clen = 0; + vp->v_socket = 0; + vp->v_writecount = 0; /* XXX */ + lockreinit(&vp->v_lock, 0, "vnode", lktimeout, lkflags); + KKASSERT(TAILQ_FIRST(&vp->v_namecache) == NULL); + } else { + /* + * A brand-new vnode (we could use malloc() here I think) XXX + */ + vp = malloc(sizeof(struct vnode), M_VNODE, M_WAITOK|M_ZERO); + lwkt_token_init(&vp->v_pollinfo.vpi_token); + lockinit(&vp->v_lock, 0, "vnode", lktimeout, lkflags); + TAILQ_INIT(&vp->v_namecache); + + /* + * short cut around vfreeing it and looping, just set it up + * as if we had pulled a reclaimed vnode off the freelist + * and reinitialized it. + */ + vp->v_usecount = 1; + if (__vxlock(vp, VXLOCKFLAGS)) + panic("getnewvnode: __vxlock failed"); + numvnodes++; + } + + TAILQ_INIT(&vp->v_cleanblkhd); + TAILQ_INIT(&vp->v_dirtyblkhd); + vp->v_type = VNON; + vp->v_tag = 0; + vp->v_ops = NULL; + vp->v_data = NULL; + KKASSERT(vp->v_mount == NULL); + return (vp); +} + +struct vnode * +allocvnode_placemarker(void) +{ + struct vnode *pvp; + + pvp = malloc(sizeof(struct vnode), + M_VNODE, M_WAITOK|M_USE_RESERVE|M_ZERO); + pvp->v_flag |= VPLACEMARKER; + return(pvp); +} + +void +freevnode_placemarker(struct vnode *pvp) +{ + KKASSERT(pvp->v_flag & VPLACEMARKER); + free(pvp, M_VNODE); +} + diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 9508b4c2ab..6155b21d8d 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.18 2004/10/07 04:20:26 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_lookup.c,v 1.19 2004/10/12 19:20:46 dillon Exp $ */ #include "opt_ktrace.h" @@ -196,7 +196,7 @@ namei(struct nameidata *ndp) return (0); } if ((cnp->cn_flags & CNP_LOCKPARENT) && ndp->ni_pathlen == 1) - VOP_UNLOCK(ndp->ni_dvp, NULL, 0, cnp->cn_td); + VOP_UNLOCK(ndp->ni_dvp, 0, cnp->cn_td); if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { error = ELOOP; break; @@ -328,7 +328,7 @@ lookup(struct nameidata *ndp) cnp->cn_flags &= ~CNP_ISSYMLINK; dp = ndp->ni_startdir; ndp->ni_startdir = NULLVP; - vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); dirloop: /* @@ -408,7 +408,7 @@ dirloop: } ndp->ni_vp = dp; if (!(cnp->cn_flags & (CNP_LOCKPARENT | CNP_LOCKLEAF))) - VOP_UNLOCK(dp, NULL, 0, cnp->cn_td); + VOP_UNLOCK(dp, 0, cnp->cn_td); /* XXX This should probably move to the top of function. */ if (cnp->cn_flags & CNP_SAVESTART) panic("lookup: CNP_SAVESTART"); @@ -448,7 +448,7 @@ dirloop: dp = dp->v_mount->mnt_vnodecovered; vput(tdp); vref(dp); - vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); } } @@ -475,7 +475,7 @@ unionlookup: else vput(tdp); vref(dp); - vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); goto unionlookup; } @@ -532,7 +532,7 @@ unionlookup: (cnp->cn_flags & CNP_NOCROSSMOUNT) == 0) { if (vfs_busy(mp, 0, NULL, td)) continue; - VOP_UNLOCK(dp, NULL, 0, td); + VOP_UNLOCK(dp, 0, td); error = VFS_ROOT(mp, &tdp); vfs_unbusy(mp, td); if (error) { @@ -603,13 +603,13 @@ nextname: vrele(ndp->ni_dvp); if ((cnp->cn_flags & CNP_LOCKLEAF) == 0) - VOP_UNLOCK(dp, NULL, 0, td); + VOP_UNLOCK(dp, 0, td); return (0); bad2: if ((cnp->cn_flags & (CNP_LOCKPARENT | CNP_PDIRUNLOCK)) == CNP_LOCKPARENT && *ndp->ni_next == '\0') - VOP_UNLOCK(ndp->ni_dvp, NULL, 0, td); + VOP_UNLOCK(ndp->ni_dvp, 0, td); vrele(ndp->ni_dvp); bad: if (dpunlocked) @@ -646,7 +646,7 @@ relookup(dvp, vpp, cnp) rdonly = cnp->cn_flags & CNP_RDONLY; cnp->cn_flags &= ~CNP_ISSYMLINK; dp = dvp; - vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); /* dirloop: */ /* @@ -680,7 +680,7 @@ relookup(dvp, vpp, cnp) goto bad; } if (!(cnp->cn_flags & CNP_LOCKLEAF)) - VOP_UNLOCK(dp, NULL, 0, td); + VOP_UNLOCK(dp, 0, td); *vpp = dp; /* XXX This should probably move to the top of function. */ if (cnp->cn_flags & CNP_SAVESTART) @@ -744,12 +744,12 @@ relookup(dvp, vpp, cnp) vfs_object_create(dp, cnp->cn_td); if ((cnp->cn_flags & CNP_LOCKLEAF) == 0) - VOP_UNLOCK(dp, NULL, 0, td); + VOP_UNLOCK(dp, 0, td); return (0); bad2: if ((cnp->cn_flags & CNP_LOCKPARENT) && (cnp->cn_flags & CNP_ISLASTCN)) - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); vrele(dvp); bad: vput(dp); diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c new file mode 100644 index 0000000000..08c83c7f81 --- /dev/null +++ b/sys/kern/vfs_mount.c @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2004 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/kern/vfs_mount.c,v 1.1 2004/10/12 19:20:46 dillon Exp $ + */ + +/* + * External virtual filesystem routines + */ +#include "opt_ddb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +static int vnlru_nowhere = 0; +SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW, + &vnlru_nowhere, 0, + "Number of times the vnlru process ran without success"); + + +static struct lwkt_token mntid_token; + +struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist); /* mounted fs */ +struct lwkt_token mountlist_token; +struct lwkt_token mntvnode_token; + + +/* + * Called from vfsinit() + */ +void +vfs_mount_init(void) +{ + lwkt_token_init(&mountlist_token); + lwkt_token_init(&mntvnode_token); + lwkt_token_init(&mntid_token); +} + +/* + * Allocate a new vnode and associate it with a tag, mount point, and + * operations vector. + * + * A VX locked and refd vnode is returned. The caller should setup the + * remaining fields and vx_put() or, if he wishes to leave a vref, + * vx_unlock() the vnode. + */ +int +getnewvnode(enum vtagtype tag, struct mount *mp, struct vop_ops *ops, + struct vnode **vpp, int lktimeout, int lkflags) +{ + struct vnode *vp; + + vp = allocvnode(lktimeout, lkflags); + vp->v_tag = tag; + vp->v_ops = ops; + vp->v_data = NULL; + + /* + * Placing the vnode on the mount point's queue makes it visible. + * VNON prevents it from being messed with, however. + */ + insmntque(vp, mp); + vfs_object_create(vp, curthread); + + /* + * A VX locked & refd vnode is returned. + */ + *vpp = vp; + return (0); +} + +/* + * Mark a mount point as busy. Used to synchronize access and to delay + * unmounting. Interlock is not released on failure. + */ +int +vfs_busy(struct mount *mp, int flags, + lwkt_tokref_t interlkp, struct thread *td) +{ + int lkflags; + + if (mp->mnt_kern_flag & MNTK_UNMOUNT) { + if (flags & LK_NOWAIT) + return (ENOENT); + mp->mnt_kern_flag |= MNTK_MWAIT; + /* + * 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); + return (ENOENT); + } + lkflags = LK_SHARED | LK_NOPAUSE; + if (interlkp) + lkflags |= LK_INTERLOCK; + if (lockmgr(&mp->mnt_lock, lkflags, interlkp, td)) + panic("vfs_busy: unexpected lock failure"); + return (0); +} + +/* + * Free a busy filesystem. + */ +void +vfs_unbusy(struct mount *mp, struct thread *td) +{ + lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td); +} + +/* + * Lookup a filesystem type, and if found allocate and initialize + * a mount structure for it. + * + * Devname is usually updated by mount(8) after booting. + */ +int +vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp) +{ + struct thread *td = curthread; /* XXX */ + struct vfsconf *vfsp; + struct mount *mp; + + if (fstypename == NULL) + return (ENODEV); + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { + if (!strcmp(vfsp->vfc_name, fstypename)) + break; + } + if (vfsp == NULL) + return (ENODEV); + 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); + vfs_busy(mp, LK_NOWAIT, NULL, td); + TAILQ_INIT(&mp->mnt_nvnodelist); + TAILQ_INIT(&mp->mnt_reservedvnlist); + mp->mnt_nvnodelistsize = 0; + mp->mnt_vfc = vfsp; + mp->mnt_op = vfsp->vfc_vfsops; + mp->mnt_flag = MNT_RDONLY; + mp->mnt_vnodecovered = NULLVP; + vfsp->vfc_refcount++; + mp->mnt_iosize_max = DFLTPHYS; + mp->mnt_stat.f_type = vfsp->vfc_typenum; + mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; + strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); + mp->mnt_stat.f_mntonname[0] = '/'; + mp->mnt_stat.f_mntonname[1] = 0; + (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); + *mpp = mp; + return (0); +} + +/* + * Lookup a mount point by filesystem identifier. + */ +struct mount * +vfs_getvfs(fsid_t *fsid) +{ + struct mount *mp; + lwkt_tokref ilock; + + 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]) { + break; + } + } + lwkt_reltoken(&ilock); + return (mp); +} + +/* + * Get a new unique fsid. Try to make its val[0] unique, since this value + * will be used to create fake device numbers for stat(). Also try (but + * not so hard) make its val[0] unique mod 2^16, since some emulators only + * support 16-bit device numbers. We end up with unique val[0]'s for the + * first 2^16 calls and unique val[0]'s mod 2^16 for the first 2^8 calls. + * + * Keep in mind that several mounts may be running in parallel. Starting + * the search one past where the previous search terminated is both a + * micro-optimization and a defense against returning the same fsid to + * different mounts. + */ +void +vfs_getnewfsid(struct mount *mp) +{ + static u_int16_t mntid_base; + lwkt_tokref ilock; + fsid_t tfsid; + int mtype; + + lwkt_gettoken(&ilock, &mntid_token); + mtype = mp->mnt_vfc->vfc_typenum; + tfsid.val[1] = mtype; + mtype = (mtype & 0xFF) << 24; + for (;;) { + tfsid.val[0] = makeudev(255, + mtype | ((mntid_base & 0xFF00) << 8) | (mntid_base & 0xFF)); + mntid_base++; + if (vfs_getvfs(&tfsid) == NULL) + break; + } + mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; + mp->mnt_stat.f_fsid.val[1] = tfsid.val[1]; + lwkt_reltoken(&ilock); +} + +/* + * This routine is called when we have too many vnodes. It attempts + * to free vnodes and will potentially free vnodes that still + * have VM backing store (VM backing store is typically the cause + * of a vnode blowout so we want to do this). Therefore, this operation + * is not considered cheap. + * + * A number of conditions may prevent a vnode from being reclaimed. + * the buffer cache may have references on the vnode, a directory + * vnode may still have references due to the namei cache representing + * underlying files, or the vnode may be in active use. It is not + * desireable to reuse such vnodes. These conditions may cause the + * number of vnodes to reach some minimum value regardless of what + * you set kern.maxvnodes to. Do not set kern.maxvnodes too low. + */ + +/* + * Return 0 if the vnode is not already on the free list, return 1 if the + * vnode, with some additional work could possibly be placed on the free list. + */ +static __inline int +vmightfree(struct vnode *vp, int use_count, int page_count) +{ + if (vp->v_flag & VFREE) + return (0); + if (vp->v_usecount != use_count || vp->v_holdcnt) + return (0); + if (vp->v_object && vp->v_object->resident_page_count >= page_count) + return (0); + return (1); +} + + +static int +vlrureclaim(struct mount *mp) +{ + struct vnode *vp; + lwkt_tokref ilock; + int done; + int trigger; + int usevnodes; + int count; + + /* + * Calculate the trigger point, don't allow user + * screwups to blow us up. This prevents us from + * recycling vnodes with lots of resident pages. We + * aren't trying to free memory, we are trying to + * free vnodes. + */ + usevnodes = desiredvnodes; + if (usevnodes <= 0) + usevnodes = 1; + trigger = vmstats.v_page_count * 2 / usevnodes; + + done = 0; + 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, and then must check again after we lock the vnode. + */ + if (vp->v_type == VNON || /* XXX */ + vp->v_type == VBAD || /* XXX */ + !vmightfree(vp, 0, trigger) /* critical path opt */ + ) { + TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); + TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes); + --count; + continue; + } + + /* + * VX get the candidate vnode. If the VX get fails the + * vnode might still be on the mountlist. Our loop depends + * on us at least cycling the vnode to the end of the + * mountlist. + */ + if (vx_get_nonblock(vp) != 0) { + if (vp->v_mount == mp) { + TAILQ_REMOVE(&mp->mnt_nvnodelist, + vp, v_nmntvnodes); + TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, + vp, v_nmntvnodes); + } + --count; + continue; + } + + /* + * Since we blocked locking the vp, make sure it is still + * a candidate for reclamation. That is, it has not already + * been reclaimed and only has our VX reference associated + * with it. + */ + if (vp->v_type == VNON || /* XXX */ + vp->v_type == VBAD || /* XXX */ + (vp->v_flag & VRECLAIMED) || + vp->v_mount != mp || + !vmightfree(vp, 1, trigger) /* critical path opt */ + ) { + if (vp->v_mount == mp) { + TAILQ_REMOVE(&mp->mnt_nvnodelist, + vp, v_nmntvnodes); + TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, + vp, v_nmntvnodes); + } + --count; + vx_put(vp); + continue; + } + + /* + * All right, we are good, move the vp to the end of the + * mountlist and clean it out. The vget will have returned + * an error if the vnode was destroyed (VRECLAIMED set), so we + * do not have to check again. The vput() will move the + * vnode to the free list if the vgone() was successful. + */ + KKASSERT(vp->v_mount == mp); + TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); + TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes); + vgone(vp); + vx_put(vp); + ++done; + --count; + } + lwkt_reltoken(&ilock); + return (done); +} + +/* + * Attempt to recycle vnodes in a context that is always safe to block. + * Calling vlrurecycle() from the bowels of file system code has some + * interesting deadlock problems. + */ +static struct thread *vnlruthread; +static int vnlruproc_sig; + +void +vnlru_proc_wait(void) +{ + if (vnlruproc_sig == 0) { + vnlruproc_sig = 1; /* avoid unnecessary wakeups */ + wakeup(vnlruthread); + } + tsleep(&vnlruproc_sig, 0, "vlruwk", hz); +} + +static void +vnlru_proc(void) +{ + struct mount *mp, *nmp; + lwkt_tokref ilock; + int s; + int done; + struct thread *td = curthread; + + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, td, + SHUTDOWN_PRI_FIRST); + + s = splbio(); + for (;;) { + kproc_suspend_loop(); + if (numvnodes - freevnodes <= desiredvnodes * 9 / 10) { + vnlruproc_sig = 0; + wakeup(&vnlruproc_sig); + tsleep(td, 0, "vlruwt", hz); + continue; + } + done = 0; + lwkt_gettoken(&ilock, &mountlist_token); + for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } + done += vlrureclaim(mp); + lwkt_gettokref(&ilock); + nmp = TAILQ_NEXT(mp, mnt_list); + vfs_unbusy(mp, td); + } + lwkt_reltoken(&ilock); + if (done == 0) { + ++vnlru_nowhere; + tsleep(td, 0, "vlrup", hz * 3); + if (vnlru_nowhere % 10 == 0) + printf("vnlru_proc: vnode recycler stopped working!\n"); + } else { + vnlru_nowhere = 0; + } + } + splx(s); +} + +static struct kproc_desc vnlru_kp = { + "vnlru", + vnlru_proc, + &vnlruthread +}; +SYSINIT(vnlru, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &vnlru_kp) + +/* + * Move a vnode from one mount queue to another. + */ +void +insmntque(struct vnode *vp, struct mount *mp) +{ + lwkt_tokref ilock; + + lwkt_gettoken(&ilock, &mntvnode_token); + /* + * Delete from old mount point vnode list, if on one. + */ + if (vp->v_mount != NULL) { + KASSERT(vp->v_mount->mnt_nvnodelistsize > 0, + ("bad mount point vnode list size")); + TAILQ_REMOVE(&vp->v_mount->mnt_nvnodelist, vp, v_nmntvnodes); + vp->v_mount->mnt_nvnodelistsize--; + } + /* + * Insert into list of vnodes for the new mount point, if available. + */ + if ((vp->v_mount = mp) == NULL) { + lwkt_reltoken(&ilock); + return; + } + TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); + mp->mnt_nvnodelistsize++; + lwkt_reltoken(&ilock); +} + + +/* + * Scan the vnodes under a mount point. The first function is called + * with just the mountlist token held (no vnode lock). The second + * function is called with the vnode VX locked. + */ +int +vmntvnodescan( + struct mount *mp, + int flags, + int (*fastfunc)(struct mount *mp, struct vnode *vp, void *data), + int (*slowfunc)(struct mount *mp, struct vnode *vp, void *data), + void *data +) { + lwkt_tokref ilock; + struct vnode *pvp; + struct vnode *vp; + int r = 0; + + /* + * Scan the vnodes on the mount's vnode list. Use a placemarker + */ + pvp = allocvnode_placemarker(); + + 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) /* another procs placemarker */ + continue; + if (vp->v_type == VNON) /* visible but not ready */ + continue; + KKASSERT(vp->v_mount == mp); + + /* + * Quick test. A negative return continues the loop without + * calling the slow test. 0 continues onto the slow test. + * A positive number aborts the loop. + */ + if (fastfunc) { + if ((r = fastfunc(mp, vp, data)) < 0) + continue; + if (r) + break; + } + + /* + * Get a vxlock on the vnode, retry if it has moved or isn't + * in the mountlist where we expect it. + */ + if (slowfunc) { + int error; + + switch(flags) { + case VMSC_GETVP: + error = vget(vp, LK_EXCLUSIVE, curthread); + break; + case VMSC_GETVP|VMSC_NOWAIT: + error = vget(vp, LK_EXCLUSIVE|LK_NOWAIT, + curthread); + break; + case VMSC_GETVX: + error = vx_get(vp); + break; + case VMSC_REFVP: + vref(vp); + /* fall through */ + default: + error = 0; + break; + } + if (error) + continue; + if (TAILQ_PREV(pvp, vnodelst, v_nmntvnodes) != vp) + goto skip; + if (vp->v_type == VNON) + goto skip; + r = slowfunc(mp, vp, data); +skip: + switch(flags) { + case VMSC_GETVP: + case VMSC_GETVP|VMSC_NOWAIT: + vput(vp); + break; + case VMSC_GETVX: + vx_put(vp); + break; + case VMSC_REFVP: + vrele(vp); + /* fall through */ + default: + break; + } + if (r != 0) + break; + } + } + TAILQ_REMOVE(&mp->mnt_nvnodelist, pvp, v_nmntvnodes); + freevnode_placemarker(pvp); + lwkt_reltoken(&ilock); + return(r); +} + +/* + * Remove any vnodes in the vnode table belonging to mount point mp. + * + * If FORCECLOSE is not specified, there should not be any active ones, + * return error if any are found (nb: this is a user error, not a + * system error). If FORCECLOSE is specified, detach any active vnodes + * that are found. + * + * If WRITECLOSE is set, only flush out regular file vnodes open for + * writing. + * + * SKIPSYSTEM causes any vnodes marked VSYSTEM to be skipped. + * + * `rootrefs' specifies the base reference count for the root vnode + * of this filesystem. The root vnode is considered busy if its + * v_usecount exceeds this value. On a successful return, vflush() + * will call vrele() on the root vnode exactly rootrefs times. + * If the SKIPSYSTEM or WRITECLOSE flags are specified, rootrefs must + * be zero. + */ +#ifdef DIAGNOSTIC +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, void *data); + +struct vflush_info { + int flags; + int busy; + thread_t td; +}; + +int +vflush(struct mount *mp, int rootrefs, int flags) +{ + struct thread *td = curthread; /* XXX */ + struct vnode *rootvp = NULL; + int error; + struct vflush_info vflush_info; + + if (rootrefs > 0) { + KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0, + ("vflush: bad args")); + /* + * Get the filesystem root vnode. We can vput() it + * immediately, since with rootrefs > 0, it won't go away. + */ + if ((error = VFS_ROOT(mp, &rootvp)) != 0) + return (error); + vput(rootvp); + } + + vflush_info.busy = 0; + vflush_info.flags = flags; + vflush_info.td = td; + vmntvnodescan(mp, VMSC_GETVX, NULL, vflush_scan, &vflush_info); + + 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. + */ + KASSERT(vflush_info.busy > 0, ("vflush: not busy")); + KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs")); + if (vflush_info.busy == 1 && rootvp->v_usecount == rootrefs) { + if (vx_lock(rootvp) == 0) { + vgone(rootvp); + vx_unlock(rootvp); + vflush_info.busy = 0; + } + } + } + if (vflush_info.busy) + return (EBUSY); + for (; rootrefs > 0; rootrefs--) + vrele(rootvp); + return (0); +} + +/* + * The scan callback is made with an VX locked vnode. + */ +static int +vflush_scan(struct mount *mp, struct vnode *vp, void *data) +{ + struct vflush_info *info = data; + struct vattr vattr; + + /* + * Skip over a vnodes marked VSYSTEM. + */ + if ((info->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { + 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)) { + 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 == 1) { + vgone(vp); + 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) { + vgone(vp); + } else { + vclean(vp, 0, info->td); + vp->v_ops = spec_vnode_vops; + insmntque(vp, NULL); + } + return(0); + } +#ifdef DIAGNOSTIC + if (busyprt) + vprint("vflush: busy vnode", vp); +#endif + ++info->busy; + return(0); +} + diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index e9c34e06f9..93fc704f72 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.42 2004/10/05 03:24:09 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_subr.c,v 1.43 2004/10/12 19:20:46 dillon Exp $ */ /* @@ -86,11 +86,7 @@ static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); -static void insmntque (struct vnode *vp, struct mount *mp); -static void vclean (struct vnode *vp, lwkt_tokref_t vlock, - int flags, struct thread *td); - -static unsigned long numvnodes; +int numvnodes; SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, ""); enum vtype iftovt_tab[16] = { @@ -102,15 +98,6 @@ int vttoif_tab[9] = { S_IFSOCK, S_IFIFO, S_IFMT, }; -static TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ - -static u_long wantfreevnodes = 25; -SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, - &wantfreevnodes, 0, ""); -static u_long freevnodes = 0; -SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, - &freevnodes, 0, ""); - static int reassignbufcalls; SYSCTL_INT(_vfs, OID_AUTO, reassignbufcalls, CTLFLAG_RW, &reassignbufcalls, 0, ""); @@ -132,95 +119,47 @@ int vfs_ioopt = 0; SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, ""); #endif -struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist); /* mounted fs */ -struct lwkt_token mountlist_token; -struct lwkt_token mntvnode_token; int nfs_mount_type = -1; -static struct lwkt_token mntid_token; -static struct lwkt_token vnode_free_list_token; static struct lwkt_token spechash_token; struct nfs_public nfs_pub; /* publicly exported FS */ -static vm_zone_t vnode_zone; - -/* - * The workitem queue. - */ -#define SYNCER_MAXDELAY 32 -static int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */ -time_t syncdelay = 30; /* max time to delay syncing data */ -SYSCTL_INT(_kern, OID_AUTO, syncdelay, CTLFLAG_RW, - &syncdelay, 0, "VFS data synchronization delay"); -time_t filedelay = 30; /* time to delay syncing files */ -SYSCTL_INT(_kern, OID_AUTO, filedelay, CTLFLAG_RW, - &filedelay, 0, "File synchronization delay"); -time_t dirdelay = 29; /* time to delay syncing directories */ -SYSCTL_INT(_kern, OID_AUTO, dirdelay, CTLFLAG_RW, - &dirdelay, 0, "Directory synchronization delay"); -time_t metadelay = 28; /* time to delay syncing metadata */ -SYSCTL_INT(_kern, OID_AUTO, metadelay, CTLFLAG_RW, - &metadelay, 0, "VFS metadata synchronization delay"); -static int rushjob; /* number of slots to run ASAP */ -static int stat_rush_requests; /* number of times I/O speeded up */ -SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, - &stat_rush_requests, 0, ""); - -static int syncer_delayno = 0; -static long syncer_mask; -LIST_HEAD(synclist, vnode); -static struct synclist *syncer_workitem_pending; int desiredvnodes; SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "Maximum number of vnodes"); -static int minvnodes; -SYSCTL_INT(_kern, OID_AUTO, minvnodes, CTLFLAG_RW, - &minvnodes, 0, "Minimum number of vnodes"); -static int vnlru_nowhere = 0; -SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW, - &vnlru_nowhere, 0, - "Number of times the vnlru process ran without success"); static void vfs_free_addrlist (struct netexport *nep); 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); - extern int dev_ref_debug; extern struct vnodeopv_entry_desc spec_vnodeop_entries[]; /* - * NOTE: the vnode interlock must be held on call. + * Return 0 if the vnode is already on the free list or cannot be placed + * on the free list. Return 1 if the vnode can be placed on the free list. */ -static __inline void -vmaybefree(struct vnode *vp) +static __inline int +vshouldfree(struct vnode *vp, int usecount) { - if (VSHOULDFREE(vp)) - vfree(vp); + if (vp->v_flag & VFREE) + return (0); /* already free */ + if (vp->v_holdcnt != 0 || vp->v_usecount != usecount) + return (0); /* other holderse */ + if (vp->v_object && + (vp->v_object->ref_count || vp->v_object->resident_page_count)) { + return (0); + } + return (1); } - + /* - * Initialize the vnode management data structures. + * Initialize the vnode management data structures. + * + * Called from vfsinit() */ void -vntblinit(void) +vfs_subr_init(void) { /* * Desired vnodes is a result of the physical page count @@ -234,163 +173,7 @@ vntblinit(void) 2 * (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / (5 * (sizeof(struct vm_object) + sizeof(struct vnode)))); - minvnodes = desiredvnodes / 4; - 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_token_init(&vnode_free_list_token); - vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5); - /* - * Initialize the filesystem syncer. - */ - syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE, - &syncer_mask); - syncer_maxdelay = syncer_mask + 1; -} - -/* - * Mark a mount point as busy. Used to synchronize access and to delay - * unmounting. Interlock is not released on failure. - */ -int -vfs_busy(struct mount *mp, int flags, - lwkt_tokref_t interlkp, struct thread *td) -{ - int lkflags; - - if (mp->mnt_kern_flag & MNTK_UNMOUNT) { - if (flags & LK_NOWAIT) - return (ENOENT); - mp->mnt_kern_flag |= MNTK_MWAIT; - /* - * 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); - return (ENOENT); - } - lkflags = LK_SHARED | LK_NOPAUSE; - if (interlkp) - lkflags |= LK_INTERLOCK; - if (lockmgr(&mp->mnt_lock, lkflags, interlkp, td)) - panic("vfs_busy: unexpected lock failure"); - return (0); -} - -/* - * Free a busy filesystem. - */ -void -vfs_unbusy(struct mount *mp, struct thread *td) -{ - lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td); -} - -/* - * Lookup a filesystem type, and if found allocate and initialize - * a mount structure for it. - * - * Devname is usually updated by mount(8) after booting. - */ -int -vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp) -{ - struct thread *td = curthread; /* XXX */ - struct vfsconf *vfsp; - struct mount *mp; - - if (fstypename == NULL) - return (ENODEV); - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { - if (!strcmp(vfsp->vfc_name, fstypename)) - break; - } - if (vfsp == NULL) - return (ENODEV); - 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); - vfs_busy(mp, LK_NOWAIT, NULL, td); - TAILQ_INIT(&mp->mnt_nvnodelist); - TAILQ_INIT(&mp->mnt_reservedvnlist); - mp->mnt_nvnodelistsize = 0; - mp->mnt_vfc = vfsp; - mp->mnt_op = vfsp->vfc_vfsops; - mp->mnt_flag = MNT_RDONLY; - mp->mnt_vnodecovered = NULLVP; - vfsp->vfc_refcount++; - mp->mnt_iosize_max = DFLTPHYS; - mp->mnt_stat.f_type = vfsp->vfc_typenum; - mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; - strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); - mp->mnt_stat.f_mntonname[0] = '/'; - mp->mnt_stat.f_mntonname[1] = 0; - (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); - *mpp = mp; - return (0); -} - -/* - * Lookup a mount point by filesystem identifier. - */ -struct mount * -vfs_getvfs(fsid_t *fsid) -{ - struct mount *mp; - lwkt_tokref ilock; - - 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]) { - break; - } - } - lwkt_reltoken(&ilock); - return (mp); -} - -/* - * Get a new unique fsid. Try to make its val[0] unique, since this value - * will be used to create fake device numbers for stat(). Also try (but - * not so hard) make its val[0] unique mod 2^16, since some emulators only - * support 16-bit device numbers. We end up with unique val[0]'s for the - * first 2^16 calls and unique val[0]'s mod 2^16 for the first 2^8 calls. - * - * Keep in mind that several mounts may be running in parallel. Starting - * the search one past where the previous search terminated is both a - * micro-optimization and a defense against returning the same fsid to - * different mounts. - */ -void -vfs_getnewfsid(struct mount *mp) -{ - static u_int16_t mntid_base; - lwkt_tokref ilock; - fsid_t tfsid; - int mtype; - - lwkt_gettoken(&ilock, &mntid_token); - mtype = mp->mnt_vfc->vfc_typenum; - tfsid.val[1] = mtype; - mtype = (mtype & 0xFF) << 24; - for (;;) { - tfsid.val[0] = makeudev(255, - mtype | ((mntid_base & 0xFF00) << 8) | (mntid_base & 0xFF)); - mntid_base++; - if (vfs_getvfs(&tfsid) == NULL) - break; - } - mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; - mp->mnt_stat.f_fsid.val[1] = tfsid.val[1]; - lwkt_reltoken(&ilock); } /* @@ -462,396 +245,6 @@ vattr_null(struct vattr *vap) vap->va_vaflags = 0; } -/* - * This routine is called when we have too many vnodes. It attempts - * to free vnodes and will potentially free vnodes that still - * have VM backing store (VM backing store is typically the cause - * of a vnode blowout so we want to do this). Therefore, this operation - * is not considered cheap. - * - * A number of conditions may prevent a vnode from being reclaimed. - * the buffer cache may have references on the vnode, a directory - * vnode may still have references due to the namei cache representing - * underlying files, or the vnode may be in active use. It is not - * desireable to reuse such vnodes. These conditions may cause the - * number of vnodes to reach some minimum value regardless of what - * you set kern.maxvnodes to. Do not set kern.maxvnodes too low. - */ -static int -vlrureclaim(struct mount *mp) -{ - struct vnode *vp; - lwkt_tokref ilock; - lwkt_tokref vlock; - int done; - int trigger; - int usevnodes; - int count; - - /* - * Calculate the trigger point, don't allow user - * screwups to blow us up. This prevents us from - * recycling vnodes with lots of resident pages. We - * aren't trying to free memory, we are trying to - * free vnodes. - */ - usevnodes = desiredvnodes; - if (usevnodes <= 0) - usevnodes = 1; - trigger = vmstats.v_page_count * 2 / usevnodes; - - done = 0; - 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); - - /* - * 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_reltoken(&vlock); - --count; - continue; - } - vgonel(vp, &vlock, curthread); - ++done; - --count; - } - lwkt_reltoken(&ilock); - return done; -} - -/* - * Attempt to recycle vnodes in a context that is always safe to block. - * Calling vlrurecycle() from the bowels of file system code has some - * interesting deadlock problems. - */ -static struct thread *vnlruthread; -static int vnlruproc_sig; - -static void -vnlru_proc(void) -{ - struct mount *mp, *nmp; - lwkt_tokref ilock; - int s; - int done; - struct thread *td = curthread; - - EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, td, - SHUTDOWN_PRI_FIRST); - - s = splbio(); - for (;;) { - kproc_suspend_loop(); - if (numvnodes - freevnodes <= desiredvnodes * 9 / 10) { - vnlruproc_sig = 0; - wakeup(&vnlruproc_sig); - tsleep(td, 0, "vlruwt", hz); - continue; - } - done = 0; - lwkt_gettoken(&ilock, &mountlist_token); - for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) { - nmp = TAILQ_NEXT(mp, mnt_list); - continue; - } - done += vlrureclaim(mp); - lwkt_gettokref(&ilock); - nmp = TAILQ_NEXT(mp, mnt_list); - vfs_unbusy(mp, td); - } - lwkt_reltoken(&ilock); - if (done == 0) { - vnlru_nowhere++; - tsleep(td, 0, "vlrup", hz * 3); - } - } - splx(s); -} - -static struct kproc_desc vnlru_kp = { - "vnlru", - vnlru_proc, - &vnlruthread -}; -SYSINIT(vnlru, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &vnlru_kp) - -/* - * Routines having to do with the management of the vnode table. - */ - -/* - * Return the next vnode from the free list. - */ -int -getnewvnode(enum vtagtype tag, struct mount *mp, struct vop_ops *ops, - struct vnode **vpp, int lktimeout, int lkflags) -{ - int s; - struct thread *td = curthread; /* XXX */ - struct vnode *vp = NULL; - struct vnode *xvp; - vm_object_t object; - lwkt_tokref ilock; - lwkt_tokref vlock; - - s = splbio(); /* YYY remove me */ - - /* - * Try to reuse vnodes if we hit the max. This situation only - * occurs in certain large-memory (2G+) situations. We cannot - * attempt to directly reclaim vnodes due to nasty recursion - * problems. - */ - while (numvnodes - freevnodes > desiredvnodes) { - if (vnlruproc_sig == 0) { - vnlruproc_sig = 1; /* avoid unnecessary wakeups */ - wakeup(vnlruthread); - } - tsleep(&vnlruproc_sig, 0, "vlruwk", hz); - } - - - /* - * Attempt to reuse a vnode already on the free list, allocating - * a new vnode if we can't find one or if we have not reached a - * good minimum for good LRU performance. - */ - 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) - panic("getnewvnode: free vnode isn't"); - - /* - * Move the vnode to the end of the list so other - * processes do not double-block trying to recycle - * the same vnode (as an optimization), then get - * the interlock. - */ - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - - /* - * 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; - } - - - /* - * 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. - */ - 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; - } - - /* - * We now safely own the vnode. If the vnode has - * an object do not recycle it if its VM object - * has resident pages or references. - */ - if ((VOP_GETVOBJECT(vp, &object) == 0 && - (object->resident_page_count || object->ref_count)) - ) { - lwkt_reltoken(&vlock); - vp = NULL; - continue; - } - - /* - * 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?) - */ - 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; - } - 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(&ilock); - cache_inval_vp(vp, CINV_SELF); /* YYY may block */ - vp->v_lease = NULL; - if (vp->v_type != VBAD) { - vgonel(vp, &vlock, td); - } else { - lwkt_reltoken(&vlock); - } - -#ifdef INVARIANTS - { - int s; - - if (vp->v_data) - panic("cleaned vnode isn't"); - s = splbio(); - if (vp->v_numoutput) - panic("Clean vnode has pending I/O's"); - splx(s); - } -#endif - vp->v_flag = 0; - vp->v_lastw = 0; - vp->v_lasta = 0; - vp->v_cstart = 0; - vp->v_clen = 0; - vp->v_socket = 0; - vp->v_writecount = 0; /* XXX */ - lockreinit(&vp->v_lock, 0, "vnode", lktimeout, lkflags); - } else { - /* - * A brand-new vnode (we could use malloc() here I think) XXX - */ - 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); - lockinit(&vp->v_lock, 0, "vnode", lktimeout, lkflags); - cache_inval_vp(vp, CINV_SELF); - TAILQ_INIT(&vp->v_namecache); - numvnodes++; - } - - TAILQ_INIT(&vp->v_cleanblkhd); - TAILQ_INIT(&vp->v_dirtyblkhd); - vp->v_type = VNON; - vp->v_tag = tag; - vp->v_ops = ops; - *vpp = vp; - vp->v_usecount = 1; - vp->v_data = NULL; - splx(s); - - /* - * Placing the vnode on the mount point's queue makes it visible. - * We had better already have a ref on it. - */ - insmntque(vp, mp); - - vfs_object_create(vp, td); - return (0); -} - -/* - * Move a vnode from one mount queue to another. - */ -static void -insmntque(struct vnode *vp, struct mount *mp) -{ - lwkt_tokref ilock; - - lwkt_gettoken(&ilock, &mntvnode_token); - /* - * Delete from old mount point vnode list, if on one. - */ - if (vp->v_mount != NULL) { - KASSERT(vp->v_mount->mnt_nvnodelistsize > 0, - ("bad mount point vnode list size")); - TAILQ_REMOVE(&vp->v_mount->mnt_nvnodelist, vp, v_nmntvnodes); - vp->v_mount->mnt_nvnodelistsize--; - } - /* - * Insert into list of vnodes for the new mount point, if available. - */ - if ((vp->v_mount = mp) == NULL) { - lwkt_reltoken(&ilock); - return; - } - TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); - mp->mnt_nvnodelistsize++; - lwkt_reltoken(&ilock); -} - /* * Update outstanding I/O count and do wakeup if requested. */ @@ -874,7 +267,8 @@ vwakeup(struct buf *bp) /* * Flush out and invalidate all buffers associated with a vnode. - * Called with the underlying object locked. + * + * vp must be locked. */ int vinvalbuf(struct vnode *vp, int flags, struct thread *td, @@ -884,7 +278,6 @@ 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(); @@ -981,12 +374,10 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td, /* * Destroy the copy in the VM cache, too. */ - 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(&vlock); if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) || !TAILQ_EMPTY(&vp->v_cleanblkhd)) panic("vinvalbuf: flush failed"); @@ -997,6 +388,8 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td, * Truncate a file's buffer and pages to a specified length. This * is in lieu of the old vinvalbuf mechanism, which performed unneeded * sync activity. + * + * The vnode must be locked. */ int vtruncbuf(struct vnode *vp, struct thread *td, off_t length, int blksize) @@ -1102,8 +495,6 @@ restartsync: void bgetvp(struct vnode *vp, struct buf *bp) { - int s; - KASSERT(bp->b_vp == NULL, ("bgetvp: not free")); vhold(vp); @@ -1112,11 +503,11 @@ bgetvp(struct vnode *vp, struct buf *bp) /* * Insert onto list for new vnode. */ - s = splbio(); + crit_enter(); bp->b_xflags |= BX_VNCLEAN; bp->b_xflags &= ~BX_VNDIRTY; TAILQ_INSERT_TAIL(&vp->v_cleanblkhd, bp, b_vnbufs); - splx(s); + crit_exit(); } /* @@ -1127,7 +518,6 @@ brelvp(struct buf *bp) { struct vnode *vp; struct buflists *listheadp; - int s; KASSERT(bp->b_vp != NULL, ("brelvp: NULL")); @@ -1135,7 +525,7 @@ brelvp(struct buf *bp) * Delete from old vnode list, if on one. */ vp = bp->b_vp; - s = splbio(); + crit_enter(); if (bp->b_xflags & (BX_VNDIRTY | BX_VNCLEAN)) { if (bp->b_xflags & BX_VNDIRTY) listheadp = &vp->v_dirtyblkhd; @@ -1148,183 +538,9 @@ brelvp(struct buf *bp) vp->v_flag &= ~VONWORKLST; LIST_REMOVE(vp, v_synclist); } - splx(s); - bp->b_vp = (struct vnode *) 0; - vdrop(vp); -} - -/* - * The workitem queue. - * - * It is useful to delay writes of file data and filesystem metadata - * for tens of seconds so that quickly created and deleted files need - * not waste disk bandwidth being created and removed. To realize this, - * we append vnodes to a "workitem" queue. When running with a soft - * updates implementation, most pending metadata dependencies should - * not wait for more than a few seconds. Thus, mounted on block devices - * are delayed only about a half the time that file data is delayed. - * Similarly, directory updates are more critical, so are only delayed - * about a third the time that file data is delayed. Thus, there are - * SYNCER_MAXDELAY queues that are processed round-robin at a rate of - * one each second (driven off the filesystem syncer process). The - * syncer_delayno variable indicates the next queue that is to be processed. - * Items that need to be processed soon are placed in this queue: - * - * syncer_workitem_pending[syncer_delayno] - * - * A delay of fifteen seconds is done by placing the request fifteen - * entries later in the queue: - * - * syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask] - * - */ - -/* - * Add an item to the syncer work queue. - */ -static void -vn_syncer_add_to_worklist(struct vnode *vp, int delay) -{ - int s, slot; - - s = splbio(); - - if (vp->v_flag & VONWORKLST) { - LIST_REMOVE(vp, v_synclist); - } - - if (delay > syncer_maxdelay - 2) - delay = syncer_maxdelay - 2; - slot = (syncer_delayno + delay) & syncer_mask; - - LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist); - vp->v_flag |= VONWORKLST; - splx(s); -} - -struct thread *updatethread; -static void sched_sync (void); -static struct kproc_desc up_kp = { - "syncer", - sched_sync, - &updatethread -}; -SYSINIT(syncer, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp) - -/* - * System filesystem synchronizer daemon. - */ -void -sched_sync(void) -{ - struct synclist *slp; - struct vnode *vp; - long starttime; - int s; - struct thread *td = curthread; - - EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, td, - SHUTDOWN_PRI_LAST); - - for (;;) { - kproc_suspend_loop(); - - starttime = time_second; - - /* - * Push files whose dirty time has expired. Be careful - * of interrupt race on slp queue. - */ - s = splbio(); - slp = &syncer_workitem_pending[syncer_delayno]; - syncer_delayno += 1; - if (syncer_delayno == syncer_maxdelay) - syncer_delayno = 0; - splx(s); - - while ((vp = LIST_FIRST(slp)) != NULL) { - if (VOP_ISLOCKED(vp, NULL) == 0) { - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); - (void) VOP_FSYNC(vp, MNT_LAZY, td); - VOP_UNLOCK(vp, NULL, 0, td); - } - s = splbio(); - if (LIST_FIRST(slp) == vp) { - /* - * Note: v_tag VT_VFS vps can remain on the - * worklist too with no dirty blocks, but - * since sync_fsync() moves it to a different - * slot we are safe. - */ - if (TAILQ_EMPTY(&vp->v_dirtyblkhd) && - !vn_isdisk(vp, NULL)) - panic("sched_sync: fsync failed vp %p tag %d", vp, vp->v_tag); - /* - * Put us back on the worklist. The worklist - * routine will remove us from our current - * position and then add us back in at a later - * position. - */ - vn_syncer_add_to_worklist(vp, syncdelay); - } - splx(s); - } - - /* - * Do soft update processing. - */ - if (bioops.io_sync) - (*bioops.io_sync)(NULL); - - /* - * The variable rushjob allows the kernel to speed up the - * processing of the filesystem syncer process. A rushjob - * value of N tells the filesystem syncer to process the next - * N seconds worth of work on its queue ASAP. Currently rushjob - * is used by the soft update code to speed up the filesystem - * syncer process when the incore state is getting so far - * ahead of the disk that the kernel memory pool is being - * threatened with exhaustion. - */ - if (rushjob > 0) { - rushjob -= 1; - continue; - } - /* - * If it has taken us less than a second to process the - * current work, then wait. Otherwise start right over - * again. We can still lose time if any single round - * takes more than two seconds, but it does not really - * matter as we are just trying to generally pace the - * filesystem activity. - */ - if (time_second == starttime) - tsleep(&lbolt, 0, "syncer", 0); - } -} - -/* - * Request the syncer daemon to speed up its work. - * We never push it to speed up more than half of its - * normal turn time, otherwise it could take over the cpu. - * - * YYY wchan field protected by the BGL. - */ -int -speedup_syncer(void) -{ - crit_enter(); - if (updatethread->td_wchan == &lbolt) { /* YYY */ - unsleep(updatethread); - lwkt_schedule(updatethread); - } crit_exit(); - if (rushjob < syncdelay / 2) { - rushjob += 1; - stat_rush_requests += 1; - return (1); - } - return(0); + bp->b_vp = NULL; + vdrop(vp); } /* @@ -1386,7 +602,6 @@ reassignbuf(struct buf *bp, struct vnode *newvp) { struct buflists *listheadp; int delay; - int s; if (newvp == NULL) { printf("reassignbuf: NULL"); @@ -1401,7 +616,7 @@ reassignbuf(struct buf *bp, struct vnode *newvp) if (bp->b_flags & B_PAGING) panic("cannot reassign paging buffer"); - s = splbio(); + crit_enter(); /* * Delete from old vnode list, if on one. */ @@ -1508,7 +723,7 @@ reassignbuf(struct buf *bp, struct vnode *newvp) bp->b_vp = newvp; vhold(bp->b_vp); } - splx(s); + crit_exit(); } /* @@ -1534,611 +749,143 @@ bdevvp(dev_t dev, struct vnode **vpp) vp = nvp; vp->v_type = VCHR; vp->v_udev = dev->si_udev; + vx_unlock(vp); *vpp = vp; return (0); -} - -int -v_associate_rdev(struct vnode *vp, dev_t dev) -{ - lwkt_tokref ilock; - - if (dev == NULL || dev == NODEV) - return(ENXIO); - if (dev_is_good(dev) == 0) - return(ENXIO); - KKASSERT(vp->v_rdev == NULL); - if (dev_ref_debug) - printf("Z1"); - vp->v_rdev = reference_dev(dev); - lwkt_gettoken(&ilock, &spechash_token); - SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext); - lwkt_reltoken(&ilock); - return(0); -} - -void -v_release_rdev(struct vnode *vp) -{ - lwkt_tokref ilock; - dev_t dev; - - if ((dev = vp->v_rdev) != NULL) { - lwkt_gettoken(&ilock, &spechash_token); - SLIST_REMOVE(&dev->si_hlist, vp, vnode, v_specnext); - if (dev_ref_debug && vp->v_opencount != 0) { - printf("releasing rdev with non-0 " - "v_opencount(%d) (revoked?)\n", - vp->v_opencount); - } - vp->v_rdev = NULL; - vp->v_opencount = 0; - release_dev(dev); - lwkt_reltoken(&ilock); - } -} - -/* - * Add a vnode to the alias list hung off the dev_t. We only associate - * the device number with the vnode. The actual device is not associated - * until the vnode is opened (usually in spec_open()), and will be - * disassociated on last close. - */ -void -addaliasu(struct vnode *nvp, udev_t nvp_udev) -{ - if (nvp->v_type != VBLK && nvp->v_type != VCHR) - panic("addaliasu on non-special vnode"); - nvp->v_udev = nvp_udev; -} - -/* - * Grab a particular vnode from the free list, increment its - * reference count and lock it. The vnode lock bit is set if the - * vnode is being eliminated in vgone. The process is awakened - * 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(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. It is possible for the vnode to be - * self-referenced during the cleaning operation. - */ - if (vp->v_flag & VXLOCK) { - 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 recycled. The - * usecount needs to be bumped before we successfully get our lock. - */ - vp->v_usecount++; - if (flags & LK_TYPE_MASK) { - 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 - * drops back to zero since it was never really - * active. We must remove it from the free list - * before sleeping so that multiple processes do - * not try to recycle it. - */ - lwkt_gettokref(vlock); - vp->v_usecount--; - vmaybefree(vp); - lwkt_reltoken(vlock); - } - return (error); - } - if (VSHOULDBUSY(vp)) - vbusy(vp); /* interlock must be held on call */ - lwkt_reltoken(vlock); - return (0); -} - -void -vref(struct vnode *vp) -{ - crit_enter(); /* YYY use crit section for moment / BGL protected */ - vp->v_usecount++; - crit_exit(); -} - -/* - * Release a usecount on a vnode. This routine does not call unlock on the - * vnode. - * - * If the usecount drops to zero, call the inactive routine and return the - * vnode to the freelist. - */ -void -vrele(struct vnode *vp) -{ - struct thread *td = curthread; /* XXX */ - lwkt_tokref vlock; - - KASSERT(vp != NULL && vp->v_usecount >= 0, - ("vrele: null vp or <=0 v_usecount")); - - lwkt_gettoken(&vlock, vp->v_interlock); - - if (vp->v_usecount > 1) { - vp->v_usecount--; - lwkt_reltoken(&vlock); - return; - } - - if (vp->v_usecount == 1) { - vp->v_usecount--; - /* - * 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, NULL, LK_EXCLUSIVE, td) == 0) - VOP_INACTIVE(vp, td); - vmaybefree(vp); - lwkt_reltoken(&vlock); - } else { -#ifdef DIAGNOSTIC - vprint("vrele: negative ref count", vp); -#endif - lwkt_reltoken(&vlock); - panic("vrele: negative ref cnt"); - } -} - -/* - * Release a usecount on a vnode. This routine does not call unlock on the - * vnode. No action is taken if the usecount drops to zero. This routine - * is typically called only from within a *_inactive() procedure to avoid - * recursing the procedure. - */ -void -vrele_noinactive(struct vnode *vp) -{ - lwkt_tokref vlock; - - KASSERT(vp != NULL && vp->v_usecount >= 0, - ("vrele: null vp or <=0 v_usecount")); - - lwkt_gettoken(&vlock, vp->v_interlock); - vp->v_usecount--; - lwkt_reltoken(&vlock); -} - -/* - * Unlock a vnode and release a usecount on it, inactivating the vnode if - * the count drops to 0. - */ -void -vput(struct vnode *vp) -{ - struct thread *td = curthread; /* XXX */ - lwkt_tokref vlock; - - KASSERT(vp != NULL, ("vput: null vp")); - - lwkt_gettoken(&vlock, vp->v_interlock); - - if (vp->v_usecount > 1) { - vp->v_usecount--; - VOP_UNLOCK(vp, &vlock, LK_INTERLOCK, td); - 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, - * so we just need to release the vnode mutex. - */ - VOP_INACTIVE(vp, td); - 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. ZZZ vnode interlock should - * be held but isn't. - */ -void -vhold(struct vnode *vp) -{ - int s; - - s = splbio(); - vp->v_holdcnt++; - if (VSHOULDBUSY(vp)) - vbusy(vp); /* interlock must be held on call */ - splx(s); -} - -/* - * One less who cares about this vnode. - */ -void -vdrop(struct vnode *vp) -{ - lwkt_tokref vlock; - - lwkt_gettoken(&vlock, vp->v_interlock); - if (vp->v_holdcnt <= 0) - panic("vdrop: holdcnt"); - vp->v_holdcnt--; - 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); -} - -/* - * Remove any vnodes in the vnode table belonging to mount point mp. - * - * If FORCECLOSE is not specified, there should not be any active ones, - * return error if any are found (nb: this is a user error, not a - * system error). If FORCECLOSE is specified, detach any active vnodes - * that are found. - * - * If WRITECLOSE is set, only flush out regular file vnodes open for - * writing. - * - * SKIPSYSTEM causes any vnodes marked VSYSTEM to be skipped. - * - * `rootrefs' specifies the base reference count for the root vnode - * of this filesystem. The root vnode is considered busy if its - * v_usecount exceeds this value. On a successful return, vflush() - * will call vrele() on the root vnode exactly rootrefs times. - * If the SKIPSYSTEM or WRITECLOSE flags are specified, rootrefs must - * be zero. - */ -#ifdef DIAGNOSTIC -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(struct mount *mp, int rootrefs, int flags) +v_associate_rdev(struct vnode *vp, dev_t dev) { - struct thread *td = curthread; /* XXX */ - struct vnode *rootvp = NULL; - int error; - lwkt_tokref vlock; - struct vflush_info vflush_info; + lwkt_tokref ilock; - if (rootrefs > 0) { - KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0, - ("vflush: bad args")); - /* - * Get the filesystem root vnode. We can vput() it - * immediately, since with rootrefs > 0, it won't go away. - */ - if ((error = VFS_ROOT(mp, &rootvp)) != 0) - return (error); - vput(rootvp); - } + if (dev == NULL || dev == NODEV) + return(ENXIO); + if (dev_is_good(dev) == 0) + return(ENXIO); + KKASSERT(vp->v_rdev == NULL); + if (dev_ref_debug) + printf("Z1"); + vp->v_rdev = reference_dev(dev); + lwkt_gettoken(&ilock, &spechash_token); + SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext); + lwkt_reltoken(&ilock); + return(0); +} - vflush_info.busy = 0; - vflush_info.flags = flags; - vflush_info.td = td; - vmntvnodescan(mp, NULL, vflush_scan, &vflush_info); +void +v_release_rdev(struct vnode *vp) +{ + lwkt_tokref ilock; + dev_t dev; - 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(&vlock, rootvp->v_interlock); - KASSERT(vflush_info.busy > 0, ("vflush: not busy")); - KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs")); - if (vflush_info.busy == 1 && rootvp->v_usecount == rootrefs) { - vgonel(rootvp, &vlock, td); - vflush_info.busy = 0; - } else { - lwkt_reltoken(&vlock); + if ((dev = vp->v_rdev) != NULL) { + lwkt_gettoken(&ilock, &spechash_token); + SLIST_REMOVE(&dev->si_hlist, vp, vnode, v_specnext); + if (dev_ref_debug && vp->v_opencount != 0) { + printf("releasing rdev with non-0 " + "v_opencount(%d) (revoked?)\n", + vp->v_opencount); } + vp->v_rdev = NULL; + vp->v_opencount = 0; + release_dev(dev); + lwkt_reltoken(&ilock); } - if (vflush_info.busy) - return (EBUSY); - for (; rootrefs > 0; rootrefs--) - vrele(rootvp); - return (0); } /* - * The scan callback is made with an interlocked vnode. + * Add a vnode to the alias list hung off the dev_t. We only associate + * the device number with the vnode. The actual device is not associated + * until the vnode is opened (usually in spec_open()), and will be + * disassociated on last close. */ -static int -vflush_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +void +addaliasu(struct vnode *nvp, udev_t nvp_udev) { - struct vflush_info *info = data; - struct vattr vattr; - - /* - * Skip over a vnodes marked VSYSTEM. - */ - if ((info->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { - lwkt_reltoken(vlock); - return(0); - } - - /* - * If WRITECLOSE is set, flush out unlinked but still open - * files (even if open only for reading) and regular file - * vnodes open for writing. - */ - if ((info->flags & WRITECLOSE) && - (vp->v_type == VNON || - (VOP_GETATTR(vp, &vattr, info->td) == 0 && - vattr.va_nlink > 0)) && - (vp->v_writecount == 0 || vp->v_type != VREG)) { - lwkt_reltoken(vlock); - return(0); - } - - /* - * With v_usecount == 0, all we need to do is clear out the - * vnode data structures and we are done. - */ - if (vp->v_usecount == 0) { - vgonel(vp, vlock, info->td); - return(0); - } - - /* - * If FORCECLOSE is set, forcibly close the vnode. For block - * or character devices, revert to an anonymous device. For - * all other files, just kill them. - */ - if (info->flags & FORCECLOSE) { - if (vp->v_type != VBLK && vp->v_type != VCHR) { - vgonel(vp, vlock, info->td); - } else { - vclean(vp, vlock, 0, info->td); - vp->v_ops = spec_vnode_vops; - insmntque(vp, (struct mount *) 0); - } - return(0); - } -#ifdef DIAGNOSTIC - if (busyprt) - vprint("vflush: busy vnode", vp); -#endif - lwkt_reltoken(vlock); - ++info->busy; - return(0); + if (nvp->v_type != VBLK && nvp->v_type != VCHR) + panic("addaliasu on non-special vnode"); + nvp->v_udev = nvp_udev; } /* - * Disassociate the underlying file system from a vnode. + * Disassociate a vnode from its underlying filesystem. + * + * The vnode must be VX locked and refd + * + * If there are v_usecount references to the vnode other then ours we have + * to VOP_CLOSE the vnode before we can deactivate and reclaim it. */ -static void -vclean(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td) +void +vclean(struct vnode *vp, int flags, struct thread *td) { int active; /* - * Check to see if the vnode is in use. If so we have to reference it - * before we clean it out so that its count cannot fall to zero and - * generate a race against ourselves to recycle it. + * If the vnode has already been reclaimed we have nothing to do. */ - if ((active = vp->v_usecount)) - vp->v_usecount++; + if (vp->v_flag & VRECLAIMED) + return; + vp->v_flag |= VRECLAIMED; /* - * Prevent the vnode from being recycled or brought into use while we - * clean it out. + * Scrap the vfs cache */ - if (vp->v_flag & VXLOCK) - panic("vclean: deadlock"); - vp->v_flag |= VXLOCK; - vp->v_vxthread = curthread; + cache_inval_vp(vp, CINV_SELF); /* - * 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(). + * Check to see if the vnode is in use. If so we have to reference it + * before we clean it out so that its count cannot fall to zero and + * generate a race against ourselves to recycle it. */ - VOP_LOCK(vp, NULL, LK_DRAIN, td); + active = (vp->v_usecount > 1); /* - * Clean out any buffers associated with the vnode. + * Clean out any buffers associated with the vnode and destroy its + * object, if it has one. */ vinvalbuf(vp, V_SAVE, td, 0, 0); VOP_DESTROYVOBJECT(vp); /* * If purging an active vnode, it must be closed and - * deactivated before being reclaimed. Note that the - * VOP_INACTIVE will unlock the vnode. + * deactivated before being reclaimed. XXX + * + * Note that neither of these routines unlocks the vnode. */ if (active) { if (flags & DOCLOSE) VOP_CLOSE(vp, FNONBLOCK, td); + } + + /* + * If the vnode has not be deactivated, deactivated it. + */ + if ((vp->v_flag & VINACTIVE) == 0) { + vp->v_flag |= VINACTIVE; VOP_INACTIVE(vp, td); - } else { - /* - * Any other processes trying to obtain this lock must first - * wait for VXLOCK to clear, then call the new lock operation. - */ - VOP_UNLOCK(vp, NULL, 0, td); } + /* * Reclaim the vnode. */ if (VOP_RECLAIM(vp, td)) panic("vclean: cannot reclaim"); - if (active) { - /* - * Inline copy of vrele() since VOP_INACTIVE - * has already been called. - */ - if (--vp->v_usecount <= 0) { -#ifdef DIAGNOSTIC - if (vp->v_usecount < 0 || vp->v_writecount != 0) { - vprint("vclean: bad ref count", vp); - panic("vclean: ref cnt"); - } -#endif - vfree(vp); - } - } - - cache_inval_vp(vp, CINV_SELF); - vmaybefree(vp); - /* * Done with purge, notify sleepers of the grim news. */ vp->v_ops = dead_vnode_vops; vn_pollgone(vp); vp->v_tag = VT_NON; - vp->v_flag &= ~VXLOCK; - vp->v_vxthread = NULL; - if (vp->v_flag & VXWANT) { - vp->v_flag &= ~VXWANT; - wakeup((caddr_t) vp); - } - lwkt_reltoken(vlock); } /* * Eliminate all activity associated with the requested vnode * and with all vnodes aliased to the requested vnode. * + * The vnode must be referenced and vx_lock()'d + * * revoke { struct vnode *a_vp, int a_flags } */ int @@ -2151,21 +898,20 @@ vop_stdrevoke(struct vop_revoke_args *ap) KASSERT((ap->a_flags & REVOKEALL) != 0, ("vop_revoke")); vp = ap->a_vp; + /* - * If a vgone (or vclean) is already in progress, - * wait until it is done and return. + * If the vnode is already dead don't try to revoke it */ - if (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - /*lwkt_reltoken(vlock); ZZZ */ - tsleep((caddr_t)vp, 0, "vop_revokeall", 0); + if (vp->v_flag & VRECLAIMED) return (0); - } /* * If the vnode has a device association, scrap all vnodes associated * with the device. Don't let the device disappear on us while we * are scrapping the vnodes. + * + * The passed vp will probably show up in the list, do not VX lock + * it twice! */ if (vp->v_type != VCHR && vp->v_type != VBLK) return(0); @@ -2174,83 +920,72 @@ vop_stdrevoke(struct vop_revoke_args *ap) return(0); } reference_dev(dev); - for (;;) { - lwkt_gettoken(&ilock, &spechash_token); - vq = SLIST_FIRST(&dev->si_hlist); - lwkt_reltoken(&ilock); - if (vq == NULL) - break; - vgone(vq); + lwkt_gettoken(&ilock, &spechash_token); + while ((vq = SLIST_FIRST(&dev->si_hlist)) != NULL) { + if (vp == vq || vx_get(vq) == 0) { + if (vq == SLIST_FIRST(&dev->si_hlist)) + vgone(vq); + if (vp != vq) + vx_put(vq); + } } + lwkt_reltoken(&ilock); release_dev(dev); return (0); } /* * Recycle an unused vnode to the front of the free list. - * Release the passed interlock if the vnode will be recycled. + * + * Returns 1 if we were successfully able to recycle the vnode, + * 0 otherwise. */ int -vrecycle(struct vnode *vp, lwkt_tokref_t inter_lkp, struct thread *td) +vrecycle(struct vnode *vp, struct thread *td) { - lwkt_tokref vlock; - - lwkt_gettoken(&vlock, vp->v_interlock); - if (vp->v_usecount == 0) { - if (inter_lkp) - lwkt_reltoken(inter_lkp); - vgonel(vp, &vlock, td); + if (vp->v_usecount == 1) { + vgone(vp); return (1); } - lwkt_reltoken(&vlock); return (0); } /* - * Eliminate all activity associated with a vnode - * in preparation for reuse. + * Eliminate all activity associated with a vnode in preparation for reuse. + * + * The vnode must be VX locked and will remain VX locked on return. This + * routine may be called with the vnode in any state, as long as it is + * VX locked. The vnode will be cleaned out and marked VRECLAIMED but will + * not actually be reused until all existing refs and holds go away. + * + * NOTE: This routine may be called on a vnode which has not yet been + * already been deactivated (VOP_INACTIVE), or on a vnode which has + * already been reclaimed. + * + * This routine is not responsible for placing us back on the freelist. + * Instead, it happens automatically when the caller releases the VX lock + * (assuming there aren't any other references). */ void vgone(struct vnode *vp) { - struct thread *td = curthread; /* XXX */ - lwkt_tokref vlock; - - lwkt_gettoken(&vlock, vp->v_interlock); - vgonel(vp, &vlock, td); -} - -/* - * vgone, with the vp interlock held. - */ -void -vgonel(struct vnode *vp, lwkt_tokref_t vlock, struct thread *td) -{ - lwkt_tokref ilock; - int s; - /* - * If a vgone (or vclean) is already in progress, - * wait until it is done and return. + * assert that the VX lock is held. This is an absolute requirement + * now for vgone() to be called. */ - if (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - lwkt_reltoken(vlock); - tsleep((caddr_t)vp, 0, "vgone", 0); - return; - } + KKASSERT(vp->v_lock.lk_exclusivecount == 1); /* - * Clean out the filesystem specific data. + * Clean out the filesystem specific data and set the VRECLAIMED + * bit. Also deactivate the vnode if necessary. */ - vclean(vp, vlock, DOCLOSE, td); - lwkt_gettokref(vlock); + vclean(vp, DOCLOSE, curthread); /* * Delete from old mount point vnode list, if on one. */ if (vp->v_mount != NULL) - insmntque(vp, (struct mount *)0); + insmntque(vp, NULL); /* * If special device, remove it from special device alias list @@ -2263,29 +998,9 @@ vgonel(struct vnode *vp, lwkt_tokref_t vlock, struct thread *td) } /* - * If it is on the freelist and not already at the head, - * move it to the head of the list. The test of the - * VDOOMED flag and the reference count of zero is because - * it will be removed from the free list by getnewvnode, - * but will not have its reference count incremented until - * after calling vgone. If the reference count were - * incremented first, vgone would (incorrectly) try to - * close the previous instance of the underlying object. + * Set us to VBAD */ - if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) { - s = splbio(); - 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(&ilock); - splx(s); - } vp->v_type = VBAD; - lwkt_reltoken(vlock); } /* @@ -2375,14 +1090,8 @@ vprint(char *label, struct vnode *vp) strcat(buf, "|VTEXT"); if (vp->v_flag & VSYSTEM) strcat(buf, "|VSYSTEM"); - if (vp->v_flag & VXLOCK) - strcat(buf, "|VXLOCK"); - if (vp->v_flag & VXWANT) - strcat(buf, "|VXWANT"); if (vp->v_flag & VBWAIT) strcat(buf, "|VBWAIT"); - if (vp->v_flag & VDOOMED) - strcat(buf, "|VDOOMED"); if (vp->v_flag & VFREE) strcat(buf, "|VFREE"); if (vp->v_flag & VOBJBUF) @@ -2881,13 +1590,13 @@ vfs_export_lookup(struct mount *mp, struct netexport *nep, * 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); +static int vfs_msync_scan2(struct mount *mp, struct vnode *vp, void *data); void vfs_msync(struct mount *mp, int flags) { - vmntvnodescan(mp, vfs_msync_scan1, vfs_msync_scan2, (void *)flags); + vmntvnodescan(mp, VMSC_REFVP, vfs_msync_scan1, vfs_msync_scan2, + (void *)flags); } /* @@ -2901,45 +1610,40 @@ vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data) { int flags = (int)data; - if ((vp->v_flag & VXLOCK) == 0) { - if (VSHOULDFREE(vp)) - return(0); + if ((vp->v_flag & VRECLAIMED) == 0) { + if (vshouldfree(vp, 0)) + return(0); /* call scan2 */ if ((mp->mnt_flag & MNT_RDONLY) == 0 && (vp->v_flag & VOBJDIRTY) && (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) { - return(0); + return(0); /* call scan2 */ } } + + /* + * do not call scan2, continue the loop + */ return(-1); } static int -vfs_msync_scan2(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +vfs_msync_scan2(struct mount *mp, struct vnode *vp, void *data) { vm_object_t obj; - int error; int flags = (int)data; - if (vp->v_flag & VXLOCK) + if (vp->v_flag & VRECLAIMED) 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); + if (VOP_GETVOBJECT(vp, &obj) == 0) { + vm_object_page_clean(obj, 0, 0, + flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC); } - return(0); } - vmaybefree(vp); - lwkt_reltoken(vlock); return(0); } @@ -2957,56 +1661,6 @@ vfs_object_create(struct vnode *vp, struct thread *td) return (VOP_CREATEVOBJECT(vp, td)); } -/* - * 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) -{ - lwkt_tokref ilock; - - 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); - } - lwkt_reltoken(&ilock); -} - -/* - * 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) -{ - lwkt_tokref ilock; - - 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 @@ -3090,187 +1744,6 @@ vn_pollgone(struct vnode *vp) lwkt_reltoken(&ilock); } - - -/* - * Routine to create and manage a filesystem syncer vnode. - */ -#define sync_close ((int (*) (struct vop_close_args *))nullop) -static int sync_fsync (struct vop_fsync_args *); -static int sync_inactive (struct vop_inactive_args *); -static int sync_reclaim (struct vop_reclaim_args *); -#define sync_lock ((int (*) (struct vop_lock_args *))vop_stdlock) -#define sync_unlock ((int (*) (struct vop_unlock_args *))vop_stdunlock) -static int sync_print (struct vop_print_args *); -#define sync_islocked ((int(*) (struct vop_islocked_args *))vop_stdislocked) - -static struct vop_ops *sync_vnode_vops; -static struct vnodeopv_entry_desc sync_vnodeop_entries[] = { - { &vop_default_desc, vop_eopnotsupp }, - { &vop_close_desc, (void *) sync_close }, /* close */ - { &vop_fsync_desc, (void *) sync_fsync }, /* fsync */ - { &vop_inactive_desc, (void *) sync_inactive }, /* inactive */ - { &vop_reclaim_desc, (void *) sync_reclaim }, /* reclaim */ - { &vop_lock_desc, (void *) sync_lock }, /* lock */ - { &vop_unlock_desc, (void *) sync_unlock }, /* unlock */ - { &vop_print_desc, (void *) sync_print }, /* print */ - { &vop_islocked_desc, (void *) sync_islocked }, /* islocked */ - { NULL, NULL } -}; - -static struct vnodeopv_desc sync_vnodeop_opv_desc = - { &sync_vnode_vops, sync_vnodeop_entries }; - -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(struct mount *mp) -{ - struct vnode *vp; - static long start, incr, next; - int error; - - /* Allocate a new vnode */ - error = getnewvnode(VT_VFS, mp, sync_vnode_vops, &vp, 0, 0); - if (error) { - mp->mnt_syncer = NULL; - return (error); - } - vp->v_type = VNON; - /* - * Place the vnode onto the syncer worklist. We attempt to - * scatter them about on the list so that they will go off - * at evenly distributed times even if all the filesystems - * are mounted at once. - */ - next += incr; - if (next == 0 || next > syncer_maxdelay) { - start /= 2; - incr /= 2; - if (start == 0) { - start = syncer_maxdelay / 2; - incr = syncer_maxdelay; - } - next = start; - } - vn_syncer_add_to_worklist(vp, syncdelay > 0 ? next % syncdelay : 0); - mp->mnt_syncer = vp; - return (0); -} - -/* - * Do a lazy sync of the filesystem. - * - * sync_fsync { struct vnode *a_vp, struct ucred *a_cred, int a_waitfor, - * struct thread *a_td } - */ -static int -sync_fsync(struct vop_fsync_args *ap) -{ - struct vnode *syncvp = ap->a_vp; - struct mount *mp = syncvp->v_mount; - struct thread *td = ap->a_td; - lwkt_tokref ilock; - int asyncflag; - - /* - * We only need to do something if this is a lazy evaluation. - */ - if (ap->a_waitfor != MNT_LAZY) - return (0); - - /* - * Move ourselves to the back of the sync list. - */ - vn_syncer_add_to_worklist(syncvp, syncdelay); - - /* - * Walk the list of vnodes pushing all that are dirty and - * 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(&ilock, &mountlist_token); - if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &ilock, td) != 0) { - lwkt_reltoken(&ilock); - return (0); - } - 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); -} - -/* - * The syncer vnode is no referenced. - * - * sync_inactive { struct vnode *a_vp, struct proc *a_p } - */ -static int -sync_inactive(struct vop_inactive_args *ap) -{ - VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); - vgone(ap->a_vp); - return (0); -} - -/* - * The syncer vnode is no longer needed and is being decommissioned. - * - * Modifications to the worklist must be protected at splbio(). - * - * sync_reclaim { struct vnode *a_vp } - */ -static int -sync_reclaim(struct vop_reclaim_args *ap) -{ - struct vnode *vp = ap->a_vp; - int s; - - s = splbio(); - vp->v_mount->mnt_syncer = NULL; - if (vp->v_flag & VONWORKLST) { - LIST_REMOVE(vp, v_synclist); - vp->v_flag &= ~VONWORKLST; - } - splx(s); - - return (0); -} - -/* - * Print out a syncer vnode. - * - * sync_print { struct vnode *a_vp } - */ -static int -sync_print(struct vop_print_args *ap) -{ - struct vnode *vp = ap->a_vp; - - printf("syncer vnode"); - lockmgr_printinfo(&vp->v_lock); - printf("\n"); - return (0); -} - /* * extract the dev_t from a VBLK or VCHR. The vnode must have been opened * (or v_rdev might be NULL). @@ -3332,7 +1805,7 @@ NDFREE(struct nameidata *ndp, const uint 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, NULL, 0, ndp->ni_cnd.cn_td); + VOP_UNLOCK(ndp->ni_dvp, 0, ndp->ni_cnd.cn_td); } if (!(flags & NDF_NO_DVP_RELE) && (ndp->ni_cnd.cn_flags & (CNP_LOCKPARENT|CNP_WANTPARENT))) { @@ -3341,7 +1814,7 @@ NDFREE(struct nameidata *ndp, const uint flags) } if (!(flags & NDF_NO_VP_UNLOCK) && (ndp->ni_cnd.cn_flags & CNP_LOCKLEAF) && ndp->ni_vp) { - VOP_UNLOCK(ndp->ni_vp, NULL, 0, ndp->ni_cnd.cn_td); + VOP_UNLOCK(ndp->ni_vp, 0, ndp->ni_cnd.cn_td); } if (!(flags & NDF_NO_VP_RELE) && ndp->ni_vp) { diff --git a/sys/kern/vfs_sync.c b/sys/kern/vfs_sync.c new file mode 100644 index 0000000000..cae909b0ab --- /dev/null +++ b/sys/kern/vfs_sync.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)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_sync.c,v 1.1 2004/10/12 19:20:46 dillon Exp $ + */ + +/* + * External virtual filesystem routines + */ +#include "opt_ddb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * The workitem queue. + */ +#define SYNCER_MAXDELAY 32 +static int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */ +time_t syncdelay = 30; /* max time to delay syncing data */ +SYSCTL_INT(_kern, OID_AUTO, syncdelay, CTLFLAG_RW, + &syncdelay, 0, "VFS data synchronization delay"); +time_t filedelay = 30; /* time to delay syncing files */ +SYSCTL_INT(_kern, OID_AUTO, filedelay, CTLFLAG_RW, + &filedelay, 0, "File synchronization delay"); +time_t dirdelay = 29; /* time to delay syncing directories */ +SYSCTL_INT(_kern, OID_AUTO, dirdelay, CTLFLAG_RW, + &dirdelay, 0, "Directory synchronization delay"); +time_t metadelay = 28; /* time to delay syncing metadata */ +SYSCTL_INT(_kern, OID_AUTO, metadelay, CTLFLAG_RW, + &metadelay, 0, "VFS metadata synchronization delay"); +static int rushjob; /* number of slots to run ASAP */ +static int stat_rush_requests; /* number of times I/O speeded up */ +SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, + &stat_rush_requests, 0, ""); + +static int syncer_delayno = 0; +static long syncer_mask; +LIST_HEAD(synclist, vnode); +static struct synclist *syncer_workitem_pending; + +/* + * Called from vfsinit() + */ +void +vfs_sync_init(void) +{ + syncer_workitem_pending = hashinit(syncer_maxdelay, M_DEVBUF, + &syncer_mask); + syncer_maxdelay = syncer_mask + 1; +} + +/* + * The workitem queue. + * + * It is useful to delay writes of file data and filesystem metadata + * for tens of seconds so that quickly created and deleted files need + * not waste disk bandwidth being created and removed. To realize this, + * we append vnodes to a "workitem" queue. When running with a soft + * updates implementation, most pending metadata dependencies should + * not wait for more than a few seconds. Thus, mounted on block devices + * are delayed only about a half the time that file data is delayed. + * Similarly, directory updates are more critical, so are only delayed + * about a third the time that file data is delayed. Thus, there are + * SYNCER_MAXDELAY queues that are processed round-robin at a rate of + * one each second (driven off the filesystem syncer process). The + * syncer_delayno variable indicates the next queue that is to be processed. + * Items that need to be processed soon are placed in this queue: + * + * syncer_workitem_pending[syncer_delayno] + * + * A delay of fifteen seconds is done by placing the request fifteen + * entries later in the queue: + * + * syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask] + * + */ + +/* + * Add an item to the syncer work queue. + */ +void +vn_syncer_add_to_worklist(struct vnode *vp, int delay) +{ + int slot; + + crit_enter(); + + if (vp->v_flag & VONWORKLST) { + LIST_REMOVE(vp, v_synclist); + } + + if (delay > syncer_maxdelay - 2) + delay = syncer_maxdelay - 2; + slot = (syncer_delayno + delay) & syncer_mask; + + LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist); + vp->v_flag |= VONWORKLST; + crit_exit(); +} + +struct thread *updatethread; +static void sched_sync (void); +static struct kproc_desc up_kp = { + "syncer", + sched_sync, + &updatethread +}; +SYSINIT(syncer, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp) + +/* + * System filesystem synchronizer daemon. + */ +void +sched_sync(void) +{ + struct synclist *slp; + struct vnode *vp; + long starttime; + int s; + struct thread *td = curthread; + + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, td, + SHUTDOWN_PRI_LAST); + + for (;;) { + kproc_suspend_loop(); + + starttime = time_second; + + /* + * Push files whose dirty time has expired. Be careful + * of interrupt race on slp queue. + */ + s = splbio(); + slp = &syncer_workitem_pending[syncer_delayno]; + syncer_delayno += 1; + if (syncer_delayno == syncer_maxdelay) + syncer_delayno = 0; + splx(s); + + while ((vp = LIST_FIRST(slp)) != NULL) { + if (VOP_ISLOCKED(vp, NULL) == 0) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + (void) VOP_FSYNC(vp, MNT_LAZY, td); + VOP_UNLOCK(vp, 0, td); + } + s = splbio(); + if (LIST_FIRST(slp) == vp) { + /* + * Note: v_tag VT_VFS vps can remain on the + * worklist too with no dirty blocks, but + * since sync_fsync() moves it to a different + * slot we are safe. + */ + if (TAILQ_EMPTY(&vp->v_dirtyblkhd) && + !vn_isdisk(vp, NULL)) + panic("sched_sync: fsync failed vp %p tag %d", vp, vp->v_tag); + /* + * Put us back on the worklist. The worklist + * routine will remove us from our current + * position and then add us back in at a later + * position. + */ + vn_syncer_add_to_worklist(vp, syncdelay); + } + splx(s); + } + + /* + * Do soft update processing. + */ + if (bioops.io_sync) + (*bioops.io_sync)(NULL); + + /* + * The variable rushjob allows the kernel to speed up the + * processing of the filesystem syncer process. A rushjob + * value of N tells the filesystem syncer to process the next + * N seconds worth of work on its queue ASAP. Currently rushjob + * is used by the soft update code to speed up the filesystem + * syncer process when the incore state is getting so far + * ahead of the disk that the kernel memory pool is being + * threatened with exhaustion. + */ + if (rushjob > 0) { + rushjob -= 1; + continue; + } + /* + * If it has taken us less than a second to process the + * current work, then wait. Otherwise start right over + * again. We can still lose time if any single round + * takes more than two seconds, but it does not really + * matter as we are just trying to generally pace the + * filesystem activity. + */ + if (time_second == starttime) + tsleep(&lbolt, 0, "syncer", 0); + } +} + +/* + * Request the syncer daemon to speed up its work. + * We never push it to speed up more than half of its + * normal turn time, otherwise it could take over the cpu. + * + * YYY wchan field protected by the BGL. + */ +int +speedup_syncer(void) +{ + crit_enter(); + if (updatethread->td_wchan == &lbolt) { /* YYY */ + unsleep(updatethread); + lwkt_schedule(updatethread); + } + crit_exit(); + if (rushjob < syncdelay / 2) { + rushjob += 1; + stat_rush_requests += 1; + return (1); + } + return(0); +} + +/* + * Routine to create and manage a filesystem syncer vnode. + */ +#define sync_close ((int (*) (struct vop_close_args *))nullop) +static int sync_fsync (struct vop_fsync_args *); +static int sync_inactive (struct vop_inactive_args *); +static int sync_reclaim (struct vop_reclaim_args *); +#define sync_lock ((int (*) (struct vop_lock_args *))vop_stdlock) +#define sync_unlock ((int (*) (struct vop_unlock_args *))vop_stdunlock) +static int sync_print (struct vop_print_args *); +#define sync_islocked ((int(*) (struct vop_islocked_args *))vop_stdislocked) + +static struct vop_ops *sync_vnode_vops; +static struct vnodeopv_entry_desc sync_vnodeop_entries[] = { + { &vop_default_desc, vop_eopnotsupp }, + { &vop_close_desc, (void *) sync_close }, /* close */ + { &vop_fsync_desc, (void *) sync_fsync }, /* fsync */ + { &vop_inactive_desc, (void *) sync_inactive }, /* inactive */ + { &vop_reclaim_desc, (void *) sync_reclaim }, /* reclaim */ + { &vop_lock_desc, (void *) sync_lock }, /* lock */ + { &vop_unlock_desc, (void *) sync_unlock }, /* unlock */ + { &vop_print_desc, (void *) sync_print }, /* print */ + { &vop_islocked_desc, (void *) sync_islocked }, /* islocked */ + { NULL, NULL } +}; + +static struct vnodeopv_desc sync_vnodeop_opv_desc = + { &sync_vnode_vops, sync_vnodeop_entries }; + +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(struct mount *mp) +{ + struct vnode *vp; + static long start, incr, next; + int error; + + /* Allocate a new vnode */ + error = getnewvnode(VT_VFS, mp, sync_vnode_vops, &vp, 0, 0); + if (error) { + mp->mnt_syncer = NULL; + return (error); + } + vp->v_type = VNON; + /* + * Place the vnode onto the syncer worklist. We attempt to + * scatter them about on the list so that they will go off + * at evenly distributed times even if all the filesystems + * are mounted at once. + */ + next += incr; + if (next == 0 || next > syncer_maxdelay) { + start /= 2; + incr /= 2; + if (start == 0) { + start = syncer_maxdelay / 2; + incr = syncer_maxdelay; + } + next = start; + } + vn_syncer_add_to_worklist(vp, syncdelay > 0 ? next % syncdelay : 0); + mp->mnt_syncer = vp; + vx_unlock(vp); + return (0); +} + +/* + * Do a lazy sync of the filesystem. + * + * sync_fsync { struct vnode *a_vp, struct ucred *a_cred, int a_waitfor, + * struct thread *a_td } + */ +static int +sync_fsync(struct vop_fsync_args *ap) +{ + struct vnode *syncvp = ap->a_vp; + struct mount *mp = syncvp->v_mount; + struct thread *td = ap->a_td; + lwkt_tokref ilock; + int asyncflag; + + /* + * We only need to do something if this is a lazy evaluation. + */ + if (ap->a_waitfor != MNT_LAZY) + return (0); + + /* + * Move ourselves to the back of the sync list. + */ + vn_syncer_add_to_worklist(syncvp, syncdelay); + + /* + * Walk the list of vnodes pushing all that are dirty and + * 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(&ilock, &mountlist_token); + if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &ilock, td) != 0) { + lwkt_reltoken(&ilock); + return (0); + } + 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); +} + +/* + * The syncer vnode is no referenced. + * + * sync_inactive { struct vnode *a_vp, struct proc *a_p } + */ +static int +sync_inactive(struct vop_inactive_args *ap) +{ + vgone(ap->a_vp); + return (0); +} + +/* + * The syncer vnode is no longer needed and is being decommissioned. + * + * Modifications to the worklist must be protected at splbio(). + * + * sync_reclaim { struct vnode *a_vp } + */ +static int +sync_reclaim(struct vop_reclaim_args *ap) +{ + struct vnode *vp = ap->a_vp; + int s; + + s = splbio(); + vp->v_mount->mnt_syncer = NULL; + if (vp->v_flag & VONWORKLST) { + LIST_REMOVE(vp, v_synclist); + vp->v_flag &= ~VONWORKLST; + } + splx(s); + + return (0); +} + +/* + * Print out a syncer vnode. + * + * sync_print { struct vnode *a_vp } + */ +static int +sync_print(struct vop_print_args *ap) +{ + struct vnode *vp = ap->a_vp; + + printf("syncer vnode"); + lockmgr_printinfo(&vp->v_lock); + printf("\n"); + return (0); +} + diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 2712bc1369..6737631764 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.44 2004/10/07 04:20:26 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.45 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -111,7 +111,6 @@ mount(struct mount_args *uap) struct vattr va; struct nlookupdata nd; char fstypename[MFSNAMELEN]; - lwkt_tokref vlock; lwkt_tokref ilock; struct nlcomponent nlc; @@ -160,7 +159,7 @@ mount(struct mount_args *uap) * now we have the locked ref'd ncp and unreferenced vnode. */ vp = ncp->nc_vp; - if ((error = vget(vp, NULL, LK_EXCLUSIVE, td)) != 0) { + if ((error = vget(vp, LK_EXCLUSIVE, td)) != 0) { cache_put(ncp); return (error); } @@ -203,20 +202,17 @@ mount(struct mount_args *uap) vput(vp); return (EBUSY); } - lwkt_gettoken(&vlock, vp->v_interlock); if ((vp->v_flag & VMOUNT) != 0 || vp->v_mountedhere != NULL) { cache_drop(ncp); - lwkt_reltoken(&vlock); vfs_unbusy(mp, td); vput(vp); return (EBUSY); } vp->v_flag |= VMOUNT; - lwkt_reltoken(&vlock); mp->mnt_flag |= SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); goto update; } /* @@ -280,16 +276,13 @@ mount(struct mount_args *uap) return (ENODEV); } } - lwkt_gettoken(&vlock, vp->v_interlock); if ((vp->v_flag & VMOUNT) != 0 || vp->v_mountedhere != NULL) { - lwkt_reltoken(&vlock); cache_drop(ncp); vput(vp); return (EBUSY); } vp->v_flag |= VMOUNT; - lwkt_reltoken(&vlock); /* * Allocate and initialize the filesystem. @@ -309,7 +302,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); update: /* * Set the mount level flags. @@ -342,14 +335,12 @@ update: mp->mnt_kern_flag = flag2; } vfs_unbusy(mp, td); - lwkt_gettoken(&vlock, vp->v_interlock); vp->v_flag &= ~VMOUNT; - lwkt_reltoken(&vlock); vrele(vp); cache_drop(ncp); return (error); } - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* * Put the new filesystem on the mount list after root. The mount * point gets its own mnt_ncp which is a special ncp linking the @@ -369,16 +360,14 @@ update: mp->mnt_ncp->nc_mount = mp; cache_drop(ncp); /* XXX get the root of the fs and cache_setvp(mnt_ncp...) */ - lwkt_gettoken(&vlock, vp->v_interlock); vp->v_flag &= ~VMOUNT; vp->v_mountedhere = mp; - lwkt_reltoken(&vlock); lwkt_gettoken(&ilock, &mountlist_token); TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); lwkt_reltoken(&ilock); checkdirs(vp, mp->mnt_ncp); cache_unlock(mp->mnt_ncp); /* leave ref intact */ - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); error = vfs_allocate_syncvnode(mp); vfs_unbusy(mp, td); if ((error = VFS_START(mp, 0, td)) != 0) @@ -387,9 +376,7 @@ update: vfs_rm_vnodeops(&mp->mnt_vn_ops); vfs_rm_vnodeops(&mp->mnt_vn_spec_ops); vfs_rm_vnodeops(&mp->mnt_vn_fifo_ops); - lwkt_gettoken(&vlock, vp->v_interlock); vp->v_flag &= ~VMOUNT; - lwkt_reltoken(&vlock); mp->mnt_vfc->vfc_refcount--; vfs_unbusy(mp, td); free(mp, M_MOUNT); @@ -851,7 +838,7 @@ fchdir(struct fchdir_args *uap) return (error); vp = (struct vnode *)fp->f_data; vref(vp); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type != VDIR || fp->f_ncp == NULL) error = ENOTDIR; else @@ -867,7 +854,7 @@ fchdir(struct fchdir_args *uap) cache_unlock(nct); /* leave ref intact */ vput(vp); vp = nct->nc_vp; - error = vget(vp, NULL, LK_SHARED, td); + error = vget(vp, LK_SHARED, td); KKASSERT(error == 0); cache_drop(ncp); ncp = nct; @@ -876,7 +863,7 @@ fchdir(struct fchdir_args *uap) if (error == 0) { ovp = fdp->fd_cdir; oncp = fdp->fd_ncdir; - VOP_UNLOCK(vp, NULL, 0, td); /* leave ref intact */ + VOP_UNLOCK(vp, 0, td); /* leave ref intact */ fdp->fd_cdir = vp; fdp->fd_ncdir = ncp; cache_drop(oncp); @@ -902,11 +889,11 @@ kern_chdir(struct nlookupdata *nd) return (error); if ((vp = nd->nl_ncp->nc_vp) == NULL) return (ENOENT); - if ((error = vget(vp, NULL, LK_SHARED, td)) != 0) + if ((error = vget(vp, LK_SHARED, td)) != 0) return (error); error = checkvp_chdir(vp, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (error == 0) { ovp = fdp->fd_cdir; oncp = fdp->fd_ncdir; @@ -1015,7 +1002,7 @@ kern_chroot(struct nlookupdata *nd) if ((vp = ncp->nc_vp) == NULL) return (ENOENT); - if ((error = vget(vp, NULL, LK_SHARED, td)) != 0) + if ((error = vget(vp, LK_SHARED, td)) != 0) return (error); /* @@ -1023,7 +1010,7 @@ kern_chroot(struct nlookupdata *nd) * associate it with rdir/jdir. */ error = checkvp_chdir(vp, td); - VOP_UNLOCK(vp, NULL, 0, td); /* leave reference intact */ + VOP_UNLOCK(vp, 0, td); /* leave reference intact */ if (error == 0) { vrele(fdp->fd_rdir); fdp->fd_rdir = vp; /* reference inherited by fd_rdir */ @@ -1165,7 +1152,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); vn_close(vp, flags & FMASK, td); fdrop(fp, td); *res = indx; @@ -1188,7 +1175,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { /* * lock request failed. Normally close the descriptor @@ -1204,13 +1191,13 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res) nlookup_done(&ndx); return (error); } - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* * If the vp is a directory locate the ncp to store with the file @@ -1597,7 +1584,7 @@ kern_unlink(struct nameidata *nd) return (error); vp = nd->ni_vp; VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EPERM; /* POSIX */ @@ -1778,7 +1765,7 @@ kern_stat(struct nlookupdata *nd, struct stat *st) return (ENOENT); td = curthread; - if ((error = vget(vp, NULL, LK_SHARED, td)) != 0) + if ((error = vget(vp, LK_SHARED, td)) != 0) return (error); error = vn_stat(vp, st, td); vput(vp); @@ -2013,11 +2000,11 @@ setfflags(struct vnode *vp, int flags) return (error); VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); VATTR_NULL(&vattr); vattr.va_flags = flags; error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -2072,11 +2059,11 @@ setfmode(struct vnode *vp, int mode) struct vattr vattr; VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return error; } @@ -2164,12 +2151,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return error; } @@ -2270,14 +2257,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return error; } @@ -2406,7 +2393,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0 && @@ -2456,7 +2443,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0) { @@ -2464,7 +2451,7 @@ kern_ftruncate(int fd, off_t length) vattr.va_size = length; error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -2502,14 +2489,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -2782,12 +2769,12 @@ unionread: auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; auio.uio_resid = count; - /* vn_lock(vp, NULL, LK_SHARED | LK_RETRY, td); */ - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (error) return (error); if (count == auio.uio_resid) { @@ -2900,8 +2887,12 @@ revoke(struct revoke_args *uap) if (p->p_ucred->cr_uid != vattr.va_uid && (error = suser_cred(p->p_ucred, PRISON_ROOT))) goto out; - if (count_udev(vp->v_udev) > 0) - VOP_REVOKE(vp, REVOKEALL); + if (count_udev(vp->v_udev) > 0) { + if ((error = vx_lock(vp)) == 0) { + VOP_REVOKE(vp, REVOKEALL); + vx_unlock(vp); + } + } out: vrele(vp); return (error); @@ -3044,9 +3035,9 @@ fhopen(struct fhopen_args *uap) goto bad; } if (fmode & O_TRUNC) { - VOP_UNLOCK(vp, NULL, 0, td); /* XXX */ + VOP_UNLOCK(vp, 0, td); /* XXX */ VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ VATTR_NULL(vap); vap->va_size = 0; error = VOP_SETATTR(vp, vap, p->p_ucred, td); @@ -3097,7 +3088,7 @@ fhopen(struct fhopen_args *uap) type = F_FLOCK; if ((fmode & FNONBLOCK) == 0) type |= F_WAIT; - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { /* * lock request failed. Normally close the descriptor @@ -3115,13 +3106,13 @@ fhopen(struct fhopen_args *uap) fdrop(fp, td); return (error); } - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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, NULL, 0, td); + VOP_UNLOCK(vp, 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 f18d0357c0..a6f76aa51d 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.22 2004/06/15 00:30:53 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.23 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -174,9 +174,9 @@ vn_open(ndp, fmode, cmode) } } if (fmode & O_TRUNC) { - VOP_UNLOCK(vp, NULL, 0, td); /* XXX */ + VOP_UNLOCK(vp, 0, td); /* XXX */ VOP_LEASE(vp, td, cred, LEASE_WRITE); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ VATTR_NULL(vap); vap->va_size = 0; error = VOP_SETATTR(vp, vap, cred, td); @@ -232,7 +232,10 @@ vn_close(struct vnode *vp, int flags, struct thread *td) if (flags & FWRITE) vp->v_writecount--; - error = VOP_CLOSE(vp, flags, td); + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) == 0) { + error = VOP_CLOSE(vp, flags, td); + VOP_UNLOCK(vp, 0, td); + } vrele(vp); return (error); } @@ -294,7 +297,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td) int error; if ((ioflg & IO_NODELOCKED) == 0) - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; @@ -315,7 +318,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -393,7 +396,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, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td); if ((flags & FOF_OFFSET) == 0) uio->uio_offset = fp->f_offset; @@ -403,7 +406,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -438,7 +441,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if ((flags & FOF_OFFSET) == 0) uio->uio_offset = fp->f_offset; ioflag |= sequential_heuristic(uio, fp); @@ -446,7 +449,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, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (error); } @@ -649,42 +652,33 @@ vn_poll(struct file *fp, int events, struct ucred *cred, struct thread *td) */ int #ifndef DEBUG_LOCKS -vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td) +vn_lock(struct vnode *vp, int flags, struct thread *td) #else -debug_vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, - struct thread *td, const char *filename, int line) +debug_vn_lock(struct vnode *vp, int flags, struct thread *td, + const char *filename, int line) #endif { int error; - lwkt_tokref vvlock; do { - 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(vlock); - tsleep((caddr_t)vp, 0, "vn_lock", 0); - error = ENOENT; - } else { -#if 0 - /* this can now occur in normal operation */ - 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; + vp->filename = filename; + vp->line = line; #endif - error = VOP_LOCK(vp, vlock, - flags | LK_NOPAUSE | LK_INTERLOCK, td); - if (error == 0) - return (0); - } - flags &= ~LK_INTERLOCK; + error = VOP_LOCK(vp, flags | LK_NOPAUSE, td); + if (error == 0) + break; } while (flags & LK_RETRY); + + /* + * Because we (had better!) have a ref on the vnode, once it + * goes to VRECLAIMED state it will not be recycled until all + * refs go away. So we can just check the flag. + */ + if (error == 0 && (vp->v_flag & VRECLAIMED)) { + VOP_UNLOCK(vp, 0, td); + error = ENOENT; + } return (error); } diff --git a/sys/kern/vfs_vopops.c b/sys/kern/vfs_vopops.c index 7070c8510c..d6b4d6fa12 100644 --- a/sys/kern/vfs_vopops.c +++ b/sys/kern/vfs_vopops.c @@ -32,7 +32,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.8 2004/09/30 18:59:48 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.9 2004/10/12 19:20:46 dillon Exp $ */ #include @@ -841,8 +841,7 @@ vop_reclaim(struct vop_ops *ops, struct vnode *vp, struct thread *td) } int -vop_lock(struct vop_ops *ops, struct vnode *vp, struct lwkt_tokref *vlock, - int flags, struct thread *td) +vop_lock(struct vop_ops *ops, struct vnode *vp, int flags, struct thread *td) { struct vop_lock_args ap; int error; @@ -850,7 +849,6 @@ vop_lock(struct vop_ops *ops, struct vnode *vp, struct lwkt_tokref *vlock, ap.a_head.a_desc = &vop_lock_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; - ap.a_vlock = vlock; ap.a_flags = flags; ap.a_td = td; @@ -859,8 +857,7 @@ vop_lock(struct vop_ops *ops, struct vnode *vp, struct lwkt_tokref *vlock, } int -vop_unlock(struct vop_ops *ops, struct vnode *vp, struct lwkt_tokref *vlock, - int flags, struct thread *td) +vop_unlock(struct vop_ops *ops, struct vnode *vp, int flags, struct thread *td) { struct vop_unlock_args ap; int error; @@ -868,7 +865,6 @@ vop_unlock(struct vop_ops *ops, struct vnode *vp, struct lwkt_tokref *vlock, ap.a_head.a_desc = &vop_unlock_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; - ap.a_vlock = vlock; ap.a_flags = flags; ap.a_td = td; diff --git a/sys/sys/namecache.h b/sys/sys/namecache.h index 2759fc258b..0f94fbb64a 100644 --- a/sys/sys/namecache.h +++ b/sys/sys/namecache.h @@ -62,7 +62,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/namecache.h,v 1.12 2004/10/05 03:24:21 dillon Exp $ + * $DragonFly: src/sys/sys/namecache.h,v 1.13 2004/10/12 19:20:48 dillon Exp $ */ #ifndef _SYS_NAMECACHE_H_ @@ -155,7 +155,7 @@ int cache_lookup(struct vnode *dvp, struct vnode **vpp, void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp); struct namecache *cache_nlookup(struct namecache *par, struct nlcomponent *nlc); -struct namecache *cache_allocroot(struct vnode *vp); +struct namecache *cache_allocroot(struct mount *mp, struct vnode *vp); void cache_inval(struct namecache *ncp, int flags); void cache_inval_vp(struct vnode *vp, int flags); void vfs_cache_setroot(struct vnode *vp, struct namecache *ncp); @@ -163,11 +163,11 @@ void vfs_cache_setroot(struct vnode *vp, struct namecache *ncp); int cache_resolve(struct namecache *ncp, struct ucred *cred); void cache_purge(struct vnode *vp); void cache_purgevfs (struct mount *mp); +int cache_get_nonblock(struct namecache *ncp); struct namecache *cache_get(struct namecache *ncp); struct namecache *cache_hold(struct namecache *ncp); void cache_put(struct namecache *ncp); void cache_drop(struct namecache *ncp); -int cache_leaf_test (struct vnode *vp); int vfs_cache_lookup(struct vop_lookup_args *ap); int cache_vget(struct namecache *, struct ucred *, int, struct vnode **); int cache_vref(struct namecache *, struct ucred *, struct vnode **); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 53fc7197f2..9dcb8fb5f0 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -37,7 +37,7 @@ * * @(#)systm.h 8.7 (Berkeley) 3/29/95 * $FreeBSD: src/sys/sys/systm.h,v 1.111.2.18 2002/12/17 18:04:02 sam Exp $ - * $DragonFly: src/sys/sys/systm.h,v 1.23 2004/09/30 18:59:50 dillon Exp $ + * $DragonFly: src/sys/sys/systm.h,v 1.24 2004/10/12 19:20:48 dillon Exp $ */ #ifndef _SYS_SYSTM_H_ @@ -217,7 +217,6 @@ void consinit (void); void cpu_initclocks (void); void nchinit (void); void usrinfoinit (void); -void vntblinit (void); /* Finalize the world. */ void shutdown_nice (int); diff --git a/sys/sys/tty.h b/sys/sys/tty.h index c55c12e30e..1ff1c85856 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -37,7 +37,7 @@ * * @(#)tty.h 8.6 (Berkeley) 1/21/94 * $FreeBSD: src/sys/sys/tty.h,v 1.53.2.1 2001/02/26 04:23:21 jlemon Exp $ - * $DragonFly: src/sys/sys/tty.h,v 1.6 2004/09/13 16:22:41 dillon Exp $ + * $DragonFly: src/sys/sys/tty.h,v 1.7 2004/10/12 19:20:48 dillon Exp $ */ #ifndef _SYS_TTY_H_ @@ -253,6 +253,7 @@ void ttychars (struct tty *tp); int ttycheckoutq (struct tty *tp, int wait); int ttyclose (struct tty *tp); void ttyclearsession (struct tty *tp); +void ttyclosesession (struct session *, int); void ttyflush (struct tty *tp, int rw); void ttyfree (struct tty *tp); void ttyinfo (struct tty *tp); diff --git a/sys/sys/vfsops.h b/sys/sys/vfsops.h index 62243ddc17..1996b4d804 100644 --- a/sys/sys/vfsops.h +++ b/sys/sys/vfsops.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/vfsops.h,v 1.7 2004/09/30 18:59:50 dillon Exp $ + * $DragonFly: src/sys/sys/vfsops.h,v 1.8 2004/10/12 19:20:48 dillon Exp $ */ /* @@ -339,7 +339,6 @@ struct vop_reclaim_args { struct vop_lock_args { struct vop_generic_args a_head; struct vnode *a_vp; - struct lwkt_tokref *a_vlock; int a_flags; struct thread *a_td; }; @@ -347,7 +346,6 @@ struct vop_lock_args { struct vop_unlock_args { struct vop_generic_args a_head; struct vnode *a_vp; - struct lwkt_tokref *a_vlock; int a_flags; struct thread *a_td; }; @@ -744,9 +742,9 @@ int vop_readlink(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int vop_inactive(struct vop_ops *ops, struct vnode *vp, struct thread *td); int vop_reclaim(struct vop_ops *ops, struct vnode *vp, struct thread *td); int vop_lock(struct vop_ops *ops, struct vnode *vp, - struct lwkt_tokref *vlock, int flags, struct thread *td); + int flags, struct thread *td); int vop_unlock(struct vop_ops *ops, struct vnode *vp, - struct lwkt_tokref *vlock, int flags, struct thread *td); + int flags, struct thread *td); int vop_bmap(struct vop_ops *ops, struct vnode *vp, daddr_t bn, struct vnode **vpp, daddr_t *bnp, int *runp, int *runb); int vop_strategy(struct vop_ops *ops, struct vnode *vp, struct buf *bp); @@ -979,10 +977,10 @@ extern struct vnodeop_desc vop_vfsset_desc; vop_inactive((vp)->v_ops, vp, td) #define VOP_RECLAIM(vp, td) \ vop_reclaim((vp)->v_ops, vp, td) -#define VOP_LOCK(vp, vlock, flags, td) \ - vop_lock((vp)->v_ops, vp, vlock, flags, td) -#define VOP_UNLOCK(vp, vlock, flags, td) \ - vop_unlock((vp)->v_ops, vp, vlock, flags, td) +#define VOP_LOCK(vp, flags, td) \ + vop_lock((vp)->v_ops, vp, flags, td) +#define VOP_UNLOCK(vp, flags, td) \ + vop_unlock((vp)->v_ops, vp, flags, td) #define VOP_BMAP(vp, bn, vpp, bnp, runp, runb) \ vop_bmap((vp)->v_ops, vp, bn, vpp, bnp, runp, runb) #define VOP_STRATEGY(vp, bp) \ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index d5e6afce5a..7ab06a2d4e 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.24 2004/10/07 01:13:20 dillon Exp $ + * $DragonFly: src/sys/sys/vnode.h,v 1.25 2004/10/12 19:20:48 dillon Exp $ */ #ifndef _SYS_VNODE_H_ @@ -116,7 +116,6 @@ 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 */ - lwkt_token_t v_interlock; /* lock on usecount and flag */ struct lock v_lock; /* file/dir ops lock */ enum vtagtype v_tag; /* type of underlying data */ void *v_data; /* private data for fs */ @@ -127,12 +126,12 @@ struct vnode { short vpi_events; /* what they are looking for */ short vpi_revents; /* what has happened */ } v_pollinfo; - struct thread *v_vxthread; /* thread owning VXLOCK */ struct vmresident *v_resident; /* optional vmresident */ #ifdef DEBUG_LOCKS const char *filename; /* Source file doing locking */ int line; /* Line number doing locking */ #endif + void *v_xaddr; }; #define v_mountedhere v_un.vu_mountedhere #define v_socket v_un.vu_socket @@ -154,24 +153,36 @@ struct vnode { #define VTEXT 0x00002 /* vnode is a pure text prototype */ #define VSYSTEM 0x00004 /* vnode being used by kernel */ #define VISTTY 0x00008 /* vnode represents a tty */ -#define VXLOCK 0x00100 /* vnode is locked to change underlying type */ -#define VXWANT 0x00200 /* process is waiting for vnode */ +#define VCTTYISOPEN 0x00010 /* controlling terminal tty is open */ +/* open for business 0x00020 */ +/* open for business 0x00040 */ +/* open for business 0x00080 */ +/* open for business 0x00100 */ +/* open for business 0x00200 */ #define VBWAIT 0x00400 /* waiting for output to complete */ /* open for business 0x00800 */ /* open for business 0x01000 */ #define VOBJBUF 0x02000 /* Allocate buffers in VM object */ -/* open for business 0x04000 */ +#define VINACTIVE 0x04000 /* The vnode is inactive */ #define VAGE 0x08000 /* Insert vnode at head of free list */ #define VOLOCK 0x10000 /* vnode is locked waiting for an object */ #define VOWANT 0x20000 /* a process is waiting for VOLOCK */ -#define VDOOMED 0x40000 /* This vnode is being recycled */ +#define VRECLAIMED 0x40000 /* This vnode has been destroyed */ #define VFREE 0x80000 /* This vnode is on the freelist */ -#define VINFREE 0x100000 /* This vnode is in the midst of being freed */ +/* open for business 0x100000 */ #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 */ +/* + * vmntvnodescan() flags + */ +#define VMSC_GETVP 1 +#define VMSC_GETVX 2 +#define VMSC_REFVP 3 +#define VMSC_NOWAIT 0x10 + /* * Flags for ioflag. (high 16 bits used to ask for read-ahead and * help with write clustering) @@ -220,10 +231,6 @@ struct vnode { #ifdef _KERNEL -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_VNODE); -#endif - /* * Convert between vnode types and inode formats (since POSIX.1 * defines mode word of stat structure in terms of inode formats). @@ -270,6 +277,8 @@ extern struct vm_zone *namei_zone; extern int prtactive; /* nonzero to call vprint() */ extern struct vattr va_null; /* predefined null vattr structure */ extern int vfs_ioopt; +extern int numvnodes; +extern int freevnodes; /* * Macro/function to check for client cache inconsistency w.r.t. leasing. @@ -280,9 +289,6 @@ extern int vfs_ioopt; extern void (*lease_updatetime) (int deltat); -#define VI_LOCK(vlock, vp) lwkt_gettoken(vlock, (vp)->v_interlock) -#define VI_UNLOCK(vlock, vp) lwkt_reltoken(vlock) - #endif /* _KERNEL */ /* @@ -510,6 +516,9 @@ void v_release_rdev(struct vnode *vp); int bdevvp (dev_t dev, struct vnode **vpp); void cvtstat (struct stat *st, struct ostat *ost); void cvtnstat (struct stat *sb, struct nstat *nsb); +struct vnode *allocvnode(int lktimeout, int lkflags); +struct vnode *allocvnode_placemarker(void); +void freevnode_placemarker(struct vnode *); int getnewvnode (enum vtagtype tag, struct mount *mp, struct vop_ops *ops, struct vnode **vpp, int timo, int lkflags); int lease_check (struct vop_lease_args *ap); @@ -517,36 +526,33 @@ int spec_vnoperate (struct vop_generic_args *); int speedup_syncer (void); void vattr_null (struct vattr *vap); int vcount (struct vnode *vp); -void vdrop (struct vnode *); int vfinddev (dev_t dev, enum vtype type, struct vnode **vpp); void vfs_add_vnodeops_sysinit (const void *); void vfs_rm_vnodeops_sysinit (const void *); void vfs_add_vnodeops(struct vop_ops **, struct vnodeopv_entry_desc *); void vfs_rm_vnodeops(struct vop_ops **); int vflush (struct mount *mp, int rootrefs, int flags); -int vmntvnodescan(struct mount *mp, +int vmntvnodescan(struct mount *mp, int flags, 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 (*slowfunc)(struct mount *mp, struct vnode *vp, void *data), + void *data); +void insmntque(struct vnode *vp, struct mount *mp); -int vget (struct vnode *vp, lwkt_tokref_t vlock, int lockflag, struct thread *td); +void vclean (struct vnode *vp, int flags, struct thread *td); void vgone (struct vnode *vp); -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_tokref *inter_lkp, - struct thread *td); +int vrecycle (struct vnode *vp, 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, lwkt_tokref_t vlock, int flags, struct thread *td); +int vn_lock (struct vnode *vp, int flags, struct thread *td); #ifdef DEBUG_LOCKS -int debug_vn_lock (struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td, +int debug_vn_lock (struct vnode *vp, int flags, struct thread *td, const char *filename, int line); -#define vn_lock(vp,vlock,flags,p) debug_vn_lock(vp,vlock,flags,p,__FILE__,__LINE__) +#define vn_lock(vp,flags,p) debug_vn_lock(vp,flags,p,__FILE__,__LINE__) #endif int vn_fullpath (struct proc *p, struct vnode *vn, char **retbuf, char **freebuf); @@ -586,11 +592,28 @@ int vop_stdcreatevobject (struct vop_createvobject_args *ap); int vop_stddestroyvobject (struct vop_destroyvobject_args *ap); int vop_stdgetvobject (struct vop_getvobject_args *ap); - +int vx_lock (struct vnode *vp); +void vx_unlock (struct vnode *vp); +int vx_get (struct vnode *vp); +int vx_get_nonblock (struct vnode *vp); +void vx_put (struct vnode *vp); +int vget (struct vnode *vp, int lockflag, struct thread *td); void vput (struct vnode *vp); -void vrele (struct vnode *vp); -void vrele_noinactive (struct vnode *vp); +void vhold (struct vnode *); +void vdrop (struct vnode *); void vref (struct vnode *vp); +void vrele (struct vnode *vp); +void vsetflags (struct vnode *vp, int flags); +void vclrflags (struct vnode *vp, int flags); + +void vfs_subr_init(void); +void vfs_mount_init(void); +void vfs_lock_init(void); +void vfs_sync_init(void); + +void vn_syncer_add_to_worklist(struct vnode *, int); +void vnlru_proc_wait(void); + extern struct vop_ops *default_vnode_vops; extern struct vop_ops *spec_vnode_vops; diff --git a/sys/vfs/coda/coda_vfsops.c b/sys/vfs/coda/coda_vfsops.c index d180679977..6c33998272 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.16 2004/09/30 18:59:53 dillon Exp $ + * $DragonFly: src/sys/vfs/coda/Attic/coda_vfsops.c,v 1.17 2004/10/12 19:20:50 dillon Exp $ * */ @@ -309,12 +309,7 @@ coda_root(struct mount *vfsp, struct vnode **vpp) { /* Found valid root. */ *vpp = mi->mi_rootvp; /* On Mach, this is vref. On NetBSD, VOP_LOCK */ -#if 1 - vref(*vpp); - vn_lock(*vpp, NULL, LK_EXCLUSIVE, td); -#else - vget(*vpp, NULL, LK_EXCLUSIVE, td); -#endif + vget(*vpp, LK_EXCLUSIVE, td); MARK_INT_SAT(CODA_ROOT_STATS); return(0); } @@ -332,12 +327,7 @@ coda_root(struct mount *vfsp, struct vnode **vpp) coda_save(VTOC(mi->mi_rootvp)); *vpp = mi->mi_rootvp; -#if 1 - vref(*vpp); - vn_lock(*vpp, NULL, LK_EXCLUSIVE, td); -#else - vget(*vpp, NULL, LK_EXCLUSIVE, td); -#endif + vget(*vpp, LK_EXCLUSIVE, td); MARK_INT_SAT(CODA_ROOT_STATS); goto exit; @@ -352,12 +342,7 @@ coda_root(struct mount *vfsp, struct vnode **vpp) * will fail. */ *vpp = mi->mi_rootvp; -#if 1 - vref(*vpp); - vn_lock(*vpp, NULL, LK_EXCLUSIVE, td); -#else - vget(*vpp, NULL, LK_EXCLUSIVE, td); -#endif + vget(*vpp, LK_EXCLUSIVE, td); MARK_INT_FAIL(CODA_ROOT_STATS); error = 0; diff --git a/sys/vfs/coda/coda_vnops.c b/sys/vfs/coda/coda_vnops.c index e2b469ade0..79092881fe 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.21 2004/10/05 03:24:23 dillon Exp $ + * $DragonFly: src/sys/vfs/coda/Attic/coda_vnops.c,v 1.22 2004/10/12 19:20:50 dillon Exp $ * */ @@ -266,7 +266,7 @@ coda_open(void *v) return (error); /* We get the vnode back locked. Needs unlocked */ - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* Keep a reference until the close comes in. */ vref(*vpp); @@ -436,7 +436,7 @@ coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, * We get the vnode back locked in both Mach and * NetBSD. Needs unlocked */ - VOP_UNLOCK(cfvp, NULL, 0, td); + VOP_UNLOCK(cfvp, 0, td); } else { opened_internally = 1; @@ -855,7 +855,7 @@ coda_inactive(void *v) struct vnode *vp = ap->a_vp; struct cnode *cp = VTOC(vp); struct ucred *cred __attribute__((unused)) = NULL; - struct thread *td = curthread; + /*struct thread *td = curthread;*/ /* upcall decl */ /* locals */ @@ -895,7 +895,6 @@ coda_inactive(void *v) printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", vp->v_usecount, vp, cp); #endif - lockmgr(&vp->v_lock, LK_RELEASE, NULL, td); } else { #ifdef OLD_DIAGNOSTIC if (CTOV(cp)->v_usecount) { @@ -905,7 +904,6 @@ coda_inactive(void *v) panic("coda_inactive: cp->ovp != NULL"); } #endif - VOP_UNLOCK(vp, NULL, 0, td); vgone(vp); } @@ -1050,7 +1048,7 @@ coda_lookup(void *v) */ if (!error || (error == EJUSTRETURN)) { if (!(cnp->cn_flags & CNP_LOCKPARENT) || !(cnp->cn_flags & CNP_ISLASTCN)) { - if ((error = VOP_UNLOCK(dvp, NULL, 0, td))) { + if ((error = VOP_UNLOCK(dvp, 0, td))) { return error; } /* @@ -1058,7 +1056,7 @@ coda_lookup(void *v) * lock it without bothering to check anything else. */ if (*ap->a_vpp) { - if ((error = VOP_LOCK(*ap->a_vpp, NULL, LK_EXCLUSIVE, td))) { + if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { printf("coda_lookup: "); panic("unlocked parent but couldn't lock child"); } @@ -1067,7 +1065,7 @@ coda_lookup(void *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, NULL, LK_EXCLUSIVE, td))) { + if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { printf("coda_lookup: "); panic("unlocked parent but couldn't lock child"); } @@ -1155,7 +1153,7 @@ coda_create(void *v) if (!error) { if (cnp->cn_flags & CNP_LOCKLEAF) { - if ((error = VOP_LOCK(*ap->a_vpp, NULL, LK_EXCLUSIVE, td))) { + if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { printf("coda_create: "); panic("unlocked parent but couldn't lock child"); } @@ -1721,7 +1719,6 @@ coda_reclaim(void *v) } #endif } - cache_inval_vp(vp, CINV_SELF); coda_free(VTOC(vp)); vp->v_data = NULL; return (0); @@ -1746,9 +1743,9 @@ coda_lock(void *v) } #ifndef DEBUG_LOCKS - return (lockmgr(&vp->v_lock, ap->a_flags, ap->a_vlock, td)); + return (lockmgr(&vp->v_lock, ap->a_flags, NULL, td)); #else - return (debuglockmgr(&vp->v_lock, ap->a_flags, ap->a_vlock, td, + return (debuglockmgr(&vp->v_lock, ap->a_flags, NULL, td, "coda_lock", vp->filename, vp->line)); #endif } @@ -1770,7 +1767,7 @@ coda_unlock(void *v) cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); } - return (lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, ap->a_vlock, td)); + return (lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, NULL, td)); } int @@ -1907,7 +1904,7 @@ make_coda_node(ViceFid *fid, struct mount *vfsp, short type) vp->v_type = type; cp->c_vnode = vp; coda_save(cp); - + vx_unlock(vp); } else { vref(CTOV(cp)); } diff --git a/sys/vfs/deadfs/dead_vnops.c b/sys/vfs/deadfs/dead_vnops.c index 2f9a87584f..b23738864c 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.10 2004/08/17 18:57:33 dillon Exp $ + * $DragonFly: src/sys/vfs/deadfs/dead_vnops.c,v 1.11 2004/10/12 19:20:52 dillon Exp $ */ #include @@ -43,7 +43,6 @@ #include #include -static int chkvnlock (struct vnode *); /* * Prototypes for dead operations on vnodes. */ @@ -132,8 +131,6 @@ dead_open(struct vop_open_args *ap) static int dead_read(struct vop_read_args *ap) { - if (chkvnlock(ap->a_vp)) - panic("dead_read: lock"); /* * Return EOF for tty devices, EIO for others */ @@ -152,8 +149,6 @@ dead_read(struct vop_read_args *ap) static int dead_write(struct vop_write_args *ap) { - if (chkvnlock(ap->a_vp)) - panic("dead_write: lock"); return (EIO); } @@ -167,33 +162,18 @@ dead_write(struct vop_write_args *ap) static int dead_ioctl(struct vop_ioctl_args *ap) { - if (!chkvnlock(ap->a_vp)) - return (ENOTTY); - return (vop_ioctl_ap(ap)); + return (ENOTTY); } /* * Wait until the vnode has finished changing state. * - * dead_lock(struct vnode *a_vp, lwkt_tokref_t a_vlock, int a_flags, - * struct proc *a_p) + * dead_lock(struct vnode *a_vp, int a_flags, struct proc *a_p) */ static int dead_lock(struct vop_lock_args *ap) { - struct vnode *vp = ap->a_vp; - - /* - * Since we are not using the lock manager, we must clear - * the interlock here. - */ - if (ap->a_flags & LK_INTERLOCK) { - lwkt_reltoken(ap->a_vlock); - ap->a_flags &= ~LK_INTERLOCK; - } - if (!chkvnlock(vp)) - return (0); - return (vop_lock_ap(ap)); + return (0); } /* @@ -205,9 +185,7 @@ dead_lock(struct vop_lock_args *ap) static int dead_bmap(struct vop_bmap_args *ap) { - if (!chkvnlock(ap->a_vp)) - return (EIO); - return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp, ap->a_runb)); + return (EIO); } /* @@ -233,23 +211,6 @@ dead_badop(void) /* NOTREACHED */ } -/* - * We have to wait during times when the vnode is - * in a state of change. - */ -int -chkvnlock(struct vnode *vp) -{ - int locked = 0; - - while (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - (void) tsleep((caddr_t)vp, 0, "ckvnlk", 0); - locked = 1; - } - return (locked); -} - /* * Trivial poll routine that always returns POLLHUP. * This is necessary so that a process which is polling a file diff --git a/sys/vfs/fdesc/fdesc_vfsops.c b/sys/vfs/fdesc/fdesc_vfsops.c index 0082cf6370..3dbe5837d2 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.9 2004/09/30 18:59:54 dillon Exp $ + * $DragonFly: src/sys/vfs/fdesc/fdesc_vfsops.c,v 1.10 2004/10/12 19:20:53 dillon Exp $ */ /* @@ -152,7 +152,7 @@ fdesc_root(struct mount *mp, struct vnode **vpp) */ vp = VFSTOFDESC(mp)->f_root; vref(vp); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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 44c8af8dbf..ce76d10081 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.14 2004/08/28 19:02:10 dillon Exp $ + * $DragonFly: src/sys/vfs/fdesc/fdesc_vnops.c,v 1.15 2004/10/12 19:20:53 dillon Exp $ */ /* @@ -105,7 +105,7 @@ fdesc_allocvp(fdntype ftype, int ix, struct mount *mp, struct vnode **vpp, loop: LIST_FOREACH(fd, fc, fd_hash) { if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { - if (vget(fd->fd_vnode, NULL, 0, td)) + if (vget(fd->fd_vnode, LK_EXCLUSIVE|LK_SLEEPFAIL, td)) goto loop; *vpp = fd->fd_vnode; return (error); @@ -141,6 +141,7 @@ loop: fd->fd_fd = -1; fd->fd_ix = ix; LIST_INSERT_HEAD(fc, fd, fd_hash); + vx_unlock(*vpp); out: fdcache_lock &= ~FDL_LOCKED; @@ -182,11 +183,11 @@ fdesc_lookup(struct vop_lookup_args *ap) goto bad; } - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); if (cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; vref(dvp); - vn_lock(dvp, NULL, LK_SHARED | LK_RETRY, td); + vn_lock(dvp, LK_SHARED | LK_RETRY, td); return (0); } @@ -218,12 +219,12 @@ fdesc_lookup(struct vop_lookup_args *ap) if (error) goto bad; VTOFDESC(fvp)->fd_fd = fd; - vn_lock(fvp, NULL, LK_SHARED | LK_RETRY, td); + vn_lock(fvp, LK_SHARED | LK_RETRY, td); *vpp = fvp; return (0); bad: - vn_lock(dvp, NULL, LK_SHARED | LK_RETRY, td); + vn_lock(dvp, LK_SHARED | LK_RETRY, td); *vpp = NULL; return (error); } @@ -492,7 +493,6 @@ fdesc_inactive(struct vop_inactive_args *ap) * Clear out the v_type field to avoid * nasty things happening in vgone(). */ - 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 d72af3d249..436f426090 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.16 2004/08/17 18:57:33 dillon Exp $ + * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.17 2004/10/12 19:20:54 dillon Exp $ */ #include @@ -127,6 +127,8 @@ static struct vnodeopv_desc fifo_vnodeop_opv_desc = VNODEOP_SET(fifo_vnodeop_opv_desc); +static MALLOC_DEFINE(M_FIFOINFO, "Fifo info", "Fifo info entries"); + /* * fifo_vnoperate(struct vnodeop_desc *a_desc, ...) */ @@ -167,11 +169,11 @@ fifo_open(struct vop_open_args *ap) int error; if ((fip = vp->v_fifoinfo) == NULL) { - MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); + MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_FIFOINFO, M_WAITOK); vp->v_fifoinfo = fip; error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_td); if (error) { - free(fip, M_VNODE); + free(fip, M_FIFOINFO); vp->v_fifoinfo = NULL; return (error); } @@ -179,7 +181,7 @@ fifo_open(struct vop_open_args *ap) error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_td); if (error) { (void)soclose(rso); - free(fip, M_VNODE); + free(fip, M_FIFOINFO); vp->v_fifoinfo = NULL; return (error); } @@ -188,7 +190,7 @@ fifo_open(struct vop_open_args *ap) if (error) { (void)soclose(wso); (void)soclose(rso); - free(fip, M_VNODE); + free(fip, M_FIFOINFO); vp->v_fifoinfo = NULL; return (error); } @@ -218,10 +220,10 @@ fifo_open(struct vop_open_args *ap) } if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { if (fip->fi_writers == 0) { - VOP_UNLOCK(vp, NULL, 0, ap->a_td); + VOP_UNLOCK(vp, 0, ap->a_td); error = tsleep((caddr_t)&fip->fi_readers, PCATCH, "fifoor", 0); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td); if (error) goto bad; /* @@ -239,10 +241,10 @@ fifo_open(struct vop_open_args *ap) } } else { if (fip->fi_readers == 0) { - VOP_UNLOCK(vp, NULL, 0, ap->a_td); + VOP_UNLOCK(vp, 0, ap->a_td); error = tsleep((caddr_t)&fip->fi_writers, PCATCH, "fifoow", 0); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td); if (error) goto bad; /* @@ -283,10 +285,10 @@ fifo_read(struct vop_read_args *ap) if (ap->a_ioflag & IO_NDELAY) rso->so_state |= SS_NBIO; startresid = uio->uio_resid; - VOP_UNLOCK(ap->a_vp, NULL, 0, td); + VOP_UNLOCK(ap->a_vp, 0, td); error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0); - vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td); if (ap->a_ioflag & IO_NDELAY) rso->so_state &= ~SS_NBIO; return (error); @@ -312,10 +314,10 @@ fifo_write(struct vop_write_args *ap) #endif if (ap->a_ioflag & IO_NDELAY) wso->so_state |= SS_NBIO; - VOP_UNLOCK(ap->a_vp, NULL, 0, td); + VOP_UNLOCK(ap->a_vp, 0, td); error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0, (struct mbuf *)0, 0, td); - vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td); if (ap->a_ioflag & IO_NDELAY) wso->so_state &= ~SS_NBIO; return (error); @@ -488,7 +490,6 @@ fifo_poll(struct vop_poll_args *ap) static int fifo_inactive(struct vop_inactive_args *ap) { - VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } @@ -540,7 +541,7 @@ fifo_close(struct vop_close_args *ap) return (0); error1 = soclose(fip->fi_readsock); error2 = soclose(fip->fi_writesock); - FREE(fip, M_VNODE); + FREE(fip, M_FIFOINFO); vp->v_fifoinfo = NULL; if (error1) return (error1); diff --git a/sys/vfs/gnu/ext2fs/ext2_lookup.c b/sys/vfs/gnu/ext2fs/ext2_lookup.c index 70582efff8..19461a33b6 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.14 2004/09/30 18:59:56 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v 1.15 2004/10/12 19:20:55 dillon Exp $ */ /* * Copyright (c) 1989, 1993 @@ -535,7 +535,7 @@ searchloop: */ cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); return (EJUSTRETURN); } /* @@ -613,7 +613,7 @@ found: } *vpp = tdp; if (!lockparent) - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); return (0); } @@ -638,7 +638,7 @@ found: *vpp = tdp; cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); return (0); } @@ -663,13 +663,13 @@ found: */ pdp = vdp; if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(pdp, NULL, 0, td); /* race to get the inode */ + VOP_UNLOCK(pdp, 0, td); /* race to get the inode */ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) { - vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } if (lockparent && (flags & CNP_ISLASTCN) && - (error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td))) { + (error = vn_lock(pdp, LK_EXCLUSIVE, td))) { vput(tdp); return (error); } @@ -681,7 +681,7 @@ found: if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) return (error); if (!lockparent || !(flags & CNP_ISLASTCN)) - VOP_UNLOCK(pdp, NULL, 0, td); + VOP_UNLOCK(pdp, 0, td); *vpp = tdp; } diff --git a/sys/vfs/gnu/ext2fs/ext2_vfsops.c b/sys/vfs/gnu/ext2fs/ext2_vfsops.c index e9967024e7..44eb43ab98 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.20 2004/09/30 18:59:56 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.21 2004/10/12 19:20:55 dillon Exp $ */ #include "opt_quota.h" @@ -237,13 +237,13 @@ ext2_mount(struct mount *mp, char *path, * that user has necessary permissions on the device. */ if (cred->cr_uid != 0) { - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, cred, td)) != 0) { - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 || @@ -293,12 +293,12 @@ ext2_mount(struct mount *mp, char *path, accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, accessmode, cred, td)) != 0) { vput(devvp); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { @@ -518,8 +518,7 @@ compute_sb_data(struct vnode *devvp, struct ext2_super_block *es, * 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); +static int ext2_reload_scan2(struct mount *mp, struct vnode *vp, void *rescan); struct scaninfo { int rescan; @@ -578,7 +577,7 @@ ext2_reload(struct mount *mountp, struct ucred *cred, struct thread *td) scaninfo.fs = fs; while (error == 0 && scaninfo.rescan) { scaninfo.rescan = 0; - error = vmntvnodescan(mountp, ext2_reload_scan1, + error = vmntvnodescan(mountp, VMSC_GETVX, ext2_reload_scan1, ext2_reload_scan2, &scaninfo); } return(error); @@ -587,20 +586,13 @@ ext2_reload(struct mount *mountp, struct ucred *cred, struct thread *td) static int ext2_reload_scan1(struct mount *mp, struct vnode *vp, void *data) { - struct scaninfo *info = 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) +ext2_reload_scan2(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; struct inode *ip; @@ -608,12 +600,14 @@ ext2_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void int error; /* - * Step 5: invalidate all cached file data. + * Try to recycle */ - if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) { - info->rescan = 1; + if (vrecycle(vp, curthread)) return(0); - } + + /* + * Step 5: invalidate all cached file data. + */ if (vinvalbuf(vp, 0, info->td, 0, 0)) panic("ext2_reload: dirty2"); /* @@ -622,15 +616,12 @@ ext2_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void 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 (error) return (error); - } 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); } @@ -668,9 +659,9 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) #endif ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return (error); dev = devvp->v_rdev; @@ -924,8 +915,7 @@ ext2_statfs(struct mount *mp, struct statfs *sbp, struct thread *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_scan(struct mount *mp, struct vnode *vp, void *data); static int ext2_sync(struct mount *mp, int waitfor, struct thread *td) @@ -950,17 +940,18 @@ ext2_sync(struct mount *mp, int waitfor, struct thread *td) scaninfo.td = td; while (scaninfo.rescan) { scaninfo.rescan = 0; - vmntvnodescan(mp, NULL, ext2_sync_scan, &scaninfo); + vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, + NULL, ext2_sync_scan, &scaninfo); } /* * Force stale file system control information to be flushed. */ if (waitfor != MNT_LAZY) { - vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0) scaninfo.allerror = error; - VOP_UNLOCK(ump->um_devvp, NULL, 0, td); + VOP_UNLOCK(ump->um_devvp, 0, td); } #if QUOTA qsync(mp); @@ -978,8 +969,7 @@ ext2_sync(struct mount *mp, int waitfor, struct thread *td) } static int -ext2_sync_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +ext2_sync_scan(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; struct inode *ip; @@ -990,19 +980,10 @@ ext2_sync_scan(struct mount *mp, struct vnode *vp, ((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); } if ((error = VOP_FSYNC(vp, info->waitfor, info->td)) != 0) info->allerror = error; - VOP_UNLOCK(vp, NULL, 0, info->td); - vrele(vp); return(0); } @@ -1073,10 +1054,10 @@ restart: ip->i_dquot[i] = NODQUOT; #endif /* - * Put it onto its hash chain and lock it so that other requests for - * this inode will block if they arrive while we are sleeping waiting - * for old data structures to be purged or for the contents of the - * disk portion of this inode to be read. + * Put it onto its hash chain. Since our vnode is locked, other + * requests for this inode will block if they arrive while we are + * sleeping waiting for old data structures to be purged or for the + * contents of the disk portion of this inode to be read. */ ufs_ihashins(ip); @@ -1096,7 +1077,7 @@ printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); * still zero, it will be unlinked and returned to the free * list by vput(). */ - vput(vp); + vx_put(vp); brelse(bp); *vpp = NULL; return (error); @@ -1128,7 +1109,7 @@ printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); * Note that the underlying vnode may have changed. */ if ((error = ufs_vinit(mp, &vp)) != 0) { - vput(vp); + vx_put(vp); *vpp = NULL; return (error); } @@ -1146,6 +1127,9 @@ printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IN_MODIFIED; } + /* + * Return the locked and refd vnode. + */ *vpp = vp; return (0); } diff --git a/sys/vfs/gnu/ext2fs/ext2_vnops.c b/sys/vfs/gnu/ext2fs/ext2_vnops.c index 751e0a079d..1cdb5faac4 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.15 2004/08/17 18:57:33 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v 1.16 2004/10/12 19:20:55 dillon Exp $ */ #include "opt_quota.h" @@ -264,10 +264,10 @@ ext2_mknod(struct vop_mknod_args *ap) * checked to see if it is an alias of an existing entry in * the inode cache. */ - vput(*vpp); (*vpp)->v_type = VNON; ino = ip->i_number; /* Save this before vgone() invalidates ip. */ vgone(*vpp); + vput(*vpp); error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp); if (error) { *vpp = NULL; @@ -327,7 +327,7 @@ ext2_link(struct vop_link_args *ap) error = EXDEV; goto out2; } - if (tdvp != vp && (error = vn_lock(vp, NULL, LK_EXCLUSIVE, td))) { + if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { goto out2; } ip = VTOI(vp); @@ -350,7 +350,7 @@ ext2_link(struct vop_link_args *ap) } out1: if (tdvp != vp) - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); out2: return (error); } @@ -418,18 +418,18 @@ abortit: goto abortit; } - if ((error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td)) != 0) + if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0) goto abortit; dp = VTOI(fdvp); ip = VTOI(fvp); if (ip->i_nlink >= LINK_MAX) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EMLINK; goto abortit; } if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EPERM; goto abortit; } @@ -440,7 +440,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, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EINVAL; goto abortit; } @@ -468,7 +468,7 @@ abortit: ip->i_nlink++; ip->i_flag |= IN_CHANGE; if ((error = UFS_UPDATE(fvp, 1)) != 0) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } @@ -483,7 +483,7 @@ abortit: * call to checkpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { @@ -706,7 +706,7 @@ bad: out: if (doingdirectory) ip->i_flag &= ~IN_RENAME; - if (vn_lock(fvp, NULL, LK_EXCLUSIVE, td) == 0) { + if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) { ip->i_nlink--; ip->i_flag |= IN_CHANGE; ip->i_flag &= ~IN_RENAME; @@ -931,7 +931,7 @@ ext2_rmdir(struct vop_rmdir_args *ap) dp->i_nlink--; dp->i_flag |= IN_CHANGE; cache_purge(dvp); - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); /* * Truncate inode. The only stuff left * in the directory is "." and "..". The @@ -946,7 +946,7 @@ ext2_rmdir(struct vop_rmdir_args *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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, 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 4a2c7c6814..d709011a01 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.4 2004/03/01 06:33:20 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/fs.h,v 1.5 2004/10/12 19:20:55 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, NULL, LK_EXCLUSIVE | LK_RETRY, curthread) -#define unlock_super(devvp) VOP_UNLOCK(devvp, NULL, 0, curthread) +#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curthread) +#define unlock_super(devvp) VOP_UNLOCK(devvp, 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 9cfa5d013a..c2b510ad93 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.13 2004/08/28 19:02:14 dillon Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs.h,v 1.14 2004/10/12 19:20:56 dillon Exp $ */ /*#define HPFS_DEBUG 10*/ @@ -398,10 +398,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), 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 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 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 3293d2a1c5..c67296eb8c 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.11 2004/04/11 18:17:21 cpressey Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_hash.c,v 1.12 2004/10/12 19:20:56 dillon Exp $ */ #include @@ -113,7 +113,6 @@ hpfs_hphashvget(dev_t dev, lsn_t ino, struct thread *td) { struct hpfsnode *hp; lwkt_tokref ilock; - lwkt_tokref vlock; struct vnode *vp; lwkt_gettoken(&ilock, &hpfs_hphash_token); @@ -122,8 +121,9 @@ loop: if (ino != hp->h_no || dev != hp->h_dev) continue; vp = HPTOV(hp); - lwkt_gettoken (&vlock, vp->v_interlock); + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; /* * We must check to see if the inode has been ripped * out from under us after blocking. @@ -133,15 +133,13 @@ loop: break; } if (hp == NULL || vp != HPTOV(hp)) { - lwkt_reltoken(&vlock); + vput(vp); 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); } diff --git a/sys/vfs/hpfs/hpfs_vfsops.c b/sys/vfs/hpfs/hpfs_vfsops.c index 17f30b8920..a9d14bb0bd 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.21 2004/09/30 18:59:57 dillon Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.22 2004/10/12 19:20:56 dillon Exp $ */ @@ -642,16 +642,10 @@ hpfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) hp->h_devvp = hpmp->hpm_devvp; vref(hp->h_devvp); - error = VN_LOCK(vp, LK_EXCLUSIVE, td); - if (error) { - vput(vp); - return (error); - } - do { if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) { dprintf(("hashed2\n")); - vput(vp); + vx_put(vp); return (0); } } while(LOCKMGR(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL)); @@ -663,7 +657,7 @@ hpfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) error = bread(hpmp->hpm_devvp, ino, FNODESIZE, &bp); if (error) { printf("hpfs_vget: can't read ino %d\n",ino); - vput(vp); + vx_put(vp); return (error); } bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); @@ -671,13 +665,14 @@ hpfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) if (hp->h_fn.fn_magic != FN_MAGIC) { printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); - vput(vp); + vx_put(vp); return (EINVAL); } vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; hp->h_flag &= ~H_INVAL; + /* Return the locked and refd vnode */ *vpp = vp; return (0); diff --git a/sys/vfs/hpfs/hpfs_vnops.c b/sys/vfs/hpfs/hpfs_vnops.c index 1e10790e63..6b1b778d4e 100644 --- a/sys/vfs/hpfs/hpfs_vnops.c +++ b/sys/vfs/hpfs/hpfs_vnops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.19 2004/10/05 03:24:25 dillon Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.20 2004/10/12 19:20:56 dillon Exp $ */ #include @@ -626,16 +626,13 @@ hpfs_inactive(struct vop_inactive_args *ap) vprint("hpfs_inactive: pushing active", vp); if (hp->h_flag & H_INVAL) { - VOP__UNLOCK(vp,0,ap->a_td); #if defined(__DragonFly__) - vrecycle(vp, NULL, ap->a_td); + vrecycle(vp, ap->a_td); #else /* defined(__NetBSD__) */ vgone(vp); #endif return (0); } - - VOP__UNLOCK(vp,0,ap->a_td); return (0); } @@ -655,7 +652,6 @@ hpfs_reclaim(struct vop_reclaim_args *ap) hpfs_hphashrem(hp); /* Purge old data structures associated with the inode. */ - cache_inval_vp(vp, CINV_SELF); if (hp->h_devvp) { vrele(hp->h_devvp); hp->h_devvp = NULL; diff --git a/sys/vfs/isofs/cd9660/cd9660_lookup.c b/sys/vfs/isofs/cd9660/cd9660_lookup.c index e2da6f008a..df637b1012 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.13 2004/09/30 18:59:59 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_lookup.c,v 1.14 2004/10/12 19:20:58 dillon Exp $ */ #include @@ -351,16 +351,16 @@ found: * it's a relocated directory. */ if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(pdp, NULL, 0, td); /* race to get the inode */ + VOP_UNLOCK(pdp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } if (lockparent && (flags & CNP_ISLASTCN)) { - if ((error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td)) != 0) { + if ((error = vn_lock(pdp, LK_EXCLUSIVE, td)) != 0) { cnp->cn_flags |= CNP_PDIRUNLOCK; vput(tdp); return (error); @@ -380,7 +380,7 @@ found: return (error); if (!lockparent || !(flags & CNP_ISLASTCN)) { cnp->cn_flags |= CNP_PDIRUNLOCK; - VOP_UNLOCK(pdp, NULL, 0, td); + VOP_UNLOCK(pdp, 0, td); } *vpp = tdp; } diff --git a/sys/vfs/isofs/cd9660/cd9660_node.c b/sys/vfs/isofs/cd9660/cd9660_node.c index c86006e6d4..c247ba35fe 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.12 2004/10/05 03:24:28 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_node.c,v 1.13 2004/10/12 19:20:58 dillon Exp $ */ #include @@ -102,7 +102,6 @@ cd9660_ihashget(dev_t dev, ino_t inum) struct thread *td = curthread; /* XXX */ struct iso_node *ip; lwkt_tokref ilock; - lwkt_tokref vlock; struct vnode *vp; lwkt_gettoken(&ilock, &cd9660_ihash_token); @@ -111,7 +110,8 @@ loop: if (inum != ip->i_number || dev != ip->i_dev) continue; vp = ITOV(ip); - lwkt_gettoken(&vlock, vp->v_interlock); + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; /* * We must check to see if the inode has been ripped * out from under us after blocking. @@ -121,11 +121,8 @@ loop: 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); } @@ -199,13 +196,12 @@ cd9660_inactive(struct vop_inactive_args *ap) if (ip) ip->i_flag = 0; - VOP_UNLOCK(vp, NULL, 0, td); /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ if (ip == NULL || ip->inode.iso_mode == 0) - vrecycle(vp, NULL, td); + vrecycle(vp, td); return error; } @@ -223,10 +219,8 @@ cd9660_reclaim(struct vop_reclaim_args *ap) if (prtactive && vp->v_usecount != 0) vprint("cd9660_reclaim: pushing active", vp); /* - * Remove the inode from its hash chain and purge namecache - * data associated with the vnode. + * Remove the inode from its hash chain. */ - cache_inval_vp(vp, CINV_SELF); vp->v_data = NULL; if (ip) { cd9660_ihashrem(ip); diff --git a/sys/vfs/isofs/cd9660/cd9660_vfsops.c b/sys/vfs/isofs/cd9660/cd9660_vfsops.c index f36b311195..534e1c8895 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.21 2004/09/30 18:59:59 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.22 2004/10/12 19:20:58 dillon Exp $ */ #include @@ -154,9 +154,9 @@ iso_mountroot(struct mount *mp, struct thread *td) } args.flags = ISOFSMNT_ROOT; - vn_lock(rootvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(rootvp, FREAD, FSCRED, td); - VOP_UNLOCK(rootvp, NULL, 0, td); + VOP_UNLOCK(rootvp, 0, td); if (error) return (error); @@ -230,7 +230,7 @@ cd9660_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) * or has superuser abilities */ accessmode = VREAD; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, 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(struct mount *mp, char *path, caddr_t data, struct thread *td) vput(devvp); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = iso_mountfs(devvp, mp, td, &args); @@ -301,9 +301,9 @@ iso_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td, if ((error = vinvalbuf(devvp, V_SAVE, td, 0, 0))) return (error); - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, FREAD, FSCRED, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return error; dev = devvp->v_rdev; @@ -694,7 +694,7 @@ int cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, int relocated, struct iso_directory_record *isodir) { - struct thread *td = curthread; + /*struct thread *td = curthread;*/ struct iso_mnt *imp; struct iso_node *ip; struct buf *bp; @@ -717,7 +717,6 @@ again: MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, M_WAITOK); bzero((caddr_t)ip, sizeof(struct iso_node)); - lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL, td); ip->i_vnode = vp; ip->i_dev = dev; ip->i_number = ino; @@ -728,7 +727,7 @@ again: */ if (cd9660_ihashins(ip) != 0) { printf("debug: cd9660 ihashins collision, retrying\n"); - vput(vp); + vx_put(vp); free(ip, M_ISOFSNODE); goto again; } @@ -739,14 +738,14 @@ again: lbn = lblkno(imp, ino); if (lbn >= imp->volume_space_size) { - vput(vp); + vx_put(vp); printf("fhtovp: lbn exceed volume space %d\n", lbn); return (ESTALE); } off = blkoff(imp, ino); if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) { - vput(vp); + vx_put(vp); printf("fhtovp: crosses block boundary %d\n", off + ISO_DIRECTORY_RECORD_SIZE); return (ESTALE); @@ -756,7 +755,7 @@ again: lbn << (imp->im_bshift - DEV_BSHIFT), imp->logical_block_size, &bp); if (error) { - vput(vp); + vx_put(vp); brelse(bp); printf("fhtovp: bread error %d\n",error); return (error); @@ -765,7 +764,7 @@ again: if (off + isonum_711(isodir->length) > imp->logical_block_size) { - vput(vp); + vx_put(vp); if (bp != 0) brelse(bp); printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n", @@ -801,7 +800,7 @@ again: if (bp != 0) brelse(bp); if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) { - vput(vp); + vx_put(vp); return (error); } isodir = (struct iso_directory_record *)bp->b_data; @@ -860,9 +859,8 @@ again: vp->v_flag |= VROOT; /* - * XXX need generation number? + * Return the locked and refd vp */ - *vpp = vp; return (0); } diff --git a/sys/vfs/mfs/mfs_vfsops.c b/sys/vfs/mfs/mfs_vfsops.c index 50f46df0e1..5be58ca415 100644 --- a/sys/vfs/mfs/mfs_vfsops.c +++ b/sys/vfs/mfs/mfs_vfsops.c @@ -32,7 +32,7 @@ * * @(#)mfs_vfsops.c 8.11 (Berkeley) 6/19/95 * $FreeBSD: src/sys/ufs/mfs/mfs_vfsops.c,v 1.81.2.3 2001/07/04 17:35:21 tegge Exp $ - * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.18 2004/09/30 19:00:01 dillon Exp $ + * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.19 2004/10/12 19:20:59 dillon Exp $ */ @@ -334,6 +334,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) &size); /* real size*/ bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + vx_unlock(devvp); if ((err = ffs_mountfs(devvp, mp, td, M_MFSNODE)) != 0) { mfsp->mfs_active = 0; goto error_2; diff --git a/sys/vfs/mfs/mfs_vnops.c b/sys/vfs/mfs/mfs_vnops.c index 63b57d9c4e..fd655bb17b 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.15 2004/08/17 18:57:33 dillon Exp $ + * $DragonFly: src/sys/vfs/mfs/mfs_vnops.c,v 1.16 2004/10/12 19:20:59 dillon Exp $ */ #include @@ -362,7 +362,6 @@ mfs_inactive(struct vop_inactive_args *ap) if (bufq_first(&mfsp->buf_queue) != NULL) panic("mfs_inactive: not inactive (next buffer %p)", bufq_first(&mfsp->buf_queue)); - 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 ccdce4890f..3aca099d19 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.16 2004/10/05 03:24:30 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.17 2004/10/12 19:21:00 dillon Exp $ */ /* $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $ */ /*- @@ -127,7 +127,6 @@ msdosfs_hashget(dev_t dev, u_long dirclust, u_long diroff) struct thread *td = curthread; /* XXX */ struct denode *dep; lwkt_tokref ilock; - lwkt_tokref vlock; struct vnode *vp; lwkt_gettoken(&ilock, &dehash_token); @@ -140,7 +139,8 @@ loop: continue; } vp = DETOV(dep); - lwkt_gettoken(&vlock, vp->v_interlock); + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; /* * We must check to see if the inode has been ripped @@ -155,11 +155,9 @@ loop: } } if (dep == NULL || DETOV(dep) != vp) { - lwkt_reltoken(&vlock); + vput(vp); goto loop; } - if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td)) - goto loop; lwkt_reltoken(&ilock); return (dep); } @@ -304,13 +302,6 @@ again: return error; } - /* - * Lock the denode so that it can't be accessed until we've read - * it in and have done what we need to it. - */ - if (lockmgr(&nvp->v_lock, LK_EXCLUSIVE, NULL, td)) - panic("deget: unexpected lock failure"); - bzero((caddr_t)ldep, sizeof *ldep); ldep->de_vnode = nvp; ldep->de_flag = 0; @@ -326,7 +317,7 @@ again: */ if (msdosfs_hashins(ldep) != 0) { printf("debug: msdosfs: hashins collision, retrying\n"); - vput(nvp); + vx_put(nvp); free(ldep, M_MSDOSFSNODE); goto again; } @@ -381,7 +372,7 @@ again: */ ldep->de_Name[0] = SLOT_DELETED; - vput(nvp); + vx_put(nvp); *depp = NULL; return (error); } @@ -422,13 +413,18 @@ again: } else printf("deget(): pcbmap returned %d\n", error); } - } else + } else { nvp->v_type = VREG; + } getmicrouptime(&tv); SETHIGH(ldep->de_modrev, tv.tv_sec); SETLOW(ldep->de_modrev, tv.tv_usec * 4294); ldep->de_devvp = pmp->pm_devvp; vref(ldep->de_devvp); + /* + * Leave nvp locked and refd so the returned inode is effectively + * locked and refd. + */ *depp = ldep; return (0); } @@ -668,10 +664,8 @@ msdosfs_reclaim(struct vop_reclaim_args *ap) if (prtactive && vp->v_usecount != 0) vprint("msdosfs_reclaim(): pushing active", vp); /* - * Remove the denode from its hash chain and purge namecache - * data associated with the vnode. + * Remove the denode from its hash chain. */ - cache_inval_vp(vp, CINV_SELF); vp->v_data = NULL; if (dep) { msdosfs_hashrem(dep); @@ -724,7 +718,6 @@ msdosfs_inactive(struct vop_inactive_args *ap) deupdat(dep, 0); out: - VOP_UNLOCK(vp, NULL, 0, ap->a_td); /* * If we are done with the denode, reclaim it * so that it can be reused immediately. @@ -734,6 +727,6 @@ out: dep->de_Name[0]); #endif if (dep->de_Name[0] == SLOT_DELETED) - vrecycle(vp, NULL, ap->a_td); + vrecycle(vp, ap->a_td); return (error); } diff --git a/sys/vfs/msdosfs/msdosfs_lookup.c b/sys/vfs/msdosfs/msdosfs_lookup.c index 12791b8c8c..97f919218d 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.11 2004/09/30 19:00:04 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_lookup.c,v 1.12 2004/10/12 19:21:00 dillon Exp $ */ /* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ /*- @@ -364,7 +364,7 @@ notfound: */ cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (EJUSTRETURN); @@ -455,7 +455,7 @@ foundroot: return (error); *vpp = DETOV(tdp); if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (0); @@ -488,7 +488,7 @@ foundroot: *vpp = DETOV(tdp); cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (0); @@ -515,16 +515,16 @@ foundroot: */ pdp = vdp; if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(pdp, NULL, 0, td); + VOP_UNLOCK(pdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; error = deget(pmp, cluster, blkoff, &tdp); if (error) { - vn_lock(pdp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td); cnp->cn_flags &= ~CNP_PDIRUNLOCK; return (error); } if (lockparent && (flags & CNP_ISLASTCN)) { - error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(pdp, LK_EXCLUSIVE, td); if (error) { vput(DETOV(tdp)); return (error); @@ -539,7 +539,7 @@ foundroot: if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) return (error); if (!lockparent || !(flags & CNP_ISLASTCN)) { - VOP_UNLOCK(pdp, NULL, 0, td); + VOP_UNLOCK(pdp, 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 c5340cd5dd..df6e0d9eed 100644 --- a/sys/vfs/msdosfs/msdosfs_vfsops.c +++ b/sys/vfs/msdosfs/msdosfs_vfsops.c @@ -1,5 +1,5 @@ /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/msdosfs/Attic/msdosfs_vfsops.c,v 1.60.2.8 2004/03/02 09:43:04 tjr Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.19 2004/09/30 19:00:04 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.20 2004/10/12 19:21:00 dillon Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */ /*- @@ -269,14 +269,14 @@ msdosfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) */ if (p->p_ucred->cr_uid != 0) { devvp = pmp->pm_devvp; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(devvp, VREAD | VWRITE, p->p_ucred, td); if (error) { - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } pmp->pm_flags &= ~MSDOSFSMNT_RONLY; } @@ -318,13 +318,13 @@ msdosfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(devvp, accessmode, p->p_ucred, td); if (error) { vput(devvp); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = mountmsdosfs(devvp, mp, td, &args); @@ -389,16 +389,16 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td, return (error); if (count_udev(devvp->v_udev) > 0) return (EBUSY); - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = vinvalbuf(devvp, V_SAVE, td, 0, 0); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return (error); dev = devvp->v_rdev; @@ -842,8 +842,7 @@ struct scaninfo { thread_t td; }; -static int msdosfs_sync_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data); +static int msdosfs_sync_scan(struct mount *mp, struct vnode *vp, void *data); static int msdosfs_sync(struct mount *mp, int waitfor, struct thread *td) @@ -871,24 +870,23 @@ msdosfs_sync(struct mount *mp, int waitfor, struct thread *td) scaninfo.td = td; while (scaninfo.rescan) { scaninfo.rescan = 0; - vmntvnodescan(mp, NULL, msdosfs_sync_scan, &scaninfo); + vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, NULL, msdosfs_sync_scan, &scaninfo); } /* * Flush filesystem control info. */ if (waitfor != MNT_LAZY) { - vn_lock(pmp->pm_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(pmp->pm_devvp, 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); + VOP_UNLOCK(pmp->pm_devvp, 0, td); } return (scaninfo.allerror); } static int -msdosfs_sync_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +msdosfs_sync_scan(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; struct denode *dep; @@ -899,19 +897,10 @@ msdosfs_sync_scan(struct mount *mp, struct vnode *vp, ((dep->de_flag & (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 && (TAILQ_EMPTY(&vp->v_dirtyblkhd) || info->waitfor == MNT_LAZY))) { - lwkt_reltoken(vlock); - return(0); - } - error = vget(vp, vlock, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, info->td); - if (error) { - if (error == ENOENT) - info->rescan = 1; return(0); } if ((error = VOP_FSYNC(vp, info->waitfor, info->td)) != 0) info->allerror = error; - VOP_UNLOCK(vp, NULL, 0, info->td); - vrele(vp); return(0); } diff --git a/sys/vfs/msdosfs/msdosfs_vnops.c b/sys/vfs/msdosfs/msdosfs_vnops.c index 4bcbe78318..caaa04c915 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.18 2004/08/28 19:02:18 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.19 2004/10/12 19:21:00 dillon Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -225,16 +225,13 @@ msdosfs_close(struct vop_close_args *ap) struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); struct timespec ts; - lwkt_tokref vlock; - lwkt_gettoken(&vlock, vp->v_interlock); if (vp->v_usecount > 1) { getnanotime(&ts); if (vp->v_usecount > 1) { DETIMES(dep, &ts, &ts, &ts); } } - lwkt_reltoken(&vlock); return 0; } @@ -1021,7 +1018,7 @@ abortit: goto abortit; } - error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(fvp, LK_EXCLUSIVE, td); if (error) goto abortit; dp = VTODE(fdvp); @@ -1042,7 +1039,7 @@ abortit: (fcnp->cn_flags & CNP_ISDOTDOT) || (tcnp->cn_flags & CNP_ISDOTDOT) || (ip->de_flag & DE_RENAME)) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EINVAL; goto abortit; } @@ -1073,7 +1070,7 @@ abortit: * call to doscheckpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) newparent = 1; if (doingdirectory && newparent) { @@ -1142,7 +1139,7 @@ abortit: if ((fcnp->cn_flags & CNP_SAVESTART) == 0) panic("msdosfs_rename: lost from startdir"); if (!newparent) - VOP_UNLOCK(tdvp, NULL, 0, td); + VOP_UNLOCK(tdvp, 0, td); if (relookup(fdvp, &fvp, fcnp) == 0) vrele(fdvp); if (fvp == NULL) { @@ -1153,7 +1150,7 @@ abortit: panic("rename: lost dir entry"); vrele(ap->a_fvp); if (newparent) - VOP_UNLOCK(tdvp, NULL, 0, td); + VOP_UNLOCK(tdvp, 0, td); vrele(tdvp); return 0; } @@ -1173,9 +1170,9 @@ abortit: if (doingdirectory) panic("rename: lost dir entry"); vrele(ap->a_fvp); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); if (newparent) - VOP_UNLOCK(fdvp, NULL, 0, td); + VOP_UNLOCK(fdvp, 0, td); xp = NULL; } else { u_long new_dirclust; @@ -1200,8 +1197,8 @@ abortit: if (error) { bcopy(oldname, ip->de_Name, 11); if (newparent) - VOP_UNLOCK(fdvp, NULL, 0, td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fdvp, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } ip->de_refcnt++; @@ -1210,8 +1207,8 @@ abortit: if (error) { /* XXX should really panic here, fs is corrupt */ if (newparent) - VOP_UNLOCK(fdvp, NULL, 0, td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fdvp, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } if (!doingdirectory) { @@ -1220,8 +1217,8 @@ abortit: if (error) { /* XXX should really panic here, fs is corrupt */ if (newparent) - VOP_UNLOCK(fdvp, NULL, 0, td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fdvp, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } if (new_dirclust == MSDOSFSROOT) @@ -1231,7 +1228,7 @@ abortit: msdosfs_reinsert(ip, new_dirclust, new_diroffset); } if (newparent) - VOP_UNLOCK(fdvp, NULL, 0, td); + VOP_UNLOCK(fdvp, 0, td); } /* @@ -1249,7 +1246,7 @@ abortit: if (error) { /* XXX should really panic here, fs is corrupt */ brelse(bp); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } dotdotp = (struct direntry *)bp->b_data + 1; @@ -1259,12 +1256,12 @@ abortit: error = bwrite(bp); if (error) { /* XXX should really panic here, fs is corrupt */ - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } } - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); bad: if (xp) vput(tvp); @@ -1460,14 +1457,14 @@ msdosfs_rmdir(struct vop_rmdir_args *ap) * the name cache. */ cache_purge(dvp); - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); /* * Truncate the directory that is being deleted. */ error = detrunc(ip, (u_long)0, IO_SYNC, td); cache_purge(vp); - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); out: return (error); } diff --git a/sys/vfs/nfs/nfs_bio.c b/sys/vfs/nfs/nfs_bio.c index a675b49921..7cbfa26e13 100644 --- a/sys/vfs/nfs/nfs_bio.c +++ b/sys/vfs/nfs/nfs_bio.c @@ -35,7 +35,7 @@ * * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 * $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_bio.c,v 1.130 2004/04/14 23:23:55 peadar Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.17 2004/06/08 02:58:52 hmp Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.18 2004/10/12 19:21:01 dillon Exp $ */ @@ -1139,9 +1139,8 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct nfsmount *nmp = VFSTONFS(vp->v_mount); int error = 0, slpflag, slptimeo; - if (vp->v_flag & VXLOCK) { + if (vp->v_flag & VRECLAIMED) return (0); - } if ((nmp->nm_flag & NFSMNT_INT) == 0) intrflg = 0; diff --git a/sys/vfs/nfs/nfs_node.c b/sys/vfs/nfs/nfs_node.c index 5db7af3225..59e0236863 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.16 2004/10/05 03:24:31 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_node.c,v 1.17 2004/10/12 19:21:01 dillon Exp $ */ @@ -107,13 +107,26 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp) retry: nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT)); loop: - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { + for (np = nhpp->lh_first; np; np = np->n_hash.le_next) { if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || - bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) + bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) { continue; + } vp = NFSTOV(np); - if (vget(vp, NULL, LK_EXCLUSIVE|LK_SLEEPFAIL, td)) + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; + for (np = nhpp->lh_first; np; np = np->n_hash.le_next) { + if (mntp == NFSTOV(np)->v_mount && + np->n_fhsize == fhsize && + bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize) == 0 + ) { + break; + } + } + if (np == NULL || NFSTOV(np) != vp) { + vput(vp); goto loop; + } *npp = np; return(0); } @@ -158,7 +171,7 @@ loop: if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) continue; - vrele(vp); + vx_put(vp); if (nfs_node_hash_lock < 0) wakeup(&nfs_node_hash_lock); nfs_node_hash_lock = 0; @@ -173,17 +186,16 @@ loop: bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); np->n_fhsize = fhsize; lockinit(&np->n_rslock, rsflags, "nfrslk", 0, LK_NOPAUSE); + + /* + * nvp is locked & refd so effectively so is np. + */ *npp = np; if (nfs_node_hash_lock < 0) wakeup(&nfs_node_hash_lock); nfs_node_hash_lock = 0; - /* - * Lock the new nfsnode. - */ - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); - return (0); } @@ -215,10 +227,14 @@ nfs_inactive(struct vop_inactive_args *ap) * associated with discarding the buffers. The vnode * is already locked. */ - vref(ap->a_vp); nfs_vinvalbuf(ap->a_vp, 0, ap->a_td, 1); - vrele_noinactive(ap->a_vp); - KKASSERT(ap->a_vp->v_usecount == 0); + + /* + * Either we have the only ref or we were vgone()'d via + * revoke and might have more. + */ + KKASSERT(ap->a_vp->v_usecount == 1 || + (ap->a_vp->v_flag & VRECLAIMED)); /* * Remove the silly file that was rename'd earlier @@ -230,7 +246,6 @@ nfs_inactive(struct vop_inactive_args *ap) } np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | NQNFSNONCACHE | NQNFSWRITE); - VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } @@ -285,7 +300,6 @@ nfs_reclaim(struct vop_reclaim_args *ap) np->n_wucred = NULL; } - cache_inval_vp(vp, CINV_SELF); vp->v_data = NULL; zfree(nfsnode_zone, np); return (0); diff --git a/sys/vfs/nfs/nfs_nqlease.c b/sys/vfs/nfs/nfs_nqlease.c index e95c9a0a42..abb5ca2ff7 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.18 2004/08/13 17:51:11 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/Attic/nfs_nqlease.c,v 1.19 2004/10/12 19:21:01 dillon Exp $ */ @@ -1053,7 +1053,7 @@ nqnfs_clientd(struct nfsmount *nmp, struct ucred *cred, struct nfsd_cargs *ncd, vp = NFSTOV(np); vpid = vp->v_id; if (np->n_expiry < time_second) { - if (vget(vp, NULL, LK_EXCLUSIVE, td) == 0) { + if (vget(vp, LK_EXCLUSIVE, td) == 0) { nmp->nm_inprog = vp; if (vpid == vp->v_id) { CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); @@ -1080,7 +1080,7 @@ nqnfs_clientd(struct nfsmount *nmp, struct ucred *cred, struct nfsd_cargs *ncd, if ((np->n_flag & (NQNFSWRITE | NQNFSNONCACHE)) == NQNFSWRITE && !TAILQ_EMPTY(&vp->v_dirtyblkhd) && - vget(vp, NULL, LK_EXCLUSIVE, td) == 0) { + vget(vp, LK_EXCLUSIVE, td) == 0) { nmp->nm_inprog = vp; if (vpid == vp->v_id && nqnfs_getlease(vp, ND_WRITE, td)==0) diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index 76ec7bba33..c1ad8301e7 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.18 2004/10/07 04:20:27 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.19 2004/10/12 19:21:01 dillon Exp $ */ /* @@ -520,7 +520,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * via the original nd. Confused? You aren't alone! */ ind = nd; - VOP_UNLOCK(nd.ni_vp, NULL, 0, td); + VOP_UNLOCK(nd.ni_vp, 0, td); ind.ni_pathlen = strlen(nfs_pub.np_index); ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf = nfs_pub.np_index; @@ -2988,7 +2988,7 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* * end section. Allocate rbuf and continue @@ -3005,7 +3005,7 @@ again: io.uio_rw = UIO_READ; io.uio_td = NULL; eofflag = 0; - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (cookies) { free((caddr_t)cookies, M_TEMP); cookies = NULL; @@ -3019,7 +3019,7 @@ again: if (!error) error = getret; } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (error) { vrele(vp); vp = NULL; @@ -3270,7 +3270,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); again: iv.iov_base = rbuf; @@ -3283,7 +3283,7 @@ again: io.uio_rw = UIO_READ; io.uio_td = NULL; eofflag = 0; - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (cookies) { free((caddr_t)cookies, M_TEMP); cookies = NULL; @@ -3291,7 +3291,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, NULL, 0, td); + VOP_UNLOCK(vp, 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 d4849d65f6..e6278a5d1b 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: /repoman/r/ncvs/src/sys/nfsclient/nfs_subs.c,v 1.128 2004/04/14 23:23:55 peadar Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.21 2004/09/16 15:15:51 joerg Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.22 2004/10/12 19:21:01 dillon Exp $ */ /* @@ -1610,7 +1610,7 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, * Validate symlink */ if ((cnp->cn_flags & CNP_LOCKPARENT) && ndp->ni_pathlen == 1) - VOP_UNLOCK(ndp->ni_dvp, NULL, 0, td); + VOP_UNLOCK(ndp->ni_dvp, 0, td); if (!pubflag) { error = EINVAL; goto badlink2; @@ -1928,7 +1928,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, nfsrv_object_create(*vpp); if (!lockflag) - VOP_UNLOCK(*vpp, NULL, 0, td); + VOP_UNLOCK(*vpp, 0, td); return (0); } diff --git a/sys/vfs/nfs/nfs_vfsops.c b/sys/vfs/nfs/nfs_vfsops.c index 9d0d42002b..fa1298385f 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.21 2004/09/30 19:00:08 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.22 2004/10/12 19:21:01 dillon Exp $ */ #include "opt_bootp.h" @@ -989,7 +989,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, /* * Lose the lock but keep the ref. */ - VOP_UNLOCK(*vpp, NULL, 0, curthread); + VOP_UNLOCK(*vpp, 0, curthread); return (0); bad: @@ -1112,7 +1112,7 @@ struct scaninfo { }; static int nfs_sync_scan1(struct mount *mp, struct vnode *vp, void *data); -static int nfs_sync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data); +static int nfs_sync_scan2(struct mount *mp, struct vnode *vp, void *data); /* * Flush out the buffer cache @@ -1135,7 +1135,7 @@ nfs_sync(struct mount *mp, int waitfor, struct thread *td) error = 0; while (error == 0 && scaninfo.rescan) { scaninfo.rescan = 0; - error = vmntvnodescan(mp, nfs_sync_scan1, + error = vmntvnodescan(mp, VMSC_GETVP, nfs_sync_scan1, nfs_sync_scan2, &scaninfo); } return(error); @@ -1156,19 +1156,14 @@ nfs_sync_scan1(struct mount *mp, struct vnode *vp, void *data) static int -nfs_sync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data) +nfs_sync_scan2(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; int error; - if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) { - info->rescan = 1; - return(0); - } error = VOP_FSYNC(vp, info->waitfor, info->td); if (error) info->allerror = error; - vput(vp); return(0); } diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index e8bc34fa3a..cf908db2bf 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.34 2004/10/07 10:03:03 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.35 2004/10/12 19:21:01 dillon Exp $ */ @@ -898,20 +898,20 @@ nfs_lookup(struct vop_lookup_args *ap) /* newvp already ref'd from lookup */ error = 0; } else if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; - error = vget(newvp, NULL, LK_EXCLUSIVE, td); + error = vget(newvp, LK_EXCLUSIVE, td); vrele(newvp); /* get rid of ref from lookup */ if (!error && lockparent && (flags & CNP_ISLASTCN)) { - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error == 0) cnp->cn_flags &= ~CNP_PDIRUNLOCK; } } else { - error = vget(newvp, NULL, LK_EXCLUSIVE, td); + error = vget(newvp, LK_EXCLUSIVE, td); vrele(newvp); /* get rid of ref from lookup */ if (!lockparent || error || !(flags & CNP_ISLASTCN)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } @@ -938,11 +938,11 @@ nfs_lookup(struct vop_lookup_args *ap) } vput(newvp); if (lockparent && dvp != newvp && (flags & CNP_ISLASTCN)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error == 0) cnp->cn_flags &= ~CNP_PDIRUNLOCK; *vpp = NULLVP; @@ -1012,24 +1012,24 @@ miss: m_freem(mrep); cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (0); } if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); if (error) { - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); cnp->cn_flags &= ~CNP_PDIRUNLOCK; return (error); /* NOTE: return error from nget */ } newvp = NFSTOV(np); if (lockparent && (flags & CNP_ISLASTCN)) { - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error) { vput(newvp); return (error); @@ -1046,7 +1046,7 @@ miss: return (error); } if (!lockparent || !(flags & CNP_ISLASTCN)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } newvp = NFSTOV(np); @@ -1074,7 +1074,7 @@ nfsmout: if ((cnp->cn_nameiop == NAMEI_CREATE || cnp->cn_nameiop == NAMEI_RENAME) && (flags & CNP_ISLASTCN) && error == ENOENT) { if (!lockparent) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } if (dvp->v_mount->mnt_flag & MNT_RDONLY) @@ -1718,12 +1718,17 @@ nfs_rename(struct vop_rename_args *ap) * If the tvp exists and is in use, sillyrename it before doing the * rename of the new file over it. * XXX Can't sillyrename a directory. + * + * We must purge tvp from the cache (old API) or further accesses + * will see the old version of the file and return ESTALE. */ if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { cache_purge(tvp); vput(tvp); tvp = NULL; + } else if (tvp) { + cache_purge(tvp); } error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, diff --git a/sys/vfs/ntfs/ntfs.h b/sys/vfs/ntfs/ntfs.h index 977920dd7d..00d4680a47 100644 --- a/sys/vfs/ntfs/ntfs.h +++ b/sys/vfs/ntfs/ntfs.h @@ -26,7 +26,7 @@ * 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.6 2004/08/17 18:57:34 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs.h,v 1.7 2004/10/12 19:21:02 dillon Exp $ */ /*#define NTFS_DEBUG 1*/ @@ -317,9 +317,9 @@ 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), 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 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), curthread) #endif /* NetBSD */ diff --git a/sys/vfs/ntfs/ntfs_vfsops.c b/sys/vfs/ntfs/ntfs_vfsops.c index 0a09f58db9..85efbdfb88 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.22 2004/09/30 19:00:11 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.23 2004/10/12 19:21:02 dillon Exp $ */ @@ -938,15 +938,9 @@ ntfs_vgetex(struct mount *mp, ino_t ino, u_int32_t attrtype, char *attrname, ntfs_ntput(ip); - if (lkflags & LK_TYPE_MASK) { - KKASSERT((lkflags & LK_INTERLOCK) == 0); - error = VN_LOCK(vp, lkflags, td); - if (error) { - vput(vp); - return (error); - } - } - + KKASSERT(lkflags & LK_TYPE_MASK); + KKASSERT((lkflags & LK_INTERLOCK) == 0); + /* XXX leave vnode locked exclusively from getnewvnode */ *vpp = vp; return (0); diff --git a/sys/vfs/ntfs/ntfs_vnops.c b/sys/vfs/ntfs/ntfs_vnops.c index cee84d914f..5a37ab2053 100644 --- a/sys/vfs/ntfs/ntfs_vnops.c +++ b/sys/vfs/ntfs/ntfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_vnops.c,v 1.9.2.4 2002/08/06 19:35:18 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.17 2004/10/05 03:24:32 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.18 2004/10/12 19:21:02 dillon Exp $ * */ @@ -270,9 +270,8 @@ ntfs_inactive(struct vop_inactive_args *ap) if (ntfs_prtactive && vp->v_usecount != 0) vprint("ntfs_inactive: pushing active", vp); - VOP__UNLOCK(vp, 0, ap->a_td); - - /* XXX since we don't support any filesystem changes + /* + * XXX since we don't support any filesystem changes * right now, nothing more needs to be done */ return (0); @@ -299,9 +298,6 @@ ntfs_reclaim(struct vop_reclaim_args *ap) if ((error = ntfs_ntget(ip)) != 0) return (error); - /* Purge old data structures associated with the inode. */ - cache_inval_vp(vp, CINV_SELF); - ntfs_frele(fp); ntfs_ntput(ip); vp->v_data = NULL; diff --git a/sys/vfs/nullfs/null_subr.c b/sys/vfs/nullfs/null_subr.c index 93b136aa5c..3f119c16a4 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.15 2004/10/07 01:13:21 dillon Exp $ + * $DragonFly: src/sys/vfs/nullfs/Attic/null_subr.c,v 1.16 2004/10/12 19:21:04 dillon Exp $ */ #include @@ -120,7 +120,7 @@ loop: for (np = *NULL_NHASH(lowervp); np; np = np->null_next) { if (np->null_lowervp == lowervp && NULLTOV(np)->v_mount == mp) { vp = NULLTOV(np); - if (vget(vp, NULL, LK_EXCLUSIVE | LK_CANRECURSE, td)) { + if (vget(vp, LK_EXCLUSIVE | LK_CANRECURSE, td)) { printf ("null_node_find: vget failed.\n"); goto loop; } @@ -147,7 +147,7 @@ loop: * SUCCESS! Returned the locked and referenced vp * and release the lock on lowervp. */ - VOP_UNLOCK(lowervp, NULL, 0, td); + VOP_UNLOCK(lowervp, 0, td); lwkt_reltoken(&ilock); return (vp); } @@ -255,11 +255,9 @@ retry: np->null_lowervp = lowervp; /* - * Lock our new vnode + * Our new vnode is already VX locked (which is effective + * LK_THISLAYER, which is what we want). */ - error = VOP_LOCK(vp, NULL, LK_EXCLUSIVE | LK_THISLAYER, td); - if (error) - panic("null_node_alloc: can't lock new vnode\n"); /* * Try to add our new node to the hash table. If a collision diff --git a/sys/vfs/nullfs/null_vfsops.c b/sys/vfs/nullfs/null_vfsops.c index dd3e541f33..96b6a8ec2a 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.12 2004/09/30 19:00:13 dillon Exp $ + * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.13 2004/10/12 19:21:04 dillon Exp $ */ /* @@ -115,7 +115,7 @@ nullfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) */ if ((mp->mnt_vnodecovered->v_tag == VT_NULL) && VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) { - VOP_UNLOCK(mp->mnt_vnodecovered, NULL, 0, td); + VOP_UNLOCK(mp->mnt_vnodecovered, 0, td); isvnunlocked = 1; } /* @@ -128,7 +128,7 @@ nullfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) * Re-lock vnode. */ if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) - vn_lock(mp->mnt_vnodecovered, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, td); if (error) return (error); @@ -169,7 +169,7 @@ nullfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) /* * Unlock the node (either the lower or the alias) */ - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* * Make sure the node alias worked */ @@ -266,7 +266,7 @@ nullfs_root(struct mount *mp, struct vnode **vpp) return (EDEADLK); } #endif - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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 f27b3ceda2..33054b6df0 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.17 2004/10/07 01:13:21 dillon Exp $ + * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.18 2004/10/12 19:21:04 dillon Exp $ * ...and... * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project * @@ -192,6 +192,7 @@ SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW, &null_bug_bypass, 0, ""); static int null_resolve(struct vop_resolve_args *ap); +static int null_revoke(struct vop_revoke_args *ap); static int null_access(struct vop_access_args *ap); static int null_createvobject(struct vop_createvobject_args *ap); static int null_destroyvobject(struct vop_destroyvobject_args *ap); @@ -326,8 +327,7 @@ null_bypass(struct vop_generic_args *ap) * actually locked once. */ if (reles & (VDESC_VP0_WILLUNLOCK << i)) { - VOP_UNLOCK(old_vps[i], NULL, - LK_THISLAYER, curthread); + VOP_UNLOCK(old_vps[i], LK_THISLAYER, curthread); for (j = i + 1; j < VDESC_MAX_VPS; ++j) { if (descp->vdesc_vp_offsets[j] == VDESC_NO_OFFSET) break; @@ -401,7 +401,7 @@ null_lookup(struct vop_lookup_args *ap) */ if (flags & CNP_ISDOTDOT) { vref(ldvp); - VOP_UNLOCK(dvp, NULL, LK_THISLAYER, td); + VOP_UNLOCK(dvp, LK_THISLAYER, td); } /* @@ -439,10 +439,10 @@ null_lookup(struct vop_lookup_args *ap) */ if (flags & CNP_ISDOTDOT) { if ((cnp->cn_flags & CNP_PDIRUNLOCK) == 0) - VOP_LOCK(dvp, NULL, LK_THISLAYER | LK_EXCLUSIVE, td); + VOP_LOCK(dvp, LK_THISLAYER | LK_EXCLUSIVE, td); vrele(ldvp); } else if (cnp->cn_flags & CNP_PDIRUNLOCK) { - VOP_UNLOCK(dvp, NULL, LK_THISLAYER, td); + VOP_UNLOCK(dvp, LK_THISLAYER, td); } return (error); } @@ -518,6 +518,26 @@ null_resolve(struct vop_resolve_args *ap) return(vop_noresolve(ap)); } +/* + * revoke is VX locked, we can't go through null_bypass + */ +static int +null_revoke(struct vop_revoke_args *ap) +{ + struct null_node *np; + struct vnode *lvp; + + np = VTONULL(ap->a_vp); + vx_unlock(ap->a_vp); + if ((lvp = np->null_lowervp) != NULL) { + vx_get(lvp); + VOP_REVOKE(lvp, ap->a_flags); + vx_put(lvp); + } + vx_lock(ap->a_vp); + vgone(ap->a_vp); +} + /* * Handle to disallow write access if mounted read-only. * @@ -608,8 +628,7 @@ null_rename(struct vop_rename_args *ap) * ONLY on the nullfs layer. Otherwise we are responsible for locking not * only our layer, but the lower layer as well. * - * null_lock(struct vnode *a_vp, lwkt_tokref_t a_vlock, int a_flags, - * struct thread *a_td) + * null_lock(struct vnode *a_vp, int a_flags, struct thread *a_td) */ static int null_lock(struct vop_lock_args *ap) @@ -624,9 +643,9 @@ null_lock(struct vop_lock_args *ap) * Lock the nullfs layer first, disposing of the interlock in the * process. */ + KKASSERT((flags & LK_INTERLOCK) == 0); error = lockmgr(&vp->v_lock, flags & ~LK_THISLAYER, - ap->a_vlock, ap->a_td); - flags &= ~LK_INTERLOCK; + NULL, ap->a_td); /* * If locking only the nullfs layer, or if there is no lower layer, @@ -650,11 +669,10 @@ null_lock(struct vop_lock_args *ap) lvp = np->null_lowervp; if ((flags & LK_TYPE_MASK) == LK_DRAIN) { NULLFSDEBUG("null_lock: avoiding LK_DRAIN\n"); - error = vn_lock(lvp, NULL, - (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE, + error = vn_lock(lvp, (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE, ap->a_td); } else { - error = vn_lock(lvp, NULL, flags, ap->a_td); + error = vn_lock(lvp, flags, ap->a_td); } /* @@ -671,8 +689,7 @@ null_lock(struct vop_lock_args *ap) * ONLY on the nullfs layer. Otherwise we are responsible for unlocking not * only our layer, but the lower layer as well. * - * null_unlock(struct vnode *a_vp, lwkt_tokref_t a_vlock, int a_flags, - * struct thread *a_td) + * null_unlock(struct vnode *a_vp, int a_flags, struct thread *a_td) */ static int null_unlock(struct vop_unlock_args *ap) @@ -683,14 +700,14 @@ null_unlock(struct vop_unlock_args *ap) struct vnode *lvp; int error; + KKASSERT((flags & LK_INTERLOCK) == 0); /* * nullfs layer only */ if (flags & LK_THISLAYER) { error = lockmgr(&vp->v_lock, (flags & ~LK_THISLAYER) | LK_RELEASE, - ap->a_vlock, - ap->a_td); + NULL, ap->a_td); return (error); } @@ -701,16 +718,15 @@ null_unlock(struct vop_unlock_args *ap) */ if (np == NULL || (lvp = np->null_lowervp) == NULL) { error = lockmgr(&vp->v_lock, flags | LK_RELEASE, - ap->a_vlock, ap->a_td); + NULL, ap->a_td); return(error); } /* * Unlock the lower layer first, then our nullfs layer. */ - VOP_UNLOCK(lvp, NULL, flags & ~LK_INTERLOCK, ap->a_td); - error = lockmgr(&vp->v_lock, flags | LK_RELEASE, - ap->a_vlock, ap->a_td); + VOP_UNLOCK(lvp, flags, ap->a_td); + error = lockmgr(&vp->v_lock, flags | LK_RELEASE, NULL, ap->a_td); return (error); } @@ -748,7 +764,7 @@ null_islocked(struct vop_islocked_args *ap) static int null_inactive(struct vop_inactive_args *ap) { - struct vnode *vp = ap->a_vp; + /*struct vnode *vp = ap->a_vp;*/ /*struct null_node *np = VTONULL(vp);*/ /* @@ -761,7 +777,6 @@ null_inactive(struct vop_inactive_args *ap) /* * Now it is safe to release our nullfs layer vnode. */ - VOP_UNLOCK(vp, NULL, 0, ap->a_td); return (0); } @@ -898,6 +913,7 @@ struct vnodeopv_entry_desc null_vnodeop_entries[] = { { &vop_rename_desc, (void *) null_rename }, { &vop_setattr_desc, (void *) null_setattr }, { &vop_unlock_desc, (void *) null_unlock }, + { &vop_revoke_desc, (void *) null_revoke }, { NULL, NULL } }; diff --git a/sys/vfs/nwfs/nwfs_io.c b/sys/vfs/nwfs/nwfs_io.c index 4c4ba905b9..4cced63ac0 100644 --- a/sys/vfs/nwfs/nwfs_io.c +++ b/sys/vfs/nwfs/nwfs_io.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/nwfs/nwfs_io.c,v 1.6.2.1 2000/10/25 02:11:10 bp Exp $ - * $DragonFly: src/sys/vfs/nwfs/nwfs_io.c,v 1.11 2004/09/30 19:00:15 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_io.c,v 1.12 2004/10/12 19:21:05 dillon Exp $ * */ #include @@ -578,7 +578,7 @@ nwfs_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg) /* struct nwmount *nmp = VTONWFS(vp);*/ int error = 0, slpflag, slptimeo; - if (vp->v_flag & VXLOCK) { + if (vp->v_flag & VRECLAIMED) { return (0); } if (intrflg) { diff --git a/sys/vfs/nwfs/nwfs_node.c b/sys/vfs/nwfs/nwfs_node.c index 7997151920..b220db8e02 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.15 2004/10/05 03:24:33 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_node.c,v 1.16 2004/10/12 19:21:05 dillon Exp $ */ #include #include @@ -141,7 +141,6 @@ 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; loop: @@ -149,10 +148,13 @@ loop: rescan: if (nwfs_hashlookup(nmp, fid, &np) == 0) { vp = NWTOV(np); - lwkt_gettoken(&vlock, vp->v_interlock); lockmgr(&nwhashlock, LK_RELEASE, NULL, td); - if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td)) + if (vget(vp, LK_EXCLUSIVE, td)) goto loop; + if (nwfs_hashlookup(nmp, fid, &np) || NWTOV(np) != vp) { + vput(vp); + goto loop; + } *vpp = vp; return(0); } @@ -172,7 +174,6 @@ rescan: } np->n_vnode = vp; np->n_mount = nmp; - lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL, td); /* * Another process can create vnode while we blocked in malloc() or @@ -181,7 +182,7 @@ rescan: lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, td); if (nwfs_hashlookup(nmp, fid, NULL) == 0) { np->n_vnode = NULL; - vput(vp); + vx_put(vp); free(np, M_NWNODE); goto rescan; } @@ -235,7 +236,6 @@ nwfs_reclaim(struct vop_reclaim_args *ap) LIST_REMOVE(np, n_hash); lockmgr(&nwhashlock, LK_RELEASE, NULL, td); } - cache_inval_vp(vp, CINV_SELF); if (nmp->n_root == np) nmp->n_root = NULL; vp->v_data = NULL; @@ -267,9 +267,7 @@ nwfs_inactive(struct vop_inactive_args *ap) error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, td, cred); np->opened = 0; } - VOP_UNLOCK(vp, NULL, 0, td); if (np == NULL || (np->n_flag & NSHOULDFREE)) { - cache_inval_vp(vp, CINV_SELF); vgone(vp); } return (0); diff --git a/sys/vfs/nwfs/nwfs_vfsops.c b/sys/vfs/nwfs/nwfs_vfsops.c index 2a50d5c2a4..a66ad8192a 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.12 2004/09/30 19:00:15 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_vfsops.c,v 1.13 2004/10/12 19:21:05 dillon Exp $ */ #include "opt_ncp.h" #ifndef NCP @@ -228,7 +228,7 @@ nwfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) /* * Lose the lock but keep the ref. */ - VOP_UNLOCK(vp, NULL, 0, curthread); + VOP_UNLOCK(vp, 0, curthread); NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_usecount); return error; bad: @@ -294,7 +294,7 @@ nwfs_root(struct mount *mp, struct vnode **vpp) conn = NWFSTOCONN(nmp); if (nmp->n_root) { *vpp = NWTOV(nmp->n_root); - while (vget(*vpp, NULL, LK_EXCLUSIVE, curthread) != 0) /* XXX */ + while (vget(*vpp, LK_EXCLUSIVE, curthread) != 0) /* XXX */ ; return 0; } @@ -497,8 +497,9 @@ loop: if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; - if (vget(vp, NULL, LK_EXCLUSIVE, td)) + if (vget(vp, LK_EXCLUSIVE, td)) goto loop; + /* XXX vp may not be retained */ error = VOP_FSYNC(vp, waitfor, td); if (error) allerror = error; diff --git a/sys/vfs/nwfs/nwfs_vnops.c b/sys/vfs/nwfs/nwfs_vnops.c index 0f9bbc417c..8c6030184c 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.17 2004/10/07 10:03:04 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.18 2004/10/12 19:21:05 dillon Exp $ */ #include #include @@ -228,32 +228,23 @@ nwfs_close(struct vop_close_args *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(&vlock, vp->v_interlock); if (np->opened == 0) { - lwkt_reltoken(&vlock); return 0; } - lwkt_reltoken(&vlock); error = nwfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1); - lwkt_gettokref(&vlock); if (np->opened == 0) { - lwkt_reltoken(&vlock); return 0; } if (--np->opened == 0) { - lwkt_reltoken(&vlock); error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, ap->a_td, proc0.p_ucred); - } else { - lwkt_reltoken(&vlock); - } + } np->n_atime = 0; return (error); } @@ -901,16 +892,16 @@ 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, NULL, 0, td); /* unlock parent */ - error = vget(vp, NULL, LK_EXCLUSIVE, td); + VOP_UNLOCK(dvp, 0, td); /* unlock parent */ + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!error && lockparent && islastcn) - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); } else { - error = vget(vp, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!lockparent || error || !islastcn) - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); } if (!error) { if (vpid == vp->v_id) { @@ -925,9 +916,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, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); } - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); *vpp = NULLVP; if (error) return (error); @@ -970,7 +961,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, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); return (EJUSTRETURN); } return ENOENT; @@ -990,7 +981,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, NULL, 0, td); + if (!lockparent) VOP_UNLOCK(dvp, 0, td); return (0); } if (nameiop == NAMEI_RENAME && islastcn && wantparent) { @@ -1002,18 +993,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, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); return (0); } if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); /* race to get the inode */ + VOP_UNLOCK(dvp, 0, td); /* race to get the inode */ error = nwfs_nget(mp, fid, NULL, NULL, &vp); if (error) { - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } if (lockparent && islastcn && - (error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td))) { + (error = vn_lock(dvp, LK_EXCLUSIVE, td))) { vput(vp); return (error); } @@ -1027,7 +1018,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, NULL, 0, td); + VOP_UNLOCK(dvp, 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 a724df1807..18b31555a6 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.12 2004/09/30 19:00:17 dillon Exp $ + * $DragonFly: src/sys/vfs/portal/portal_vfsops.c,v 1.13 2004/10/12 19:21:06 dillon Exp $ */ /* @@ -145,6 +145,7 @@ portal_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy("portal", mp->mnt_stat.f_mntfromname, sizeof("portal")); #endif + vx_unlock(rvp); (void)portal_statfs(mp, &mp->mnt_stat, td); fdrop(fp, td); @@ -205,7 +206,7 @@ portal_root(struct mount *mp, struct vnode **vpp) */ vp = VFSTOPORTAL(mp)->pm_root; vref(vp); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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 ed6064d5db..b04345afc7 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.16 2004/08/28 19:02:25 dillon Exp $ + * $DragonFly: src/sys/vfs/portal/portal_vnops.c,v 1.17 2004/10/12 19:21:06 dillon Exp $ */ /* @@ -158,6 +158,7 @@ portal_lookup(struct vop_lookup_args *ap) pt->pt_fileid = portal_fileid++; *vpp = fvp; + vx_unlock(fvp); /*VOP_LOCK(fvp);*/ return (0); @@ -519,7 +520,6 @@ portal_readdir(struct vop_readdir_args *ap) static int portal_inactive(struct vop_inactive_args *ap) { - 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 afe0369ffa..6ccdf2f6b0 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.10 2004/08/28 19:02:27 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_subr.c,v 1.11 2004/10/12 19:21:07 dillon Exp $ */ #include @@ -88,7 +88,6 @@ procfs_allocvp(struct mount *mp, struct vnode **vpp, long pid, pfstype pfs_type) struct vnode *vp; struct pfsnode **pp; int error; - lwkt_tokref vlock; pp = PFSHASH(pid); loop: @@ -96,7 +95,8 @@ loop: if (pfs->pfs_pid == pid && pfs->pfs_type == pfs_type && PFSTOV(pfs)->v_mount == mp) { vp = PFSTOV(pfs); - lwkt_gettoken(&vlock, vp->v_interlock); + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; /* * Make sure the vnode is still in the cache after @@ -110,13 +110,11 @@ loop: break; } } - if (pfs == NULL) { - lwkt_reltoken(&vlock); + if (pfs == NULL || PFSTOV(pfs) != vp) { + vput(vp); goto loop; } - if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td)) - goto loop; *vpp = vp; return (0); } @@ -137,6 +135,9 @@ loop: * Do the MALLOC before the getnewvnode since doing so afterward * might cause a bogus v_data pointer to get dereferenced * elsewhere if MALLOC should block. + * + * XXX this may not matter anymore since getnewvnode now returns + * a VX locked vnode. */ MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); @@ -147,9 +148,6 @@ loop: } vp = *vpp; - if (lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL, td)) - panic("procfs_allocvp: unexpected lock vailure"); - vp->v_data = pfs; pfs->pfs_next = 0; @@ -399,6 +397,7 @@ void procfs_exit(struct thread *td) { struct pfsnode *pfs; + struct vnode *vp; pid_t pid; KKASSERT(td->td_proc); @@ -426,7 +425,11 @@ again: pfs = *PFSHASH(pid); while (pfs) { if (pfs->pfs_pid == pid) { - vgone(PFSTOV(pfs)); + vp = PFSTOV(pfs); + if (vx_lock(vp) == 0) { + vgone(vp); + vx_unlock(vp); + } goto again; } pfs = pfs->pfs_next; diff --git a/sys/vfs/procfs/procfs_vnops.c b/sys/vfs/procfs/procfs_vnops.c index d862df6b39..1741eec553 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.19 2004/08/28 19:02:27 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.20 2004/10/12 19:21:07 dillon Exp $ */ /* @@ -347,9 +347,7 @@ procfs_bmap(struct vop_bmap_args *ap) static int procfs_inactive(struct vop_inactive_args *ap) { - struct vnode *vp = ap->a_vp; - - VOP_UNLOCK(vp, NULL, 0, ap->a_td); + /*struct vnode *vp = ap->a_vp;*/ return (0); } @@ -757,7 +755,7 @@ out: if (error == 0) { if (*vpp != dvp && (cnp->cn_flags & CNP_LOCKPARENT) == 0) { cnp->cn_flags |= CNP_PDIRUNLOCK; - VOP_UNLOCK(dvp, NULL, 0, cnp->cn_td); + VOP_UNLOCK(dvp, 0, cnp->cn_td); } } return (error); diff --git a/sys/vfs/smbfs/smbfs_io.c b/sys/vfs/smbfs/smbfs_io.c index d3b81070bd..dceb4102b8 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.12 2004/09/30 19:00:21 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_io.c,v 1.13 2004/10/12 19:21:08 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, NULL, LK_UPGRADE | LK_RETRY, td); + vn_lock(vp, LK_UPGRADE | LK_RETRY, td); error = smbfs_readvdir(vp, uiop, cred); if (lks == LK_SHARED) - vn_lock(vp, NULL, LK_DOWNGRADE | LK_RETRY, td); + vn_lock(vp, LK_DOWNGRADE | LK_RETRY, td); return error; } @@ -609,7 +609,7 @@ smbfs_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg) struct smbnode *np = VTOSMB(vp); int error = 0, slpflag, slptimeo; - if (vp->v_flag & VXLOCK) + if (vp->v_flag & VRECLAIMED) return 0; if (intrflg) { slpflag = PCATCH; diff --git a/sys/vfs/smbfs/smbfs_node.c b/sys/vfs/smbfs/smbfs_node.c index d0e0090100..7f4865284f 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.14 2004/10/05 03:24:34 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_node.c,v 1.15 2004/10/12 19:21:08 dillon Exp $ */ #include #include @@ -168,7 +168,6 @@ 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 +179,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, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); if (error == 0) *vpp = vp; return error; @@ -199,14 +198,25 @@ retry: loop: nhpp = SMBFS_NOHASH(smp, hashval); LIST_FOREACH(np, nhpp, n_hash) { - vp = SMBTOV(np); if (np->n_parent != dvp || np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0) continue; - VI_LOCK(&vlock, vp); + vp = SMBTOV(np); smbfs_hash_unlock(smp, td); - if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0) + if (vget(vp, LK_EXCLUSIVE, td) != 0) goto retry; + /* + * relookup after we blocked. + */ + LIST_FOREACH(np2, nhpp, n_hash) { + if (np2->n_parent == dvp && np2->n_nmlen == nmlen && + bcmp(name, np2->n_name, nmlen) == 0) + break; + } + if (np2 != np || SMBTOV(np2) != vp) { + vput(vp); + goto retry; + } *vpp = vp; return 0; } @@ -243,20 +253,21 @@ loop: } else if (vp->v_type == VREG) SMBERROR("new vnode '%s' born without parent ?\n", np->n_name); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); - smbfs_hash_lock(smp, td); LIST_FOREACH(np2, nhpp, n_hash) { if (np2->n_parent != dvp || np2->n_nmlen != nmlen || bcmp(name, np2->n_name, nmlen) != 0) continue; - vput(vp); + vx_put(vp); /* smb_name_free(np->n_name); FREE(np, M_SMBNODE);*/ goto loop; } LIST_INSERT_HEAD(nhpp, np, n_hash); smbfs_hash_unlock(smp, td); + /* + * Return a locked and refd vnode + */ *vpp = vp; return 0; } @@ -293,7 +304,6 @@ smbfs_reclaim(struct vop_reclaim_args *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); @@ -304,7 +314,6 @@ smbfs_reclaim(struct vop_reclaim_args *ap) if (np->n_hash.le_prev) LIST_REMOVE(np, n_hash); - cache_inval_vp(vp, CINV_SELF); if (smp->sm_root == np) { SMBVDEBUG("root vnode\n"); smp->sm_root = NULL; @@ -315,19 +324,12 @@ smbfs_reclaim(struct vop_reclaim_args *ap) smbfs_name_free(np->n_name); FREE(np, M_SMBNODE); if (dvp) { - VI_LOCK(&vlock, dvp); - if (dvp->v_usecount >= 1) { - VI_UNLOCK(&vlock, dvp); - vrele(dvp); - /* - * Indicate that we released something; see comment - * in smbfs_unmount(). - */ - smp->sm_didrele = 1; - } else { - VI_UNLOCK(&vlock, dvp); - SMBERROR("BUG: negative use count for parent!\n"); - } + /* + * Indicate that we released something; see comment + * in smbfs_unmount(). + */ + smp->sm_didrele = 1; + vrele(dvp); } return 0; } @@ -356,7 +358,6 @@ smbfs_inactive(struct vop_inactive_args *ap) &np->n_mtime, &scred); np->n_opencount = 0; } - 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 28c6a47da4..d24a86c346 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.14 2004/09/30 19:00:21 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_vfsops.c,v 1.15 2004/10/12 19:21:08 dillon Exp $ */ #include "opt_netsmb.h" #ifndef NETSMB @@ -227,7 +227,7 @@ smbfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) error = smbfs_root(mp, &vp); if (error) goto bad; - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); SMBVDEBUG("root.v_usecount = %d\n", vp->v_usecount); #ifdef DIAGNOSTICS @@ -321,7 +321,7 @@ smbfs_root(struct mount *mp, struct vnode **vpp) } if (smp->sm_root) { *vpp = SMBTOV(smp->sm_root); - return vget(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td); } smb_makescred(&scred, td, cred); error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred); @@ -448,7 +448,7 @@ loop: if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; - if (vget(vp, NULL, LK_EXCLUSIVE, td)) + if (vget(vp, 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 d5ced56081..eb991bb54e 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.19 2004/10/07 10:03:06 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.20 2004/10/12 19:21:08 dillon Exp $ */ #include #include @@ -64,7 +64,7 @@ static int smbfs_create(struct vop_create_args *); static int smbfs_mknod(struct vop_mknod_args *); static int smbfs_open(struct vop_open_args *); -static int smbfs_close(struct vop_close_args *); +static int smbfs_closel(struct vop_close_args *); static int smbfs_access(struct vop_access_args *); static int smbfs_getattr(struct vop_getattr_args *); static int smbfs_setattr(struct vop_setattr_args *); @@ -91,7 +91,7 @@ struct vnodeopv_entry_desc smbfs_vnodeop_entries[] = { { &vop_access_desc, (void *) smbfs_access }, { &vop_advlock_desc, (void *) smbfs_advlock }, { &vop_bmap_desc, (void *) smbfs_bmap }, - { &vop_close_desc, (void *) smbfs_close }, + { &vop_close_desc, (void *) smbfs_closel }, { &vop_create_desc, (void *) smbfs_create }, { &vop_fsync_desc, (void *) smbfs_fsync }, { &vop_getattr_desc, (void *) smbfs_getattr }, @@ -262,33 +262,6 @@ smbfs_closel(struct vop_close_args *ap) return error; } -/* - * XXX: VOP_CLOSE() usually called without lock held which is suck. Here we - * do some heruistic to determine if vnode should be locked. - * - * smbfs_close(struct vnodeop_desc *a_desc, struct vnode *a_vp, int a_fflag, - * struct ucred *a_cred, struct thread *a_td) - */ -static int -smbfs_close(struct vop_close_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct thread *td = ap->a_td; - int error, dolock; - lwkt_tokref vlock; - - VI_LOCK(&vlock, vp); - dolock = (vp->v_flag & VXLOCK) == 0; - if (dolock) - vn_lock(vp, &vlock, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td); - else - VI_UNLOCK(&vlock, vp); - error = smbfs_closel(ap); - if (dolock) - VOP_UNLOCK(vp, NULL, 0, td); - return error; -} - /* * smbfs_getattr call from vfs. * @@ -633,6 +606,7 @@ out: vrele(fdvp); vrele(fvp); #ifdef possible_mistake +#error x vgone(fvp); if (tvp) vgone(tvp); @@ -1117,20 +1091,20 @@ smbfs_lookup(struct vop_lookup_args *ap) error = 0; SMBVDEBUG("cached '.'\n"); } else if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); /* unlock parent */ + VOP_UNLOCK(dvp, 0, td); /* unlock parent */ cnp->cn_flags |= CNP_PDIRUNLOCK; - error = vget(vp, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!error && lockparent && islastcn) { - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error == 0) cnp->cn_flags &= ~CNP_PDIRUNLOCK; } } else { - error = vget(vp, NULL, LK_EXCLUSIVE, td); + error = vget(vp, LK_EXCLUSIVE, td); vrele(vp); if (!lockparent || error || !islastcn) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } @@ -1147,9 +1121,9 @@ smbfs_lookup(struct vop_lookup_args *ap) } vput(vp); if (lockparent && dvp != vp && islastcn) - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); } - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); *vpp = NULLVP; if (error) { cnp->cn_flags |= CNP_PDIRUNLOCK; @@ -1186,7 +1160,7 @@ smbfs_lookup(struct vop_lookup_args *ap) return error; cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (EJUSTRETURN); @@ -1213,7 +1187,7 @@ smbfs_lookup(struct vop_lookup_args *ap) *vpp = vp; cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return 0; @@ -1230,20 +1204,20 @@ smbfs_lookup(struct vop_lookup_args *ap) *vpp = vp; cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return 0; } if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); error = smbfs_nget(mp, dvp, name, nmlen, NULL, &vp); if (error) { - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); return error; } if (lockparent && islastcn) { - error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td); + error = vn_lock(dvp, LK_EXCLUSIVE, td); if (error) { cnp->cn_flags |= CNP_PDIRUNLOCK; vput(vp); @@ -1261,7 +1235,7 @@ smbfs_lookup(struct vop_lookup_args *ap) *vpp = vp; SMBVDEBUG("lookup: getnewvp!\n"); if (!lockparent || !islastcn) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } } diff --git a/sys/vfs/specfs/spec_vnops.c b/sys/vfs/specfs/spec_vnops.c index 2992d20189..38cf70727a 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.20 2004/08/17 18:57:35 dillon Exp $ + * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.21 2004/10/12 19:21:09 dillon Exp $ */ #include @@ -238,9 +238,9 @@ spec_open(struct vop_open_args *ap) * dev_dopen() is always called for each open. dev_dclose() is * only called for the last close unless D_TRACKCLOSE is set. */ - VOP_UNLOCK(vp, NULL, 0, ap->a_td); + VOP_UNLOCK(vp, 0, ap->a_td); error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_td); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td); if (error) goto done; @@ -304,9 +304,9 @@ spec_read(struct vop_read_args *ap) if (uio->uio_resid == 0) return (0); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); error = dev_dread(dev, uio, ap->a_ioflag); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } @@ -334,9 +334,9 @@ spec_write(struct vop_write_args *ap) if (dev == NULL) /* device was revoked */ return (EBADF); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); error = dev_dwrite(dev, uio, ap->a_ioflag); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } @@ -473,7 +473,6 @@ loop2: static int spec_inactive(struct vop_inactive_args *ap) { - VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } @@ -601,7 +600,7 @@ spec_close(struct vop_close_args *ap) if (dev) reference_dev(dev); if (vcount(vp) == 2 && vp->v_opencount <= 1 && - p && (vp->v_flag & VXLOCK) == 0 && vp == p->p_session->s_ttyvp) { + p && vp == p->p_session->s_ttyvp) { p->p_session->s_ttyvp = NULL; vrele(vp); } @@ -615,7 +614,7 @@ spec_close(struct vop_close_args *ap) * XXX the VXLOCK (force close) case can leave vnodes referencing * a closed device. */ - if (dev && ((vp->v_flag & VXLOCK) || + if (dev && ((vp->v_flag & VRECLAIMED) || (dev_dflags(dev) & D_TRACKCLOSE) || (vcount(vp) <= 1 && vp->v_opencount == 1))) { error = dev_dclose(dev, ap->a_fflag, S_IFCHR, ap->a_td); diff --git a/sys/vfs/udf/udf_vfsops.c b/sys/vfs/udf/udf_vfsops.c index 07552d2a87..c1b3a6ccc4 100644 --- a/sys/vfs/udf/udf_vfsops.c +++ b/sys/vfs/udf/udf_vfsops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.16 2003/11/05 06:56:08 scottl Exp $ - * $DragonFly: src/sys/vfs/udf/udf_vfsops.c,v 1.8 2004/09/30 19:00:23 dillon Exp $ + * $DragonFly: src/sys/vfs/udf/udf_vfsops.c,v 1.9 2004/10/12 19:21:10 dillon Exp $ */ /* udf_vfsops.c */ @@ -173,7 +173,7 @@ udf_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) } /* Check the access rights on the mount device */ - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(devvp, VREAD, td->td_proc->p_ucred, td); if (error) error = suser(td); @@ -181,7 +181,7 @@ udf_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) vput(devvp); return(error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if ((error = udf_mountfs(devvp, mp, td))) { vrele(devvp); @@ -254,9 +254,9 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) if ((error = vinvalbuf(devvp, V_SAVE, td, 0, 0))) return(error); - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, FREAD, FSCRED, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return(error); needclose = 1; @@ -573,6 +573,9 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp) vp->v_type = VLNK; break; } + /* + * Locked and refd vnode returned + */ *vpp = vp; return(0); diff --git a/sys/vfs/udf/udf_vnops.c b/sys/vfs/udf/udf_vnops.c index 653c0391c2..c1338f258d 100644 --- a/sys/vfs/udf/udf_vnops.c +++ b/sys/vfs/udf/udf_vnops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/udf/udf_vnops.c,v 1.33 2003/12/07 05:04:49 scottl Exp $ - * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.8 2004/09/30 19:00:23 dillon Exp $ + * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.9 2004/10/12 19:21:10 dillon Exp $ */ /* udf_vnops.c */ @@ -92,20 +92,24 @@ udf_hashlookup(struct udf_mnt *udfmp, ino_t id, struct vnode **vpp) { struct udf_node *node; struct udf_hash_lh *lh; - int error; - lwkt_tokref vlock, hashlock; + struct vnode *vp; + lwkt_tokref hashlock; *vpp = NULL; lwkt_gettoken(&hashlock, &udfmp->hash_token); loop: lh = &udfmp->hashtbl[id % udfmp->hashsz]; - if (lh == NULL) + if (lh == NULL) { + lwkt_reltoken(&hashlock); return(ENOENT); + } LIST_FOREACH(node, lh, le) { if (node->hash_id != id) continue; - lwkt_gettoken(&vlock, node->i_vnode->v_interlock); + vp = node->i_vnode; + if (vget(vp, LK_EXCLUSIVE, curthread)) + goto loop; /* * We must check to see if the inode has been ripped * out from under us after blocking. @@ -115,18 +119,12 @@ loop: if (node->hash_id == id) break; } - if (node == NULL) { - lwkt_reltoken(&vlock); + if (node == NULL || vp != node->i_vnode) { + vput(vp); goto loop; } - error = vget(node->i_vnode, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, - curthread); - if (error == ENOENT) - goto loop; lwkt_reltoken(&hashlock); - if (error) - return(error); - *vpp = node->i_vnode; + *vpp = vp; return(0); } @@ -143,7 +141,6 @@ udf_hashins(struct udf_node *node) udfmp = node->udfmp; - vn_lock(node->i_vnode, NULL, LK_EXCLUSIVE | LK_RETRY, curthread); lwkt_gettoken(&hashlock, &udfmp->hash_token); lh = &udfmp->hashtbl[node->hash_id % udfmp->hashsz]; if (lh == NULL) @@ -997,7 +994,7 @@ lookloop: gd->gd_nchstats->ncs_pass2++; if (!(flags & CNP_LOCKPARENT) || !(flags & CNP_ISLASTCN)) { a->a_cnp->cn_flags |= CNP_PDIRUNLOCK; - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); } *vpp = tdp; diff --git a/sys/vfs/ufs/ffs_rawread.c b/sys/vfs/ufs/ffs_rawread.c index 9e9eba44e0..48b5fb4e61 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.8 2004/07/18 19:43:48 drhodus Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_rawread.c,v 1.9 2004/10/12 19:21:12 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, NULL, LK_UPGRADE | LK_NOPAUSE, td); + VOP_LOCK(vp, 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, NULL, LK_DOWNGRADE, td); + VOP_LOCK(vp, 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, NULL, LK_DOWNGRADE, td); + VOP_LOCK(vp, 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, NULL, LK_DOWNGRADE, td); + VOP_LOCK(vp, LK_DOWNGRADE, td); } else { splx(spl); } diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c index 5040e5e60f..6b831bcc63 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.17 2004/09/16 22:12:07 joerg Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_softdep.c,v 1.18 2004/10/12 19:21:12 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_FSYNC(devvp, MNT_WAIT, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) break; } @@ -3969,7 +3969,7 @@ softdep_fsync(vp) * not now, but then the user was not asking to have it * written, so we are not breaking any promises. */ - if (vp->v_flag & VXLOCK) + if (vp->v_flag & VRECLAIMED) break; /* * We prevent deadlock by always fetching inodes from the @@ -3979,9 +3979,9 @@ softdep_fsync(vp) * ufs_lookup for details on possible races. */ FREE_LOCK(&lk); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); error = VFS_VGET(mnt, parentino, &pvp); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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 c377e3770b..daaf674e79 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.25 2004/09/30 19:00:25 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.26 2004/10/12 19:21:12 dillon Exp $ */ #include "opt_quota.h" @@ -228,13 +228,13 @@ ffs_mount(struct mount *mp, /* mount struct pointer */ * that user has necessary permissions on the device. */ if (cred->cr_uid != 0) { - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, cred, td)) != 0) { - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } fs->fs_flags &= ~FS_UNCLEAN; @@ -308,12 +308,12 @@ ffs_mount(struct mount *mp, /* mount struct pointer */ accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, accessmode, cred, td)) != 0) { vput(devvp); return (error); } - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); } if (mp->mnt_flag & MNT_UPDATE) { @@ -428,9 +428,7 @@ success: * 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); +static int ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data); struct scaninfo { int rescan; @@ -451,7 +449,6 @@ ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td) struct partinfo dpart; dev_t dev; int i, blks, size, error; - lwkt_tokref vlock; struct scaninfo scaninfo; int32_t *lp; @@ -461,9 +458,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = vinvalbuf(devvp, 0, td, 0, 0); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) panic("ffs_reload: dirty1"); @@ -473,10 +470,9 @@ 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); vfs_object_create(devvp, td); - lwkt_gettoken(&vlock, devvp->v_interlock); - VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td); + VOP_UNLOCK(devvp, 0, td); } /* @@ -553,29 +549,14 @@ ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td) scaninfo.td = td; while (error == 0 && scaninfo.rescan) { scaninfo.rescan = 0; - error = vmntvnodescan(mp, ffs_reload_scan1, - ffs_reload_scan2, &scaninfo); + error = vmntvnodescan(mp, VMSC_GETVX, + NULL, 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, info->td)) { - 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) +ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; struct inode *ip; @@ -583,12 +564,11 @@ ffs_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void * int error; /* - * Step 5: invalidate all cached file data. + * Try to recycle */ - if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) { - info->rescan = 1; + if (vrecycle(vp, info->td)) return(0); - } + if (vinvalbuf(vp, 0, info->td, 0, 0)) panic("ffs_reload: dirty2"); /* @@ -600,14 +580,12 @@ ffs_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void * (int)info->fs->fs_bsize, &bp); if (error) { brelse(bp); - vput(vp); return (error); } 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); } @@ -625,7 +603,6 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td, struct partinfo dpart; void *space; int error, i, blks, size, ronly; - lwkt_tokref vlock; int32_t *lp; uint64_t maxfilesize; /* XXX */ size_t strsize; @@ -640,9 +617,9 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td, return (error); if (count_udev(devvp->v_udev) > 0) return (EBUSY); - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = vinvalbuf(devvp, V_SAVE, td, 0, 0); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return (error); @@ -653,16 +630,15 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td, * increases the opportunity for metadata caching. */ if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) { - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); vfs_object_create(devvp, td); - lwkt_gettoken(&vlock, devvp->v_interlock); - VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td); + VOP_UNLOCK(devvp, 0, td); } ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td); - VOP_UNLOCK(devvp, NULL, 0, td); + VOP_UNLOCK(devvp, 0, td); if (error) return (error); dev = devvp->v_rdev; @@ -944,9 +920,9 @@ ffs_flushfiles(struct mount *mp, int flags, struct thread *td) /* * Flush filesystem metadata. */ - vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, td); - VOP_UNLOCK(ump->um_devvp, NULL, 0, td); + VOP_UNLOCK(ump->um_devvp, 0, td); return (error); } @@ -991,8 +967,7 @@ ffs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) 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); +static int ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data); int ffs_sync(struct mount *mp, int waitfor, struct thread *td) @@ -1016,7 +991,8 @@ ffs_sync(struct mount *mp, int waitfor, struct thread *td) scaninfo.waitfor = waitfor; while (scaninfo.rescan) { scaninfo.rescan = 0; - vmntvnodescan(mp, ffs_sync_scan1, ffs_sync_scan2, &scaninfo); + vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, + ffs_sync_scan1, ffs_sync_scan2, &scaninfo); } /* @@ -1025,10 +1001,10 @@ ffs_sync(struct mount *mp, int waitfor, struct thread *td) if (waitfor != MNT_LAZY) { if (ump->um_mountp->mnt_flag & MNT_SOFTDEP) waitfor = MNT_NOWAIT; - vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0) scaninfo.allerror = error; - VOP_UNLOCK(ump->um_devvp, NULL, 0, td); + VOP_UNLOCK(ump->um_devvp, 0, td); } #ifdef QUOTA qsync(mp); @@ -1065,8 +1041,7 @@ 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) +ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data) { struct scaninfo *info = data; thread_t td = curthread; /* XXX */ @@ -1080,31 +1055,19 @@ ffs_sync_scan2(struct mount *mp, struct vnode *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); - } + if ((error = VOP_FSYNC(vp, info->waitfor, td)) != 0) + info->allerror = error; } 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); } @@ -1140,6 +1103,9 @@ restart: * found by ffs_sync() if a sync happens to fire right then, * which will cause a panic because ffs_sync() blindly * dereferences vp->v_data (as well it should). + * + * XXX this may no longer be true since getnewvnode returns a + * VX locked vnode now. */ MALLOC(ip, struct inode *, sizeof(struct inode), ump->um_malloctype, M_WAITOK); @@ -1153,7 +1119,6 @@ restart: return (error); } bzero((caddr_t)ip, sizeof(struct inode)); - lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL, curthread); ip->i_vnode = vp; ip->i_fs = fs = ump->um_fs; ip->i_dev = dev; @@ -1173,7 +1138,7 @@ restart: if (ufs_ihashins(ip) != 0) { printf("debug: ufs ihashins collision, retrying inode %ld\n", (long)ip->i_number); - vput(vp); + vx_put(vp); free(ip, ump->um_malloctype); goto restart; } @@ -1190,7 +1155,7 @@ restart: * list by vput(). */ brelse(bp); - vput(vp); + vx_put(vp); *vpp = NULL; return (error); } @@ -1207,7 +1172,7 @@ restart: */ error = ufs_vinit(mp, &vp); if (error) { - vput(vp); + vx_put(vp); *vpp = NULL; return (error); } @@ -1234,6 +1199,10 @@ restart: ip->i_gid = ip->i_din.di_ogid; /* XXX */ } /* XXX */ + /* + * return a VX locked and refd vnode (VX == same as normal vget() + * vnode so we are ok) + */ *vpp = vp; return (0); } diff --git a/sys/vfs/ufs/ufs_ihash.c b/sys/vfs/ufs/ufs_ihash.c index bb6d97b861..3384bc5fb5 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.13 2004/08/28 19:02:30 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.14 2004/10/12 19:21:12 dillon Exp $ */ #include @@ -106,7 +106,6 @@ 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; @@ -116,7 +115,8 @@ loop: if (inum != ip->i_number || dev != ip->i_dev) continue; vp = ITOV(ip); - lwkt_gettoken(&vlock, vp->v_interlock); + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; /* * We must check to see if the inode has been ripped * out from under us after blocking. @@ -126,11 +126,9 @@ loop: break; } if (ip == NULL || ITOV(ip) != vp) { - lwkt_reltoken(&vlock); + vput(vp); goto loop; } - if (vget(vp, &vlock, LK_EXCLUSIVE | LK_INTERLOCK, td)) - goto loop; lwkt_reltoken(&ilock); return (vp); } diff --git a/sys/vfs/ufs/ufs_inode.c b/sys/vfs/ufs/ufs_inode.c index 3ced24524b..9c365838d9 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.10 2004/10/05 03:24:35 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_inode.c,v 1.11 2004/10/12 19:21:12 dillon Exp $ */ #include "opt_quota.h" @@ -95,13 +95,12 @@ ufs_inactive(struct vop_inactive_args *ap) if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) UFS_UPDATE(vp, 0); out: - VOP_UNLOCK(vp, NULL, 0, td); /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ if (ip == NULL || ip->i_mode == 0) - vrecycle(vp, NULL, td); + vrecycle(vp, td); return (error); } @@ -130,7 +129,6 @@ ufs_reclaim(struct vop_reclaim_args *ap) * Remove the inode from its hash chain and purge namecache * data associated with the vnode. */ - cache_inval_vp(vp, CINV_SELF); vp->v_data = NULL; if (ip) { ufs_ihashrem(ip); diff --git a/sys/vfs/ufs/ufs_lookup.c b/sys/vfs/ufs/ufs_lookup.c index 630f29e663..07913788c3 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.14 2004/09/30 19:00:25 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_lookup.c,v 1.15 2004/10/12 19:21:12 dillon Exp $ */ #include "opt_ufs.h" @@ -442,7 +442,7 @@ notfound: */ cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (EJUSTRETURN); @@ -506,10 +506,10 @@ found: return (0); } if (flags & CNP_ISDOTDOT) - VOP_UNLOCK(vdp, NULL, 0, td);/* race to get the inode */ + VOP_UNLOCK(vdp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td) != 0) + if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0) cnp->cn_flags |= CNP_PDIRUNLOCK; } if (error) @@ -529,7 +529,7 @@ found: } *vpp = tdp; if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (0); @@ -551,10 +551,10 @@ found: if (dp->i_number == dp->i_ino) return (EISDIR); if (flags & CNP_ISDOTDOT) - VOP_UNLOCK(vdp, NULL, 0, td); /* race to get the inode */ + VOP_UNLOCK(vdp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td) != 0) + if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0) cnp->cn_flags |= CNP_PDIRUNLOCK; } if (error) @@ -562,7 +562,7 @@ found: *vpp = tdp; cnp->cn_flags |= CNP_SAVENAME; if (!lockparent) { - VOP_UNLOCK(vdp, NULL, 0, td); + VOP_UNLOCK(vdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } return (0); @@ -589,15 +589,15 @@ found: */ pdp = vdp; if (flags & CNP_ISDOTDOT) { - VOP_UNLOCK(pdp, NULL, 0, td); /* race to get the inode */ + VOP_UNLOCK(pdp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td) == 0) + if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td) == 0) cnp->cn_flags &= ~CNP_PDIRUNLOCK; return (error); } if (lockparent && (flags & CNP_ISLASTCN)) { - if ((error = vn_lock(pdp, NULL, LK_EXCLUSIVE, td)) != 0) { + if ((error = vn_lock(pdp, LK_EXCLUSIVE, td)) != 0) { vput(tdp); return (error); } @@ -612,7 +612,7 @@ found: if (error) return (error); if (!lockparent || !(flags & CNP_ISLASTCN)) { - VOP_UNLOCK(pdp, NULL, 0, td); + VOP_UNLOCK(pdp, 0, td); cnp->cn_flags |= CNP_PDIRUNLOCK; } *vpp = tdp; @@ -932,14 +932,14 @@ ufs_direnter(struct vnode *dvp, struct vnode *tvp, struct direct *dirp, */ if (error == 0 && dp->i_endoff && dp->i_endoff < dp->i_size) { if (tvp != NULL) - VOP_UNLOCK(tvp, NULL, 0, td); + VOP_UNLOCK(tvp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td); } return (error); } diff --git a/sys/vfs/ufs/ufs_quota.c b/sys/vfs/ufs/ufs_quota.c index f929965c32..5d9ca51055 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.15 2004/08/02 13:22:34 joerg Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_quota.c,v 1.16 2004/10/12 19:21:12 dillon Exp $ */ #include @@ -371,8 +371,7 @@ struct scaninfo { /* * Q_QUOTAON - set up a quota file for a particular filesystem. */ -static int quotaon_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data); +static int quotaon_scan(struct mount *mp, struct vnode *vp, void *data); int quotaon(struct thread *td, struct mount *mp, int type, caddr_t fname) @@ -395,7 +394,7 @@ quotaon(struct thread *td, struct mount *mp, int type, caddr_t fname) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, td); return (EACCES); @@ -429,7 +428,8 @@ quotaon(struct thread *td, struct mount *mp, int type, caddr_t fname) scaninfo.td = td; while (scaninfo.rescan) { scaninfo.rescan = 0; - error = vmntvnodescan(mp, NULL, quotaon_scan, &scaninfo); + error = vmntvnodescan(mp, VMSC_GETVP, + NULL, quotaon_scan, &scaninfo); if (error) break; } @@ -440,22 +440,14 @@ quotaon(struct thread *td, struct mount *mp, int type, caddr_t fname) } static int -quotaon_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +quotaon_scan(struct mount *mp, struct vnode *vp, void *data) { int error; - struct scaninfo *info = data; + /*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; + if (vp->v_writecount == 0) return(0); - } error = getinoquota(VTOI(vp)); - vput(vp); return(error); } @@ -463,8 +455,7 @@ quotaon_scan(struct mount *mp, struct vnode *vp, * 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); +static int quotaoff_scan(struct mount *mp, struct vnode *vp, void *data); int quotaoff(struct thread *td, struct mount *mp, int type) @@ -491,7 +482,7 @@ quotaoff(struct thread *td, struct mount *mp, int type) scaninfo.type = type; while (scaninfo.rescan) { scaninfo.rescan = 0; - vmntvnodescan(mp, NULL, quotaoff_scan, &scaninfo); + vmntvnodescan(mp, VMSC_GETVP, NULL, quotaoff_scan, &scaninfo); } dqflush(qvp); qvp->v_flag &= ~VSYSTEM; @@ -510,26 +501,19 @@ quotaoff(struct thread *td, struct mount *mp, int type) } static int -quotaoff_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +quotaoff_scan(struct mount *mp, struct vnode *vp, 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); } @@ -655,8 +639,8 @@ setuse(struct mount *mp, u_long id, int type, caddr_t addr) * Q_SYNC - sync quota files to disk. */ -static int qsync_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data); +static int qsync_scan(struct mount *mp, struct vnode *vp, void *data); + int qsync(struct mount *mp) { @@ -682,36 +666,25 @@ qsync(struct mount *mp) scaninfo.td = td; while (scaninfo.rescan) { scaninfo.rescan = 0; - vmntvnodescan(mp, NULL, qsync_scan, &scaninfo); + vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, + NULL, qsync_scan, &scaninfo); } return (0); } static int -qsync_scan(struct mount *mp, struct vnode *vp, - lwkt_tokref_t vlock, void *data) +qsync_scan(struct mount *mp, struct vnode *vp, void *data) { - struct scaninfo *info = data; + /*struct scaninfo *info = data;*/ struct dquot *dq; - int error; + /* 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); } @@ -805,7 +778,7 @@ dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, * Initialize the contents of the dquot structure. */ if (vp != dqvp) - vn_lock(dqvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, td); LIST_INSERT_HEAD(dqh, dq, dq_hash); DQREF(dq); dq->dq_flags = DQ_LOCK; @@ -825,7 +798,7 @@ dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, if (auio.uio_resid == sizeof(struct dqblk) && error == 0) bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk)); if (vp != dqvp) - VOP_UNLOCK(dqvp, NULL, 0, td); + VOP_UNLOCK(dqvp, 0, td); if (dq->dq_flags & DQ_WANT) wakeup((caddr_t)dq); dq->dq_flags = 0; @@ -905,13 +878,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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dqvp, 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, NULL, 0, td); + VOP_UNLOCK(dqvp, 0, td); return (0); } } @@ -932,7 +905,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, NULL, 0, td); + VOP_UNLOCK(dqvp, 0, td); return (error); } diff --git a/sys/vfs/ufs/ufs_vnops.c b/sys/vfs/ufs/ufs_vnops.c index 0c06358225..76781c2628 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.22 2004/10/07 04:20:28 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.23 2004/10/12 19:21:12 dillon Exp $ */ #include "opt_quota.h" @@ -235,10 +235,10 @@ ufs_mknod(struct vop_mknod_args *ap) * checked to see if it is an alias of an existing entry in * the inode cache. */ - vput(*vpp); (*vpp)->v_type = VNON; ino = ip->i_number; /* Save this before vgone() invalidates ip. */ vgone(*vpp); + vput(*vpp); error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp); if (error) { *vpp = NULL; @@ -283,12 +283,9 @@ int ufs_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; - lwkt_tokref vlock; - lwkt_gettoken(&vlock, vp->v_interlock); if (vp->v_usecount > 1) ufs_itimes(vp); - lwkt_reltoken(&vlock); return (0); } @@ -728,7 +725,7 @@ ufs_link(struct vop_link_args *ap) error = EXDEV; goto out2; } - if (tdvp != vp && (error = vn_lock(vp, NULL, LK_EXCLUSIVE, td))) { + if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { goto out2; } ip = VTOI(vp); @@ -760,7 +757,7 @@ ufs_link(struct vop_link_args *ap) } out1: if (tdvp != vp) - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); out2: VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(tdvp, NOTE_WRITE); @@ -904,18 +901,18 @@ abortit: goto abortit; } - if ((error = vn_lock(fvp, NULL, LK_EXCLUSIVE, td)) != 0) + if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0) goto abortit; dp = VTOI(fdvp); ip = VTOI(fvp); if (ip->i_nlink >= LINK_MAX) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EMLINK; goto abortit; } if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EPERM; goto abortit; } @@ -926,7 +923,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, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); error = EINVAL; goto abortit; } @@ -959,7 +956,7 @@ abortit: softdep_change_linkcnt(ip); if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) | DOINGASYNC(fvp)))) != 0) { - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); goto bad; } @@ -974,7 +971,7 @@ abortit: * call to checkpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_td); - VOP_UNLOCK(fvp, NULL, 0, td); + VOP_UNLOCK(fvp, 0, td); if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { @@ -1211,7 +1208,7 @@ bad: out: if (doingdirectory) ip->i_flag &= ~IN_RENAME; - if (vn_lock(fvp, NULL, LK_EXCLUSIVE, td) == 0) { + if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) { ip->i_effnlink--; ip->i_nlink--; ip->i_flag |= IN_CHANGE; @@ -1818,12 +1815,9 @@ int ufsspec_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; - lwkt_tokref vlock; - lwkt_gettoken(&vlock, vp->v_interlock); if (vp->v_usecount > 1) ufs_itimes(vp); - lwkt_reltoken(&vlock); return (VOCALL(spec_vnode_vops, &ap->a_head)); } @@ -1887,12 +1881,9 @@ int ufsfifo_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; - lwkt_tokref vlock; - lwkt_gettoken(&vlock, vp->v_interlock); if (vp->v_usecount > 1) ufs_itimes(vp); - lwkt_reltoken(&vlock); return (VOCALL(fifo_vnode_vops, &ap->a_head)); } diff --git a/sys/vfs/umapfs/umap_subr.c b/sys/vfs/umapfs/umap_subr.c index b71ebf4645..16abc5ffbc 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.11 2004/08/28 19:02:31 dillon Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_subr.c,v 1.12 2004/10/12 19:21:13 dillon Exp $ */ #include @@ -160,7 +160,7 @@ loop: * stuff, but we don't want to lock * the lower node. */ - if (vget(vp, NULL, 0, td)) { + if (vget(vp, LK_EXCLUSIVE|LK_SLEEPFAIL, td)) { #ifdef DEBUG printf ("umap_node_find: vget failed.\n"); #endif @@ -221,7 +221,7 @@ umap_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) if (othervp) { FREE(xp, M_TEMP); vp->v_type = VBAD; /* node is discarded */ - vp->v_usecount = 0; /* XXX */ + vx_put(vp); *vpp = othervp; return (0); } diff --git a/sys/vfs/umapfs/umap_vfsops.c b/sys/vfs/umapfs/umap_vfsops.c index 6670f28025..af0eeaa017 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.12 2004/09/30 19:00:27 dillon Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vfsops.c,v 1.13 2004/10/12 19:21:13 dillon Exp $ */ /* @@ -206,7 +206,7 @@ umapfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) /* * Unlock the node (either the lower or the alias) */ - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); /* * Make sure the node alias worked */ @@ -309,7 +309,7 @@ umapfs_root(struct mount *mp, struct vnode **vpp) */ vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; vref(vp); - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, 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 1140a4a299..f3c210eb7b 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.11 2004/08/28 19:02:31 dillon Exp $ + * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vnops.c,v 1.12 2004/10/12 19:21:13 dillon Exp $ */ /* @@ -350,16 +350,11 @@ umap_getattr(struct vop_getattr_args *ap) * interlock flag as it applies only to our vnode, not the * vnodes below us on the stack. * - * umap_lock(struct vnode *a_vp, lwkt_tokref_t a_vlock, int a_flags, - * struct thread *a_td) + * umap_lock(struct vnode *a_vp, int a_flags, struct thread *a_td) */ static int umap_lock(struct vop_lock_args *ap) { - if (ap->a_flags & LK_INTERLOCK) { - lwkt_reltoken(ap->a_vlock); - ap->a_flags &= ~LK_INTERLOCK; - } if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN) return (0); return (null_bypass(&ap->a_head)); @@ -375,10 +370,6 @@ umap_lock(struct vop_lock_args *ap) int umap_unlock(struct vop_unlock_args *ap) { - if (ap->a_flags & LK_INTERLOCK) { - lwkt_reltoken(ap->a_vlock); - ap->a_flags &= ~LK_INTERLOCK; - } return (null_bypass(&ap->a_head)); } @@ -399,7 +390,6 @@ umap_inactive(struct vop_inactive_args *ap) * */ VOP_INACTIVE(lowervp, ap->a_td); - VOP_UNLOCK(ap->a_vp, NULL, 0, ap->a_td); return (0); } diff --git a/sys/vfs/union/union.h b/sys/vfs/union/union.h index 2f1b41fdb5..e65b034a24 100644 --- a/sys/vfs/union/union.h +++ b/sys/vfs/union/union.h @@ -36,7 +36,7 @@ * * @(#)union.h 8.9 (Berkeley) 12/10/94 * $FreeBSD: src/sys/miscfs/union/union.h,v 1.17 1999/12/29 04:54:48 peter Exp $ - * $DragonFly: src/sys/vfs/union/union.h,v 1.7 2004/08/17 18:57:36 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union.h,v 1.8 2004/10/12 19:21:14 dillon Exp $ */ struct union_args { @@ -77,13 +77,8 @@ struct union_mount { /* * A cache of vnode references (hangs off v_data) - * - * Placing un_lock as the first elements theoretically allows us to - * use the vop_stdlock functions. However, we need to make sure of - * certain side effects so we will still punch in our own code. */ struct union_node { - struct lock un_lock; LIST_ENTRY(union_node) un_cache; /* Hash chain */ struct vnode *un_vnode; /* Back pointer */ struct vnode *un_uppervp; /* overlaying object */ diff --git a/sys/vfs/union/union_subr.c b/sys/vfs/union/union_subr.c index 4aea225681..131c102070 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.15 2004/08/28 19:02:33 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_subr.c,v 1.16 2004/10/12 19:21:14 dillon Exp $ */ #include @@ -392,7 +392,7 @@ loop: (un->un_uppervp == uppervp || un->un_uppervp == NULLVP) && (UNIONTOV(un)->v_mount == mp)) { - if (vget(UNIONTOV(un), NULL, 0, + if (vget(UNIONTOV(un), LK_EXCLUSIVE|LK_SLEEPFAIL, cnp ? cnp->cn_td : NULL)) { union_list_unlock(hash); goto loop; @@ -433,21 +433,21 @@ loop: * while moving up the tree). */ vref(dvp); - 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); + VOP_UNLOCK(dvp, 0, td); + error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); vrele(dvp); } else { /* * our new un is under dvp */ - error = vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE, td); + error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td); } } else if (dvp == NULLVP) { /* * dvp is NULL, we need to lock un. */ - error = vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE, td); + error = vn_lock(un->un_vnode, LK_EXCLUSIVE, td); } else { /* * dvp == un->un_vnode, we are already locked. @@ -555,9 +555,6 @@ loop: un = VTOUNION(*vpp); bzero(un, sizeof(*un)); - lockinit(&un->un_lock, 0, "unlock", VLKTIMEOUT, 0); - vn_lock(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td); - un->un_vnode = *vpp; un->un_uppervp = uppervp; un->un_uppersz = VNOVAL; @@ -584,6 +581,10 @@ loop: un->un_flags |= UN_CACHED; } + /* + * locked refd vpp is returned + */ + out: if (docache) union_list_unlock(hash); @@ -728,9 +729,9 @@ union_copyup(struct union_node *un, int docopy, struct ucred *cred, * If the user does not have read permission, the vnode should not * be copied to upper layer. */ - vn_lock(un->un_lowervp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(un->un_lowervp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(un->un_lowervp, VREAD, cred, td); - VOP_UNLOCK(un->un_lowervp, NULL, 0, td); + VOP_UNLOCK(un->un_lowervp, 0, td); if (error) return (error); @@ -746,20 +747,20 @@ union_copyup(struct union_node *un, int docopy, struct ucred *cred, * XX - should not ignore errors * from VOP_CLOSE */ - vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(lvp, 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, NULL, 0, td); + VOP_UNLOCK(lvp, 0, td); (void) VOP_CLOSE(lvp, FREAD, td); } if (error == 0) UDEBUG(("union: copied up %s\n", un->un_path)); } - VOP_UNLOCK(uvp, NULL, 0, td); + VOP_UNLOCK(uvp, 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); @@ -834,7 +835,7 @@ union_relookup(struct union_mount *um, struct vnode *dvp, struct vnode **vpp, cn->cn_consume = cnp->cn_consume; vref(dvp); - VOP_UNLOCK(dvp, NULL, 0, cnp->cn_td); + VOP_UNLOCK(dvp, 0, cnp->cn_td); /* * Pass dvp unlocked and referenced on call to relookup(). @@ -843,7 +844,7 @@ union_relookup(struct union_mount *um, struct vnode *dvp, struct vnode **vpp, */ if ((error = relookup(dvp, vpp, cn)) != 0) { - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, cnp->cn_td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_td); return(error); } @@ -1182,7 +1183,7 @@ union_dircache(struct vnode *vp, struct thread *td) struct union_node *un; int error; - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); dircache = VTOUNION(vp)->un_dircache; nvp = NULLVP; @@ -1208,7 +1209,7 @@ union_dircache(struct vnode *vp, struct thread *td) if (*vpp == NULLVP) goto out; - /*vn_lock(*vpp, NULL, LK_EXCLUSIVE | LK_RETRY, td);*/ + /*vn_lock(*vpp, 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); @@ -1221,7 +1222,7 @@ union_dircache(struct vnode *vp, struct thread *td) un->un_dircache = dircache; out: - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); return (nvp); } @@ -1293,7 +1294,7 @@ union_dircheck(struct thread *td, struct vnode **vp, struct file *fp) vput(lvp); return (error); } - VOP_UNLOCK(lvp, NULL, 0, td); + VOP_UNLOCK(lvp, 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 faa3f4d036..8f08bb887e 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.15 2004/09/30 19:00:29 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_vfsops.c,v 1.16 2004/10/12 19:21:14 dillon Exp $ */ /* @@ -127,7 +127,7 @@ union_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) * Unlock lower node to avoid deadlock. */ if (lowerrootvp->v_tag == VT_UNION) - VOP_UNLOCK(lowerrootvp, NULL, 0, td); + VOP_UNLOCK(lowerrootvp, 0, td); #endif /* @@ -141,7 +141,7 @@ union_mount(struct mount *mp, char *path, caddr_t data, struct thread *td) #if 0 if (lowerrootvp->v_tag == VT_UNION) - vn_lock(lowerrootvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY, td); #endif if (error) goto bad; diff --git a/sys/vfs/union/union_vnops.c b/sys/vfs/union/union_vnops.c index 02d64642a3..c716faa56c 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.15 2004/09/26 06:00:10 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.16 2004/10/12 19:21:14 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, NULL, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td); + vn_lock(uppervp, 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, NULL, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td); } return(vp); } @@ -199,7 +199,7 @@ union_lookup1(struct vnode *udvp, struct vnode **pdvp, struct vnode **vpp, dvp = dvp->v_mount->mnt_vnodecovered; vref(dvp); vput(tdvp); - vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); } } @@ -230,7 +230,7 @@ union_lookup1(struct vnode *udvp, struct vnode **pdvp, struct vnode **vpp, 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, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); /* * Lastly check if the current node is a mount point in @@ -262,7 +262,7 @@ union_lookup1(struct vnode *udvp, struct vnode **pdvp, struct vnode **vpp, vfs_unbusy(mp, td); if (relock_pdvp) - vn_lock(*pdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY, td); if (error) { *vpp = NULL; @@ -441,7 +441,7 @@ union_lookup(struct vop_lookup_args *ap) * to us so we NULL it out. */ vref(lowerdvp); - vn_lock(lowerdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, td); lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp); if (lowerdvp == lowervp) vrele(lowerdvp); @@ -465,7 +465,7 @@ union_lookup(struct vop_lookup_args *ap) if ((cnp->cn_flags & CNP_ISDOTDOT) && dun->un_pvp != NULLVP) { if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) { vref(lowervp); - vn_lock(lowervp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, td); lerror = 0; } } @@ -528,11 +528,11 @@ union_lookup(struct vop_lookup_args *ap) */ if (uppervp && uppervp != upperdvp) - VOP_UNLOCK(uppervp, NULL, 0, td); + VOP_UNLOCK(uppervp, 0, td); if (lowervp) - VOP_UNLOCK(lowervp, NULL, 0, td); + VOP_UNLOCK(lowervp, 0, td); if (upperdvp) - VOP_UNLOCK(upperdvp, NULL, 0, td); + VOP_UNLOCK(upperdvp, 0, td); error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, uppervp, lowervp, 1); @@ -595,7 +595,7 @@ out: if (*ap->a_vpp != dvp) { if ((error == 0 || error == EJUSTRETURN) && (!lockparent || (cnp->cn_flags & CNP_ISLASTCN) == 0)) { - VOP_UNLOCK(dvp, NULL, 0, td); + VOP_UNLOCK(dvp, 0, td); } } @@ -639,7 +639,7 @@ union_create(struct vop_create_args *ap) error = VOP_CREATE(dvp, NCPNULL, &vp, cnp, ap->a_vap); if (error == 0) { mp = ap->a_dvp->v_mount; - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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); @@ -737,7 +737,7 @@ union_open(struct vop_open_args *ap) } else { un->un_openl++; vref(tvp); - vn_lock(tvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td); tvpisupper = 0; } } @@ -839,7 +839,7 @@ union_access(struct vop_access_args *ap) } if ((vp = un->un_lowervp) != NULLVP) { - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); ap->a_head.a_ops = vp->v_ops; ap->a_vp = vp; @@ -861,7 +861,7 @@ union_access(struct vop_access_args *ap) error = vop_access_ap(ap); } } - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); } return(error); } @@ -1156,11 +1156,20 @@ static int union_revoke(struct vop_revoke_args *ap) { struct vnode *vp = ap->a_vp; + struct vnode *vx; - if (UPPERVP(vp)) - VOP_REVOKE(UPPERVP(vp), ap->a_flags); - if (LOWERVP(vp)) - VOP_REVOKE(LOWERVP(vp), ap->a_flags); + if ((vx = UPPERVP(vp)) != NULL) { + if (vx_get(vx) == 0) { + VOP_REVOKE(vx, ap->a_flags); + vx_put(vx); + } + } + if ((vx = LOWERVP(vp)) != NULL) { + if (vx_get(vx) == 0) { + VOP_REVOKE(vx, ap->a_flags); + vx_put(vx); + } + } vgone(vp); return (0); } @@ -1267,24 +1276,24 @@ union_link(struct vop_link_args *ap) struct union_node *tun = VTOUNION(ap->a_vp); if (tun->un_uppervp == NULLVP) { - vn_lock(ap->a_vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ap->a_vp, 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, NULL, 0, td); + VOP_UNLOCK(dun->un_uppervp, 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, NULL, + vn_lock(dun->un_uppervp, LK_EXCLUSIVE | LK_RETRY, td); dun->un_flags |= UN_ULOCK; } #endif - VOP_UNLOCK(ap->a_vp, NULL, 0, td); + VOP_UNLOCK(ap->a_vp, 0, td); } vp = tun->un_uppervp; } @@ -1302,7 +1311,7 @@ union_link(struct vop_link_args *ap) if ((tdvp = union_lock_upper(dun, td)) == NULLVP) return (EROFS); - VOP_UNLOCK(ap->a_tdvp, NULL, 0, td); /* unlock calling node */ + VOP_UNLOCK(ap->a_tdvp, 0, td); /* unlock calling node */ error = VOP_LINK(tdvp, NCPNULL, vp, cnp); /* call link on upper */ /* @@ -1310,7 +1319,7 @@ union_link(struct vop_link_args *ap) * order to avoid a deadlock. */ union_unlock_upper(tdvp, td); - vn_lock(ap->a_tdvp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } @@ -1364,9 +1373,9 @@ union_rename(struct vop_rename_args *ap) if (un->un_uppervp == NULLVP) { switch(fvp->v_type) { case VREG: - vn_lock(un->un_vnode, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td); + vn_lock(un->un_vnode, 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, NULL, 0, ap->a_fcnp->cn_td); + VOP_UNLOCK(un->un_vnode, 0, ap->a_fcnp->cn_td); if (error) goto bad; break; @@ -1382,12 +1391,12 @@ union_rename(struct vop_rename_args *ap) #if 0 vrele(fvp); fvp = NULL; - vn_lock(fdvp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td); + vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_td); error = union_mkshadow(um, fdvp, ap->a_fcnp, &un->un_uppervp); - VOP_UNLOCK(fdvp, NULL, 0, ap->a_fcnp->cn_td); + VOP_UNLOCK(fdvp, 0, ap->a_fcnp->cn_td); if (un->un_uppervp) - VOP_UNLOCK(un->un_uppervp, NULL, 0, ap->a_fcnp->cn_td); + VOP_UNLOCK(un->un_uppervp, 0, ap->a_fcnp->cn_td); if (error) goto bad; break; @@ -1496,7 +1505,7 @@ union_mkdir(struct vop_mkdir_args *ap) union_unlock_upper(upperdvp, td); if (error == 0) { - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 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); @@ -1626,7 +1635,7 @@ static int union_inactive(struct vop_inactive_args *ap) { struct vnode *vp = ap->a_vp; - struct thread *td = ap->a_td; + /*struct thread *td = ap->a_td;*/ struct union_node *un = VTOUNION(vp); struct vnode **vpp; @@ -1653,12 +1662,10 @@ union_inactive(struct vop_inactive_args *ap) #if 0 if ((un->un_flags & UN_ULOCK) && un->un_uppervp) { un->un_flags &= ~UN_ULOCK; - VOP_UNLOCK(un->un_uppervp, NULL, 0, td); + VOP_UNLOCK(un->un_uppervp, 0, td); } #endif - VOP_UNLOCK(vp, NULL, 0, td); - if ((un->un_flags & UN_CACHED) == 0) vgone(vp); @@ -1699,12 +1706,10 @@ union_lock(struct vop_lock_args *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, ap->a_vlock, - flags, td); + error = vn_lock(un->un_uppervp, 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); @@ -1723,8 +1728,7 @@ union_lock(struct vop_lock_args *ap) * * Unlock our union node. This also unlocks uppervp. * - * union_unlock(struct vnode *a_vp, lwkt_tokref_t a_vlock, int a_flags, - * struct thread *a_td) + * union_unlock(struct vnode *a_vp, int a_flags, struct thread *a_td) */ static int union_unlock(struct vop_unlock_args *ap) @@ -1747,7 +1751,7 @@ union_unlock(struct vop_unlock_args *ap) if ((un->un_flags & UN_ULOCK) && lockstatus(&un->un_lock, NULL) != LK_EXCLUSIVE) { un->un_flags &= ~UN_ULOCK; - VOP_UNLOCK(un->un_uppervp, NULL, LK_EXCLUSIVE, td); + VOP_UNLOCK(un->un_uppervp, LK_EXCLUSIVE, td); } #endif return(error); diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 68bdf76377..1a8a658406 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -64,7 +64,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $DragonFly: src/sys/vm/vm_contig.c,v 1.9 2004/08/17 18:57:36 dillon Exp $ + * $DragonFly: src/sys/vm/vm_contig.c,v 1.10 2004/10/12 19:21:16 dillon Exp $ */ /* @@ -116,6 +116,8 @@ #include #include #include + +#include #include /* @@ -133,6 +135,8 @@ * * Otherwise if the object is of any other type, the generic * pageout (daemon) flush routine is invoked. + * + * We must be in a critical section. */ static int vm_contig_pg_clean(int queue) @@ -153,11 +157,11 @@ vm_contig_pg_clean(int queue) if (m->dirty) { object = m->object; if (object->type == OBJT_VNODE) { - vn_lock(object->handle, NULL, + vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curthread); vm_object_page_clean(object, 0, 0, OBJPC_SYNC); VOP_UNLOCK(((struct vnode *)object->handle), - NULL, 0, curthread); + 0, curthread); return (TRUE); } else if (object->type == OBJT_SWAP || object->type == OBJT_DEFAULT) { @@ -193,7 +197,7 @@ vm_contig_pg_alloc( unsigned long alignment, unsigned long boundary) { - int i, s, start, pass; + int i, start, pass; vm_offset_t phys; vm_page_t pga = vm_page_array; @@ -207,7 +211,7 @@ vm_contig_pg_alloc( start = 0; for (pass = 0; pass <= 1; pass++) { - s = splvm(); + crit_enter(); again: /* * Find first page in array that is free, within range, aligned, and @@ -239,13 +243,15 @@ again1: if (vm_contig_pg_clean(PQ_ACTIVE)) goto again1; - splx(s); + crit_exit(); continue; /* next pass */ } start = i; /* * Check successive pages for contiguous and free. + * + * (still in critical section) */ for (i = start + 1; i < (start + size / PAGE_SIZE); i++) { int pqtype; @@ -258,6 +264,9 @@ again1: } } + /* + * (still in critical section) + */ for (i = start; i < (start + size / PAGE_SIZE); i++) { int pqtype; vm_page_t m = &pga[i]; @@ -283,15 +292,14 @@ again1: /* * Our job is done, return the index page of vm_page_array. */ - - splx(s); + crit_exit(); return (start); /* aka &pga[start] */ } /* * Failed. */ - splx(s); + crit_exit(); return (-1); } @@ -329,13 +337,13 @@ vm_contig_pg_kmap(int start, u_long size, vm_map_t map, int flags) { vm_offset_t addr, tmp_addr; vm_page_t pga = vm_page_array; - int i, s, count; + int i, count; size = round_page(size); if (size == 0) panic("vm_contig_pg_kmap: size must not be 0"); - s = splvm(); /* XXX: is this really needed? */ + crit_enter(); /* * We've found a contiguous chunk that meets our requirements. @@ -353,7 +361,7 @@ vm_contig_pg_kmap(int start, u_long size, vm_map_t map, int flags) */ vm_map_unlock(map); vm_map_entry_release(count); - splx(s); + crit_exit(); return (0); } vm_object_reference(kernel_object); @@ -375,7 +383,7 @@ vm_contig_pg_kmap(int start, u_long size, vm_map_t map, int flags) } vm_map_wire(map, addr, addr + size, 0); - splx(s); + crit_exit(); return (addr); } diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 61cc6f8302..efe5a94828 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.32 2004/08/17 18:57:36 dillon Exp $ + * $DragonFly: src/sys/vm/vm_map.c,v 1.33 2004/10/12 19:21:16 dillon Exp $ */ /* @@ -1871,7 +1871,6 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t real_end, int kmflags) vm_offset_t end; int rv = KERN_SUCCESS; int count; - int s; if (kmflags & KM_KRESERVE) count = vm_map_entry_kreserve(MAP_RESERVE_COUNT); @@ -1965,16 +1964,17 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t real_end, int kmflags) * protects us from most changes but note that * clipping may still occur. To prevent clipping from * occuring after the unlock, except for when we are - * blocking in vm_fault_wire, we must run at splvm(). - * Otherwise our accesses to entry->start and entry->end - * could be corrupted. We have to set splvm() prior to - * unlocking so start_entry does not change out from - * under us at the very beginning of the loop. + * blocking in vm_fault_wire, we must run in a critical + * section, otherwise our accesses to entry->start and + * entry->end could be corrupted. We have to enter the + * critical section prior to unlocking so start_entry does + * not change out from under us at the very beginning of the + * loop. * * HACK HACK HACK HACK */ - s = splvm(); + crit_enter(); entry = start_entry; while (entry != &map->header && entry->start < end) { @@ -2005,7 +2005,7 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t real_end, int kmflags) CLIP_CHECK_FWD(entry, save_end); entry = entry->next; } - splx(s); + crit_exit(); /* * If a failure occured undo everything by falling through @@ -2187,7 +2187,7 @@ vm_map_clean(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t syncio, int flags; vm_object_reference(object); - vn_lock(object->handle, NULL, + vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curthread); flags = (syncio || invalidate) ? OBJPC_SYNC : 0; flags |= invalidate ? OBJPC_INVAL : 0; @@ -2196,7 +2196,7 @@ vm_map_clean(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t syncio, OFF_TO_IDX(offset + size + PAGE_MASK), flags); VOP_UNLOCK(((struct vnode *)object->handle), - NULL, 0, curthread); + 0, curthread); vm_object_deallocate(object); } if (object && invalidate && @@ -2484,18 +2484,17 @@ vm_map_split(vm_map_entry_t entry) for (idx = 0; idx < size; idx++) { vm_page_t m; - int ss; /* s used */ /* - * splvm protection is required to avoid a race between + * A critical section is required to avoid a race between * the lookup and an interrupt/unbusy/free and our busy * check. */ - ss = splvm(); + crit_enter(); retry: m = vm_page_lookup(orig_object, offidxstart + idx); if (m == NULL) { - splx(ss); + crit_exit(); continue; } @@ -2512,7 +2511,7 @@ vm_map_split(vm_map_entry_t entry) vm_page_rename(m, new_object, idx); /* page automatically made dirty by rename and cache handled */ vm_page_busy(m); - splx(ss); + crit_exit(); } if (orig_object->type == OBJT_SWAP) { @@ -3331,11 +3330,11 @@ vm_uiomove(vm_map_t mapa, vm_object_t srcobject, off_t cp, int cnta, * the lookup and an interrupt/unbusy/free occuring * prior to our busy check. */ - s = splvm(); + crit_enter(); for (idx = 0; idx < osize; idx++) { vm_page_t m; if ((m = vm_page_lookup(srcobject, oindex + idx)) == NULL) { - splx(s); + crit_exit(); vm_map_lookup_done(map, entry, count); return 0; } @@ -3345,12 +3344,12 @@ vm_uiomove(vm_map_t mapa, vm_object_t srcobject, off_t cp, int cnta, */ if ((m->flags & PG_BUSY) || ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL)) { - splx(s); + crit_exit(); vm_map_lookup_done(map, entry, count); return 0; } } - splx(s); + crit_exit(); } /* diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 35b5084667..d58f049a2d 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.19 2004/09/17 10:02:12 dillon Exp $ + * $DragonFly: src/sys/vm/vm_object.c,v 1.20 2004/10/12 19:21:16 dillon Exp $ */ /* @@ -92,6 +92,8 @@ #include #include +#include + #define EASY_SCAN_FACTOR 8 #define MSYNC_FLUSH_HARDSEQ 0x01 @@ -257,10 +259,14 @@ vm_object_reference(vm_object_t object) object->ref_count++; if (object->type == OBJT_VNODE) { - while (vget((struct vnode *) object->handle, NULL, + vref(object->handle); + /* XXX what if the vnode is being destroyed? */ +#if 0 + while (vget((struct vnode *) object->handle, LK_RETRY|LK_NOOBJ, curthread)) { printf("vm_object_reference: delay in getting object\n"); } +#endif } } @@ -406,7 +412,6 @@ vm_object_terminate(vm_object_t object) { lwkt_tokref ilock; vm_page_t p; - int s; /* * Make sure no one uses us. @@ -456,7 +461,7 @@ vm_object_terminate(vm_object_t object) * removes them from paging queues. Don't free wired pages, just * remove them from the object. */ - s = splvm(); + crit_enter(); while ((p = TAILQ_FIRST(&object->memq)) != NULL) { if (p->busy || (p->flags & PG_BUSY)) panic("vm_object_terminate: freeing busy page %p", p); @@ -470,7 +475,7 @@ vm_object_terminate(vm_object_t object) vm_page_wakeup(p); } } - splx(s); + crit_exit(); /* * Let the pager know object is dead. @@ -517,8 +522,6 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int clearobjflags; int pagerflags; int curgeneration; - lwkt_tokref vlock; - int s; if (object->type != OBJT_VNODE || (object->flags & OBJ_MIGHTBEDIRTY) == 0) @@ -568,7 +571,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, * race that might occur prior to the busy check in * vm_object_page_collect_flush(). */ - s = splvm(); + crit_enter(); while (tscan < tend) { curgeneration = object->generation; p = vm_page_lookup(object, tscan); @@ -605,7 +608,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, tscan += vm_object_page_collect_flush(object, p, curgeneration, pagerflags); } - splx(s); + crit_exit(); /* * If everything was dirty and we flushed it successfully, @@ -633,7 +636,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, */ clearobjflags = 1; - s = splvm(); + crit_enter(); for (p = TAILQ_FIRST(&object->memq); p; p = TAILQ_NEXT(p, listq)) { vm_page_flag_set(p, PG_CLEANCHK); if ((flags & OBJPC_NOSYNC) && (p->flags & PG_NOSYNC)) @@ -641,7 +644,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, else vm_page_protect(p, VM_PROT_READ); } - splx(s); + crit_exit(); if (clearobjflags && (tstart == 0) && (tend == object->size)) { struct vnode *vp; @@ -649,11 +652,8 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, vm_object_clear_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY); if (object->type == OBJT_VNODE && (vp = (struct vnode *)object->handle) != NULL) { - if (vp->v_flag & VOBJDIRTY) { - lwkt_gettoken(&vlock, vp->v_interlock); - vp->v_flag &= ~VOBJDIRTY; - lwkt_reltoken(&vlock); - } + if (vp->v_flag & VOBJDIRTY) + vclrflags(vp, VOBJDIRTY); } } @@ -663,10 +663,10 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, * memq is consistent. We do not want a busy page to be ripped out * from under us. */ - s = splvm(); + crit_enter(); rescan: - splx(s); /* give interrupts a chance */ - s = splvm(); + crit_exit(); + crit_enter(); curgeneration = object->generation; for (p = TAILQ_FIRST(&object->memq); p; p = np) { @@ -716,7 +716,7 @@ again: goto again; } } - splx(s); + crit_exit(); #if 0 VOP_FSYNC(vp, NULL, (pagerflags & VM_PAGER_PUT_SYNC)?MNT_WAIT:0, curproc); @@ -727,8 +727,8 @@ again: } /* - * This routine must be called at splvm() to properly avoid an interrupt - * unbusy/free race that can occur prior to the busy check. + * This routine must be called within a critical section to properly avoid + * an interrupt unbusy/free race that can occur prior to the busy check. * * Using the object generation number here to detect page ripout is not * the best idea in the world. XXX @@ -860,12 +860,12 @@ vm_object_deactivate_pages(vm_object_t object) vm_page_t p, next; int s; - s = splvm(); + crit_enter(); for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { next = TAILQ_NEXT(p, listq); vm_page_deactivate(p); } - splx(s); + crit_exit(); } #endif @@ -885,7 +885,6 @@ vm_object_pmap_copy_1(vm_object_t object, vm_pindex_t start, vm_pindex_t end) { vm_pindex_t idx; vm_page_t p; - int s; if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) return; @@ -894,14 +893,14 @@ vm_object_pmap_copy_1(vm_object_t object, vm_pindex_t start, vm_pindex_t end) * spl protection needed to prevent races between the lookup, * an interrupt unbusy/free, and our protect call. */ - s = splvm(); + crit_enter(); for (idx = start; idx < end; idx++) { p = vm_page_lookup(object, idx); if (p == NULL) continue; vm_page_protect(p, VM_PROT_READ); } - splx(s); + crit_exit(); } /* @@ -916,7 +915,6 @@ void vm_object_pmap_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end) { vm_page_t p; - int s; if (object == NULL) return; @@ -925,7 +923,7 @@ vm_object_pmap_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end) * spl protection is required because an interrupt can unbusy/free * a page. */ - s = splvm(); + crit_enter(); for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq) @@ -933,7 +931,7 @@ vm_object_pmap_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end) if (p->pindex >= start && p->pindex < end) vm_page_protect(p, VM_PROT_NONE); } - splx(s); + crit_exit(); if ((start == 0) && (object->size == end)) vm_object_clear_flag(object, OBJ_WRITEABLE); } @@ -965,7 +963,6 @@ vm_object_madvise(vm_object_t object, vm_pindex_t pindex, int count, int advise) vm_pindex_t end, tpindex; vm_object_t tobject; vm_page_t m; - int s; if (object == NULL) return; @@ -998,7 +995,7 @@ shadowlookup: * lookup, an interrupt unbusy/free, and our busy check. */ - s = splvm(); + crit_enter(); m = vm_page_lookup(tobject, tpindex); if (m == NULL) { @@ -1011,7 +1008,7 @@ shadowlookup: /* * next object */ - splx(s); + crit_exit(); if (tobject->backing_object == NULL) continue; tpindex += OFF_TO_IDX(tobject->backing_object_offset); @@ -1031,15 +1028,15 @@ shadowlookup: (m->flags & PG_UNMANAGED) || m->valid != VM_PAGE_BITS_ALL ) { - splx(s); + crit_exit(); continue; } if (vm_page_sleep_busy(m, TRUE, "madvpo")) { - splx(s); + crit_exit(); goto relookup; } - splx(s); + crit_exit(); /* * Theoretically once a page is known not to be busy, an @@ -1155,7 +1152,6 @@ vm_object_shadow(vm_object_t *object, /* IN/OUT */ static __inline int vm_object_backing_scan(vm_object_t object, int op) { - int s; int r = 1; vm_page_t p; vm_object_t backing_object; @@ -1166,7 +1162,7 @@ vm_object_backing_scan(vm_object_t object, int op) * an interrupt doing an unbusy/free, and our busy check. Amoung * other things. */ - s = splvm(); + crit_enter(); backing_object = object->backing_object; backing_offset_index = OFF_TO_IDX(object->backing_object_offset); @@ -1186,7 +1182,7 @@ vm_object_backing_scan(vm_object_t object, int op) * shadow test may succeed! XXX */ if (backing_object->type != OBJT_DEFAULT) { - splx(s); + crit_exit(); return(0); } } @@ -1343,7 +1339,7 @@ vm_object_backing_scan(vm_object_t object, int op) } p = next; } - splx(s); + crit_exit(); return(r); } @@ -1573,7 +1569,6 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, vm_page_t p, next; unsigned int size; int all; - int s; if (object == NULL || object->resident_page_count == 0) return; @@ -1595,7 +1590,7 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, * an interrupt unbusy/free, and the busy check. */ vm_object_pip_add(object, 1); - s = splvm(); + crit_enter(); again: size = end - start; if (all || size > object->resident_page_count / 4) { @@ -1664,7 +1659,7 @@ again: size -= 1; } } - splx(s); + crit_exit(); vm_object_pip_wakeup(object); } @@ -1755,15 +1750,12 @@ 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(&vlock, vp->v_interlock); - vp->v_flag |= VOBJDIRTY; - lwkt_reltoken(&vlock); + vsetflags(vp, VOBJDIRTY); } } } diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 6d4d431d6b..bb7aa97758 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.11 2004/05/13 17:40:19 dillon Exp $ + * $DragonFly: src/sys/vm/vm_pageout.c,v 1.12 2004/10/12 19:21:16 dillon Exp $ */ /* @@ -95,6 +95,8 @@ #include #include #include + +#include #include /* @@ -449,7 +451,6 @@ vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object, vm_page_t p, next; int rcount; int remove_mode; - int s; if (object->type == OBJT_DEVICE || object->type == OBJT_PHYS) return; @@ -469,14 +470,14 @@ vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object, * required to avoid an interrupt unbusy/free race against * our busy check. */ - s = splvm(); + crit_enter(); rcount = object->resident_page_count; p = TAILQ_FIRST(&object->memq); while (p && (rcount-- > 0)) { int actcount; if (pmap_resident_count(vm_map_pmap(map)) <= desired) { - splx(s); + crit_exit(); return; } next = TAILQ_NEXT(p, listq); @@ -525,7 +526,7 @@ vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object, } p = next; } - splx(s); + crit_exit(); object = object->backing_object; } } @@ -594,7 +595,6 @@ vm_pageout_map_deactivate_pages(vm_map_t map, vm_pindex_t desired) pmap_remove(vm_map_pmap(map), VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); vm_map_unlock(map); - return; } #endif @@ -634,7 +634,6 @@ vm_pageout_scan(int pass) int actcount; int vnodes_skipped = 0; int maxlaunder; - int s; /* * Do whatever cleanup that the pmap code can. @@ -680,14 +679,14 @@ vm_pageout_scan(int pass) maxlaunder = 10000; /* - * We will generally be at splvm() throughout the scan, but we - * can release it temporarily when we are sitting on a non-busy - * page without fear. The spl protection is required because an - * an interrupt can come along and unbusy/free a busy page prior - * to our busy check, leaving us on the wrong queue or checking - * the wrong page. + * We will generally be in a critical section throughout the + * scan, but we can release it temporarily when we are sitting on a + * non-busy page without fear. this is required to prevent an + * interrupt from unbusying or freeing a page prior to our busy + * check, leaving us on the wrong queue or checking the wrong + * page. */ - s = splvm(); + crit_enter(); rescan0: addl_page_shortage = addl_page_shortage_init; maxscan = vmstats.v_inactive_count; @@ -700,8 +699,8 @@ rescan0: /* * Give interrupts a chance */ - splx(s); - s = splvm(); + crit_exit(); + crit_enter(); /* * It's easier for some of the conditions below to just loop @@ -886,7 +885,7 @@ rescan0: if (object->type == OBJT_VNODE) { vp = object->handle; - if (vget(vp, NULL, LK_EXCLUSIVE|LK_NOOBJ|LK_TIMELOCK, curthread)) { + if (vget(vp, LK_EXCLUSIVE|LK_NOOBJ|LK_TIMELOCK, curthread)) { ++pageout_lock_miss; if (object->flags & OBJ_MIGHTBEDIRTY) vnodes_skipped++; @@ -973,7 +972,7 @@ rescan0: * track the per-page activity counter and use it to locate * deactivation candidates. * - * NOTE: we are still at splvm(). + * NOTE: we are still in a critical section. */ pcount = vmstats.v_active_count; m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl); @@ -982,8 +981,8 @@ rescan0: /* * Give interrupts a chance. */ - splx(s); - s = splvm(); + crit_exit(); + crit_enter(); /* * If the page was ripped out from under us, just stop. @@ -1067,7 +1066,7 @@ rescan0: * are considered basically 'free', moving pages from cache to free * does not effect other calculations. * - * NOTE: we are still at splvm(). + * NOTE: we are still in a critical section. */ while (vmstats.v_free_count < vmstats.v_free_reserved) { @@ -1090,7 +1089,7 @@ rescan0: mycpu->gd_cnt.v_dfree++; } - splx(s); + crit_exit(); #if !defined(NO_SWAPPING) /* @@ -1181,12 +1180,10 @@ rescan0: static void vm_pageout_page_stats(void) { - int s; vm_page_t m,next; int pcount,tpcount; /* Number of pages to check */ static int fullintervalcount = 0; int page_shortage; - int s0; page_shortage = (vmstats.v_inactive_target + vmstats.v_cache_max + vmstats.v_free_min) - @@ -1195,7 +1192,7 @@ vm_pageout_page_stats(void) if (page_shortage <= 0) return; - s0 = splvm(); + crit_enter(); pcount = vmstats.v_active_count; fullintervalcount += vm_pageout_stats_interval; @@ -1222,10 +1219,8 @@ vm_pageout_page_stats(void) if ((m->busy != 0) || (m->flags & PG_BUSY) || (m->hold_count != 0)) { - s = splvm(); TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); - splx(s); m = next; continue; } @@ -1241,10 +1236,8 @@ vm_pageout_page_stats(void) m->act_count += ACT_ADVANCE + actcount; if (m->act_count > ACT_MAX) m->act_count = ACT_MAX; - s = splvm(); TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); - splx(s); } else { if (m->act_count == 0) { /* @@ -1260,16 +1253,14 @@ vm_pageout_page_stats(void) vm_page_deactivate(m); } else { m->act_count -= min(m->act_count, ACT_DECLINE); - s = splvm(); TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq); - splx(s); } } m = next; } - splx(s0); + crit_exit(); } static int @@ -1370,7 +1361,6 @@ vm_pageout(void) */ while (TRUE) { int error; - int s = splvm(); /* * If we have enough free memory, wakeup waiters. Do @@ -1378,6 +1368,7 @@ vm_pageout(void) * otherwise we may be woken up over and over again and * waste a lot of cpu. */ + crit_enter(); if (vm_pages_needed && !vm_page_count_min()) { if (vm_paging_needed() <= 0) vm_pages_needed = 0; @@ -1404,7 +1395,7 @@ vm_pageout(void) error = tsleep(&vm_pages_needed, 0, "psleep", vm_pageout_stats_interval * hz); if (error && !vm_pages_needed) { - splx(s); + crit_exit(); pass = 0; vm_pageout_page_stats(); continue; @@ -1413,7 +1404,7 @@ vm_pageout(void) if (vm_pages_needed) mycpu->gd_cnt.v_pdwakeups++; - splx(s); + crit_exit(); vm_pageout_scan(pass); vm_pageout_deficit = 0; } diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c index 737e462a74..c4de00f3cf 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.14 2004/08/28 19:02:35 dillon Exp $ + * $DragonFly: src/sys/vm/vm_swap.c,v 1.15 2004/10/12 19:21:16 dillon Exp $ */ #include "opt_swap.h" @@ -252,6 +252,7 @@ swaponvp(struct thread *td, struct vnode *vp, u_long nblks) if (error) panic("Cannot get vnode for swapdev"); swapdev_vp->v_type = VNON; /* Untyped */ + vx_unlock(swapdev_vp); } ASSERT_VOP_UNLOCKED(vp, "swaponvp"); @@ -264,9 +265,9 @@ swaponvp(struct thread *td, struct vnode *vp, u_long nblks) } return EINVAL; found: - vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(vp, FREAD | FWRITE, cred, td); - VOP_UNLOCK(vp, NULL, 0, td); + VOP_UNLOCK(vp, 0, td); if (error) return (error); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 39453ac34a..7e673002ec 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.15 2004/08/17 18:57:36 dillon Exp $ + * $DragonFly: src/sys/vm/vnode_pager.c,v 1.16 2004/10/12 19:21:16 dillon Exp $ */ /* @@ -54,6 +54,7 @@ #include #include +#include #include #include #include @@ -197,7 +198,7 @@ vnode_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, * If no vp or vp is doomed or marked transparent to VM, we do not * have the page. */ - if ((vp == NULL) || (vp->v_flag & VDOOMED)) + if ((vp == NULL) || (vp->v_flag & VRECLAIMED)) return FALSE; /* @@ -1027,6 +1028,7 @@ struct vnode * vnode_pager_lock(vm_object_t object) { struct thread *td = curthread; /* XXX */ + int error; for (; object != NULL; object = object->backing_object) { if (object->type != OBJT_VNODE) @@ -1034,15 +1036,24 @@ vnode_pager_lock(vm_object_t object) if (object->flags & OBJ_DEAD) return NULL; - while (vget(object->handle, NULL, - LK_NOPAUSE | LK_SHARED | LK_RETRY | LK_CANRECURSE, td)) { + for (;;) { + struct vnode *vp = object->handle; + error = vget(vp, LK_NOPAUSE | LK_SHARED | + LK_RETRY | LK_CANRECURSE, td); + if (error == 0) { + if (object->handle != vp) { + vput(vp); + continue; + } + return (vp); + } if ((object->flags & OBJ_DEAD) || (object->type != OBJT_VNODE)) { return NULL; } - printf("vnode_pager_lock: retrying\n"); + printf("vnode_pager_lock: vp %p error %d lockstatus %d, retrying\n", vp, error, lockstatus(&vp->v_lock, td)); + tsleep(object->handle, 0, "vnpgrl", hz); } - return object->handle; } return NULL; } -- 2.41.0