>The problem is following: > >FS driver recieves VOP_FSYNC request, >then it scan the queue and pick up dirty buffers to >bwrite(bp) them. bwrite calls VOP_STRATEGY, >FS's strategy routine is trying to VOP_BMAP buf, and >fails (suppose it fails), then xxfs_strategy do: > > bp->b_error = error; > bp->b_flags |= B_ERROR; > biodone(bp); > return(bp); > >(Looks right, at least IMO) >But: >biodone will not rel*se(bp), as it is not B_ASYNC, >then it returns to bwrite, where it will brelse(bp) after >biowait(bp). Then bp will come to brelse with B_ERROR set. >in the begining, brelse: > > ... > > if ((bp->b_flags & (B_READ | B_ERROR)) == B_ERROR) { > bp->b_flags &= ~B_ERROR; > bdirty(bp); > } ... > >then buffer returns to dirty queue, and is dirty, all >repeates infinite.
Also, for async writes, the file may be closed before the write completes (the write never completes...). Then vinvalbuf() calls VOP_FSYNC() to write all dirty buffers and panics when VOP_FSYNC() fails to do this. >How this is solved? This isn't solved. It was less serious before rev.1.196 of vfs_bio.c when B_ERROR buffers were discarded insead of re-dirtied in the above code fragment. See also PR 11697, and about 20 PRs reporting problems with i/o errors and EOF "errors" (ENOSPC/EINVAL) for (mis)using buffered devices (especially fd0). I use the following variant of the patch in PR 11697: diff -c2 vfs_bio.c~ vfs_bio.c *** vfs_bio.c~ Thu May 13 14:42:10 1999 --- vfs_bio.c Thu May 13 16:36:09 1999 *************** *** 744,752 **** bp->b_flags &= ~B_ERROR; ! if ((bp->b_flags & (B_READ | B_ERROR)) == B_ERROR) { /* * Failed write, redirty. Must clear B_ERROR to prevent ! * pages from being scrapped. Note: B_INVAL is ignored ! * here but will presumably be dealt with later. */ bp->b_flags &= ~B_ERROR; --- 800,808 ---- bp->b_flags &= ~B_ERROR; ! if ((bp->b_flags & (B_READ | B_ERROR | B_INVAL)) == B_ERROR && ! (bp->b_error == EIO || bp->b_error == 0)) { /* * Failed write, redirty. Must clear B_ERROR to prevent ! * pages from being scrapped. */ bp->b_flags &= ~B_ERROR; This fixes the primary problem in all cases except the most interesting one: for real i/o errors. It doesn't touch the secondary problem that most VOP_FSYNC() routines don't try hard enough to write all dirty buffers in the MNT_WAIT case, so vinvalbuf() may panic. Bruce To Unsubscribe: send mail to majord...@freebsd.org with "unsubscribe freebsd-current" in the body of the message