Resolver prefetch issue with qtype ANY
In lib/ns/query.c:query_respond_any()
, when there are several datasets in the database node, only one of them has a chance to trigger a prefetch, because when one does, the FETCH_RECTYPE_PREFETCH(client) != NULL
check (see below) does not pass for the rest of the datasets, even if they are eligible for a prefetch, as the client's fetch reserved for the prefetch operation is already in progress:
static void
query_prefetch(ns_client_t *client, dns_name_t *qname,
dns_rdataset_t *rdataset) {
CTRACE(ISC_LOG_DEBUG(3), "query_prefetch");
if (FETCH_RECTYPE_PREFETCH(client) != NULL ||
client->view->prefetch_trigger == 0U ||
rdataset->ttl > client->view->prefetch_trigger ||
(rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0)
{
return;
}
fetch_and_forget(client, qname, rdataset->type, RECTYPE_PREFETCH);
dns_rdataset_clearprefetch(rdataset);
ns_stats_increment(client->manager->sctx->nsstats,
ns_statscounter_prefetch);
}
I will use the resolver
system test's check prefetch qtype * (${n})
check to demonstrate it. Please note that if you want to reproduce it, you'll need to use the branch in !6937 (merged) which fixes another prefetch issue (unless it is already merged).
Run the test:
$ ./run.sh -n resolver
...
...
I:resolver:check prefetch qtype * (32)
...
PASS: resolver
Check the first answer, all records start with TTL value of 10:
$ cat resolver/dig.out.1.32
...
;; QUESTION SECTION:
;fetchall.tld. IN ANY
;; ANSWER SECTION:
fetchall.tld. 10 IN AAAA ::1
fetchall.tld. 10 IN A 1.2.3.4
fetchall.tld. 10 IN TXT "A" "short" "ttl"
...
Check the second answer (for a request after 7 seconds), this should had triggered a prefetch for all 3 records, because TTL value 3 is smaller than the configured trigger value 4:
$ cat resolver/dig.out.2.32
...
;; QUESTION SECTION:
;fetchall.tld. IN ANY
;; ANSWER SECTION:
fetchall.tld. 3 IN AAAA ::1
fetchall.tld. 3 IN A 1.2.3.4
fetchall.tld. 3 IN TXT "A" "short" "ttl"
...
Check the third answer (for a request after 1 second):
$ cat resolver/dig.out.3.32
...
;; QUESTION SECTION:
;fetchall.tld. IN ANY
;; ANSWER SECTION:
fetchall.tld. 9 IN AAAA ::1
fetchall.tld. 2 IN A 1.2.3.4
fetchall.tld. 2 IN TXT "A" "short" "ttl"
...
As you can see, only the first record was prefetched.
Here are the logs which confirm that, where you can see that query_prefetch()
was called three times, but a prefetch was initiated only for the first call: fetchall.tld-any.log.gz.
I think, as suggest by @fanf in MM, ANY should not trigger prefetching at all. Or, otherwise, all records which are eligible for prefetch should be prefetched.