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:
Semen Ustimenko 2002-06-13 18:25:06 +00:00
parent ebe0bdddac
commit 08720e34b0
3 changed files with 26 additions and 19 deletions

View File

@ -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);

View File

@ -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"

View File

@ -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);
}