From 2b3e34f03675d6c71a654fe2094f3b9c063a70ea Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 7 Jul 2005 00:51:05 +0000 Subject: [PATCH] 1896. [bug] The cache could delete expired records too fast for clients with a virtual time in the past. [RT #14991] --- CHANGES | 3 +++ lib/dns/rbtdb.c | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index af12c92b41..b0c9bc8a50 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1896. [bug] The cache could delete expired records too fast for + clients with a virtual time in the past. [RT #14991] + 1895. [bug] fctx_create() could return success even though it failed. [RT #14993] diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index a68d2ff049..44986367ed 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.210 2005/07/04 03:50:32 marka Exp $ */ +/* $Id: rbtdb.c,v 1.211 2005/07/07 00:51:05 marka Exp $ */ /*! \file */ @@ -182,6 +182,12 @@ typedef isc_mutex_t nodelock_t; #define NODE_WEAKUNLOCK(l, t) #endif +/* + * Allow clients with a virtual time of upto 5 minutes in the past to see + * records that would have otherwise have expired. + */ +#define RBTDB_VIRTUAL 300 + struct noqname { dns_name_t name; void * nsec; @@ -2878,8 +2884,9 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) { * the node as dirty, so it will get cleaned * up later. */ - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= search->now + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only when we * can get write access; otherwise, we leave @@ -2992,8 +2999,10 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node, * the node as dirty, so it will get cleaned * up later. */ - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= search->now + + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only * when we can get write access. @@ -3153,8 +3162,9 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, * node as dirty, so it will get cleaned up * later. */ - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= now + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only * when we can get write access. @@ -3331,8 +3341,9 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * mark it as stale, and the node as dirty, so it will * get cleaned up later. */ - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= now + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only when we * can get write access. @@ -3623,8 +3634,9 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, * mark it as stale, and the node as dirty, so it will * get cleaned up later. */ - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= now + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only when we * can get write access. @@ -3837,7 +3849,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { isc_rwlocktype_write); for (header = rbtnode->data; header != NULL; header = header->next) - if (header->ttl <= now) { + if (header->ttl <= now + RBTDB_VIRTUAL) { /* * We don't check if refcurrent(rbtnode) == 0 and try * to free like we do in cache_find(), because @@ -4083,8 +4095,9 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, for (header = rbtnode->data; header != NULL; header = header_next) { header_next = header->next; if (header->ttl <= now) { - if (locktype == isc_rwlocktype_write || - NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS) { + if ((header->ttl <= now + RBTDB_VIRTUAL) && + (locktype == isc_rwlocktype_write || + NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { /* * We update the node's status only when we * can get write access.