- Ignore clean vnodes in vflush(). May fix false EBUSY when unmounting.

- Use vrelel() where v_usecount might become 0. Could fix "vnode sez".
- Add some assertions, fix a lock leak.
This commit is contained in:
ad 2008-01-17 13:06:04 +00:00
parent 42c90ece4c
commit 231d556f22

View File

@ -1,7 +1,7 @@
/* $NetBSD: vfs_subr.c,v 1.314 2008/01/10 13:05:01 pooka Exp $ */ /* $NetBSD: vfs_subr.c,v 1.315 2008/01/17 13:06:04 ad Exp $ */
/*- /*-
* Copyright (c) 1997, 1998, 2004, 2005, 2007 The NetBSD Foundation, Inc. * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
* *
* This code is derived from software contributed to The NetBSD Foundation * This code is derived from software contributed to The NetBSD Foundation
@ -82,7 +82,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.314 2008/01/10 13:05:01 pooka Exp $"); __KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.315 2008/01/17 13:06:04 ad Exp $");
#include "opt_inet.h" #include "opt_inet.h"
#include "opt_ddb.h" #include "opt_ddb.h"
@ -265,6 +265,7 @@ try_nextlist:
* Don't return to freelist - the holder of the last * Don't return to freelist - the holder of the last
* reference will destroy it. * reference will destroy it.
*/ */
KASSERT(vp->v_usecount > 1);
vp->v_usecount--; vp->v_usecount--;
mutex_exit(&vp->v_interlock); mutex_exit(&vp->v_interlock);
mutex_enter(&vnode_free_list_lock); mutex_enter(&vnode_free_list_lock);
@ -360,8 +361,10 @@ vfs_rootmountalloc(const char *fstypename, const char *devname,
if (!strncmp(vfsp->vfs_name, fstypename, if (!strncmp(vfsp->vfs_name, fstypename,
sizeof(mp->mnt_stat.f_fstypename))) sizeof(mp->mnt_stat.f_fstypename)))
break; break;
if (vfsp == NULL) if (vfsp == NULL) {
mutex_exit(&vfs_list_lock);
return (ENODEV); return (ENODEV);
}
vfsp->vfs_refcount++; vfsp->vfs_refcount++;
mutex_exit(&vfs_list_lock); mutex_exit(&vfs_list_lock);
@ -830,12 +833,11 @@ vget(vnode_t *vp, int flags)
*/ */
if ((vp->v_iflag & (VI_XLOCK | VI_FREEING)) != 0) { if ((vp->v_iflag & (VI_XLOCK | VI_FREEING)) != 0) {
if ((flags & LK_NOWAIT) != 0) { if ((flags & LK_NOWAIT) != 0) {
vp->v_usecount--; vrelel(vp, 0, 0);
mutex_exit(&vp->v_interlock);
return EBUSY; return EBUSY;
} }
vwait(vp, VI_XLOCK | VI_FREEING); vwait(vp, VI_XLOCK | VI_FREEING);
vrelel(vp, 1, 0); vrelel(vp, 0, 0);
return ENOENT; return ENOENT;
} }
if (flags & LK_TYPE_MASK) { if (flags & LK_TYPE_MASK) {
@ -874,6 +876,7 @@ vrelel(vnode_t *vp, int doinactive, int onhead)
KASSERT(mutex_owned(&vp->v_interlock)); KASSERT(mutex_owned(&vp->v_interlock));
KASSERT((vp->v_iflag & VI_MARKER) == 0); KASSERT((vp->v_iflag & VI_MARKER) == 0);
KASSERT(vp->v_freelisthd == NULL);
if (vp->v_op == dead_vnodeop_p && (vp->v_iflag & VI_CLEAN) == 0) { if (vp->v_op == dead_vnodeop_p && (vp->v_iflag & VI_CLEAN) == 0) {
vpanic(vp, "dead but not clean"); vpanic(vp, "dead but not clean");
@ -947,6 +950,7 @@ vrelel(vnode_t *vp, int doinactive, int onhead)
KASSERT(vp->v_usecount == 1); KASSERT(vp->v_usecount == 1);
vp->v_iflag |= VI_INACTPEND; vp->v_iflag |= VI_INACTPEND;
mutex_enter(&vrele_lock); mutex_enter(&vrele_lock);
vp->v_freelisthd = &vrele_list;
TAILQ_INSERT_TAIL(&vrele_list, vp, v_freelist); TAILQ_INSERT_TAIL(&vrele_list, vp, v_freelist);
if (++vrele_pending > (desiredvnodes >> 8)) if (++vrele_pending > (desiredvnodes >> 8))
cv_signal(&vrele_cv); cv_signal(&vrele_cv);
@ -1060,6 +1064,8 @@ vrele_thread(void *cookie)
vp = TAILQ_FIRST(&vrele_list); vp = TAILQ_FIRST(&vrele_list);
TAILQ_REMOVE(&vrele_list, vp, v_freelist); TAILQ_REMOVE(&vrele_list, vp, v_freelist);
vrele_pending--; vrele_pending--;
KASSERT(vp->v_freelisthd == &vrele_list);
vp->v_freelisthd = NULL;
mutex_exit(&vrele_lock); mutex_exit(&vrele_lock);
/* /*
@ -1188,6 +1194,13 @@ vflush(struct mount *mp, vnode_t *skipvp, int flags)
if (vp == skipvp) if (vp == skipvp)
continue; continue;
mutex_enter(&vp->v_interlock); mutex_enter(&vp->v_interlock);
/*
* Ignore clean but still referenced vnodes.
*/
if ((vp->v_iflag & VI_CLEAN) != 0) {
mutex_exit(&vp->v_interlock);
continue;
}
/* /*
* Skip over a vnodes marked VSYSTEM. * Skip over a vnodes marked VSYSTEM.
*/ */
@ -1712,8 +1725,10 @@ vfs_scrubvnlist(struct mount *mp)
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) { for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
nvp = TAILQ_NEXT(vp, v_mntvnodes); nvp = TAILQ_NEXT(vp, v_mntvnodes);
mutex_enter(&vp->v_interlock); mutex_enter(&vp->v_interlock);
if ((vp->v_iflag & VI_CLEAN) != 0) if ((vp->v_iflag & VI_CLEAN) != 0) {
TAILQ_REMOVE(&mp->mnt_vnodelist, vp, v_mntvnodes); TAILQ_REMOVE(&mp->mnt_vnodelist, vp, v_mntvnodes);
vp->v_mount = NULL;
}
mutex_exit(&vp->v_interlock); mutex_exit(&vp->v_interlock);
} }
mutex_exit(&mntvnode_lock); mutex_exit(&mntvnode_lock);