A panic occurs during an fsync when a dirty block associated with

a vnode has not been written (which would clear certain of its
dependencies). The problems arises because fsync with MNT_NOWAIT
no longer pushes all the dirty blocks associated with a vnode. It
skips those that require rollbacks, since they will just get instantly
dirty again. Such skipped blocks are marked so that they will not be
skipped a second time (otherwise circular dependencies would never
clear). So, we fsync twice to ensure that everything will be written
at least once.
This commit is contained in:
Kirk McKusick 2000-01-13 07:17:39 +00:00
parent 1f3e0d3de8
commit 94313add1f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55885
2 changed files with 14 additions and 8 deletions

View File

@ -52,7 +52,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ffs_softdep.c 9.48 (McKusick) 1/10/00
* from: @(#)ffs_softdep.c 9.49 (McKusick) 1/12/00
* $FreeBSD$
*/
@ -4227,10 +4227,13 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* the full semantics of a synchronous VOP_FSYNC as
* that may end up here again, once for each directory
* level in the filesystem. Instead, we push the blocks
* and wait for them to clear.
* and wait for them to clear. We have to fsync twice
* because the first call may choose to defer blocks
* that still have dependencies, but deferral will
* happen at most once.
*/
if ((error =
VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p))) {
if ((error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p)) ||
(error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p))) {
vput(vp);
break;
}

View File

@ -52,7 +52,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ffs_softdep.c 9.48 (McKusick) 1/10/00
* from: @(#)ffs_softdep.c 9.49 (McKusick) 1/12/00
* $FreeBSD$
*/
@ -4227,10 +4227,13 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* the full semantics of a synchronous VOP_FSYNC as
* that may end up here again, once for each directory
* level in the filesystem. Instead, we push the blocks
* and wait for them to clear.
* and wait for them to clear. We have to fsync twice
* because the first call may choose to defer blocks
* that still have dependencies, but deferral will
* happen at most once.
*/
if ((error =
VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p))) {
if ((error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p)) ||
(error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT, p))) {
vput(vp);
break;
}