mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 08:05:21 +00:00
Reuse recursion type code for refresh stale RRset
Refreshing a stale RRset is similar to prefetching an RRset, so reuse the existing code. When refreshing an RRset we need to clear all db options related to serve-stale so that stale RRsets in cache are ignored during the refresh. We no longer need to set the "nodetach" flag, because the refresh fetch is now a "fetch and forget". So we can detach from the client in the query_send(). This code will break some serve-stale test cases, this will be fixed in the successor commit. TODO: add explanation why the serve-stale test cases fail.
This commit is contained in:
110
lib/ns/query.c
110
lib/ns/query.c
@@ -2543,6 +2543,7 @@ cleanup_after_fetch(isc_task_t *task, isc_event_t *event, const char *ctracestr,
|
|||||||
fetchp = &client->query.recursions[recursion_type].fetch;
|
fetchp = &client->query.recursions[recursion_type].fetch;
|
||||||
|
|
||||||
LOCK(&client->query.fetchlock);
|
LOCK(&client->query.fetchlock);
|
||||||
|
|
||||||
if (*fetchp != NULL) {
|
if (*fetchp != NULL) {
|
||||||
INSIST(devent->fetch == *fetchp);
|
INSIST(devent->fetch == *fetchp);
|
||||||
*fetchp = NULL;
|
*fetchp = NULL;
|
||||||
@@ -2550,7 +2551,6 @@ cleanup_after_fetch(isc_task_t *task, isc_event_t *event, const char *ctracestr,
|
|||||||
UNLOCK(&client->query.fetchlock);
|
UNLOCK(&client->query.fetchlock);
|
||||||
|
|
||||||
recursionquotatype_detach(client, recursion_type);
|
recursionquotatype_detach(client, recursion_type);
|
||||||
|
|
||||||
free_devent(client, &event, &devent);
|
free_devent(client, &event, &devent);
|
||||||
isc_nmhandle_detach(handlep);
|
isc_nmhandle_detach(handlep);
|
||||||
}
|
}
|
||||||
@@ -2566,8 +2566,9 @@ rpzfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
refresh_done(isc_task_t *task, isc_event_t *event) {
|
stale_refresh_done(isc_task_t *task, isc_event_t *event) {
|
||||||
cleanup_after_fetch(task, event, "refresh_done", RECTYPE_REFRESH);
|
cleanup_after_fetch(task, event, "stale_refresh_done",
|
||||||
|
RECTYPE_STALE_REFRESH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2611,9 +2612,9 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype,
|
|||||||
options = client->query.fetchoptions;
|
options = client->query.fetchoptions;
|
||||||
action = rpzfetch_done;
|
action = rpzfetch_done;
|
||||||
break;
|
break;
|
||||||
case RECTYPE_REFRESH:
|
case RECTYPE_STALE_REFRESH:
|
||||||
options = client->query.fetchoptions;
|
options = client->query.fetchoptions;
|
||||||
action = refresh_done;
|
action = stale_refresh_done;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@@ -2655,19 +2656,29 @@ query_prefetch(ns_client_t *client, dns_name_t *qname,
|
|||||||
ns_statscounter_prefetch);
|
ns_statscounter_prefetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static void
|
static void
|
||||||
query_refresh(ns_client_t *client, dns_name_t *qname,
|
query_stale_refresh(ns_client_t *client) {
|
||||||
dns_rdataset_t *rdataset) {
|
dns_name_t *qname;
|
||||||
CTRACE(ISC_LOG_DEBUG(3), "query_refresh");
|
|
||||||
|
|
||||||
if (FETCH_RECTYPE_REFRESH(client) != NULL) {
|
CTRACE(ISC_LOG_DEBUG(3), "query_stale_refresh");
|
||||||
|
|
||||||
|
if (FETCH_RECTYPE_STALE_REFRESH(client) != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch_and_forget(client, qname, rdataset->type, RECTYPE_REFRESH);
|
client->query.dboptions &= ~(DNS_DBFIND_STALETIMEOUT |
|
||||||
|
DNS_DBFIND_STALEOK |
|
||||||
|
DNS_DBFIND_STALEENABLED);
|
||||||
|
|
||||||
|
if (client->query.origqname != NULL) {
|
||||||
|
qname = client->query.origqname;
|
||||||
|
} else {
|
||||||
|
qname = client->query.qname;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_and_forget(client, qname, client->query.qtype,
|
||||||
|
RECTYPE_STALE_REFRESH);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
|
rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
|
||||||
@@ -5225,26 +5236,6 @@ qctx_init(ns_client_t *client, dns_fetchevent_t **eventp, dns_rdatatype_t qtype,
|
|||||||
CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
|
CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Make 'dst' and exact copy of 'src', with exception of the
|
|
||||||
* option field, which is reset to zero.
|
|
||||||
* This function also attaches dst's view and db to the src's
|
|
||||||
* view and cachedb.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
qctx_copy(const query_ctx_t *qctx, query_ctx_t *dst) {
|
|
||||||
REQUIRE(qctx != NULL);
|
|
||||||
REQUIRE(dst != NULL);
|
|
||||||
|
|
||||||
memmove(dst, qctx, sizeof(*dst));
|
|
||||||
dst->view = NULL;
|
|
||||||
dst->db = NULL;
|
|
||||||
dst->options = 0;
|
|
||||||
dns_view_attach(qctx->view, &dst->view);
|
|
||||||
dns_db_attach(qctx->view->cachedb, &dst->db);
|
|
||||||
CCTRACE(ISC_LOG_DEBUG(3), "qctx_copy");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Clean up and disassociate the rdataset and node pointers in qctx.
|
* Clean up and disassociate the rdataset and node pointers in qctx.
|
||||||
*/
|
*/
|
||||||
@@ -5749,54 +5740,6 @@ qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer) {
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup a new query context for resolving a query.
|
|
||||||
*
|
|
||||||
* This function is only called if both these conditions are met:
|
|
||||||
* 1. BIND is configured with stale-answer-client-timeout 0.
|
|
||||||
* 2. A stale RRset is found in cache during initial query
|
|
||||||
* database lookup.
|
|
||||||
*
|
|
||||||
* We continue with this function for refreshing/resolving an RRset
|
|
||||||
* after answering a client with stale data.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
query_refresh_rrset(query_ctx_t *orig_qctx) {
|
|
||||||
isc_buffer_t buffer;
|
|
||||||
query_ctx_t qctx;
|
|
||||||
|
|
||||||
REQUIRE(orig_qctx != NULL);
|
|
||||||
REQUIRE(orig_qctx->client != NULL);
|
|
||||||
|
|
||||||
qctx_copy(orig_qctx, &qctx);
|
|
||||||
qctx.client->query.dboptions &= ~(DNS_DBFIND_STALETIMEOUT |
|
|
||||||
DNS_DBFIND_STALEOK |
|
|
||||||
DNS_DBFIND_STALEENABLED);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We'll need some resources...
|
|
||||||
*/
|
|
||||||
if (qctx_prepare_buffers(&qctx, &buffer) != ISC_R_SUCCESS) {
|
|
||||||
dns_db_detach(&qctx.db);
|
|
||||||
qctx_destroy(&qctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pretend we didn't find anything in cache.
|
|
||||||
*/
|
|
||||||
(void)query_gotanswer(&qctx, ISC_R_NOTFOUND);
|
|
||||||
|
|
||||||
if (qctx.fname != NULL) {
|
|
||||||
ns_client_releasename(qctx.client, &qctx.fname);
|
|
||||||
}
|
|
||||||
if (qctx.rdataset != NULL) {
|
|
||||||
ns_client_putrdataset(qctx.client, &qctx.rdataset);
|
|
||||||
}
|
|
||||||
|
|
||||||
qctx_destroy(&qctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Perform a local database lookup, in either an authoritative or
|
* Perform a local database lookup, in either an authoritative or
|
||||||
* cache database. If unable to answer, call ns_query_done(); otherwise
|
* cache database. If unable to answer, call ns_query_done(); otherwise
|
||||||
@@ -11548,12 +11491,7 @@ ns_query_done(query_ctx_t *qctx) {
|
|||||||
/*
|
/*
|
||||||
* Client may have been detached after query_send(), so
|
* Client may have been detached after query_send(), so
|
||||||
* we test and store the flag state here, for safety.
|
* we test and store the flag state here, for safety.
|
||||||
* If we are refreshing the RRSet, we must not detach from the client
|
|
||||||
* in the query_send(), so we need to override the flag.
|
|
||||||
*/
|
*/
|
||||||
if (qctx->refresh_rrset) {
|
|
||||||
qctx->client->nodetach = true;
|
|
||||||
}
|
|
||||||
nodetach = qctx->client->nodetach;
|
nodetach = qctx->client->nodetach;
|
||||||
query_send(qctx->client);
|
query_send(qctx->client);
|
||||||
|
|
||||||
@@ -11568,7 +11506,7 @@ ns_query_done(query_ctx_t *qctx) {
|
|||||||
* refresh.
|
* refresh.
|
||||||
*/
|
*/
|
||||||
message_clearrdataset(qctx->client->message, 0);
|
message_clearrdataset(qctx->client->message, 0);
|
||||||
query_refresh_rrset(qctx);
|
query_stale_refresh(qctx->client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nodetach) {
|
if (!nodetach) {
|
||||||
|
Reference in New Issue
Block a user