svn commit: r285981 - head/sys/kern
Jeff Roberson
jeff at FreeBSD.org
Tue Jul 28 20:24:11 UTC 2015
Author: jeff
Date: Tue Jul 28 20:24:09 2015
New Revision: 285981
URL: https://svnweb.freebsd.org/changeset/base/285981
Log:
- Eliminate the EMPTYKVA queue. It served as a cache of KVA allocations
attached to bufs to avoid the overhead of the vm. This purposes is now
better served by vmem. Freeing the kva immediately when a buf is
destroyed leads to lower fragmentation and a much simpler scan algorithm.
Reviewed by: kib
Sponsored by: EMC / Isilon Storage Division
Modified:
head/sys/kern/vfs_bio.c
Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c Tue Jul 28 19:59:22 2015 (r285980)
+++ head/sys/kern/vfs_bio.c Tue Jul 28 20:24:09 2015 (r285981)
@@ -309,13 +309,12 @@ static int bdirtywait;
/*
* Definitions for the buffer free lists.
*/
-#define BUFFER_QUEUES 5 /* number of free buffer queues */
+#define BUFFER_QUEUES 4 /* number of free buffer queues */
#define QUEUE_NONE 0 /* on no queue */
#define QUEUE_CLEAN 1 /* non-B_DELWRI buffers */
#define QUEUE_DIRTY 2 /* B_DELWRI buffers */
-#define QUEUE_EMPTYKVA 3 /* empty buffer headers w/KVA assignment */
-#define QUEUE_EMPTY 4 /* empty buffer headers */
+#define QUEUE_EMPTY 3 /* empty buffer headers */
#define QUEUE_SENTINEL 1024 /* not an queue index, but mark for sentinel */
/* Queues for free buffers with various properties */
@@ -1862,10 +1861,8 @@ brelse(struct buf *bp)
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
if (bp->b_vflags & BV_BKGRDINPROG)
panic("losing buffer 1");
- if (bp->b_kvasize)
- qindex = QUEUE_EMPTYKVA;
- else
- qindex = QUEUE_EMPTY;
+ bufkvafree(bp);
+ qindex = QUEUE_EMPTY;
bp->b_flags |= B_AGE;
/* buffers with junk contents */
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
@@ -2251,8 +2248,6 @@ getnewbuf_reuse_bp(struct buf *bp, int q
LIST_INIT(&bp->b_dep);
}
-static int flushingbufs;
-
static struct buf *
getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata)
{
@@ -2261,64 +2256,25 @@ getnewbuf_scan(int maxsize, int defrag,
KASSERT(!unmapped || !defrag, ("both unmapped and defrag"));
- pass = 1;
+ pass = 0;
restart:
- atomic_add_int(&getnewbufrestarts, 1);
+ if (pass != 0)
+ atomic_add_int(&getnewbufrestarts, 1);
- /*
- * Setup for scan. If we do not have enough free buffers,
- * we setup a degenerate case that immediately fails. Note
- * that if we are specially marked process, we are allowed to
- * dip into our reserves.
- *
- * The scanning sequence is nominally: EMPTY->EMPTYKVA->CLEAN
- * for the allocation of the mapped buffer. For unmapped, the
- * easiest is to start with EMPTY outright.
- *
- * We start with EMPTYKVA. If the list is empty we backup to EMPTY.
- * However, there are a number of cases (defragging, reusing, ...)
- * where we cannot backup.
- */
nbp = NULL;
mtx_lock(&bqclean);
- if (!defrag && unmapped) {
- nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
- }
- if (nbp == NULL) {
- nqindex = QUEUE_EMPTYKVA;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTYKVA]);
- }
-
/*
- * If no EMPTYKVA buffers and we are either defragging or
- * reusing, locate a CLEAN buffer to free or reuse. If
- * bufspace useage is low skip this step so we can allocate a
- * new buffer.
+ * If we're not defragging or low on bufspace attempt to make a new
+ * buf from a header.
*/
- if (nbp == NULL && (defrag || bufspace >= lobufspace)) {
- nqindex = QUEUE_CLEAN;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
- }
-
- /*
- * If we could not find or were not allowed to reuse a CLEAN
- * buffer, check to see if it is ok to use an EMPTY buffer.
- * We can only use an EMPTY buffer if allocating its KVA would
- * not otherwise run us out of buffer space. No KVA is needed
- * for the unmapped allocation.
- */
- if (nbp == NULL && defrag == 0 && (bufspace + maxsize < hibufspace ||
- metadata)) {
+ if (defrag == 0 && bufspace + maxsize < hibufspace) {
nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
}
-
/*
- * All available buffers might be clean, retry ignoring the
- * lobufspace as the last resort.
+ * All available buffers might be clean or we need to start recycling.
*/
- if (nbp == NULL && !TAILQ_EMPTY(&bufqueues[QUEUE_CLEAN])) {
+ if (nbp == NULL) {
nqindex = QUEUE_CLEAN;
nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
}
@@ -2332,28 +2288,21 @@ restart:
/*
* Calculate next bp (we can only use it if we do not
- * block or do other fancy things).
+ * release the bqlock)
*/
if ((nbp = TAILQ_NEXT(bp, b_freelist)) == NULL) {
switch (qindex) {
case QUEUE_EMPTY:
- nqindex = QUEUE_EMPTYKVA;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTYKVA]);
- if (nbp != NULL)
- break;
- /* FALLTHROUGH */
- case QUEUE_EMPTYKVA:
nqindex = QUEUE_CLEAN;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
if (nbp != NULL)
break;
/* FALLTHROUGH */
case QUEUE_CLEAN:
- if (metadata && pass == 1) {
- pass = 2;
+ if (metadata && pass == 0) {
+ pass = 1;
nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(
- &bufqueues[QUEUE_EMPTY]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
}
/*
* nbp is NULL.
@@ -2399,11 +2348,11 @@ restart:
bremfreel(bp);
mtx_unlock(&bqclean);
+
/*
* NOTE: nbp is now entirely invalid. We can only restart
* the scan from this point on.
*/
-
getnewbuf_reuse_bp(bp, qindex);
mtx_assert(&bqclean, MA_NOTOWNED);
@@ -2412,7 +2361,6 @@ restart:
*/
if (defrag) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
defrag = 0;
goto restart;
@@ -2424,7 +2372,6 @@ restart:
*/
if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp)) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
goto restart;
}
@@ -2437,16 +2384,11 @@ restart:
* KVM space. This occurs in rare situations when multiple
* processes are blocked in getnewbuf() or allocbuf().
*/
- if (bufspace >= hibufspace)
- flushingbufs = 1;
- if (flushingbufs && bp->b_kvasize != 0) {
+ if (bufspace >= hibufspace && bp->b_kvasize != 0) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
goto restart;
}
- if (bufspace < lobufspace)
- flushingbufs = 0;
break;
}
return (bp);
@@ -2492,7 +2434,6 @@ getnewbuf(struct vnode *vp, int slpflag,
* async I/O rather then sync I/O.
*/
atomic_add_int(&getnewbufcalls, 1);
- atomic_subtract_int(&getnewbufrestarts, 1);
restart:
bp = getnewbuf_scan(maxsize, defrag, (gbflags & (GB_UNMAPPED |
GB_KVAALLOC)) == GB_UNMAPPED, metadata);
More information about the svn-src-all
mailing list