summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-03-20 21:08:00 +0000
committerkib <kib@FreeBSD.org>2013-03-20 21:08:00 +0000
commitfbd9d518d57802d082c329f2089e625810bfb956 (patch)
treef93d3e2d1cfcd0859b3dde3fad99529302b754dc /sys/kern/vfs_bio.c
parent6fbc70a0bc5387f75b59d76d9857ee9aceab716a (diff)
downloadFreeBSD-src-fbd9d518d57802d082c329f2089e625810bfb956.zip
FreeBSD-src-fbd9d518d57802d082c329f2089e625810bfb956.tar.gz
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
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 19eb895..0a2b89e 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -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);
/*
OpenPOWER on IntegriCloud