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:
Mark Andrews 2024-05-31 06:16:24 +00:00
commit 52a2fb1ab3
6 changed files with 106 additions and 71 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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
*

View file

@ -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);