Page MenuHomeFreeBSD

D55680.id173245.diff
No OneTemporary

D55680.id173245.diff

diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -908,9 +908,9 @@
{
mtx_lock(&rbreqlock);
- if (runningbufreq) {
- runningbufreq = 0;
- wakeup(&runningbufreq);
+ if (runningbufreq > 0) {
+ runningbufreq--;
+ wakeup_one(&runningbufreq);
}
mtx_unlock(&rbreqlock);
}
@@ -943,6 +943,7 @@
runningwakeup();
}
+/* Do we need to return this? Everybody ignores it now */
long
runningbufclaim(struct buf *bp, int space)
{
@@ -970,10 +971,8 @@
{
mtx_lock(&rbreqlock);
- while (runningbufspace > hirunningspace) {
- runningbufreq = 1;
- msleep(&runningbufreq, &rbreqlock, PVM, "wdrain", 0);
- }
+ runningbufreq++;
+ msleep(&runningbufreq, &rbreqlock, PVM, "wdrain", 0);
mtx_unlock(&rbreqlock);
}
@@ -2318,9 +2317,8 @@
bufwrite(struct buf *bp)
{
struct vnode *vp;
- long space;
int oldflags, retval;
- bool vp_md;
+ bool vp_md, waited = false;
CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
if ((bp->b_bufobj->bo_flag & BO_DEAD) != 0) {
@@ -2345,6 +2343,32 @@
vp = bp->b_vp;
vp_md = vp != NULL && (vp->v_vflag & VV_MD) != 0;
+ /*
+ * If we're going to do runningbuf throttling, do it before we do
+ * expensive things to start the write. We're woken up one at a time
+ * when we're sleeping, so it's OK not to loop here.
+ *
+ * Don't allow the async write to saturate the I/O system. We do not
+ * block here if it is the update or syncer daemon trying to clean up as
+ * that can lead to deadlock.
+ */
+ if ((bp->b_flags & B_ASYNC) != 0 &&
+ (curthread->td_pflags & TDP_NORUNNINGBUF) == 0 &&
+ !vp_md &&
+ runningbufspace >= hirunningspace) {
+ waitrunningbufspace();
+ waited = true;
+ } else if ((bp->b_flags & B_ASYNC) == 0 &&
+ runningbufspace >= hirunningspace) {
+ /*
+ * If we're over the limit and this is a sync write, go ahead
+ * and wakeup one more async write if we have it. This will
+ * help keep us from starving async writes for too long a
+ * period, while still allowing us to throttle them into the
+ * lower layer.
+ */
+ runningwakeup();
+ }
/*
* Mark the buffer clean. Increment the bufobj write count
* before bundirty() call, to prevent other thread from seeing
@@ -2364,7 +2388,7 @@
/*
* Normal bwrites pipeline writes
*/
- space = runningbufclaim(bp, bp->b_bufsize);
+ runningbufclaim(bp, bp->b_bufsize);
#ifdef RACCT
if (racct_enable) {
@@ -2384,17 +2408,17 @@
retval = bufwait(bp);
brelse(bp);
return (retval);
- } else if (space > hirunningspace) {
- /*
- * Don't allow the async write to saturate the I/O
- * system. We do not block here if it is the update
- * or syncer daemon trying to clean up as that can
- * lead to deadlock.
- */
- if ((curthread->td_pflags & TDP_NORUNNINGBUF) == 0 && !vp_md)
- waitrunningbufspace();
}
+ /*
+ * For Async I/O, if there's still space, go ahead and wakeup one. We
+ * need to do this because we're only waking one up at a time. So if
+ * after submitting this I/O if there's space, wakeup one more. Note, we
+ * do this only if we waited.
+ */
+ if (waited && runningbufspace < hirunningspace)
+ runningwakeup();
+
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 22, 1:52 PM (2 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35366120
Default Alt Text
D55680.id173245.diff (3 KB)

Event Timeline