Do not need (or want) to take a reference on an NFS file that

is being deleted due to an forcible unmount. The problem is
that vgone calls vclean() which then calls calls nfs_inactive()
with VXLOCK set on the vnode. Nfs_inactive() was calling vget()
to get a reference on the vnode, which in turn hung on VXLOCK.
Nfs_inactive() now checks v_usecount to make sure that the vnode
is not coming from vclean() before it does a vget().
This commit is contained in:
Kirk McKusick 1998-09-29 23:15:25 +00:00
parent 96438eb911
commit 35800d700a
2 changed files with 24 additions and 12 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
* $Id: nfs_node.c,v 1.26 1998/05/13 07:49:08 peter Exp $
* $Id: nfs_node.c,v 1.27 1998/05/24 14:41:49 peter Exp $
*/
@ -203,21 +203,27 @@ nfs_inactive(ap)
sp = (struct sillyrename *)0;
if (sp) {
/*
* XXX We need a reference to keep the vnode from being
* We need a reference to keep the vnode from being
* recycled by getnewvnode while we do the I/O
* associated with discarding the buffers.
* associated with discarding the buffers unless we
* are being forcibly unmounted in which case we already
* have our own reference.
*/
if (vget(ap->a_vp, 0, p))
if (ap->a_vp->v_usecount > 0)
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
else if (vget(ap->a_vp, 0, p))
panic("nfs_inactive: lost vnode");
else {
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
vrele(ap->a_vp);
}
/*
* Remove the silly file that was rename'd earlier
*/
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
nfs_removeit(sp);
crfree(sp->s_cred);
vrele(sp->s_dvp);
FREE((caddr_t)sp, M_NFSREQ);
vrele(ap->a_vp); /* XXX Undo above reference */
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
* $Id: nfs_node.c,v 1.26 1998/05/13 07:49:08 peter Exp $
* $Id: nfs_node.c,v 1.27 1998/05/24 14:41:49 peter Exp $
*/
@ -203,21 +203,27 @@ nfs_inactive(ap)
sp = (struct sillyrename *)0;
if (sp) {
/*
* XXX We need a reference to keep the vnode from being
* We need a reference to keep the vnode from being
* recycled by getnewvnode while we do the I/O
* associated with discarding the buffers.
* associated with discarding the buffers unless we
* are being forcibly unmounted in which case we already
* have our own reference.
*/
if (vget(ap->a_vp, 0, p))
if (ap->a_vp->v_usecount > 0)
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
else if (vget(ap->a_vp, 0, p))
panic("nfs_inactive: lost vnode");
else {
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
vrele(ap->a_vp);
}
/*
* Remove the silly file that was rename'd earlier
*/
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
nfs_removeit(sp);
crfree(sp->s_cred);
vrele(sp->s_dvp);
FREE((caddr_t)sp, M_NFSREQ);
vrele(ap->a_vp); /* XXX Undo above reference */
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);