From 6bdfe06ad9337a33a402bc933006265c30980780 Mon Sep 17 00:00:00 2001 From: Eivind Eklund Date: Sat, 11 Dec 1999 16:13:02 +0000 Subject: [PATCH] Lock reporting and assertion changes. * lockstatus() and VOP_ISLOCKED() gets a new process argument and a new return value: LK_EXCLOTHER, when the lock is held exclusively by another process. * The ASSERT_VOP_(UN)LOCKED family is extended to use what this gives them * Extend the vnode_if.src format to allow more exact specification than locked/unlocked. This commit should not do any semantic changes unless you are using DEBUG_VFS_LOCKS. Discussed with: grog, mch, peter, phk Reviewed by: peter --- sys/coda/coda_vnops.c | 2 +- sys/contrib/softupdates/ffs_softdep.c | 2 +- sys/dev/vn/vn.c | 2 +- sys/fs/coda/coda_vnops.c | 2 +- sys/fs/nullfs/null_vfsops.c | 6 +-- sys/fs/nullfs/null_vnops.c | 4 +- sys/fs/nwfs/nwfs_vfsops.c | 2 +- sys/fs/unionfs/union_vfsops.c | 9 +++-- sys/fs/unionfs/union_vnops.c | 8 ++-- sys/kern/kern_lock.c | 12 ++++-- sys/kern/vfs_default.c | 6 ++- sys/kern/vfs_export.c | 6 +-- sys/kern/vfs_subr.c | 6 +-- sys/kern/vnode_if.src | 7 +++- sys/miscfs/devfs/devfs_vfsops.c | 2 +- sys/miscfs/nullfs/null_vfsops.c | 6 +-- sys/miscfs/nullfs/null_vnops.c | 4 +- sys/miscfs/union/union_vfsops.c | 9 +++-- sys/miscfs/union/union_vnops.c | 8 ++-- sys/nfs/nfs_node.c | 1 + sys/nfs/nfs_vfsops.c | 2 +- sys/nfsclient/nfs_node.c | 1 + sys/nfsclient/nfs_vfsops.c | 2 +- sys/nwfs/nwfs_vfsops.c | 2 +- sys/sys/lock.h | 5 ++- sys/sys/lockmgr.h | 5 ++- sys/sys/vnode.h | 57 +++++++++++++++++++++++---- sys/ufs/ffs/ffs_softdep.c | 2 +- sys/vm/vm_pageout.c | 2 +- sys/vm/vm_zone.c | 2 +- 30 files changed, 125 insertions(+), 59 deletions(-) diff --git a/sys/coda/coda_vnops.c b/sys/coda/coda_vnops.c index 5f86c09a9185..1ef09bc19297 100644 --- a/sys/coda/coda_vnops.c +++ b/sys/coda/coda_vnops.c @@ -1865,7 +1865,7 @@ coda_islocked(v) struct cnode *cp = VTOC(ap->a_vp); ENTRY; - return (lockstatus(&cp->c_lock)); + return (lockstatus(&cp->c_lock, ap->a_p)); } /* How one looks up a vnode given a device/inode pair: */ diff --git a/sys/contrib/softupdates/ffs_softdep.c b/sys/contrib/softupdates/ffs_softdep.c index 79a1aeee14f5..a0252d20889c 100644 --- a/sys/contrib/softupdates/ffs_softdep.c +++ b/sys/contrib/softupdates/ffs_softdep.c @@ -3978,7 +3978,7 @@ loop: * way to accomplish this is to sync the entire filesystem (luckily * this happens rarely). */ - if (vn_isdisk(vp) && vp->v_specmountpoint && !VOP_ISLOCKED(vp) && + if (vn_isdisk(vp) && vp->v_specmountpoint && !VOP_ISLOCKED(vp, NULL) && (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, ap->a_cred, ap->a_p)) != 0) return (error); diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c index 0730696ad82d..0c164505920b 100644 --- a/sys/dev/vn/vn.c +++ b/sys/dev/vn/vn.c @@ -362,7 +362,7 @@ vnstrategy(struct buf *bp) auio.uio_rw = UIO_WRITE; auio.uio_resid = bp->b_bcount; auio.uio_procp = curproc; - if (!VOP_ISLOCKED(vn->sc_vp)) { + if (!VOP_ISLOCKED(vn->sc_vp, NULL)) { isvplocked = 1; vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc); } diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c index 5f86c09a9185..1ef09bc19297 100644 --- a/sys/fs/coda/coda_vnops.c +++ b/sys/fs/coda/coda_vnops.c @@ -1865,7 +1865,7 @@ coda_islocked(v) struct cnode *cp = VTOC(ap->a_vp); ENTRY; - return (lockstatus(&cp->c_lock)); + return (lockstatus(&cp->c_lock, ap->a_p)); } /* How one looks up a vnode given a device/inode pair: */ diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 06e1be04617b..e48a516da0cb 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -119,7 +119,7 @@ nullfs_mount(mp, path, data, ndp, p) * (XXX) VOP_ISLOCKED is needed? */ if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) && - VOP_ISLOCKED(mp->mnt_vnodecovered)) { + VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) { VOP_UNLOCK(mp->mnt_vnodecovered, 0, p); isvnunlocked = 1; } @@ -132,7 +132,7 @@ nullfs_mount(mp, path, data, ndp, p) /* * Re-lock vnode. */ - if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered)) + if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p); if (error) @@ -296,7 +296,7 @@ nullfs_root(mp, vpp) */ vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; VREF(vp); - if (VOP_ISLOCKED(vp)) { + if (VOP_ISLOCKED(vp, NULL)) { /* * XXX * Should we check type of node? diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 225ac09ad5da..9600f3c11ea6 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -372,13 +372,13 @@ null_lookup(ap) vp = *ap->a_vpp; if (dvp == vp) return (error); - if (!VOP_ISLOCKED(dvp)) { + if (!VOP_ISLOCKED(dvp, NULL)) { unlockargs.a_vp = dvp; unlockargs.a_flags = 0; unlockargs.a_p = p; vop_nounlock(&unlockargs); } - if (vp != NULLVP && VOP_ISLOCKED(vp)) { + if (vp != NULLVP && VOP_ISLOCKED(vp, NULL)) { lockargs.a_vp = vp; lockargs.a_flags = LK_SHARED; lockargs.a_p = p; diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c index d9e5f57827f8..f99bba74c7e9 100644 --- a/sys/fs/nwfs/nwfs_vfsops.c +++ b/sys/fs/nwfs/nwfs_vfsops.c @@ -498,7 +498,7 @@ loop: */ if (vp->v_mount != mp) goto loop; - if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || + if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; if (vget(vp, LK_EXCLUSIVE, p)) diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index 1a53f88bcc7b..ccd9a13ca17f 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -148,7 +148,8 @@ union_mount(mp, path, data, ndp, p) vrele(ndp->ni_dvp); ndp->ni_dvp = NULL; - UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp, VOP_ISLOCKED(upperrootvp))); + UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp, + VOP_ISLOCKED(upperrootvp, NULL))); /* * Check multi union mount to avoid `lock myself again' panic. @@ -396,7 +397,8 @@ union_root(mp, vpp) * root union_node being locked. We let union_allocvp() deal with * it. */ - UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp, VOP_ISLOCKED(um->um_uppervp))); + UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp, + VOP_ISLOCKED(um->um_uppervp, NULL))); VREF(um->um_uppervp); if (um->um_lowervp) @@ -405,7 +407,8 @@ union_root(mp, vpp) error = union_allocvp(vpp, mp, NULLVP, NULLVP, NULL, um->um_uppervp, um->um_lowervp, 1); UDEBUG(("error %d\n", error)); - UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp, VOP_ISLOCKED(um->um_uppervp))); + UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp, + VOP_ISLOCKED(um->um_uppervp, NULL))); return (error); } diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 08763ce5259b..5ab10366cb84 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -363,10 +363,10 @@ union_lookup(ap) uerror, upperdvp, upperdvp->v_usecount, - VOP_ISLOCKED(upperdvp), + VOP_ISLOCKED(upperdvp, NULL), uppervp, (uppervp ? uppervp->v_usecount : -99), - (uppervp ? VOP_ISLOCKED(uppervp) : -99) + (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99) )); /* @@ -1698,7 +1698,7 @@ union_abortop(ap) struct componentname *cnp = ap->a_cnp; struct proc *p = cnp->cn_proc; struct union_node *un = VTOUNION(ap->a_dvp); - int islocked = VOP_ISLOCKED(ap->a_dvp); + int islocked = VOP_ISLOCKED(ap->a_dvp, NULL); struct vnode *vp; int error; @@ -1850,7 +1850,7 @@ union_unlock(ap) */ if ((un->un_flags & UN_ULOCK) && - lockstatus(&un->un_lock) != LK_EXCLUSIVE) { + lockstatus(&un->un_lock, NULL) != LK_EXCLUSIVE) { un->un_flags &= ~UN_ULOCK; VOP_UNLOCK(un->un_uppervp, LK_EXCLUSIVE, p); } diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index d80561dfe8aa..b47ca55c2aac 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -511,15 +511,19 @@ lockinit(lkp, prio, wmesg, timo, flags) * Determine the status of a lock. */ int -lockstatus(lkp) +lockstatus(lkp, p) struct lock *lkp; + struct proc *p; { int lock_type = 0; simple_lock(&lkp->lk_interlock); - if (lkp->lk_exclusivecount != 0) - lock_type = LK_EXCLUSIVE; - else if (lkp->lk_sharecount != 0) + if (lkp->lk_exclusivecount != 0) { + if (p == NULL || lkp->lk_lockholder == p->p_pid) + lock_type = LK_EXCLUSIVE; + else + lock_type = LK_EXCLOTHER; + } else if (lkp->lk_sharecount != 0) lock_type = LK_SHARED; simple_unlock(&lkp->lk_interlock); return (lock_type); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index fe5d94d0135e..600df41e1e28 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -255,6 +255,7 @@ int vop_stdislocked(ap) struct vop_islocked_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { struct lock *l; @@ -262,7 +263,7 @@ vop_stdislocked(ap) if ((l = (struct lock *)ap->a_vp->v_data) == NULL) return 0; - return (lockstatus(l)); + return (lockstatus(l, ap->a_p)); } /* @@ -484,13 +485,14 @@ int vop_noislocked(ap) struct vop_islocked_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { struct vnode *vp = ap->a_vp; if (vp->v_vnlock == NULL) return (0); - return (lockstatus(vp->v_vnlock)); + return (lockstatus(vp->v_vnlock, ap->a_p)); } /* diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index a19c3d266991..1f6b7a46cd1b 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -990,7 +990,7 @@ sched_sync(void) splx(s); while ((vp = LIST_FIRST(slp)) != NULL) { - if (VOP_ISLOCKED(vp) == 0) { + if (VOP_ISLOCKED(vp, NULL) == 0) { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p); VOP_UNLOCK(vp, 0, p); @@ -1962,7 +1962,7 @@ DB_SHOW_COMMAND(lockedvnodes, lockedvnodes) continue; } LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { - if (VOP_ISLOCKED(vp)) + if (VOP_ISLOCKED(vp, NULL)) vprint((char *)0, vp); } simple_lock(&mountlist_slock); @@ -2450,7 +2450,7 @@ loop: obj = vp->v_object; if (obj == NULL || (obj->flags & OBJ_MIGHTBEDIRTY) == 0) continue; - if (VOP_ISLOCKED(vp)) + if (VOP_ISLOCKED(vp, NULL)) continue; } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index a19c3d266991..1f6b7a46cd1b 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -990,7 +990,7 @@ sched_sync(void) splx(s); while ((vp = LIST_FIRST(slp)) != NULL) { - if (VOP_ISLOCKED(vp) == 0) { + if (VOP_ISLOCKED(vp, NULL) == 0) { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p); VOP_UNLOCK(vp, 0, p); @@ -1962,7 +1962,7 @@ DB_SHOW_COMMAND(lockedvnodes, lockedvnodes) continue; } LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { - if (VOP_ISLOCKED(vp)) + if (VOP_ISLOCKED(vp, NULL)) vprint((char *)0, vp); } simple_lock(&mountlist_slock); @@ -2450,7 +2450,7 @@ loop: obj = vp->v_object; if (obj == NULL || (obj->flags & OBJ_MIGHTBEDIRTY) == 0) continue; - if (VOP_ISLOCKED(vp)) + if (VOP_ISLOCKED(vp, NULL)) continue; } diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 2b16704b2a5f..c41816485f3e 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -43,7 +43,11 @@ # "error" column defines the locking state on error exit. # # The locking value can take the following values: -# L: locked. +# L: locked; not converted to type of lock. +# A: any lock type. +# S: locked with shared lock. +# E: locked with exclusive lock for this process. +# O: locked with exclusive lock for other process. # U: unlocked. # -: not applicable. vnode does not yet (or no longer) exists. # =: the same on input and output, may be either L or U. @@ -55,6 +59,7 @@ # vop_islocked { IN struct vnode *vp; + IN struct proc *p; }; # diff --git a/sys/miscfs/devfs/devfs_vfsops.c b/sys/miscfs/devfs/devfs_vfsops.c index 287ca99910d1..73f7d70b89f3 100644 --- a/sys/miscfs/devfs/devfs_vfsops.c +++ b/sys/miscfs/devfs/devfs_vfsops.c @@ -264,7 +264,7 @@ loop: if (vp->v_mount != mp) goto loop; nvp = vp->v_mntvnodes.le_next; - if (VOP_ISLOCKED(vp)) + if (VOP_ISLOCKED(vp, NULL)) continue; if (TAILQ_EMPTY(&vp->v_dirtyblkhd)) continue; diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c index 06e1be04617b..e48a516da0cb 100644 --- a/sys/miscfs/nullfs/null_vfsops.c +++ b/sys/miscfs/nullfs/null_vfsops.c @@ -119,7 +119,7 @@ nullfs_mount(mp, path, data, ndp, p) * (XXX) VOP_ISLOCKED is needed? */ if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) && - VOP_ISLOCKED(mp->mnt_vnodecovered)) { + VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) { VOP_UNLOCK(mp->mnt_vnodecovered, 0, p); isvnunlocked = 1; } @@ -132,7 +132,7 @@ nullfs_mount(mp, path, data, ndp, p) /* * Re-lock vnode. */ - if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered)) + if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p); if (error) @@ -296,7 +296,7 @@ nullfs_root(mp, vpp) */ vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; VREF(vp); - if (VOP_ISLOCKED(vp)) { + if (VOP_ISLOCKED(vp, NULL)) { /* * XXX * Should we check type of node? diff --git a/sys/miscfs/nullfs/null_vnops.c b/sys/miscfs/nullfs/null_vnops.c index 225ac09ad5da..9600f3c11ea6 100644 --- a/sys/miscfs/nullfs/null_vnops.c +++ b/sys/miscfs/nullfs/null_vnops.c @@ -372,13 +372,13 @@ null_lookup(ap) vp = *ap->a_vpp; if (dvp == vp) return (error); - if (!VOP_ISLOCKED(dvp)) { + if (!VOP_ISLOCKED(dvp, NULL)) { unlockargs.a_vp = dvp; unlockargs.a_flags = 0; unlockargs.a_p = p; vop_nounlock(&unlockargs); } - if (vp != NULLVP && VOP_ISLOCKED(vp)) { + if (vp != NULLVP && VOP_ISLOCKED(vp, NULL)) { lockargs.a_vp = vp; lockargs.a_flags = LK_SHARED; lockargs.a_p = p; diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c index 1a53f88bcc7b..ccd9a13ca17f 100644 --- a/sys/miscfs/union/union_vfsops.c +++ b/sys/miscfs/union/union_vfsops.c @@ -148,7 +148,8 @@ union_mount(mp, path, data, ndp, p) vrele(ndp->ni_dvp); ndp->ni_dvp = NULL; - UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp, VOP_ISLOCKED(upperrootvp))); + UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp, + VOP_ISLOCKED(upperrootvp, NULL))); /* * Check multi union mount to avoid `lock myself again' panic. @@ -396,7 +397,8 @@ union_root(mp, vpp) * root union_node being locked. We let union_allocvp() deal with * it. */ - UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp, VOP_ISLOCKED(um->um_uppervp))); + UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp, + VOP_ISLOCKED(um->um_uppervp, NULL))); VREF(um->um_uppervp); if (um->um_lowervp) @@ -405,7 +407,8 @@ union_root(mp, vpp) error = union_allocvp(vpp, mp, NULLVP, NULLVP, NULL, um->um_uppervp, um->um_lowervp, 1); UDEBUG(("error %d\n", error)); - UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp, VOP_ISLOCKED(um->um_uppervp))); + UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp, + VOP_ISLOCKED(um->um_uppervp, NULL))); return (error); } diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c index 08763ce5259b..5ab10366cb84 100644 --- a/sys/miscfs/union/union_vnops.c +++ b/sys/miscfs/union/union_vnops.c @@ -363,10 +363,10 @@ union_lookup(ap) uerror, upperdvp, upperdvp->v_usecount, - VOP_ISLOCKED(upperdvp), + VOP_ISLOCKED(upperdvp, NULL), uppervp, (uppervp ? uppervp->v_usecount : -99), - (uppervp ? VOP_ISLOCKED(uppervp) : -99) + (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99) )); /* @@ -1698,7 +1698,7 @@ union_abortop(ap) struct componentname *cnp = ap->a_cnp; struct proc *p = cnp->cn_proc; struct union_node *un = VTOUNION(ap->a_dvp); - int islocked = VOP_ISLOCKED(ap->a_dvp); + int islocked = VOP_ISLOCKED(ap->a_dvp, NULL); struct vnode *vp; int error; @@ -1850,7 +1850,7 @@ union_unlock(ap) */ if ((un->un_flags & UN_ULOCK) && - lockstatus(&un->un_lock) != LK_EXCLUSIVE) { + lockstatus(&un->un_lock, NULL) != LK_EXCLUSIVE) { un->un_flags &= ~UN_ULOCK; VOP_UNLOCK(un->un_uppervp, LK_EXCLUSIVE, p); } diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c index 13ff9b2902a0..53c73a165d9e 100644 --- a/sys/nfs/nfs_node.c +++ b/sys/nfs/nfs_node.c @@ -380,6 +380,7 @@ int nfs_islocked(ap) struct vop_islocked_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index dc9e053ac8cd..8a0c36869410 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -1062,7 +1062,7 @@ loop: */ if (vp->v_mount != mp) goto loop; - if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || + if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; if (vget(vp, LK_EXCLUSIVE, p)) diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c index 13ff9b2902a0..53c73a165d9e 100644 --- a/sys/nfsclient/nfs_node.c +++ b/sys/nfsclient/nfs_node.c @@ -380,6 +380,7 @@ int nfs_islocked(ap) struct vop_islocked_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index dc9e053ac8cd..8a0c36869410 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -1062,7 +1062,7 @@ loop: */ if (vp->v_mount != mp) goto loop; - if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || + if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; if (vget(vp, LK_EXCLUSIVE, p)) diff --git a/sys/nwfs/nwfs_vfsops.c b/sys/nwfs/nwfs_vfsops.c index d9e5f57827f8..f99bba74c7e9 100644 --- a/sys/nwfs/nwfs_vfsops.c +++ b/sys/nwfs/nwfs_vfsops.c @@ -498,7 +498,7 @@ loop: */ if (vp->v_mount != mp) goto loop; - if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || + if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) continue; if (vget(vp, LK_EXCLUSIVE, p)) diff --git a/sys/sys/lock.h b/sys/sys/lock.h index 04157c0fc3dc..57b8b05aae77 100644 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -95,6 +95,8 @@ struct lock { * LK_DRAIN - wait for all activity on the lock to end, then mark it * decommissioned. This feature is used before freeing a lock that * is part of a piece of memory that is about to be freed. + * LK_EXCLOTHER - return for lockstatus(). Used when another process + * holds the lock exclusively. * * These are flags that are passed to the lockmgr routine. */ @@ -106,6 +108,7 @@ struct lock { #define LK_DOWNGRADE 0x00000005 /* exclusive-to-shared downgrade */ #define LK_RELEASE 0x00000006 /* release any type of lock */ #define LK_DRAIN 0x00000007 /* wait for all lock activity to end */ +#define LK_EXCLOTHER 0x00000008 /* other process holds lock */ /* * External lock flags. * @@ -187,7 +190,7 @@ int lockmgr __P((struct lock *, u_int flags, struct simplelock *, struct proc *p)); #endif void lockmgr_printinfo __P((struct lock *)); -int lockstatus __P((struct lock *)); +int lockstatus __P((struct lock *, struct proc *)); int lockcount __P((struct lock *)); #ifdef SIMPLELOCK_DEBUG diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h index 04157c0fc3dc..57b8b05aae77 100644 --- a/sys/sys/lockmgr.h +++ b/sys/sys/lockmgr.h @@ -95,6 +95,8 @@ struct lock { * LK_DRAIN - wait for all activity on the lock to end, then mark it * decommissioned. This feature is used before freeing a lock that * is part of a piece of memory that is about to be freed. + * LK_EXCLOTHER - return for lockstatus(). Used when another process + * holds the lock exclusively. * * These are flags that are passed to the lockmgr routine. */ @@ -106,6 +108,7 @@ struct lock { #define LK_DOWNGRADE 0x00000005 /* exclusive-to-shared downgrade */ #define LK_RELEASE 0x00000006 /* release any type of lock */ #define LK_DRAIN 0x00000007 /* wait for all lock activity to end */ +#define LK_EXCLOTHER 0x00000008 /* other process holds lock */ /* * External lock flags. * @@ -187,7 +190,7 @@ int lockmgr __P((struct lock *, u_int flags, struct simplelock *, struct proc *p)); #endif void lockmgr_printinfo __P((struct lock *)); -int lockstatus __P((struct lock *)); +int lockstatus __P((struct lock *, struct proc *)); int lockcount __P((struct lock *)); #ifdef SIMPLELOCK_DEBUG diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 86e8fd5052af..366c2d5bd9d8 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -421,15 +421,56 @@ struct vop_generic_args { || (vp)->v_tag == VT_MSDOSFS \ || (vp)->v_tag == VT_DEVFS) -#define ASSERT_VOP_LOCKED(vp, str) \ - if ((vp) && IS_LOCKING_VFS(vp) && !VOP_ISLOCKED(vp)) { \ - panic("%s: %p is not locked but should be", str, vp); \ - } +#define ASSERT_VOP_LOCKED(vp, str) \ +do { \ + struct vnode *_vp = (vp); \ + \ + if (_vp && IS_LOCKING_VFS(_vp) && !VOP_ISLOCKED(_vp, NULL)) \ + panic("%s: %p is not locked but should be", str, _vp); \ +} while (0) -#define ASSERT_VOP_UNLOCKED(vp, str) \ - if ((vp) && IS_LOCKING_VFS(vp) && VOP_ISLOCKED(vp)) { \ - panic("%s: %p is locked but shouldn't be", str, vp); \ - } +#define ASSERT_VOP_UNLOCKED(vp, str) \ +do { \ + struct vnode *_vp = (vp); \ + int lockstate; \ + \ + if (_vp && IS_LOCKING_VFS(_vp)) { \ + lockstate = VOP_ISLOCKED(_vp, curproc); \ + if (lockstate == LK_EXCLUSIVE) \ + panic("%s: %p is locked but should not be", \ + str, _vp); \ + } \ +} while (0) + +#define ASSERT_VOP_ELOCKED(vp, str) \ +do { \ + struct vnode *_vp = (vp); \ + \ + if (_vp && IS_LOCKING_VFS(_vp) && \ + VOP_ISLOCKED(_vp, curproc) != LK_EXCLUSIVE) \ + panic("%s: %p is not exclusive locked but should be", \ + str, _vp); \ +} while (0) + +#define ASSERT_VOP_ELOCKED_OTHER(vp, str) \ +do { \ + struct vnode *_vp = (vp); \ + \ + if (_vp && IS_LOCKING_VFS(_vp) && \ + VOP_ISLOCKED(_vp, curproc) != LK_EXCLOTHER) \ + panic("%s: %p is not exclusive locked by another proc", \ + str, _vp); \ +} while (0) + +#define ASSERT_VOP_SLOCKED(vp, str) \ +do { \ + struct vnode *_vp = (vp); \ + \ + if (_vp && IS_LOCKING_VFS(_vp) && \ + VOP_ISLOCKED(_vp, NULL) != LK_SHARED) \ + panic("%s: %p is not locked shared but should be", \ + str, _vp); \ +} while (0) #else diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 79a1aeee14f5..a0252d20889c 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -3978,7 +3978,7 @@ loop: * way to accomplish this is to sync the entire filesystem (luckily * this happens rarely). */ - if (vn_isdisk(vp) && vp->v_specmountpoint && !VOP_ISLOCKED(vp) && + if (vn_isdisk(vp) && vp->v_specmountpoint && !VOP_ISLOCKED(vp, NULL) && (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, ap->a_cred, ap->a_p)) != 0) return (error); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 8f930af37321..1adb7e46921f 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -852,7 +852,7 @@ rescan0: if (object->type == OBJT_VNODE) { vp = object->handle; - if (VOP_ISLOCKED(vp) || + if (VOP_ISLOCKED(vp, NULL) || vp->v_data == NULL || vget(vp, LK_EXCLUSIVE|LK_NOOBJ, curproc)) { if ((m->queue == PQ_INACTIVE) && diff --git a/sys/vm/vm_zone.c b/sys/vm/vm_zone.c index e111b835a93b..b53cfa0220b7 100644 --- a/sys/vm/vm_zone.c +++ b/sys/vm/vm_zone.c @@ -324,7 +324,7 @@ _zget(vm_zone_t z) * We can wait, so just do normal map allocation in the appropriate * map. */ - if (lockstatus(&kernel_map->lock)) { + if (lockstatus(&kernel_map->lock, NULL)) { int s; s = splvm(); #ifdef SMP