diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2012-02-29 15:06:00 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2012-02-29 15:06:00 +0000 |
commit | 67e3d54f804f8e9c6c1436999fa39be5bf9cf59c (patch) | |
tree | fe7ccdfea2451c5232f1a7cd3d62cc4d5a2004cb | |
parent | c8b4c0aa6ca7e36fe401d14520557e0862603aab (diff) | |
download | src-67e3d54f804f8e9c6c1436999fa39be5bf9cf59c.tar.gz src-67e3d54f804f8e9c6c1436999fa39be5bf9cf59c.zip |
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
Notes
Notes:
svn path=/head/; revision=232299
-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 f676b04b3b85..6bfae2cf529c 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; |