diff --git a/bin/named/server.c b/bin/named/server.c index 8ce865f2c7..bd3f5a8dca 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -155,8 +155,6 @@ #define SIZE_AS_PERCENT ((size_t)-2) #endif /* ifndef SIZE_AS_PERCENT */ -#define RESOLVER_NTASKS 523 - /* RFC7828 defines timeout as 16-bit value specified in units of 100 * milliseconds, so the maximum and minimum advertised and keepalive * timeouts are capped by the data type (it's ~109 minutes) @@ -503,6 +501,104 @@ static isc_result_t nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); #endif /* ifdef HAVE_LMDB */ +static const uint32_t primes[] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, + 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, + 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, + 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, + 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, + 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, + 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, + 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, + 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, + 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, + 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, + 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, + 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, + 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, + 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, + 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, + 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, + 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, + 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, + 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, + 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, + 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, + 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, + 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, + 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, + 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, + 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, + 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, + 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, + 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, + 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, + 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, + 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, + 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, + 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, + 7883, 7901, 7907, 7919, +}; + +static uint32_t +closest_prime(uint32_t n) { + for (size_t i = 0; i < ARRAY_SIZE(primes); i++) { + if (primes[i] >= n) { + return primes[i]; + } + } + + return primes[ARRAY_SIZE(primes) - 1]; +} + /*% * Configure a single view ACL at '*aclp'. Get its configuration from * 'vconfig' (for per-view configuration) and maybe from 'config' @@ -4221,7 +4317,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, named_cache_t *nsc; bool zero_no_soattl; dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; - unsigned int query_timeout, ndisp; + unsigned int query_timeout, ndisp, ntasks; bool old_rpz_ok = false; dns_dyndbctx_t *dctx = NULL; unsigned int resolver_param; @@ -4880,10 +4976,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, } dns_view_setresquerystats(view, resquerystats); + ntasks = closest_prime(2 * named_g_cpus); ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH); - CHECK(dns_view_createresolver(view, named_g_taskmgr, RESOLVER_NTASKS, - ndisp, named_g_netmgr, named_g_timermgr, - resopts, named_g_dispatchmgr, dispatch4, + CHECK(dns_view_createresolver(view, named_g_taskmgr, ntasks, ndisp, + named_g_netmgr, named_g_timermgr, resopts, + named_g_dispatchmgr, dispatch4, dispatch6)); /* diff --git a/lib/dns/client.c b/lib/dns/client.c index ed6bf0e0cb..bde6ec61a3 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -60,8 +60,6 @@ #define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x') #define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC) -#define RESOLVER_NTASKS 523 - #define CHECK(r) \ do { \ result = (r); \ @@ -328,9 +326,8 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, isc_refcount_init(&client->references, 1); /* Create the default view for class IN */ - result = createview(mctx, dns_rdataclass_in, taskmgr, RESOLVER_NTASKS, - nm, timermgr, client->dispatchmgr, dispatchv4, - dispatchv6, &view); + result = createview(mctx, dns_rdataclass_in, taskmgr, 1, nm, timermgr, + client->dispatchmgr, dispatchv4, dispatchv6, &view); if (result != ISC_R_SUCCESS) { goto cleanup_references; } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e612eb7bb3..2178a17b5e 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include #include @@ -327,6 +329,7 @@ struct fetchctx { unsigned int options; unsigned int bucketnum; unsigned int dbucketnum; + bool hashed; char *info; isc_mem_t *mctx; isc_stdtime_t now; @@ -341,7 +344,6 @@ struct fetchctx { bool cloned; bool spilled; isc_event_t control_event; - ISC_LINK(struct fetchctx) link; ISC_LIST(dns_fetchevent_t) events; /*% Locked by task event serialization. */ @@ -514,10 +516,14 @@ struct dns_fetch { #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h') #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC) +#define DNS_FCTX_KEYSIZE \ + (DNS_NAME_MAXWIRE + sizeof(dns_rdatatype_t) + sizeof(unsigned int)) + typedef struct fctxbucket { isc_task_t *task; isc_mutex_t lock; - ISC_LIST(fetchctx_t) fctxs; + isc_refcount_t nfctxs; + isc_ht_t *fctxs; atomic_bool exiting; } fctxbucket_t; @@ -529,12 +535,11 @@ struct fctxcount { uint32_t allowed; uint32_t dropped; isc_stdtime_t logged; - ISC_LINK(fctxcount_t) link; }; typedef struct zonebucket { isc_mutex_t lock; - ISC_LIST(fctxcount_t) list; + isc_ht_t *counters; } zonebucket_t; typedef struct alternate { @@ -603,9 +608,6 @@ struct dns_resolver { /* Locked by primelock. */ dns_fetch_t *primefetch; - - /* Atomic. */ - atomic_uint_fast32_t nfctx; }; #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!') @@ -1623,6 +1625,25 @@ fcount_logspill(fetchctx_t *fctx, fctxcount_t *counter, bool final) { counter->logged = now; } +static void +fcount_makekey(const dns_name_t *name, uint8_t *key, size_t *keysizep) { + REQUIRE(*keysizep >= name->length); + + size_t keysize = 0; + isc_buffer_t buffer; + dns_name_t downname; + isc_result_t result; + + DNS_NAME_INIT(&downname, NULL); + isc_buffer_init(&buffer, key, *keysizep); + + result = dns_name_downcase(name, &downname, &buffer); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + keysize += isc_buffer_usedlength(&buffer); + + *keysizep = keysize; +} + static isc_result_t fcount_incr(fetchctx_t *fctx, bool force) { isc_result_t result = ISC_R_SUCCESS; @@ -1630,6 +1651,9 @@ fcount_incr(fetchctx_t *fctx, bool force) { fctxcount_t *counter = NULL; uint32_t hashval; uint32_t dbucketnum; + uint8_t key[DNS_NAME_MAXWIRE]; + size_t keysize = sizeof(key); + uint_fast32_t spill; REQUIRE(fctx != NULL); REQUIRE(fctx->res != NULL); @@ -1641,15 +1665,14 @@ fcount_incr(fetchctx_t *fctx, bool force) { dbucket = &fctx->res->dbuckets[dbucketnum]; LOCK(&dbucket->lock); - for (counter = ISC_LIST_HEAD(dbucket->list); counter != NULL; - counter = ISC_LIST_NEXT(counter, link)) - { - if (dns_name_equal(counter->domain, fctx->domain)) { - break; - } - } - if (counter == NULL) { + fcount_makekey(fctx->domain, key, &keysize); + + result = isc_ht_find(dbucket->counters, key, keysize, + (void **)&counter); + + switch (result) { + case ISC_R_NOTFOUND: counter = isc_mem_get(fctx->res->mctx, sizeof(*counter)); *counter = (fctxcount_t){ .count = 1, @@ -1657,11 +1680,11 @@ fcount_incr(fetchctx_t *fctx, bool force) { }; counter->domain = dns_fixedname_initname(&counter->dfname); - ISC_LINK_INIT(counter, link); dns_name_copy(fctx->domain, counter->domain); - ISC_LIST_APPEND(dbucket->list, counter, link); - } else { - uint_fast32_t spill = atomic_load_acquire(&fctx->res->zspill); + result = isc_ht_add(dbucket->counters, key, keysize, counter); + break; + case ISC_R_SUCCESS: + spill = atomic_load_acquire(&fctx->res->zspill); if (!force && spill != 0 && counter->count >= spill) { counter->dropped++; fcount_logspill(fctx, counter, false); @@ -1670,6 +1693,9 @@ fcount_incr(fetchctx_t *fctx, bool force) { counter->count++; counter->allowed++; } + break; + default: + UNREACHABLE(); } UNLOCK(&dbucket->lock); @@ -1684,6 +1710,9 @@ static void fcount_decr(fetchctx_t *fctx) { zonebucket_t *dbucket = NULL; fctxcount_t *counter = NULL; + uint8_t key[DNS_NAME_MAXWIRE]; + size_t keysize = sizeof(key); + isc_result_t result; REQUIRE(fctx != NULL); @@ -1694,24 +1723,22 @@ fcount_decr(fetchctx_t *fctx) { dbucket = &fctx->res->dbuckets[fctx->dbucketnum]; LOCK(&dbucket->lock); - for (counter = ISC_LIST_HEAD(dbucket->list); counter != NULL; - counter = ISC_LIST_NEXT(counter, link)) - { - if (dns_name_equal(counter->domain, fctx->domain)) { - break; - } - } - if (counter != NULL) { - INSIST(counter->count != 0); - counter->count--; - fctx->dbucketnum = RES_NOBUCKET; + fcount_makekey(fctx->domain, key, &keysize); - if (counter->count == 0) { - fcount_logspill(fctx, counter, true); - ISC_LIST_UNLINK(dbucket->list, counter, link); - isc_mem_put(fctx->res->mctx, counter, sizeof(*counter)); - } + result = isc_ht_find(dbucket->counters, key, keysize, + (void **)&counter); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + INSIST(counter->count != 0); + counter->count--; + fctx->dbucketnum = RES_NOBUCKET; + + if (counter->count == 0) { + fcount_logspill(fctx, counter, true); + result = isc_ht_delete(dbucket->counters, key, keysize); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + isc_mem_put(fctx->res->mctx, counter, sizeof(*counter)); } UNLOCK(&dbucket->lock); @@ -1830,6 +1857,73 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) { } } +static void +fctx_makekey(const dns_name_t *name, dns_rdatatype_t type, unsigned int options, + uint8_t *key, size_t *keysizep) { + REQUIRE(*keysizep >= name->length + sizeof(type) + sizeof(options)); + + size_t keysize = 0; + isc_buffer_t buffer; + dns_name_t downname; + isc_result_t result; + + DNS_NAME_INIT(&downname, NULL); + isc_buffer_init(&buffer, key, *keysizep); + + result = dns_name_downcase(name, &downname, &buffer); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + keysize += isc_buffer_usedlength(&buffer); + + memmove(&key[keysize], &type, sizeof(type)); + keysize += sizeof(type); + + memmove(&key[keysize], &options, sizeof(options)); + keysize += sizeof(options); + + *keysizep = keysize; +} + +static void +fctx_unhash(fetchctx_t *fctx) { + dns_resolver_t *res = fctx->res; + unsigned int bucketnum = fctx->bucketnum; + uint8_t key[DNS_FCTX_KEYSIZE] = { 0 }; + size_t keysize = sizeof(key); + isc_result_t result; + + if (!fctx->hashed) { + return; + } + + fctx_makekey(fctx->name, fctx->type, fctx->options, key, &keysize); + + result = isc_ht_delete(res->buckets[bucketnum].fctxs, key, keysize); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + fctx->hashed = false; +} + +static void +fctx_hash(fetchctx_t *fctx) { + dns_resolver_t *res = fctx->res; + unsigned int bucketnum = fctx->bucketnum; + uint8_t key[DNS_FCTX_KEYSIZE] = { 0 }; + size_t keysize = sizeof(key); + isc_result_t result; + bool unshared = ((fctx->options & DNS_FETCHOPT_UNSHARED) != 0); + + if (unshared) { + return; + } + + fctx_makekey(fctx->name, fctx->type, fctx->options, key, &keysize); + + result = isc_ht_add(res->buckets[bucketnum].fctxs, key, keysize, fctx); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + fctx->hashed = true; +} + static void fctx__done_detach(fetchctx_t **fctxp, isc_result_t result, const char *file, unsigned int line, const char *func) { @@ -1857,6 +1951,7 @@ fctx__done_detach(fetchctx_t **fctxp, isc_result_t result, const char *file, LOCK(&res->buckets[fctx->bucketnum].lock); INSIST(fctx->state != fetchstate_done); fctx->state = fetchstate_done; + fctx_unhash(fctx); UNLOCK(&res->buckets[fctx->bucketnum].lock); if (result == ISC_R_SUCCESS) { @@ -2089,6 +2184,10 @@ resquery_timeout(resquery_t *query) { event->result = ISC_R_TIMEDOUT; isc_task_sendanddetach(&sender, ISC_EVENT_PTR(&event)); } + + if (ISC_LIST_EMPTY(fctx->events)) { + fctx_unhash(fctx); + } UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); /* @@ -4481,7 +4580,6 @@ fctx_destroy(fetchctx_t *fctx, bool exiting) { struct tried *tried = NULL; unsigned int bucketnum; bool bucket_empty = false; - uint_fast32_t nfctx; REQUIRE(VALID_FCTX(fctx)); REQUIRE(ISC_LIST_EMPTY(fctx->events)); @@ -4501,18 +4599,19 @@ fctx_destroy(fetchctx_t *fctx, bool exiting) { LOCK(&res->buckets[bucketnum].lock); REQUIRE(fctx->state != fetchstate_active); - ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link); + fctx_unhash(fctx); - nfctx = atomic_fetch_sub_release(&res->nfctx, 1); - INSIST(nfctx > 0); - - dec_stats(res, dns_resstatscounter_nfetch); + INSIST(res->buckets[bucketnum].nfctxs > 0); + res->buckets[bucketnum].nfctxs--; if (atomic_load_acquire(&res->buckets[bucketnum].exiting) && - ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs)) + res->buckets[bucketnum].nfctxs == 0) { bucket_empty = true; } + + dec_stats(res, dns_resstatscounter_nfetch); + UNLOCK(&res->buckets[bucketnum].lock); if (bucket_empty && exiting && @@ -4654,6 +4753,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) { if (fctx->state == fetchstate_active) { fctx->state = fetchstate_done; + fctx_unhash(fctx); fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__); @@ -4828,7 +4928,6 @@ fctx_create(dns_resolver_t *res, isc_task_t *task, const dns_name_t *name, isc_interval_t interval; unsigned int findoptions = 0; char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 1]; - uint_fast32_t nfctx; size_t p; /* @@ -5110,7 +5209,6 @@ fctx_create(dns_resolver_t *res, isc_task_t *task, const dns_name_t *name, isc_mem_attach(res->mctx, &fctx->mctx); ISC_LIST_INIT(fctx->events); - ISC_LINK_INIT(fctx, link); fctx->magic = FCTX_MAGIC; /* @@ -5124,10 +5222,9 @@ fctx_create(dns_resolver_t *res, isc_task_t *task, const dns_name_t *name, fctx_minimize_qname(fctx); } - ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link); + fctx_hash(fctx); - nfctx = atomic_fetch_add_relaxed(&res->nfctx, 1); - INSIST(nfctx < UINT32_MAX); + res->buckets[bucketnum].nfctxs++; inc_stats(res, dns_resstatscounter_nfetch); @@ -5334,6 +5431,7 @@ clone_results(fetchctx_t *fctx) { * Caller must be holding the appropriate lock. */ + fctx_unhash(fctx); fctx->cloned = true; for (event = ISC_LIST_HEAD(fctx->events); event != NULL; @@ -10356,12 +10454,12 @@ destroy(dns_resolver_t *res) { RTRACE("destroy"); - REQUIRE(atomic_load_acquire(&res->nfctx) == 0); - isc_mutex_destroy(&res->primelock); isc_mutex_destroy(&res->lock); for (i = 0; i < res->nbuckets; i++) { - INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs)); + INSIST(res->buckets[i].nfctxs == 0); + INSIST(isc_ht_count(res->buckets[i].fctxs) == 0); + isc_ht_destroy(&res->buckets[i].fctxs); isc_task_shutdown(res->buckets[i].task); isc_task_detach(&res->buckets[i].task); isc_mutex_destroy(&res->buckets[i].lock); @@ -10369,7 +10467,8 @@ destroy(dns_resolver_t *res) { isc_mem_put(res->mctx, res->buckets, res->nbuckets * sizeof(fctxbucket_t)); for (i = 0; i < HASHSIZE(res->dhashbits); i++) { - INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list)); + INSIST(isc_ht_count(res->dbuckets[i].counters) == 0); + isc_ht_destroy(&res->dbuckets[i].counters); isc_mutex_destroy(&res->dbuckets[i].lock); } isc_mem_put(res->mctx, res->dbuckets, @@ -10500,7 +10599,6 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, atomic_init(&res->exiting, false); atomic_init(&res->priming, false); atomic_init(&res->zspill, 0); - atomic_init(&res->nfctx, 0); ISC_LIST_INIT(res->whenshutdown); ISC_LIST_INIT(res->alternates); @@ -10537,7 +10635,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, snprintf(name, sizeof(name), "res%" PRIu32, i); isc_task_setname(res->buckets[i].task, name, res); - ISC_LIST_INIT(res->buckets[i].fctxs); + isc_ht_init(&res->buckets[i].fctxs, res->mctx, 8, + ISC_HT_CASE_SENSITIVE); atomic_init(&res->buckets[i].exiting, false); } @@ -10545,8 +10644,10 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, HASHSIZE(res->dhashbits) * sizeof(res->dbuckets[0])); for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { - res->dbuckets[i] = (zonebucket_t){ .list = { 0 } }; - ISC_LIST_INIT(res->dbuckets[i].list); + res->dbuckets[i] = (zonebucket_t){ 0 }; + isc_ht_init(&res->dbuckets[i].counters, res->mctx, 8, + ISC_HT_CASE_SENSITIVE); + isc_mutex_init(&res->dbuckets[i].lock); } @@ -10774,33 +10875,45 @@ dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task, void dns_resolver_shutdown(dns_resolver_t *res) { unsigned int i; - fetchctx_t *fctx; isc_result_t result; - bool is_false = false; bool is_done = false; REQUIRE(VALID_RESOLVER(res)); RTRACE("shutdown"); - if (atomic_compare_exchange_strong(&res->exiting, &is_false, true)) { + if (atomic_compare_exchange_strong(&res->exiting, &(bool){ false }, + true)) + { RTRACE("exiting"); for (i = 0; i < res->nbuckets; i++) { LOCK(&res->buckets[i].lock); - for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs); - fctx != NULL; fctx = ISC_LIST_NEXT(fctx, link)) + isc_ht_iter_t *it = NULL; + + isc_ht_iter_create(res->buckets[i].fctxs, &it); + + for (result = isc_ht_iter_first(it); + result == ISC_R_SUCCESS; + result = isc_ht_iter_next(it)) { + fetchctx_t *fctx = NULL; + isc_ht_iter_current(it, (void **)&fctx); fctx_shutdown(fctx); } + + isc_ht_iter_destroy(&it); + atomic_store(&res->buckets[i].exiting, true); - if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) { + + if (res->buckets[i].nfctxs == 0) { if (isc_refcount_decrement( &res->activebuckets) == 1) { is_done = true; } } + UNLOCK(&res->buckets[i].lock); } if (is_done) { @@ -10831,24 +10944,6 @@ dns_resolver_detach(dns_resolver_t **resp) { } } -static bool -fctx_match(fetchctx_t *fctx, const dns_name_t *name, dns_rdatatype_t type, - unsigned int options) { - /* - * Don't match fetch contexts that are shutting down. - */ - if (fctx->cloned || fctx->state == fetchstate_done || - ISC_LIST_EMPTY(fctx->events)) - { - return false; - } - - if (fctx->type != type || fctx->options != options) { - return false; - } - return dns_name_equal(fctx->name, name); -} - static void log_fetch(const dns_name_t *name, dns_rdatatype_t type) { char namebuf[DNS_NAME_FORMATSIZE]; @@ -11039,13 +11134,13 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, } if ((options & DNS_FETCHOPT_UNSHARED) == 0) { - for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs); - fctx != NULL; fctx = ISC_LIST_NEXT(fctx, link)) - { - if (fctx_match(fctx, name, type, options)) { - break; - } - } + uint8_t key[DNS_FCTX_KEYSIZE]; + size_t keysize = sizeof(key); + + fctx_makekey(name, type, options, key, &keysize); + + (void)isc_ht_find(res->buckets[bucketnum].fctxs, key, keysize, + (void **)&fctx); } /* @@ -11192,6 +11287,7 @@ dns_resolver_cancelfetch(dns_fetch_t *fetch) { } } } + /* * The "trystale" event must be sent before the "fetchdone" event, * because the latter clears the "recursing" query attribute, which is @@ -11810,17 +11906,24 @@ dns_resolver_dumpfetches(dns_resolver_t *resolver, isc_statsformat_t format, REQUIRE(format == isc_statsformat_file); for (size_t i = 0; i < HASHSIZE(resolver->dhashbits); i++) { - fctxcount_t *fc; LOCK(&resolver->dbuckets[i].lock); - for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list); fc != NULL; - fc = ISC_LIST_NEXT(fc, link)) + isc_ht_iter_t *it = NULL; + isc_result_t result; + + isc_ht_iter_create(resolver->dbuckets[i].counters, &it); + for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS; + result = isc_ht_iter_next(it)) { - dns_name_print(fc->domain, fp); + fctxcount_t *counter = NULL; + isc_ht_iter_current(it, (void **)&counter); + dns_name_print(counter->domain, fp); fprintf(fp, ": %u active (%u spilled, %u " "allowed)\n", - fc->count, fc->dropped, fc->allowed); + counter->count, counter->dropped, + counter->allowed); } + isc_ht_iter_destroy(&it); UNLOCK(&resolver->dbuckets[i].lock); } }