Extend expire_header() to check node lock type

Extend the expire_header() to accept the node lock type as one of the
arguments and check whether the the node lock is always write locked +
fix that bug.

While doing that, it was found that expire_header() invocation in
rdataset_expire() passes `false` as a type of tree lock instead of
`isc_rwlocktype_none`.

(Un)fortunately, both values mapped to 0, so no harm was done, but it
has been fixed nevertheless.
This commit is contained in:
Ondřej Surý 2023-01-05 22:26:23 +01:00
parent 20670ee22d
commit d693c2e7a0

View file

@ -714,7 +714,8 @@ static void
update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_stdtime_t now);
static void
expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
isc_rwlocktype_t *tlocktypep, expire_t reason);
isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep,
expire_t reason);
static void
overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
isc_rwlocktype_t *tlocktypep);
@ -7086,7 +7087,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
header->rdh_ttl + STALE_TTL(header, rbtdb) <
now - RBTDB_VIRTUAL)
{
expire_header(rbtdb, header, &tlocktype, expire_ttl);
expire_header(rbtdb, header, &nlocktype, &tlocktype,
expire_ttl);
}
/*
@ -8802,11 +8804,13 @@ rdataset_expire(dns_rdataset_t *rdataset) {
dns_rbtnode_t *rbtnode = rdataset->private2;
rdatasetheader_t *header = rdataset->private3;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
header--;
NODE_WRLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype);
expire_header(rbtdb, header, false, expire_flush);
expire_header(rbtdb, header, &nlocktype, &tlocktype, expire_flush);
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
static void
@ -10178,7 +10182,8 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
header = isc_heap_element(rbtdb->heaps[locknum], 1);
if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) {
expire_header(rbtdb, header, tlocktypep, expire_ttl);
expire_header(rbtdb, header, &nlocktype, tlocktypep,
expire_ttl);
purgecount--;
}
@ -10195,7 +10200,8 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
*/
ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
link);
expire_header(rbtdb, header, tlocktypep, expire_lru);
expire_header(rbtdb, header, &nlocktype, tlocktypep,
expire_lru);
purgecount--;
}
@ -10205,13 +10211,15 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
static void
expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
isc_rwlocktype_t *tlocktypep, expire_t reason) {
isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep,
expire_t reason) {
set_ttl(rbtdb, header, 0);
mark_header_ancient(rbtdb, header);
/*
* Caller must hold the node (write) lock.
*/
INSIST(*nlocktypep == isc_rwlocktype_write);
if (isc_refcount_current(&header->node->references) == 0) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_write;