mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-02 08:42:48 +00:00
Fix an old-standing bug that crept in along the several revisions:
B_DELWRI cleanup and vnode disassociation should happen just before to assign the buffer to a queue. Reported by: miwi, Volker <volker at vwsoft dot com>, Ben Kaduk <minimarmot at gmail dot com>, Christopher Mallon <christoph dot mallon at gmx dot de> Tested by: lulf, miwi
This commit is contained in:
parent
a15a45ac9d
commit
76ed3c71f1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=189933
@ -1369,9 +1369,23 @@ brelse(struct buf *bp)
|
||||
if (bp->b_qindex != QUEUE_NONE)
|
||||
panic("brelse: free buffer onto another queue???");
|
||||
|
||||
/*
|
||||
* If the buffer has junk contents signal it and eventually
|
||||
* clean up B_DELWRI and diassociate the vnode so that gbincore()
|
||||
* doesn't find it.
|
||||
*/
|
||||
if (bp->b_bufsize == 0 || (bp->b_ioflags & BIO_ERROR) != 0 ||
|
||||
(bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF)) != 0)
|
||||
bp->b_flags |= B_INVAL;
|
||||
if (bp->b_flags & B_INVAL) {
|
||||
if (bp->b_flags & B_DELWRI)
|
||||
bundirty(bp);
|
||||
if (bp->b_vp)
|
||||
brelvp(bp);
|
||||
}
|
||||
|
||||
/* buffers with no memory */
|
||||
if (bp->b_bufsize == 0) {
|
||||
bp->b_flags |= B_INVAL;
|
||||
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
|
||||
if (bp->b_vflags & BV_BKGRDINPROG)
|
||||
panic("losing buffer 1");
|
||||
@ -1384,7 +1398,6 @@ brelse(struct buf *bp)
|
||||
/* buffers with junk contents */
|
||||
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
|
||||
(bp->b_ioflags & BIO_ERROR)) {
|
||||
bp->b_flags |= B_INVAL;
|
||||
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
|
||||
if (bp->b_vflags & BV_BKGRDINPROG)
|
||||
panic("losing buffer 2");
|
||||
@ -1406,19 +1419,6 @@ brelse(struct buf *bp)
|
||||
}
|
||||
mtx_unlock(&bqlock);
|
||||
|
||||
/*
|
||||
* If B_INVAL and B_DELWRI is set, clear B_DELWRI. We have already
|
||||
* placed the buffer on the correct queue. We must also disassociate
|
||||
* the device and vnode for a B_INVAL buffer so gbincore() doesn't
|
||||
* find it.
|
||||
*/
|
||||
if (bp->b_flags & B_INVAL) {
|
||||
if (bp->b_flags & B_DELWRI)
|
||||
bundirty(bp);
|
||||
if (bp->b_vp)
|
||||
brelvp(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixup numfreebuffers count. The bp is on an appropriate queue
|
||||
* unless locked. We then bump numfreebuffers if it is not B_DELWRI.
|
||||
|
Loading…
Reference in New Issue
Block a user