summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-10-05 00:35:41 +0000
committerjeff <jeff@FreeBSD.org>2003-10-05 00:35:41 +0000
commit8d0f78003f6eab88720d169d6ea2e52de66708f0 (patch)
treee6ca35f22b9314456cd0adb4a8aaa5c79649a495 /sys/kern/vfs_subr.c
parent7e17f7f78efc73be08b54e8d1844c2d004f90d59 (diff)
downloadFreeBSD-src-8d0f78003f6eab88720d169d6ea2e52de66708f0.zip
FreeBSD-src-8d0f78003f6eab88720d169d6ea2e52de66708f0.tar.gz
- Solve a LOR with the sync_mtx by using the VI_ONWORKLST flag to determine
whether or not the sync failed. This could potentially get set between the time that we VOP_UNLOCK and VI_LOCK() but the race would harmelssly lead to the sync being delayed by an extra 30 seconds. If we do not move the vnode it could cause an endless loop if it continues to fail to sync. - Use vhold and vdrop to stop the vnode from changing identities while we have it unlocked. Other internal vfs lists are likely to follow this scheme.
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index e0c811e..412a47c4 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1725,15 +1725,20 @@ sched_sync(void)
vn_finished_write(mp);
continue;
}
+ /*
+ * We use vhold in case the vnode does not
+ * successfully sync. vhold prevents the vnode from
+ * going away when we unlock the sync_mtx so that
+ * we can acquire the vnode interlock.
+ */
+ vholdl(vp);
mtx_unlock(&sync_mtx);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td);
(void) VOP_FSYNC(vp, td->td_ucred, MNT_LAZY, td);
VOP_UNLOCK(vp, 0, td);
vn_finished_write(mp);
- mtx_lock(&sync_mtx);
- if (LIST_FIRST(slp) == vp) {
- VI_LOCK(vp);
- mtx_unlock(&sync_mtx);
+ VI_LOCK(vp);
+ if ((vp->v_iflag | VI_ONWORKLST) != 0) {
/*
* Put us back on the worklist. The worklist
* routine will remove us from our current
@@ -1741,9 +1746,10 @@ sched_sync(void)
* position.
*/
vn_syncer_add_to_worklist(vp, syncdelay);
- VI_UNLOCK(vp);
- mtx_lock(&sync_mtx);
}
+ vdropl(vp);
+ VI_UNLOCK(vp);
+ mtx_lock(&sync_mtx);
}
mtx_unlock(&sync_mtx);
OpenPOWER on IntegriCloud