Because cylinder group blocks are now written in background,

it is no longer sufficient to get a lock on a buffer to know
that its write has been completed. We have to first get the
lock on the buffer, then check to see if it is doing a
background write. If it is doing background write, we have
to wait for the background write to finish, then check to see
if that fullfilled our dependency, and if not to start another
write. Luckily the explanation is longer than the fix.
This commit is contained in:
Kirk McKusick 2000-01-13 07:20:01 +00:00
parent 94313add1f
commit 1c2ceb2880
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55886
2 changed files with 26 additions and 6 deletions

View File

@ -52,7 +52,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)ffs_softdep.c 9.49 (McKusick) 1/12/00 * from: @(#)ffs_softdep.c 9.50 (McKusick) 1/12/00
* $FreeBSD$ * $FreeBSD$
*/ */
@ -4556,8 +4556,18 @@ getdirtybuf(bpp, waitfor)
for (;;) { for (;;) {
if ((bp = *bpp) == NULL) if ((bp = *bpp) == NULL)
return (0); return (0);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT) == 0) if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT) == 0) {
break; if ((bp->b_xflags & BX_BKGRDINPROG) == 0)
break;
BUF_UNLOCK(bp);
if (waitfor != MNT_WAIT)
return (0);
bp->b_xflags |= BX_BKGRDWAIT;
tsleep(&bp->b_xflags, PRIBIO, "getbuf", 0);
if (bp->b_xflags & BX_BKGRDINPROG)
panic("getdirtybuf: still writing");
continue;
}
if (waitfor != MNT_WAIT) if (waitfor != MNT_WAIT)
return (0); return (0);
FREE_LOCK_INTERLOCKED(&lk); FREE_LOCK_INTERLOCKED(&lk);

View File

@ -52,7 +52,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)ffs_softdep.c 9.49 (McKusick) 1/12/00 * from: @(#)ffs_softdep.c 9.50 (McKusick) 1/12/00
* $FreeBSD$ * $FreeBSD$
*/ */
@ -4556,8 +4556,18 @@ getdirtybuf(bpp, waitfor)
for (;;) { for (;;) {
if ((bp = *bpp) == NULL) if ((bp = *bpp) == NULL)
return (0); return (0);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT) == 0) if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT) == 0) {
break; if ((bp->b_xflags & BX_BKGRDINPROG) == 0)
break;
BUF_UNLOCK(bp);
if (waitfor != MNT_WAIT)
return (0);
bp->b_xflags |= BX_BKGRDWAIT;
tsleep(&bp->b_xflags, PRIBIO, "getbuf", 0);
if (bp->b_xflags & BX_BKGRDINPROG)
panic("getdirtybuf: still writing");
continue;
}
if (waitfor != MNT_WAIT) if (waitfor != MNT_WAIT)
return (0); return (0);
FREE_LOCK_INTERLOCKED(&lk); FREE_LOCK_INTERLOCKED(&lk);