From: Evan Hunt Date: Tue, 16 May 2017 15:47:20 +0000 (-0700) Subject: [master] don't keep an LMDB transaction open across an exclusive section X-Git-Tag: v9.12.0a1~289 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=03a7a952c0ea6e6c3a225ec9b9de540cb0598019;p=thirdparty%2Fbind9.git [master] don't keep an LMDB transaction open across an exclusive section 4625. [bug] Running "rndc addzone" and "rndc delzone" at close to the same time could trigger a deadlock if using LMDB. [RT #45209] --- diff --git a/CHANGES b/CHANGES index 0c7e6318595..7d89538a285 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4625. [bug] Running "rndc addzone" and "rndc delzone" at close + to the same time could trigger a deadlock if using + LMDB. [RT #45209] + 4624. [placeholder] 4623. [bug] Use --with-protobuf-c and --with-libfstrm to find diff --git a/bin/named/server.c b/bin/named/server.c index 46641bc15cc..30d54ff8d2e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -478,6 +478,9 @@ count_zones(const cfg_obj_t *conf); static isc_result_t migrate_nzf(dns_view_t *view); +static isc_result_t +nzd_writable(dns_view_t *view); + static isc_result_t nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); @@ -11239,6 +11242,37 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, return (result); } +static isc_result_t +nzd_writable(dns_view_t *view) { + isc_result_t result = ISC_R_SUCCESS; + int status; + MDB_dbi dbi; + MDB_txn *txn = NULL; + + REQUIRE(view != NULL); + + status = mdb_txn_begin((MDB_env *) view->new_zone_dbenv, 0, 0, &txn); + if (status != 0) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_WARNING, "mdb_txn_begin: %s", + mdb_strerror(status)); + return (ISC_R_FAILURE); + } + + status = mdb_dbi_open(txn, NULL, 0, &dbi); + if (status != 0) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_WARNING, "mdb_dbi_open: %s", + mdb_strerror(status)); + result = ISC_R_FAILURE; + } + + mdb_txn_abort(txn); + return (result); +} + static isc_result_t nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { int status; @@ -11711,7 +11745,7 @@ do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, fp = NULL; #else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ - result = nzd_open(view, 0, &txn, &dbi); + result = nzd_writable(view); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open NZD database for '")); TCHECK(putstr(text, view->new_zone_db)); @@ -11802,12 +11836,13 @@ do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, /* Flag the zone as having been added at runtime */ dns_zone_setadded(zone, ISC_TRUE); -#ifndef HAVE_LMDB +#ifdef HAVE_LMDB + /* Save the new zone configuration into the NZD */ + CHECK(nzd_open(view, 0, &txn, &dbi)); + CHECK(nzd_save(&txn, dbi, zone, zoneobj)); +#else /* Append the zone configuration to the NZF */ result = nzf_append(view, zoneobj); -#else /* HAVE_LMDB */ - /* Save the new zone configuration into the NZD */ - result = nzd_save(&txn, dbi, zone, zoneobj); #endif /* HAVE_LMDB */ cleanup: @@ -11884,7 +11919,7 @@ do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, fp = NULL; #else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ - result = nzd_open(view, 0, &txn, &dbi); + result = nzd_writable(view); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open NZD database for '")); TCHECK(putstr(text, view->new_zone_db)); @@ -12001,15 +12036,16 @@ do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #endif /* HAVE_LMDB */ if (added) { -#ifndef HAVE_LMDB +#ifdef HAVE_LMDB + CHECK(nzd_open(view, 0, &txn, &dbi)); + CHECK(nzd_save(&txn, dbi, zone, zoneobj)); +#else result = nzf_append(view, zoneobj); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "\nNew zone config not saved: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } -#else /* HAVE_LMDB */ - nzd_save(&txn, dbi, zone, zoneobj); #endif /* HAVE_LMDB */ TCHECK(putstr(text, "zone '"));