Commit 081cff0c authored by Mark Andrews's avatar Mark Andrews
Browse files

1073. [bug] The adb cache should also be space driven,

                        max-adb-size.  [RT #1915, #1938]
parent 2562a84d
1073. [bug] The adb cache should also be space driven,
max-adb-size. [RT #1915, #1938]
1072. [bug] The TCP client quota could be exceeded when
recursion occurred. [RT #1937]
1071. [bug] Sockets listening for TCP DNS connections
specified an excessive listen backlog. [RT #1937]
specified an excessive listen backlog. [RT #1937]
1070. [bug] Copy DNSSEC OK (DO) to response as specified by
draft-ietf-dnsext-dnssec-okbit-03.txt.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.c,v 1.16 2001/09/20 21:51:21 gson Exp $ */
/* $Id: config.c,v 1.17 2001/10/25 04:57:37 marka Exp $ */
#include <config.h>
......@@ -116,6 +116,7 @@ options {\n\
max-ncache-ttl 10800; /* 3 hours */\n\
max-cache-ttl 604800; /* 1 week */\n\
transfer-format many-answers;\n\
max-adb-size 0;\n\
max-cache-size 0;\n\
check-names master ignore;\n\
check-names slave ignore;\n\
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.353 2001/10/24 03:10:15 marka Exp $ */
/* $Id: server.c,v 1.354 2001/10/25 04:57:38 marka Exp $ */
#include <config.h>
......@@ -39,6 +39,7 @@
#include <bind9/check.h>
#include <dns/adb.h>
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dispatch.h>
......@@ -495,6 +496,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
in_port_t port;
dns_cache_t *cache = NULL;
isc_result_t result;
isc_uint32_t max_adb_size;
isc_uint32_t max_cache_size;
isc_uint32_t lame_ttl;
dns_tsig_keyring_t *ring;
......@@ -644,6 +646,36 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
if (dispatch6 != NULL)
dns_dispatch_detach(&dispatch6);
/*
* Set ADB cache size
*/
obj = NULL;
result = ns_config_get(maps, "max-adb-size", &obj);
INSIST(result == ISC_R_SUCCESS);
if (cfg_obj_isstring(obj)) {
str = cfg_obj_asstring(obj);
INSIST(strcasecmp(str, "unlimited") == 0);
max_adb_size = ISC_UINT32_MAX;
} else {
isc_resourcevalue_t value;
value = cfg_obj_asuint64(obj);
if (value > ISC_UINT32_MAX) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"'max-adb-size "
"%" ISC_PRINT_QUADFORMAT "d' is too large",
value);
result = ISC_R_RANGE;
goto cleanup;
}
max_adb_size = (isc_uint32_t)value;
if (max_adb_size == 0 && max_cache_size != 0) {
max_adb_size = max_cache_size/8;
if (max_adb_size == 0)
max_adb_size = 1; /* Force minimum. */
}
}
dns_adb_setadbsize(view->adb, max_adb_size);
/*
* Set resolver's lame-ttl.
*/
......
......@@ -2,7 +2,7 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
<!-- File: $Id: Bv9ARM-book.xml,v 1.169 2001/10/24 23:00:22 gson Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.170 2001/10/25 04:57:40 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
......@@ -2828,6 +2828,7 @@ statement in the <filename>named.conf</filename> file:</para>
<optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
<optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional>
<optional> random-device <replaceable>path_name</replaceable> ; </optional>
<optional> max-adb-size <replaceable>size_spec</replaceable> ; </optional>
<optional> max-cache-size <replaceable>size_spec</replaceable> ; </optional>
<optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
};
......@@ -3599,6 +3600,7 @@ amount of memory used by the server, but it can be used
to raise an operating system data size limit that is
too small by default. If you wish to limit the amount
of memory used by the server, use the
<command>max-adb-size</command> and
<command>max-cache-size</command> and
<command>recursive-clients</command>
options instead.
......@@ -3649,6 +3651,17 @@ connections that the server will accept.
The default is <literal>100</literal>.</para>
</listitem></varlistentry>
<varlistentry><term><command>max-adb-size</command></term>
<listitem><para>The server maintains a per view cache of remote
server characteristics including addresses constructed from A6
chains. The amount of memory used for this cache can be set via
<command>max-adb-size</command> and defaults to 1/8th of
<command>max-cache-size</command> if that is set otherwise it is
<literal>unlimited</literal>, meaning that records are purged from
the cache only when their TTLs expire.
</para>
</listitem></varlistentry>
<varlistentry><term><command>max-cache-size</command></term>
<listitem><para>The maximum amount of memory to use for the
server's cache, in bytes. When the amount of data in the cache
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: adb.c,v 1.183 2001/10/19 01:29:41 gson Exp $ */
/* $Id: adb.c,v 1.184 2001/10/25 04:57:42 marka Exp $ */
/*
* Implementation notes
......@@ -101,6 +101,8 @@
#define DNS_ADB_INVALIDBUCKET (-1) /* invalid bucket address */
#define DNS_ADB_MINADBSIZE (1024*1024) /* 1 Megabyte */
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
typedef struct dns_adbnamehook dns_adbnamehook_t;
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
......@@ -120,6 +122,7 @@ struct dns_adb {
isc_timer_t *timer;
isc_taskmgr_t *taskmgr;
isc_task_t *task;
isc_boolean_t overmem;
isc_interval_t tick_interval;
int next_cleanbucket;
......@@ -310,7 +313,8 @@ static void clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
static void clean_target(dns_adb_t *, dns_name_t *);
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
unsigned int);
static void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
static void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t,
isc_boolean_t);
static void cancel_fetches_at_name(dns_adbname_t *);
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
dns_rdatatype_t);
......@@ -329,6 +333,7 @@ static inline void unlink_entry(dns_adb_t *, dns_adbentry_t *);
static void kill_name(dns_adbname_t **, isc_eventtype_t);
static void fetch_callback_a6(isc_task_t *, isc_event_t *);
static isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t);
static void water(void *arg, int mark);
/*
* MUST NOT overlap DNS_ADBFIND_* flags!
......@@ -722,17 +727,30 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
* Requires the name's bucket be locked and no entry buckets be locked.
*/
static void
check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
isc_boolean_t overmem)
{
dns_adb_t *adb;
isc_boolean_t expire;
INSIST(DNS_ADBNAME_VALID(name));
adb = name->adb;
INSIST(DNS_ADB_VALID(adb));
if (overmem) {
isc_uint32_t val;
isc_random_get(&val);
expire = ISC_TF((val % 4) == 0);
} else
expire = ISC_FALSE;
/*
* Check to see if we need to remove the v4 addresses
*/
if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
if (!NAME_FETCH_V4(name) &&
(expire || EXPIRE_OK(name->expire_v4, now))) {
if (NAME_HAS_V4(name)) {
DP(DEF_LEVEL, "expiring v4 for name %p", name);
clean_namehooks(adb, &name->v4);
......@@ -744,7 +762,8 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
/*
* Check to see if we need to remove the v6 addresses
*/
if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
if (!NAME_FETCH_V6(name) &&
(expire || EXPIRE_OK(name->expire_v6, now))) {
if (NAME_HAS_V6(name)) {
DP(DEF_LEVEL, "expiring v6 for name %p", name);
clean_namehooks(adb, &name->v6);
......@@ -756,7 +775,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
/*
* Check to see if we need to remove the alias target.
*/
if (EXPIRE_OK(name->expire_target, now)) {
if (expire || EXPIRE_OK(name->expire_target, now)) {
clean_target(adb, &name->target);
name->expire_target = INT_MAX;
}
......@@ -2001,15 +2020,25 @@ static void
check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
{
dns_adbentry_t *entry;
isc_boolean_t expire;
INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
entry = *entryp;
if (entry->refcnt != 0)
return;
if (entry->expires == 0 || entry->expires > now)
return;
if (adb->overmem) {
isc_uint32_t val;
isc_random_get(&val);
expire = ISC_TF((val % 4) == 0);
} else
expire = ISC_FALSE;
if (entry->expires == 0 || expire ? ISC_FALSE : entry->expires > now)
return;
/*
* The entry is not in use. Delete it.
*/
......@@ -2039,7 +2068,7 @@ cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
name = ISC_LIST_HEAD(adb->names[bucket]);
while (name != NULL) {
next_name = ISC_LIST_NEXT(name, plink);
check_expire_namehooks(name, now);
check_expire_namehooks(name, now, adb->overmem);
check_expire_name(&name, now);
name = next_name;
}
......@@ -2070,6 +2099,7 @@ timer_cleanup(isc_task_t *task, isc_event_t *ev) {
dns_adb_t *adb;
isc_stdtime_t now;
unsigned int i;
isc_interval_t interval;
UNUSED(task);
......@@ -2105,8 +2135,11 @@ timer_cleanup(isc_task_t *task, isc_event_t *ev) {
* ISC_R_NOMEMORY, but it isn't clear what could be done here
* if either one of those things happened.
*/
interval = adb->tick_interval;
if (adb->overmem)
isc_interval_set(&interval, 0, 1);
(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
&adb->tick_interval, ISC_FALSE);
&interval, ISC_FALSE);
UNLOCK(&adb->lock);
......@@ -2138,7 +2171,7 @@ destroy(dns_adb_t *adb) {
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
isc_mem_put(adb->mctx, adb, sizeof (dns_adb_t));
isc_mem_putanddetach(&adb->mctx, adb, sizeof (dns_adb_t));
}
......@@ -2181,7 +2214,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->af6mp = NULL;
adb->task = NULL;
adb->timer = NULL;
adb->mctx = mem;
adb->mctx = NULL;
adb->view = view;
adb->timermgr = timermgr;
adb->taskmgr = taskmgr;
......@@ -2191,8 +2224,11 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb, NULL, NULL);
adb->cevent_sent = ISC_FALSE;
adb->shutting_down = ISC_FALSE;
adb->overmem = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
if (result != ISC_R_SUCCESS)
goto fail0b;
......@@ -2317,7 +2353,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
fail0c:
DESTROYLOCK(&adb->lock);
fail0b:
isc_mem_put(mem, adb, sizeof (dns_adb_t));
isc_mem_putanddetach(&adb->mctx, adb, sizeof (dns_adb_t));
return (result);
}
......@@ -2401,6 +2437,7 @@ dns_adb_shutdown(dns_adb_t *adb) {
if (!adb->shutting_down) {
adb->shutting_down = ISC_TRUE;
isc_mem_setwater(adb->mctx, water, adb, 0, 0);
shutdown_names(adb);
shutdown_entries(adb);
check_exit(adb);
......@@ -2517,7 +2554,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
/*
* Expire old entries, etc.
*/
check_expire_namehooks(adbname, now);
check_expire_namehooks(adbname, now, adb->overmem);
/*
* Do we know that the name is an alias?
......@@ -4068,3 +4105,38 @@ dns_adb_flush(dns_adb_t *adb) {
UNLOCK(&adb->lock);
}
static void
water(void *arg, int mark) {
dns_adb_t *adb = arg;
isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
isc_interval_t interval;
REQUIRE(DNS_ADB_VALID(adb));
adb->overmem = overmem;
if (overmem) {
isc_interval_set(&interval, 0, 1);
(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
&interval, ISC_TRUE);
}
}
void
dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) {
isc_uint32_t hiwater;
isc_uint32_t lowater;
INSIST(DNS_ADB_VALID(adb));
if (size != 0 && size < DNS_ADB_MINADBSIZE)
size = DNS_ADB_MINADBSIZE;
hiwater = size - (size >> 3); /* Approximately 7/8ths. */
lowater = size - (size >> 2); /* Approximately 3/4ths. */
if (size == 0 || hiwater == 0 || lowater == 0)
isc_mem_setwater(adb->mctx, water, adb, 0, 0);
else
isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
}
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: adb.h,v 1.66 2001/08/28 03:58:12 marka Exp $ */
/* $Id: adb.h,v 1.67 2001/10/25 04:57:44 marka Exp $ */
#ifndef DNS_ADB_H
#define DNS_ADB_H 1
......@@ -568,6 +568,19 @@ dns_adb_flush(dns_adb_t *adb);
* adb is valid.
*/
void
dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size);
/*
* Set a target memory size. If memory usage exceeds the target
* size entries will be removed before they would have expired on
* a random basis.
*
* If 'size' is 0 then memory usage is unlimited.
*
* Requires:
* 'adb' is valid.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_ADB_H */
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.c,v 1.104 2001/08/30 05:52:15 marka Exp $ */
/* $Id: view.c,v 1.105 2001/10/25 04:57:43 marka Exp $ */
#include <config.h>
......@@ -467,6 +467,7 @@ dns_view_createresolver(dns_view_t *view,
{
isc_result_t result;
isc_event_t *event;
isc_mem_t *mctx = NULL;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
......@@ -489,8 +490,9 @@ dns_view_createresolver(dns_view_t *view,
dns_resolver_whenshutdown(view->resolver, view->task, &event);
view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
result = dns_adb_create(view->mctx, view, timermgr, taskmgr,
&view->adb);
isc_mem_create(0, 0, &mctx);
result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
isc_mem_detach(&mctx);
if (result != ISC_R_SUCCESS) {
dns_resolver_shutdown(view->resolver);
return (result);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: parser.c,v 1.83 2001/10/23 01:49:35 gson Exp $ */
/* $Id: parser.c,v 1.84 2001/10/25 04:57:46 marka Exp $ */
#include <config.h>
......@@ -928,6 +928,7 @@ view_clauses[] = {
{ "max-cache-ttl", &cfg_type_uint32, 0 },
{ "transfer-format", &cfg_type_ustring, 0 },
{ "max-cache-size", &cfg_type_sizenodefault, 0 },
{ "max-adb-size", &cfg_type_sizenodefault, 0 },
{ "check-names", &cfg_type_checknames,
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NOTIMP },
{ "cache-file", &cfg_type_qstring, 0 },
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment