mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 23:25:38 +00:00
lib/dns/adb.c: Use atomics for adb quota values and reference counting
This commit is contained in:
committed by
Ondřej Surý
parent
b9f4ba19a6
commit
bad5a523c2
@@ -252,8 +252,8 @@ struct dns_adbentry {
|
|||||||
unsigned char to4096; /* Our max. */
|
unsigned char to4096; /* Our max. */
|
||||||
|
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint32_t quota;
|
atomic_uint_fast32_t quota;
|
||||||
uint32_t active;
|
atomic_uint_fast32_t active;
|
||||||
double atr;
|
double atr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1832,9 +1832,9 @@ new_adbentry(dns_adb_t *adb) {
|
|||||||
e->srtt = (isc_random_uniform(0x1f)) + 1;
|
e->srtt = (isc_random_uniform(0x1f)) + 1;
|
||||||
e->lastage = 0;
|
e->lastage = 0;
|
||||||
e->expires = 0;
|
e->expires = 0;
|
||||||
e->active = 0;
|
atomic_init(&e->active, 0);
|
||||||
e->mode = 0;
|
e->mode = 0;
|
||||||
e->quota = adb->quota;
|
atomic_init(&e->quota, adb->quota);
|
||||||
e->atr = 0.0;
|
e->atr = 0.0;
|
||||||
ISC_LIST_INIT(e->lameinfo);
|
ISC_LIST_INIT(e->lameinfo);
|
||||||
ISC_LINK_INIT(e, plink);
|
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_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
|
||||||
|
|
||||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
|
||||||
ISC_LOG_INFO, "adb: quota %s (%u/%u): %s",
|
ISC_LOG_INFO,
|
||||||
addrbuf, entry->active, entry->quota, msgbuf);
|
"adb: quota %s (%" PRIuFAST32 "/%" PRIuFAST32 "): %s",
|
||||||
|
addrbuf, atomic_load_relaxed(&entry->active),
|
||||||
|
atomic_load_relaxed(&entry->quota), msgbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2185,9 +2187,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
|
|||||||
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
|
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
|
||||||
LOCK(&adb->entrylocks[bucket]);
|
LOCK(&adb->entrylocks[bucket]);
|
||||||
|
|
||||||
if (entry->quota != 0 &&
|
if (dns_adbentry_overquota(entry)) {
|
||||||
entry->active >= entry->quota)
|
|
||||||
{
|
|
||||||
find->options |=
|
find->options |=
|
||||||
(DNS_ADBFIND_LAMEPRUNED|
|
(DNS_ADBFIND_LAMEPRUNED|
|
||||||
DNS_ADBFIND_OVERQUOTA);
|
DNS_ADBFIND_OVERQUOTA);
|
||||||
@@ -2225,9 +2225,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
|
|||||||
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
|
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
|
||||||
LOCK(&adb->entrylocks[bucket]);
|
LOCK(&adb->entrylocks[bucket]);
|
||||||
|
|
||||||
if (entry->quota != 0 &&
|
if (dns_adbentry_overquota(entry)) {
|
||||||
entry->active >= entry->quota)
|
|
||||||
{
|
|
||||||
find->options |=
|
find->options |=
|
||||||
(DNS_ADBFIND_LAMEPRUNED|
|
(DNS_ADBFIND_LAMEPRUNED|
|
||||||
DNS_ADBFIND_OVERQUOTA);
|
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));
|
fprintf(f, " [ttl %d]", (int)(entry->expires - now));
|
||||||
|
|
||||||
if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) {
|
if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) {
|
||||||
fprintf(f, " [atr %0.2f] [quota %u]",
|
fprintf(f, " [atr %0.2f] [quota %" PRIuFAST32 "]",
|
||||||
entry->atr, entry->quota);
|
entry->atr, atomic_load_relaxed(&entry->quota));
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "\n");
|
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);
|
addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0);
|
||||||
|
|
||||||
if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) {
|
if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) {
|
||||||
addr->entry->quota = adb->quota *
|
uint_fast32_t new_quota =
|
||||||
quota_adj[--addr->entry->mode] / 10000;
|
adb->quota * quota_adj[--addr->entry->mode] / 10000;
|
||||||
log_quota(addr->entry, "atr %0.2f, quota increased to %u",
|
atomic_store_release(&addr->entry->quota,
|
||||||
addr->entry->atr, 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 &&
|
} else if (addr->entry->atr > adb->atr_high &&
|
||||||
addr->entry->mode < (QUOTA_ADJ_SIZE - 1)) {
|
addr->entry->mode < (QUOTA_ADJ_SIZE - 1)) {
|
||||||
addr->entry->quota = adb->quota *
|
uint_fast32_t new_quota =
|
||||||
quota_adj[++addr->entry->mode] / 10000;
|
adb->quota * quota_adj[++addr->entry->mode] / 10000;
|
||||||
log_quota(addr->entry, "atr %0.2f, quota decreased to %u",
|
atomic_store_release(&addr->entry->quota,
|
||||||
addr->entry->atr, 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
|
#define EDNSTOS 3U
|
||||||
@@ -4773,34 +4775,25 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq,
|
|||||||
bool
|
bool
|
||||||
dns_adbentry_overquota(dns_adbentry_t *entry) {
|
dns_adbentry_overquota(dns_adbentry_t *entry) {
|
||||||
REQUIRE(DNS_ADBENTRY_VALID(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
|
void
|
||||||
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
||||||
int bucket;
|
|
||||||
|
|
||||||
REQUIRE(DNS_ADB_VALID(adb));
|
REQUIRE(DNS_ADB_VALID(adb));
|
||||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||||
|
|
||||||
bucket = addr->entry->lock_bucket;
|
INSIST(atomic_fetch_add_relaxed(&addr->entry->active, 1) != UINT32_MAX);
|
||||||
|
|
||||||
LOCK(&adb->entrylocks[bucket]);
|
|
||||||
addr->entry->active++;
|
|
||||||
UNLOCK(&adb->entrylocks[bucket]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
||||||
int bucket;
|
|
||||||
|
|
||||||
REQUIRE(DNS_ADB_VALID(adb));
|
REQUIRE(DNS_ADB_VALID(adb));
|
||||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||||
|
|
||||||
bucket = addr->entry->lock_bucket;
|
INSIST(atomic_fetch_sub_release(&addr->entry->active, 1) != 0);
|
||||||
|
|
||||||
LOCK(&adb->entrylocks[bucket]);
|
|
||||||
if (addr->entry->active > 0)
|
|
||||||
addr->entry->active--;
|
|
||||||
UNLOCK(&adb->entrylocks[bucket]);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user