#define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
load. */
-#define UNREACH_CHACHE_SIZE 10U
+#define UNREACH_CACHE_SIZE 10U
#define UNREACH_HOLD_TIME 600 /* 10 minutes */
#define CHECK(op) \
struct dns_unreachable {
isc_sockaddr_t remote;
isc_sockaddr_t local;
- uint32_t expire;
- uint32_t last;
- uint32_t count;
+ atomic_uint_fast32_t expire;
+ atomic_uint_fast32_t last;
+ uint32_t count;
};
struct dns_zonemgr {
/* Locked by urlock. */
/* LRU cache */
- struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
+ struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
};
/*%
isc_sockaddr_t *local, isc_time_t *now)
{
unsigned int i;
- isc_rwlocktype_t locktype;
- isc_result_t result;
uint32_t seconds = isc_time_seconds(now);
uint32_t count = 0;
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->urlock, locktype);
- for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
+ RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
+ for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
if (zmgr->unreachable[i].expire >= seconds &&
isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
- result = isc_rwlock_tryupgrade(&zmgr->urlock);
- if (result == ISC_R_SUCCESS) {
- locktype = isc_rwlocktype_write;
- zmgr->unreachable[i].last = seconds;
- count = zmgr->unreachable[i].count;
- }
+ atomic_store_relaxed(&zmgr->unreachable[i].last,
+ seconds);
+ count = zmgr->unreachable[i].count;
break;
}
}
- RWUNLOCK(&zmgr->urlock, locktype);
- return (i < UNREACH_CHACHE_SIZE && count > 1U);
+ RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
+ return (i < UNREACH_CACHE_SIZE && count > 1U);
}
void
isc_sockaddr_t *local)
{
unsigned int i;
- isc_rwlocktype_t locktype;
- isc_result_t result;
-
char master[ISC_SOCKADDR_FORMATSIZE];
char source[ISC_SOCKADDR_FORMATSIZE];
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->urlock, locktype);
- for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
+ RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
+ for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
- if (zmgr->unreachable[i].expire == 0)
- break;
- result = isc_rwlock_tryupgrade(&zmgr->urlock);
- if (result == ISC_R_SUCCESS) {
- locktype = isc_rwlocktype_write;
- zmgr->unreachable[i].expire = 0;
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
- DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
- "master %s (source %s) deleted "
- "from unreachable cache",
- master, source);
- }
+ atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
break;
}
}
- RWUNLOCK(&zmgr->urlock, locktype);
+ RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
}
void
{
uint32_t seconds = isc_time_seconds(now);
uint32_t last = seconds;
- unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
-
+ unsigned int i, slot = UNREACH_CACHE_SIZE, oldest = 0;
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
- for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
+ for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
/* Existing entry? */
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
break;
/* Empty slot? */
- if (zmgr->unreachable[i].expire < seconds)
+ if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds) {
slot = i;
+ }
/* Least recently used slot? */
- if (zmgr->unreachable[i].last < last) {
- last = zmgr->unreachable[i].last;
+ if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
+ last = atomic_load_relaxed(&zmgr->unreachable[i].last);
oldest = i;
}
}
- if (i < UNREACH_CHACHE_SIZE) {
+ if (i < UNREACH_CACHE_SIZE) {
/*
* Found a existing entry. Update the expire timer and
* last usage timestamps.
*/
- zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
- zmgr->unreachable[i].last = seconds;
- if (zmgr->unreachable[i].expire < seconds)
+ if (atomic_load_relaxed(&zmgr->unreachable[i].expire)
+ < seconds) {
zmgr->unreachable[i].count = 1;
- else
+ } else {
zmgr->unreachable[i].count++;
- } else if (slot != UNREACH_CHACHE_SIZE) {
+ }
+ atomic_store_relaxed(&zmgr->unreachable[i].expire,
+ seconds + UNREACH_HOLD_TIME);
+ atomic_store_relaxed(&zmgr->unreachable[i].last, seconds);
+ } else {
/*
- * Found a empty slot. Add a new entry to the cache.
+ * We need to write a new entry.
*/
- zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
- zmgr->unreachable[slot].last = seconds;
+ if (slot == UNREACH_CACHE_SIZE) {
+ /*
+ * We don't have an empty slot, use the oldest one.
+ */
+ slot = oldest;
+ }
+ atomic_store_relaxed(&zmgr->unreachable[slot].expire,
+ seconds + UNREACH_HOLD_TIME);
+ atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
+ zmgr->unreachable[slot].count = 1;
zmgr->unreachable[slot].remote = *remote;
zmgr->unreachable[slot].local = *local;
- zmgr->unreachable[slot].count = 1;
- } else {
- /*
- * Replace the least recently used entry in the cache.
- */
- zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
- zmgr->unreachable[oldest].last = seconds;
- zmgr->unreachable[oldest].remote = *remote;
- zmgr->unreachable[oldest].local = *local;
- zmgr->unreachable[oldest].count = 1;
}
RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
}