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:
tls 2004-02-11 17:36:31 +00:00
parent 41ba62f48c
commit eb9b96577c

View File

@ -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)));
}
/*