diff --git a/lib/dns/adb.c b/lib/dns/adb.c index ce879f09d5..d07dcd36ad 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -252,8 +252,8 @@ struct dns_adbentry { unsigned char to4096; /* Our max. */ uint8_t mode; - uint32_t quota; - uint32_t active; + atomic_uint_fast32_t quota; + atomic_uint_fast32_t active; double atr; /* @@ -1832,9 +1832,9 @@ new_adbentry(dns_adb_t *adb) { e->srtt = (isc_random_uniform(0x1f)) + 1; e->lastage = 0; e->expires = 0; - e->active = 0; + atomic_init(&e->active, 0); e->mode = 0; - e->quota = adb->quota; + atomic_init(&e->quota, adb->quota); e->atr = 0.0; ISC_LIST_INIT(e->lameinfo); ISC_LINK_INIT(e, plink); @@ -2161,8 +2161,10 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) { isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, - ISC_LOG_INFO, "adb: quota %s (%u/%u): %s", - addrbuf, entry->active, entry->quota, msgbuf); + ISC_LOG_INFO, + "adb: quota %s (%" PRIuFAST32 "/%" PRIuFAST32 "): %s", + addrbuf, atomic_load_relaxed(&entry->active), + atomic_load_relaxed(&entry->quota), msgbuf); } static void @@ -2185,9 +2187,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, INSIST(bucket != DNS_ADB_INVALIDBUCKET); LOCK(&adb->entrylocks[bucket]); - if (entry->quota != 0 && - entry->active >= entry->quota) - { + if (dns_adbentry_overquota(entry)) { find->options |= (DNS_ADBFIND_LAMEPRUNED| DNS_ADBFIND_OVERQUOTA); @@ -2225,9 +2225,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, INSIST(bucket != DNS_ADB_INVALIDBUCKET); LOCK(&adb->entrylocks[bucket]); - if (entry->quota != 0 && - entry->active >= entry->quota) - { + if (dns_adbentry_overquota(entry)) { find->options |= (DNS_ADBFIND_LAMEPRUNED| DNS_ADBFIND_OVERQUOTA); @@ -3534,8 +3532,8 @@ dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry, fprintf(f, " [ttl %d]", (int)(entry->expires - now)); if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) { - fprintf(f, " [atr %0.2f] [quota %u]", - entry->atr, entry->quota); + fprintf(f, " [atr %0.2f] [quota %" PRIuFAST32 "]", + entry->atr, atomic_load_relaxed(&entry->quota)); } fprintf(f, "\n"); @@ -4257,21 +4255,25 @@ maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0); if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) { - addr->entry->quota = adb->quota * - quota_adj[--addr->entry->mode] / 10000; - log_quota(addr->entry, "atr %0.2f, quota increased to %u", - addr->entry->atr, addr->entry->quota); + uint_fast32_t new_quota = + adb->quota * quota_adj[--addr->entry->mode] / 10000; + atomic_store_release(&addr->entry->quota, + ISC_MIN(1, new_quota)); + log_quota(addr->entry, "atr %0.2f, quota increased to %" + PRIuFAST32, + addr->entry->atr, + new_quota); } else if (addr->entry->atr > adb->atr_high && addr->entry->mode < (QUOTA_ADJ_SIZE - 1)) { - addr->entry->quota = adb->quota * - quota_adj[++addr->entry->mode] / 10000; - log_quota(addr->entry, "atr %0.2f, quota decreased to %u", - addr->entry->atr, addr->entry->quota); + uint_fast32_t new_quota = + adb->quota * quota_adj[++addr->entry->mode] / 10000; + atomic_store_release(&addr->entry->quota, + ISC_MIN(1, new_quota)); + log_quota(addr->entry, "atr %0.2f, quota decreased to %" + PRIuFAST32, + addr->entry->atr, + new_quota); } - - /* Ensure we don't drop to zero */ - if (addr->entry->quota == 0) - addr->entry->quota = 1; } #define EDNSTOS 3U @@ -4773,34 +4775,25 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq, bool dns_adbentry_overquota(dns_adbentry_t *entry) { REQUIRE(DNS_ADBENTRY_VALID(entry)); - return (entry->quota != 0 && entry->active >= entry->quota); + + uint_fast32_t quota = atomic_load_relaxed(&entry->quota); + uint_fast32_t active = atomic_load_acquire(&entry->active); + + return (quota != 0 && active >= quota); } void dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { - int bucket; - REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADBADDRINFO_VALID(addr)); - bucket = addr->entry->lock_bucket; - - LOCK(&adb->entrylocks[bucket]); - addr->entry->active++; - UNLOCK(&adb->entrylocks[bucket]); + INSIST(atomic_fetch_add_relaxed(&addr->entry->active, 1) != UINT32_MAX); } void dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { - int bucket; - REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADBADDRINFO_VALID(addr)); - bucket = addr->entry->lock_bucket; - - LOCK(&adb->entrylocks[bucket]); - if (addr->entry->active > 0) - addr->entry->active--; - UNLOCK(&adb->entrylocks[bucket]); + INSIST(atomic_fetch_sub_release(&addr->entry->active, 1) != 0); }