diff options
author | jeff <jeff@FreeBSD.org> | 2003-10-05 00:35:41 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2003-10-05 00:35:41 +0000 |
commit | 8d0f78003f6eab88720d169d6ea2e52de66708f0 (patch) | |
tree | e6ca35f22b9314456cd0adb4a8aaa5c79649a495 /sys/kern/vfs_subr.c | |
parent | 7e17f7f78efc73be08b54e8d1844c2d004f90d59 (diff) | |
download | FreeBSD-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.c | 18 |
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); |