Fix the "error" path (when dropping not fully initialized vnode).
Also move hash operations out of null_vnops.c and explicitly initialize v_lock in null_node_alloc (to set wmesg). Reviewed by: bp MFC after: 2 weeks
This commit is contained in:
parent
ebe0bdddac
commit
08720e34b0
@ -60,6 +60,7 @@ struct null_node {
|
||||
int nullfs_init(struct vfsconf *vfsp);
|
||||
int nullfs_uninit(struct vfsconf *vfsp);
|
||||
int null_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
|
||||
void null_hashrem(struct null_node *xp);
|
||||
int null_bypass(struct vop_generic_args *ap);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -70,7 +71,6 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
|
||||
#endif
|
||||
|
||||
extern vop_t **null_vnodeop_p;
|
||||
extern struct lock null_hashlock;
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_NULLFSNODE);
|
||||
|
@ -183,10 +183,15 @@ null_node_alloc(mp, lowervp, vpp)
|
||||
}
|
||||
vp = *vpp;
|
||||
|
||||
vp->v_type = lowervp->v_type;
|
||||
xp->null_vnode = vp;
|
||||
vp->v_data = xp;
|
||||
xp->null_lowervp = lowervp;
|
||||
|
||||
vp->v_type = lowervp->v_type;
|
||||
vp->v_data = xp;
|
||||
|
||||
/* Though v_lock is inited by getnewvnode(), we want our own wmesg */
|
||||
lockinit(&vp->v_lock, PVFS, "nunode", VLKTIMEOUT, LK_NOPAUSE);
|
||||
|
||||
/*
|
||||
* Before we insert our new node onto the hash chains,
|
||||
* check to see if someone else has beaten us to it.
|
||||
@ -194,9 +199,7 @@ null_node_alloc(mp, lowervp, vpp)
|
||||
*/
|
||||
othervp = null_node_find(mp, lowervp);
|
||||
if (othervp) {
|
||||
vp->v_data = NULL;
|
||||
FREE(xp, M_NULLFSNODE);
|
||||
vp->v_type = VBAD; /* node is discarded */
|
||||
xp->null_lowervp = NULL;
|
||||
vrele(vp);
|
||||
*vpp = othervp;
|
||||
return 0;
|
||||
@ -286,6 +289,17 @@ null_node_create(mp, lowervp, newvpp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
null_hashrem(xp)
|
||||
struct null_node *xp;
|
||||
{
|
||||
struct thread *td = curthread; /* XXX */
|
||||
|
||||
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, td);
|
||||
LIST_REMOVE(xp, null_hash);
|
||||
lockmgr(&null_hashlock, LK_RELEASE, NULL, td);
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
#include "opt_ddb.h"
|
||||
|
||||
|
@ -739,26 +739,19 @@ null_reclaim(ap)
|
||||
struct thread *a_td;
|
||||
} */ *ap;
|
||||
{
|
||||
struct thread *td = ap->a_td;
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct null_node *xp = VTONULL(vp);
|
||||
struct vnode *lowervp = xp->null_lowervp;
|
||||
void *vdata;
|
||||
|
||||
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, td);
|
||||
LIST_REMOVE(xp, null_hash);
|
||||
lockmgr(&null_hashlock, LK_RELEASE, NULL, td);
|
||||
if (lowervp) {
|
||||
null_hashrem(xp);
|
||||
|
||||
/*
|
||||
* Now it is safe to drop references to the lower vnode.
|
||||
* VOP_INACTIVE() will be called by vrele() if necessary.
|
||||
*/
|
||||
vrele(lowervp);
|
||||
vrele(lowervp);
|
||||
vrele(lowervp);
|
||||
vrele(lowervp);
|
||||
}
|
||||
|
||||
vdata = vp->v_data;
|
||||
vp->v_data = NULL;
|
||||
FREE(vdata, M_NULLFSNODE);
|
||||
FREE(xp, M_NULLFSNODE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user