In bufwrite(), a dirty buffer is moved to the clean queue before the

bufobj counter of the writes in progress is incremented.  Other thread
inspecting the bufobj would consider it clean.

For the regular vnodes, the vnode lock is typically held both by the
thread performing the bufwrite() and an other thread doing syncing,
which prevents the situation.  On the other hand, writes to the VCHR
vnodes are done without holding vnode lock.

Increment the write ref counter for the buffer object before calling
bundirty().

Sponsored by:	The FreeBSD Foundation
Tested by:	pho
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2013-03-20 21:08:00 +00:00
parent 8d6884ce9c
commit e3269b5096
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248563

View File

@ -1044,7 +1044,13 @@ bufwrite(struct buf *bp)
else
vp_md = 0;
/* Mark the buffer clean */
/*
* Mark the buffer clean. Increment the bufobj write count
* before bundirty() call, to prevent other thread from seeing
* empty dirty list and zero counter for writes in progress,
* falsely indicating that the bufobj is clean.
*/
bufobj_wref(bp->b_bufobj);
bundirty(bp);
bp->b_flags &= ~B_DONE;
@ -1052,7 +1058,6 @@ bufwrite(struct buf *bp)
bp->b_flags |= B_CACHE;
bp->b_iocmd = BIO_WRITE;
bufobj_wref(bp->b_bufobj);
vfs_busy_pages(bp, 1);
/*