mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '2744-warning-checkhints-unable-to-get-root-ns-rrset-from-cache-not-found' into 'main'
Resolve "warning: checkhints: unable to get root NS rrset from cache: not found" Closes #2744 See merge request isc-projects/bind9!8745
This commit is contained in:
commit
52a2fb1ab3
6 changed files with 106 additions and 71 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
6391. [bug] Use a completely new memory context when flushing the
|
||||
cache. [GL #2744]
|
||||
|
||||
6390. [placeholder]
|
||||
|
||||
6389. [bug] dnssec-verify and dnssec-signzone could fail if there
|
||||
|
|
|
|||
|
|
@ -2151,7 +2151,7 @@ run_server(void *arg) {
|
|||
|
||||
CHECK(dns_view_create(mctx, dispatchmgr, dns_rdataclass_in, "_default",
|
||||
&view));
|
||||
CHECK(dns_cache_create(loopmgr, dns_rdataclass_in, "", &cache));
|
||||
CHECK(dns_cache_create(loopmgr, dns_rdataclass_in, "", mctx, &cache));
|
||||
dns_view_setcache(view, cache, false);
|
||||
dns_cache_detach(&cache);
|
||||
dns_view_setdstport(view, destport);
|
||||
|
|
|
|||
|
|
@ -4671,7 +4671,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
* is simply a named cache that is not shared.
|
||||
*/
|
||||
CHECK(dns_cache_create(named_g_loopmgr, view->rdclass,
|
||||
cachename, &cache));
|
||||
cachename, mctx, &cache));
|
||||
}
|
||||
nsc = isc_mem_get(mctx, sizeof(*nsc));
|
||||
nsc->cache = NULL;
|
||||
|
|
|
|||
164
lib/dns/cache.c
164
lib/dns/cache.c
|
|
@ -66,8 +66,9 @@ struct dns_cache {
|
|||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
isc_mutex_t lock;
|
||||
isc_mem_t *mctx; /* Main cache memory */
|
||||
isc_mem_t *mctx; /* Memory context for the dns_cache object */
|
||||
isc_mem_t *hmctx; /* Heap memory */
|
||||
isc_mem_t *tmctx; /* Tree memory */
|
||||
isc_loop_t *loop;
|
||||
char *name;
|
||||
isc_refcount_t references;
|
||||
|
|
@ -86,62 +87,19 @@ struct dns_cache {
|
|||
***/
|
||||
|
||||
static isc_result_t
|
||||
cache_create_db(dns_cache_t *cache, dns_db_t **db) {
|
||||
cache_create_db(dns_cache_t *cache, dns_db_t **dbp, isc_mem_t **tmctxp,
|
||||
isc_mem_t **hmctxp) {
|
||||
isc_result_t result;
|
||||
char *argv[1] = { 0 };
|
||||
dns_db_t *db = NULL;
|
||||
isc_mem_t *tmctx = NULL, *hmctx = NULL;
|
||||
|
||||
/*
|
||||
* For databases of type "qpcache" or "rbt" (which are the
|
||||
* only cache implementations currently in existence) we pass
|
||||
* hmctx to dns_db_create() via argv[0].
|
||||
*/
|
||||
argv[0] = (char *)cache->hmctx;
|
||||
result = dns_db_create(cache->mctx, CACHEDB_DEFAULT, dns_rootname,
|
||||
dns_dbtype_cache, cache->rdclass, 1, argv, db);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
dns_db_setservestalettl(*db, cache->serve_stale_ttl);
|
||||
dns_db_setservestalerefresh(*db, cache->serve_stale_refresh);
|
||||
dns_db_setloop(*db, cache->loop);
|
||||
|
||||
result = dns_db_setcachestats(*db, cache->stats);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_db_detach(db);
|
||||
return (result);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_destroy(dns_cache_t *cache) {
|
||||
isc_stats_detach(&cache->stats);
|
||||
isc_mutex_destroy(&cache->lock);
|
||||
isc_mem_free(cache->mctx, cache->name);
|
||||
isc_loop_detach(&cache->loop);
|
||||
isc_mem_detach(&cache->hmctx);
|
||||
isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
||||
const char *cachename, dns_cache_t **cachep) {
|
||||
isc_result_t result;
|
||||
dns_cache_t *cache = NULL;
|
||||
isc_mem_t *mctx = NULL, *hmctx = NULL;
|
||||
|
||||
REQUIRE(loopmgr != NULL);
|
||||
REQUIRE(cachename != NULL);
|
||||
REQUIRE(cachep != NULL && *cachep == NULL);
|
||||
|
||||
/*
|
||||
* This will be the main cache memory context, which is subject
|
||||
* This will be the cache memory context, which is subject
|
||||
* to cleaning when the configured memory limits are exceeded.
|
||||
*/
|
||||
isc_mem_create(&mctx);
|
||||
isc_mem_setname(mctx, "cache");
|
||||
isc_mem_create(&tmctx);
|
||||
isc_mem_setname(tmctx, "cache");
|
||||
|
||||
/*
|
||||
* This will be passed to RBTDB to use for heaps. This is separate
|
||||
|
|
@ -152,10 +110,66 @@ dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
|||
isc_mem_create(&hmctx);
|
||||
isc_mem_setname(hmctx, "cache_heap");
|
||||
|
||||
/*
|
||||
* For databases of type "qpcache" or "rbt" (which are the
|
||||
* only cache implementations currently in existence) we pass
|
||||
* hmctx to dns_db_create() via argv[0].
|
||||
*/
|
||||
argv[0] = (char *)hmctx;
|
||||
result = dns_db_create(tmctx, CACHEDB_DEFAULT, dns_rootname,
|
||||
dns_dbtype_cache, cache->rdclass, 1, argv, &db);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_mctx;
|
||||
}
|
||||
result = dns_db_setcachestats(db, cache->stats);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_db;
|
||||
}
|
||||
dns_db_setservestalettl(db, cache->serve_stale_ttl);
|
||||
dns_db_setservestalerefresh(db, cache->serve_stale_refresh);
|
||||
dns_db_setloop(db, cache->loop);
|
||||
*dbp = db;
|
||||
*hmctxp = hmctx;
|
||||
*tmctxp = tmctx;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_db:
|
||||
dns_db_detach(&db);
|
||||
cleanup_mctx:
|
||||
isc_mem_detach(&hmctx);
|
||||
isc_mem_detach(&tmctx);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_destroy(dns_cache_t *cache) {
|
||||
isc_stats_detach(&cache->stats);
|
||||
isc_mutex_destroy(&cache->lock);
|
||||
isc_mem_free(cache->mctx, cache->name);
|
||||
isc_loop_detach(&cache->loop);
|
||||
if (cache->hmctx != NULL) {
|
||||
isc_mem_detach(&cache->hmctx);
|
||||
}
|
||||
if (cache->tmctx != NULL) {
|
||||
isc_mem_detach(&cache->tmctx);
|
||||
}
|
||||
isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
||||
const char *cachename, isc_mem_t *mctx, dns_cache_t **cachep) {
|
||||
isc_result_t result;
|
||||
dns_cache_t *cache = NULL;
|
||||
|
||||
REQUIRE(loopmgr != NULL);
|
||||
REQUIRE(cachename != NULL);
|
||||
REQUIRE(cachep != NULL && *cachep == NULL);
|
||||
|
||||
cache = isc_mem_get(mctx, sizeof(*cache));
|
||||
*cache = (dns_cache_t){
|
||||
.mctx = mctx,
|
||||
.hmctx = hmctx,
|
||||
.rdclass = rdclass,
|
||||
.name = isc_mem_strdup(mctx, cachename),
|
||||
.loop = isc_loop_ref(isc_loop_main(loopmgr)),
|
||||
|
|
@ -164,13 +178,15 @@ dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
|||
};
|
||||
|
||||
isc_mutex_init(&cache->lock);
|
||||
isc_mem_attach(mctx, &cache->mctx);
|
||||
|
||||
isc_stats_create(mctx, &cache->stats, dns_cachestatscounter_max);
|
||||
|
||||
/*
|
||||
* Create the database
|
||||
*/
|
||||
result = cache_create_db(cache, &cache->db);
|
||||
result = cache_create_db(cache, &cache->db, &cache->tmctx,
|
||||
&cache->hmctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -190,7 +206,7 @@ cache_cleanup(dns_cache_t *cache) {
|
|||
isc_refcount_destroy(&cache->references);
|
||||
cache->magic = 0;
|
||||
|
||||
isc_mem_clearwater(cache->mctx);
|
||||
isc_mem_clearwater(cache->tmctx);
|
||||
dns_db_detach(&cache->db);
|
||||
|
||||
cache_destroy(cache);
|
||||
|
|
@ -220,6 +236,17 @@ dns_cache_getname(dns_cache_t *cache) {
|
|||
return (cache->name);
|
||||
}
|
||||
|
||||
static void
|
||||
updatewater(dns_cache_t *cache) {
|
||||
size_t hi = cache->size - (cache->size >> 3); /* ~ 7/8ths. */
|
||||
size_t lo = cache->size - (cache->size >> 2); /* ~ 3/4ths. */
|
||||
if (cache->size == 0U || hi == 0U || lo == 0U) {
|
||||
isc_mem_clearwater(cache->tmctx);
|
||||
} else {
|
||||
isc_mem_setwater(cache->tmctx, hi, lo);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_setcachesize(dns_cache_t *cache, size_t size) {
|
||||
REQUIRE(VALID_CACHE(cache));
|
||||
|
|
@ -234,15 +261,8 @@ dns_cache_setcachesize(dns_cache_t *cache, size_t size) {
|
|||
|
||||
LOCK(&cache->lock);
|
||||
cache->size = size;
|
||||
updatewater(cache);
|
||||
UNLOCK(&cache->lock);
|
||||
|
||||
size_t hi = size - (size >> 3); /* Approximately 7/8ths. */
|
||||
size_t lo = size - (size >> 2); /* Approximately 3/4ths. */
|
||||
if (size == 0U || hi == 0U || lo == 0U) {
|
||||
isc_mem_clearwater(cache->mctx);
|
||||
} else {
|
||||
isc_mem_setwater(cache->mctx, hi, lo);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
@ -309,19 +329,29 @@ dns_cache_getservestalerefresh(dns_cache_t *cache) {
|
|||
isc_result_t
|
||||
dns_cache_flush(dns_cache_t *cache) {
|
||||
dns_db_t *db = NULL, *olddb;
|
||||
isc_mem_t *tmctx = NULL, *oldtmctx;
|
||||
isc_mem_t *hmctx = NULL, *oldhmctx;
|
||||
isc_result_t result;
|
||||
|
||||
result = cache_create_db(cache, &db);
|
||||
result = cache_create_db(cache, &db, &tmctx, &hmctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
LOCK(&cache->lock);
|
||||
isc_mem_clearwater(cache->tmctx);
|
||||
oldhmctx = cache->hmctx;
|
||||
cache->hmctx = hmctx;
|
||||
oldtmctx = cache->tmctx;
|
||||
cache->tmctx = tmctx;
|
||||
updatewater(cache);
|
||||
olddb = cache->db;
|
||||
cache->db = db;
|
||||
UNLOCK(&cache->lock);
|
||||
|
||||
dns_db_detach(&olddb);
|
||||
isc_mem_detach(&oldhmctx);
|
||||
isc_mem_detach(&oldtmctx);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
@ -583,7 +613,7 @@ dns_cache_dumpstats(dns_cache_t *cache, FILE *fp) {
|
|||
fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)dns_db_hashsize(cache->db),
|
||||
"cache database hash buckets");
|
||||
|
||||
fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_inuse(cache->mctx),
|
||||
fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_inuse(cache->tmctx),
|
||||
"cache tree memory in use");
|
||||
|
||||
fprintf(fp, "%20" PRIu64 " %s\n", (uint64_t)isc_mem_inuse(cache->hmctx),
|
||||
|
|
@ -643,7 +673,7 @@ dns_cache_renderxml(dns_cache_t *cache, void *writer0) {
|
|||
dns_db_nodecount(cache->db, dns_dbtree_nsec), writer));
|
||||
TRY0(renderstat("CacheBuckets", dns_db_hashsize(cache->db), writer));
|
||||
|
||||
TRY0(renderstat("TreeMemInUse", isc_mem_inuse(cache->mctx), writer));
|
||||
TRY0(renderstat("TreeMemInUse", isc_mem_inuse(cache->tmctx), writer));
|
||||
|
||||
TRY0(renderstat("HeapMemInUse", isc_mem_inuse(cache->hmctx), writer));
|
||||
error:
|
||||
|
|
@ -715,7 +745,7 @@ dns_cache_renderjson(dns_cache_t *cache, void *cstats0) {
|
|||
CHECKMEM(obj);
|
||||
json_object_object_add(cstats, "CacheBuckets", obj);
|
||||
|
||||
obj = json_object_new_int64(isc_mem_inuse(cache->mctx));
|
||||
obj = json_object_new_int64(isc_mem_inuse(cache->tmctx));
|
||||
CHECKMEM(obj);
|
||||
json_object_object_add(cstats, "TreeMemInUse", obj);
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ ISC_REFCOUNT_DECL(dns_cache);
|
|||
|
||||
isc_result_t
|
||||
dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
||||
const char *cachename, dns_cache_t **cachep);
|
||||
const char *cachename, isc_mem_t *mctx, dns_cache_t **cachep);
|
||||
/*%<
|
||||
* Create a new DNS cache.
|
||||
*
|
||||
|
|
@ -84,6 +84,8 @@ dns_cache_create(isc_loopmgr_t *loopmgr, dns_rdataclass_t rdclass,
|
|||
*\li 'loopmgr' is a valid loop manager.
|
||||
*
|
||||
*\li 'cachename' is a valid string. This must not be NULL.
|
||||
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*
|
||||
*\li 'cachep' is a valid pointer, and *cachep == NULL
|
||||
*
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ dns_test_makeview(const char *name, bool with_dispatchmgr, bool with_cache,
|
|||
}
|
||||
|
||||
if (with_cache) {
|
||||
result = dns_cache_create(loopmgr, dns_rdataclass_in, "",
|
||||
result = dns_cache_create(loopmgr, dns_rdataclass_in, "", mctx,
|
||||
&cache);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_view_detach(&view);
|
||||
|
|
|
|||
Loading…
Reference in a new issue