diff options
author | kib <kib@FreeBSD.org> | 2012-02-29 15:06:00 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-02-29 15:06:00 +0000 |
commit | 2ebb3c07b936648b7394ca73ec90ff4195207cad (patch) | |
tree | fe7ccdfea2451c5232f1a7cd3d62cc4d5a2004cb /sys/fs/nullfs | |
parent | 2a733f909a52c0dec8dd99f83ca793589eff7810 (diff) | |
download | FreeBSD-src-2ebb3c07b936648b7394ca73ec90ff4195207cad.zip FreeBSD-src-2ebb3c07b936648b7394ca73ec90ff4195207cad.tar.gz |
Move the code to destroy half-contructed nullfs vnode into helper
function null_destroy_proto() from null_insmntque_dtr(). Also
apply null_destroy_proto() in null_nodeget() when we raced and a vnode
is found in the hash, so the currently allocated protonode shall be
destroyed.
Lock the vnode interlock around reassigning the v_vnlock.
In fact, this path will not be exercised after several later commits,
since null_nodeget() cannot take shared-locked lowervp at all due to
insmntque() requirements.
Reported by: rea
Tested by: pho
MFC after: 1 week
Diffstat (limited to 'sys/fs/nullfs')
-rw-r--r-- | sys/fs/nullfs/null_subr.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index f676b04..6bfae2c 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -169,17 +169,26 @@ null_hashins(mp, xp) } static void -null_insmntque_dtr(struct vnode *vp, void *xp) +null_destroy_proto(struct vnode *vp, void *xp) { - vput(((struct null_node *)xp)->null_lowervp); + VI_LOCK(vp); vp->v_data = NULL; vp->v_vnlock = &vp->v_lock; - free(xp, M_NULLFSNODE); vp->v_op = &dead_vnodeops; + VI_UNLOCK(vp); (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vgone(vp); vput(vp); + free(xp, M_NULLFSNODE); +} + +static void +null_insmntque_dtr(struct vnode *vp, void *xp) +{ + + vput(((struct null_node *)xp)->null_lowervp); + null_destroy_proto(vp, xp); } /* @@ -247,9 +256,7 @@ null_nodeget(mp, lowervp, vpp) *vpp = null_hashins(mp, xp); if (*vpp != NULL) { vrele(lowervp); - vp->v_vnlock = &vp->v_lock; - xp->null_lowervp = NULL; - vrele(vp); + null_destroy_proto(vp, xp); return (0); } *vpp = vp; |