diff options
author | semenu <semenu@FreeBSD.org> | 2002-06-13 21:49:09 +0000 |
---|---|---|
committer | semenu <semenu@FreeBSD.org> | 2002-06-13 21:49:09 +0000 |
commit | 50d99cdfecd92f5323a18aa791a5b1cb9d8b7191 (patch) | |
tree | 6951958eefa7c3d066580c5bb379863dacb57268 /sys/fs/nullfs/null_vnops.c | |
parent | e930b35ecdd23d857aaa5efd37d78e7bfc0b3966 (diff) | |
download | FreeBSD-src-50d99cdfecd92f5323a18aa791a5b1cb9d8b7191.zip FreeBSD-src-50d99cdfecd92f5323a18aa791a5b1cb9d8b7191.tar.gz |
Fix a race during null node creation between relookuping the hash and
adding vnode to hash. The fix is to use atomic hash-lookup-and-add-if-
not-found operation. The odd thing is that this race can't happen
actually because the lowervp vnode is locked exclusively now during the
whole process of null node creation. This must be thought as a step
toward shared lookups.
Also remove vp->v_mount checks when looking for a match in the hash,
as this is the vestige.
Also add comments and cosmetic changes.
Diffstat (limited to 'sys/fs/nullfs/null_vnops.c')
-rw-r--r-- | sys/fs/nullfs/null_vnops.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index f3201e2..2b141be 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -346,7 +346,7 @@ null_bypass(ap) vppp = VOPARG_OFFSETTO(struct vnode***, descp->vdesc_vpp_offset,ap); if (*vppp) - error = null_node_create(old_vps[0]->v_mount, **vppp, *vppp); + error = null_nodeget(old_vps[0]->v_mount, **vppp, *vppp); } out: @@ -400,9 +400,12 @@ null_lookup(ap) VREF(dvp); vrele(lvp); } else { - error = null_node_create(dvp->v_mount, lvp, &vp); - if (error == 0) - *ap->a_vpp = vp; + error = null_nodeget(dvp->v_mount, lvp, &vp); + if (error) { + /* XXX Cleanup needed... */ + panic("null_nodeget failed"); + } + *ap->a_vpp = vp; } } return (error); @@ -706,6 +709,11 @@ null_islocked(ap) * There is no way to tell that someone issued remove/rmdir operation * on the underlying filesystem. For now we just have to release lowevrp * as soon as possible. + * + * Note, we can't release any resources nor remove vnode from hash before + * appropriate VXLOCK stuff is is done because other process can find this + * vnode in hash during inactivation and may be sitting in vget() and waiting + * for null_inactive to unlock vnode. Thus we will do all those in VOP_RECLAIM. */ static int null_inactive(ap) @@ -729,8 +737,7 @@ null_inactive(ap) } /* - * We can free memory in null_inactive, but we do this - * here. (Possible to guard vp->v_data to point somewhere) + * Now, the VXLOCK is in force and we're free to destroy the null vnode. */ static int null_reclaim(ap) |