Fix bug noted by yamt@netbsd.org: the UVM free target is in *pages*,
so the last change has us comparing pages to bytes instead of pages to buffers! The consequence was to try to free radically less memory than UVM wanted us to -- though always at least one buffer, which is probably why the results weren't dire. This does suggest that buf_canrelease() could be a *lot* more conservative about how much to release than "2 * page deficit". In fact, serious trouble seems to ensue if it's not -- when anything else on the system demands enough pages, we slam down to the low water mark nd stay there. I've adjusted it to use min(page defecit, buffer memory / 16), which still isn't quite right but seems better. Another change: consider the case of an infinite loop that does "tar xzf pkgsrc.tar.gz ; rm -rf pkgsrc". Each time the rm runs, all the dead metadata will go on the AGE list -- and, until we hit the high-water mark, stay there, at which point it may be slowly recycled. Two adjustments seem to solve this: 1) whack buf_lotsfree() to return 0 if there's anything on the AGE list; 2) whack buf_canrelease() to count the memory used by the AGE list and always return at least that much. This basically turns the AGE list into a "delayed free" list, since we can't entirely eliminate it as we can't free pool items from interrupt context (e.g. from biodone()). To consider: with the bookkeeping corrected, should buf_drain() move back to the _end_ of the pagedaemon, and should the calculation then try to give back at least the current defecit?
This commit is contained in:
parent
41ba62f48c
commit
eb9b96577c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_bio.c,v 1.114 2004/01/30 11:32:16 tls Exp $ */
|
||||
/* $NetBSD: vfs_bio.c,v 1.115 2004/02/11 17:36:31 tls Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -81,7 +81,7 @@
|
||||
#include "opt_softdep.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.114 2004/01/30 11:32:16 tls Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.115 2004/02/11 17:36:31 tls Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -399,6 +399,11 @@ buf_lotsfree(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If there's anything on the AGE list, it should be eaten. */
|
||||
|
||||
if(TAILQ_FIRST(&bufqueues[BQ_AGE]) != NULL)
|
||||
return 0;
|
||||
|
||||
try = random() & 0x0000000fL;
|
||||
|
||||
thresh = (16 * bufmem) / bufmem_hiwater;
|
||||
@ -417,15 +422,20 @@ buf_lotsfree(void)
|
||||
static int
|
||||
buf_canrelease(void)
|
||||
{
|
||||
int n;
|
||||
int pagedemand, ninvalid = 0;
|
||||
struct buf *bp;
|
||||
|
||||
TAILQ_FOREACH(bp, &bufqueues[BQ_AGE], b_freelist)
|
||||
ninvalid += bp->b_bufsize;
|
||||
|
||||
if (bufmem < bufmem_lowater)
|
||||
return 0;
|
||||
|
||||
n = uvmexp.freetarg - uvmexp.free;
|
||||
if (n < 0)
|
||||
return 0;
|
||||
return 2 * n;
|
||||
pagedemand = uvmexp.freetarg - uvmexp.free;
|
||||
if (pagedemand < 0)
|
||||
return ninvalid;
|
||||
return MAX(ninvalid, MIN(2 * MAXBSIZE,
|
||||
MIN((bufmem - bufmem_lowater) / 16, pagedemand * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user