summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_bio.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 97e4cec..33ef805 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -39,11 +39,11 @@
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/kernel.h>
-#include <sys/lock.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/vmmeter.h>
+#include <sys/lock.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
@@ -114,6 +114,7 @@ static int bufspace, maxbufspace, vmiospace, maxvmiobufspace,
bufmallocspace, maxbufmallocspace;
int numdirtybuffers, lodirtybuffers, hidirtybuffers;
static int numfreebuffers, lofreebuffers, hifreebuffers;
+static int kvafreespace;
SYSCTL_INT(_vfs, OID_AUTO, numdirtybuffers, CTLFLAG_RD,
&numdirtybuffers, 0, "");
@@ -139,6 +140,8 @@ SYSCTL_INT(_vfs, OID_AUTO, maxmallocbufspace, CTLFLAG_RW,
&maxbufmallocspace, 0, "");
SYSCTL_INT(_vfs, OID_AUTO, bufmallocspace, CTLFLAG_RD,
&bufmallocspace, 0, "");
+SYSCTL_INT(_vfs, OID_AUTO, kvafreespace, CTLFLAG_RD,
+ &kvafreespace, 0, "");
static LIST_HEAD(bufhashhdr, buf) bufhashtbl[BUFHSZ], invalhash;
static TAILQ_HEAD(bqueues, buf) bufqueues[BUFFER_QUEUES];
@@ -214,6 +217,7 @@ bufinit()
lofreebuffers = nbuf / 18 + 5;
hifreebuffers = 2 * lofreebuffers;
numfreebuffers = nbuf;
+ kvafreespace = 0;
bogus_offset = kmem_alloc_pageable(kernel_map, PAGE_SIZE);
bogus_page = vm_page_alloc(kernel_object,
@@ -250,6 +254,9 @@ bremfree(struct buf * bp)
int s = splbio();
if (bp->b_qindex != QUEUE_NONE) {
+ if (bp->b_qindex == QUEUE_EMPTY) {
+ kvafreespace -= bp->b_kvasize;
+ }
TAILQ_REMOVE(&bufqueues[bp->b_qindex], bp, b_freelist);
bp->b_qindex = QUEUE_NONE;
} else {
@@ -263,6 +270,7 @@ bremfree(struct buf * bp)
splx(s);
}
+
/*
* Get a buffer with the specified data. Look in the cache first.
*/
@@ -652,6 +660,7 @@ brelse(struct buf * bp)
LIST_REMOVE(bp, b_hash);
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
bp->b_dev = NODEV;
+ kvafreespace += bp->b_kvasize;
/* buffers with junk contents */
} else if (bp->b_flags & (B_ERROR | B_INVAL | B_NOCACHE | B_RELBUF)) {
@@ -1066,14 +1075,19 @@ findkvaspace:
*/
if (vm_map_findspace(buffer_map,
vm_map_min(buffer_map), maxsize, &addr)) {
- for (bp1 = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
- bp1 != NULL; bp1 = TAILQ_NEXT(bp1, b_freelist))
- if (bp1->b_kvasize != 0) {
- bremfree(bp1);
- bfreekva(bp1);
- brelse(bp1);
- goto findkvaspace;
- }
+ if (kvafreespace > 0) {
+ int tfree = 0;
+ for (bp1 = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
+ bp1 != NULL; bp1 = TAILQ_NEXT(bp1, b_freelist))
+ if (bp1->b_kvasize != 0) {
+ tfree += bp1->b_kvasize;
+ bremfree(bp1);
+ bfreekva(bp1);
+ brelse(bp1);
+ if (tfree >= maxsize)
+ goto findkvaspace;
+ }
+ }
bp->b_flags |= B_INVAL;
brelse(bp);
goto trytofreespace;
@@ -1151,9 +1165,7 @@ flushdirtybuffers(int slpflag, int slptimeo) {
}
if (bp) {
- splx(s);
vfs_bio_awrite(bp);
- s = splbio();
continue;
}
break;
OpenPOWER on IntegriCloud