diff options
author | mckusick <mckusick@FreeBSD.org> | 2002-02-02 01:49:18 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2002-02-02 01:49:18 +0000 |
commit | ca79facdf4005810aaa1b757a00e3a8428d8cfd8 (patch) | |
tree | 4b9bff2b22a1824b424f5f96db6c16813f5dceeb | |
parent | a7a7cb3eff86ba390846478e2d9618a87dc8dcb3 (diff) | |
download | FreeBSD-src-ca79facdf4005810aaa1b757a00e3a8428d8cfd8.zip FreeBSD-src-ca79facdf4005810aaa1b757a00e3a8428d8cfd8.tar.gz |
In the routines vrele() and vput(), we must lock the vnode and
call VOP_INACTIVE before placing the vnode back on the free list.
Otherwise there is a race condition on SMP machines between
getnewvnode() locking the vnode to reclaim it and vrele()
locking the vnode to inactivate it. This window of vulnerability
becomes exaggerated in the presence of filesystems that have
been suspended as the inactive routine may need to temporarily
release the lock on the vnode to avoid deadlock with the syncer
process.
-rw-r--r-- | sys/kern/vfs_subr.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 277430d..3c61b17 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1727,18 +1727,18 @@ vrele(vp) if (vp->v_usecount == 1) { vp->v_usecount--; + /* + * We must call VOP_INACTIVE with the node locked. + * If we are doing a vput, the node is already locked, + * but, in the case of vrele, we must explicitly lock + * the vnode before calling VOP_INACTIVE. + */ + if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0) + VOP_INACTIVE(vp, td); if (VSHOULDFREE(vp)) vfree(vp); else vlruvp(vp); - /* - * If we are doing a vput, the node is already locked, and we must - * call VOP_INACTIVE with the node locked. So, in the case of - * vrele, we explicitly lock the vnode before calling VOP_INACTIVE. - */ - if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0) { - VOP_INACTIVE(vp, td); - } } else { #ifdef DIAGNOSTIC @@ -1776,17 +1776,17 @@ vput(vp) if (vp->v_usecount == 1) { vp->v_usecount--; + /* + * We must call VOP_INACTIVE with the node locked. + * If we are doing a vput, the node is already locked, + * so we just need to release the vnode mutex. + */ + mtx_unlock(&vp->v_interlock); + VOP_INACTIVE(vp, td); if (VSHOULDFREE(vp)) vfree(vp); else vlruvp(vp); - /* - * If we are doing a vput, the node is already locked, and we must - * call VOP_INACTIVE with the node locked. So, in the case of - * vrele, we explicitly lock the vnode before calling VOP_INACTIVE. - */ - mtx_unlock(&vp->v_interlock); - VOP_INACTIVE(vp, td); } else { #ifdef DIAGNOSTIC |