diff options
author | jeff <jeff@FreeBSD.org> | 2006-02-22 06:15:12 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2006-02-22 06:15:12 +0000 |
commit | 79ca2be05cf1a1b1dee266ef4bf5cbd75045936e (patch) | |
tree | 067b6f65a44a12b75ef538046e05d2d0d364e5c8 /sys/fs/nullfs | |
parent | c925b62ee4b3dac1f343e7e1239075089fffc941 (diff) | |
download | FreeBSD-src-79ca2be05cf1a1b1dee266ef4bf5cbd75045936e.zip FreeBSD-src-79ca2be05cf1a1b1dee266ef4bf5cbd75045936e.tar.gz |
- Assert that the lowervp is locked in null_hashget().
- Simplify the logic dealing with recycled vnodes in null_hashget() and
null_hashins(). Since we hold the lower node locked in both cases
the null node can not be undergoing recycling unless reclaim somehow
called null_nodeget(). The logic that was in place was not safe and
was essentially dead code.
MFC After: 1 week
Diffstat (limited to 'sys/fs/nullfs')
-rw-r--r-- | sys/fs/nullfs/null_subr.c | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index a5a45ea..5dc7c63 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -107,6 +107,9 @@ null_hashget(mp, lowervp) struct null_node_hashhead *hd; struct null_node *a; struct vnode *vp; + int error; + + ASSERT_VOP_LOCKED(lowervp, "null_hashget"); /* * Find hash base, and then search the (two-way) linked @@ -115,31 +118,27 @@ null_hashget(mp, lowervp) * reference count (but NOT the lower vnode's VREF counter). */ hd = NULL_NHASH(lowervp); -loop: mtx_lock(&null_hashmtx); LIST_FOREACH(a, hd, null_hash) { if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) { vp = NULLTOV(a); VI_LOCK(vp); - /* - * If the nullfs node is being recycled we have - * to wait until it finishes prior to scanning - * again. - */ mtx_unlock(&null_hashmtx); - if ((vp->v_iflag & VI_DOOMED) != 0) { - /* Wait for recycling to finish. */ - VOP_LOCK(vp, LK_EXCLUSIVE|LK_INTERLOCK, td); - VOP_UNLOCK(vp, 0, td); - goto loop; - } /* * We need to clear the OWEINACT flag here as this * may lead vget() to try to lock our vnode which * is already locked via lowervp. */ vp->v_iflag &= ~VI_OWEINACT; - vget(vp, LK_INTERLOCK, td); + error = vget(vp, LK_INTERLOCK, td); + /* + * Since we have the lower node locked the nullfs + * node can not be in the process of recycling. If + * it had been recycled before we grabed the lower + * lock it would not have been found on the hash. + */ + if (error) + panic("null_hashget: vget error %d", error); return (vp); } } @@ -160,28 +159,24 @@ null_hashins(mp, xp) struct null_node_hashhead *hd; struct null_node *oxp; struct vnode *ovp; + int error; hd = NULL_NHASH(xp->null_lowervp); -loop: mtx_lock(&null_hashmtx); LIST_FOREACH(oxp, hd, null_hash) { if (oxp->null_lowervp == xp->null_lowervp && NULLTOV(oxp)->v_mount == mp) { - ovp = NULLTOV(oxp); - VI_LOCK(ovp); /* - * If the nullfs node is being recycled we have - * to wait until it finishes prior to scanning - * again. + * See null_hashget for a description of this + * operation. */ + ovp = NULLTOV(oxp); + VI_LOCK(ovp); mtx_unlock(&null_hashmtx); - if ((ovp->v_iflag & VI_DOOMED) != 0) { - VOP_LOCK(ovp, LK_EXCLUSIVE|LK_INTERLOCK, td); - VOP_UNLOCK(ovp, 0, td); - goto loop; - } - ovp->v_iflag &= ~VI_OWEINACT; /* see hashget comment */ - vget(ovp, LK_INTERLOCK, td); + ovp->v_iflag &= ~VI_OWEINACT; + error = vget(ovp, LK_INTERLOCK, td); + if (error) + panic("null_hashins: vget error %d", error); return (ovp); } } |