summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2006-03-08 23:43:39 +0000
committertegge <tegge@FreeBSD.org>2006-03-08 23:43:39 +0000
commit2e0e03c06ff6c78e7d6f269c98e20d8e2eeb58dc (patch)
tree8446efea303e7dd86046218298bbbd2e8b1e8a1b /sys/kern/vfs_subr.c
parentb33c92af90c5ffdd40c36b6a8094d3ae01b92331 (diff)
downloadFreeBSD-src-2e0e03c06ff6c78e7d6f269c98e20d8e2eeb58dc.zip
FreeBSD-src-2e0e03c06ff6c78e7d6f269c98e20d8e2eeb58dc.tar.gz
Use vn_start_secondary_write() and vn_finished_secondary_write() as a
replacement for vn_write_suspend_wait() to better account for secondary write processing. Close race where secondary writes could be started after ffs_sync() returned but before the file system was marked as suspended. Detect if secondary writes or softdep processing occurred during vnode sync loop in ffs_sync() and retry the loop if needed.
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index add6991..c286f0b 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2052,12 +2052,19 @@ vrele(struct vnode *vp)
* We must call VOP_INACTIVE with the node locked. Mark
* as VI_DOINGINACT to avoid recursion.
*/
+ vp->v_iflag |= VI_OWEINACT;
if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0) {
VI_LOCK(vp);
- vinactive(vp, td);
+ if (vp->v_usecount > 0)
+ vp->v_iflag &= ~VI_OWEINACT;
+ if (vp->v_iflag & VI_OWEINACT)
+ vinactive(vp, td);
VOP_UNLOCK(vp, 0, td);
- } else
+ } else {
VI_LOCK(vp);
+ if (vp->v_usecount > 0)
+ vp->v_iflag &= ~VI_OWEINACT;
+ }
vdropl(vp);
}
@@ -2104,9 +2111,14 @@ vput(struct vnode *vp)
if (VOP_ISLOCKED(vp, NULL) != LK_EXCLUSIVE) {
error = VOP_LOCK(vp, LK_EXCLUPGRADE|LK_INTERLOCK|LK_NOWAIT, td);
VI_LOCK(vp);
- if (error)
+ if (error) {
+ if (vp->v_usecount > 0)
+ vp->v_iflag &= ~VI_OWEINACT;
goto done;
+ }
}
+ if (vp->v_usecount > 0)
+ vp->v_iflag &= ~VI_OWEINACT;
if (vp->v_iflag & VI_OWEINACT)
vinactive(vp, td);
VOP_UNLOCK(vp, 0, td);
@@ -2368,6 +2380,7 @@ vgonel(struct vnode *vp)
struct thread *td;
int oweinact;
int active;
+ struct mount *mp;
CTR1(KTR_VFS, "vgonel: vp %p", vp);
ASSERT_VOP_LOCKED(vp, "vgonel");
@@ -2396,8 +2409,9 @@ vgonel(struct vnode *vp)
* Clean out any buffers associated with the vnode.
* If the flush fails, just toss the buffers.
*/
+ mp = NULL;
if (!TAILQ_EMPTY(&vp->v_bufobj.bo_dirty.bv_hd))
- (void) vn_write_suspend_wait(vp, NULL, V_WAIT);
+ (void) vn_start_secondary_write(vp, &mp, V_WAIT);
if (vinvalbuf(vp, V_SAVE, td, 0, 0) != 0)
vinvalbuf(vp, 0, td, 0, 0);
@@ -2418,6 +2432,8 @@ vgonel(struct vnode *vp)
*/
if (VOP_RECLAIM(vp, td))
panic("vgone: cannot reclaim");
+ if (mp != NULL)
+ vn_finished_secondary_write(mp);
VNASSERT(vp->v_object == NULL, vp,
("vop_reclaim left v_object vp=%p, tag=%s", vp, vp->v_tag));
/*
OpenPOWER on IntegriCloud