From 7e59b8a4a1ee3b29cc3127cc4890ef9b53d82216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Fri, 4 Jun 2021 09:22:09 +0200 Subject: [PATCH] Pause the dbiterator when dumping the zone to the disk When we rewrote the zone dumping to use the separate threadpool, the dumping would acquire the read lock for the whole time the zone dumping process is dumping the zone. When combined with incoming IXFR that tries to acquire the write lock on the same rwlock, we would end up blocking all the other readers. In this commit, we pause the dbiterator every time we get next record and before start dumping it to the disk. --- lib/dns/masterdump.c | 45 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index c5f00bd1c3..31304380d4 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -254,7 +254,6 @@ struct dns_dumpctx { isc_mutex_t lock; isc_refcount_t references; atomic_bool canceled; - bool first; bool do_date; isc_stdtime_t now; FILE *f; @@ -1578,7 +1577,6 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, dctx->done = NULL; dctx->done_arg = NULL; dctx->task = NULL; - dctx->first = true; atomic_init(&dctx->canceled, false); dctx->file = NULL; dctx->tmpfile = NULL; @@ -1737,7 +1735,6 @@ dumptostream(dns_dumpctx_t *dctx) { char *bufmem; dns_name_t *name; dns_fixedname_t fixname; - isc_time_t start; bufmem = isc_mem_get(dctx->mctx, initial_buffer_length); @@ -1745,32 +1742,24 @@ dumptostream(dns_dumpctx_t *dctx) { name = dns_fixedname_initname(&fixname); - if (dctx->first) { - CHECK(writeheader(dctx)); + CHECK(writeheader(dctx)); - /* - * Fast format is not currently written incrementally, - * so we make the call to dns_db_serialize() here. - * If the database is anything other than an rbtdb, - * this should result in not implemented - */ - if (dctx->format == dns_masterformat_map) { - result = dns_db_serialize(dctx->db, dctx->version, - dctx->f); - goto cleanup; - } - - result = dns_dbiterator_first(dctx->dbiter); - if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) { - goto cleanup; - } - - dctx->first = false; - } else { - result = ISC_R_SUCCESS; + /* + * Fast format is not currently written incrementally, + * so we make the call to dns_db_serialize() here. + * If the database is anything other than an rbtdb, + * this should result in not implemented + */ + if (dctx->format == dns_masterformat_map) { + result = dns_db_serialize(dctx->db, dctx->version, dctx->f); + goto cleanup; + } + + result = dns_dbiterator_first(dctx->dbiter); + if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) { + goto cleanup; } - isc_time_now(&start); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_t *rdsiter = NULL; dns_dbnode_t *node = NULL; @@ -1790,6 +1779,10 @@ dumptostream(dns_dumpctx_t *dctx) { } dctx->tctx.neworigin = origin; } + + result = dns_dbiterator_pause(dctx->dbiter); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = dns_db_allrdatasets(dctx->db, node, dctx->version, dctx->now, &rdsiter); if (result != ISC_R_SUCCESS) {