]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_11] Fix LMDB support on OpenBSD; clean up and refactor LMDB-related code
authorMichał Kępień <michal@isc.org>
Thu, 30 Nov 2017 12:54:30 +0000 (13:54 +0100)
committerMichał Kępień <michal@isc.org>
Thu, 30 Nov 2017 13:34:43 +0000 (14:34 +0100)
4835.   [cleanup]       Clean up and refactor LMDB-related code. [RT #46718]

4834.   [port]          Fix LMDB support on OpenBSD. [RT #46718]

(cherry picked from commit 2c20fc0d135e3d3fb6b468e4807caa18ff8974f0)

CHANGES
bin/named/server.c
bin/tools/named-nzd2nzf.c
lib/dns/include/dns/view.h
lib/dns/view.c

diff --git a/CHANGES b/CHANGES
index cd99ac1cb71d52f5b7c8542af2e855713918d27d..83564be2f5dcd7455530de1ca9b5e23e8eef6196 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4835.  [cleanup]       Clean up and refactor LMDB-related code. [RT #46718]
+
+4834.  [port]          Fix LMDB support on OpenBSD. [RT #46718]
+
 4833.  [bug]           isc_event_free should check that the event is not
                        linked when called. [RT #46725]
 
index 9098084e845914a5b2add185855adf7d20d2750a..f2936713a5d75a8bc6b282aa24bd61b60fce5c3f 100644 (file)
@@ -6904,115 +6904,160 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data,
        return (result);
 }
 
+/*%
+ * Prototype for a callback which can be used with for_all_newzone_cfgs().
+ */
+typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig,
+                                        cfg_obj_t *config, cfg_obj_t *vconfig,
+                                        isc_mem_t *mctx, dns_view_t *view,
+                                        cfg_aclconfctx_t *actx);
+
+/*%
+ * For each zone found in a NZD opened by the caller, create an object
+ * representing its configuration and invoke "callback" with the created
+ * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all
+ * these are non-global variables required to invoke configure_zone()).
+ * Immediately interrupt processing if an error is encountered while
+ * transforming NZD data into a zone configuration object or if "callback"
+ * returns an error.
+ */
 static isc_result_t
-configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
-                  isc_mem_t *mctx, cfg_aclconfctx_t *actx)
+for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config,
+                    cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+                    cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi)
 {
+       const cfg_obj_t *zconfig, *zlist = NULL;
        isc_result_t result = ISC_R_SUCCESS;
-       int status;
+       cfg_obj_t *zconfigobj = NULL;
        isc_buffer_t *text = NULL;
-       cfg_obj_t *zoneconf = NULL;
        MDB_cursor *cursor = NULL;
-       MDB_txn *txn = NULL;
-       MDB_dbi dbi;
-       MDB_val key, data;
-
-       if (view->new_zone_config == NULL) {
-               return (ISC_R_SUCCESS);
-       }
-
-       result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
-       if (result != ISC_R_SUCCESS) {
-               return (ISC_R_SUCCESS);
-       }
-
-       isc_log_write(ns_g_lctx,
-                     NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
-                     ISC_LOG_INFO, "loading NZD configs from '%s' "
-                     "for view '%s'",
-                     view->new_zone_db, view->name);
+       MDB_val data, key;
+       int status;
 
        status = mdb_cursor_open(txn, dbi, &cursor);
-       if (status != 0) {
-               result = ISC_R_FAILURE;
-               goto cleanup;
+       if (status != MDB_SUCCESS) {
+               return (ISC_R_FAILURE);
        }
 
-       while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
-               const cfg_obj_t *zlist = NULL;
-               const cfg_obj_t *zoneobj = NULL;
-
-               result = data_to_cfg(view, &key, &data, &text, &zoneconf);
+       for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+            status == MDB_SUCCESS;
+            status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))
+       {
+               /*
+                * Create a configuration object from data fetched from NZD.
+                */
+               result = data_to_cfg(view, &key, &data, &text, &zconfigobj);
                if (result != ISC_R_SUCCESS) {
-                       goto cleanup;
+                       break;
                }
 
-               CHECK(cfg_map_get(zoneconf, "zone", &zlist));
-               if (!cfg_obj_islist(zlist)) {
-                       CHECK(ISC_R_FAILURE);
+               /*
+                * Extract zone configuration from configuration object.
+                */
+               result = cfg_map_get(zconfigobj, "zone", &zlist);
+               if (result != ISC_R_SUCCESS) {
+                       break;
+               } else if (!cfg_obj_islist(zlist)) {
+                       result = ISC_R_FAILURE;
+                       break;
                }
+               zconfig = cfg_listelt_value(cfg_list_first(zlist));
 
-               zoneobj = cfg_listelt_value(cfg_list_first(zlist));
-               CHECK(configure_zone(config, zoneobj, vconfig, mctx,
-                                    view, &ns_g_server->viewlist, actx,
-                                    ISC_TRUE, ISC_FALSE, ISC_FALSE));
+               /*
+                * Invoke callback.
+                */
+               result = callback(zconfig, config, vconfig, mctx, view, actx);
+               if (result != ISC_R_SUCCESS) {
+                       break;
+               }
 
-               cfg_obj_destroy(ns_g_addparser, &zoneconf);
+               /*
+                * Destroy the configuration object created in this iteration.
+                */
+               cfg_obj_destroy(ns_g_addparser, &zconfigobj);
        }
 
-       result = ISC_R_SUCCESS;
-
- cleanup:
-       if (zoneconf != NULL) {
-               cfg_obj_destroy(ns_g_addparser, &zoneconf);
+       if (text != NULL) {
+               isc_buffer_free(&text);
        }
-       if (cursor != NULL) {
-               mdb_cursor_close(cursor);
-               cursor = NULL;
+       if (zconfigobj != NULL) {
+               cfg_obj_destroy(ns_g_addparser, &zconfigobj);
        }
+       mdb_cursor_close(cursor);
 
-       if (result != ISC_R_SUCCESS) {
-               status = mdb_cursor_open(txn, dbi, &cursor);
-               if (status != 0) {
-                       goto cleanup2;
-               }
-               while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
-                       const cfg_obj_t *zlist = NULL;
-                       const cfg_obj_t *zconfig = NULL;
-                       isc_result_t result2;
+       return (result);
+}
 
-                       result2 = data_to_cfg(view, &key, &data, &text,
-                                             &zoneconf);
-                       if (result2 != ISC_R_SUCCESS) {
-                               goto cleanup2;
-                       }
+/*%
+ * Attempt to configure a zone found in NZD and return the result.
+ */
+static isc_result_t
+configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config,
+                 cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+                 cfg_aclconfctx_t *actx)
+{
+       return (configure_zone(config, zconfig, vconfig, mctx, view,
+                              &ns_g_server->viewlist, actx, ISC_TRUE,
+                              ISC_FALSE, ISC_FALSE));
+}
 
-                       result2 = cfg_map_get(zoneconf, "zone", &zlist);
-                       if (result2 != ISC_R_SUCCESS) {
-                               goto cleanup2;
-                       }
+/*%
+ * Revert new view assignment for a zone found in NZD.
+ */
+static isc_result_t
+configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config,
+                        cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+                        cfg_aclconfctx_t *actx)
+{
+       UNUSED(config);
+       UNUSED(vconfig);
+       UNUSED(mctx);
+       UNUSED(actx);
 
-                       if (!cfg_obj_islist(zlist)) {
-                               goto cleanup2;
-                       }
+       configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view);
 
-                       zconfig = cfg_listelt_value(cfg_list_first(zlist));
-                       configure_zone_setviewcommit(result, zconfig, view);
+       return (ISC_R_SUCCESS);
+}
 
-                       cfg_obj_destroy(ns_g_addparser, &zoneconf);
-               }
-       }
+static isc_result_t
+configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
+                  isc_mem_t *mctx, cfg_aclconfctx_t *actx)
+{
+       isc_result_t result;
+       MDB_txn *txn = NULL;
+       MDB_dbi dbi;
 
- cleanup2:
-       if (text != NULL) {
-               isc_buffer_free(&text);
+       if (view->new_zone_config == NULL) {
+               return (ISC_R_SUCCESS);
        }
-       if (zoneconf != NULL) {
-               cfg_obj_destroy(ns_g_addparser, &zoneconf);
+
+       result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
+       if (result != ISC_R_SUCCESS) {
+               return (ISC_R_SUCCESS);
        }
-       if (cursor != NULL) {
-               mdb_cursor_close(cursor);
+
+       isc_log_write(ns_g_lctx,
+                     NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+                     ISC_LOG_INFO, "loading NZD configs from '%s' "
+                     "for view '%s'",
+                     view->new_zone_db, view->name);
+
+       result = for_all_newzone_cfgs(configure_newzone, config, vconfig, mctx,
+                                     view, actx, txn, dbi);
+       if (result != ISC_R_SUCCESS) {
+               /*
+                * An error was encountered while attempting to configure zones
+                * found in NZD.  As this error may have been caused by a
+                * configure_zone() failure, try restoring a sane configuration
+                * by reattaching all zones found in NZD to the old view.  If
+                * this also fails, too bad, there is nothing more we can do in
+                * terms of trying to make things right.
+                */
+               (void) for_all_newzone_cfgs(configure_newzone_revert, config,
+                                           vconfig, mctx, view, actx, txn,
+                                           dbi);
        }
+
        (void) nzd_close(&txn, ISC_FALSE);
        return (result);
 }
@@ -7056,8 +7101,9 @@ get_newzone_config(dns_view_t *view, const char *zonename,
        key.mv_size = strlen(zname);
 
        status = mdb_get(txn, dbi, &key, &data);
-       if (status != 0)
+       if (status != MDB_SUCCESS) {
                CHECK(ISC_R_FAILURE);
+       }
 
        CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf));
 
@@ -7068,10 +7114,12 @@ get_newzone_config(dns_view_t *view, const char *zonename,
  cleanup:
        (void) nzd_close(&txn, ISC_FALSE);
 
-       if (zoneconf != NULL)
+       if (zoneconf != NULL) {
                cfg_obj_destroy(ns_g_addparser, &zoneconf);
-       if (text != NULL)
+       }
+       if (text != NULL) {
                isc_buffer_free(&text);
+       }
 
        return (result);
 }
@@ -11254,7 +11302,7 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
        if (zconfig == NULL) {
                /* We're deleting the zone from the database */
                status = mdb_del(*txnp, dbi, &key, NULL);
-               if (status != 0 && status != MDB_NOTFOUND) {
+               if (status != MDB_SUCCESS && status != MDB_NOTFOUND) {
                        isc_log_write(ns_g_lctx,
                                      NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER,
@@ -11264,8 +11312,9 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
                                      namebuf, mdb_strerror(status));
                        result = ISC_R_FAILURE;
                        goto cleanup;
-               } else if (status != MDB_NOTFOUND)
+               } else if (status != MDB_NOTFOUND) {
                        commit = ISC_TRUE;
+               }
        } else {
                /* We're creating or overwriting the zone */
                const cfg_obj_t *zoptions;
@@ -11300,7 +11349,7 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
                data.mv_size = isc_buffer_usedlength(text);
 
                status = mdb_put(*txnp, dbi, &key, &data, 0);
-               if (status != 0) {
+               if (status != MDB_SUCCESS) {
                        isc_log_write(ns_g_lctx,
                                      NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER,
@@ -11318,11 +11367,11 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
        result = ISC_R_SUCCESS;
 
  cleanup:
-       if (!commit || result != ISC_R_SUCCESS)
+       if (!commit || result != ISC_R_SUCCESS) {
                (void) mdb_txn_abort(*txnp);
-       else {
+       else {
                status = mdb_txn_commit(*txnp);
-               if (status != 0) {
+               if (status != MDB_SUCCESS) {
                        isc_log_write(ns_g_lctx,
                                      NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER,
@@ -11337,8 +11386,10 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
 
        UNLOCK(&view->new_zone_lock);
 
-       if (text != NULL)
+       if (text != NULL) {
                isc_buffer_free(&text);
+       }
+
        return (result);
 }
 
@@ -11352,7 +11403,7 @@ nzd_writable(dns_view_t *view) {
        REQUIRE(view != NULL);
 
        status = mdb_txn_begin((MDB_env *) view->new_zone_dbenv, 0, 0, &txn);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(ns_g_lctx,
                              NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
                              ISC_LOG_WARNING, "mdb_txn_begin: %s",
@@ -11361,7 +11412,7 @@ nzd_writable(dns_view_t *view) {
        }
 
        status = mdb_dbi_open(txn, NULL, 0, &dbi);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(ns_g_lctx,
                      NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
                              ISC_LOG_WARNING, "mdb_dbi_open: %s",
@@ -11384,7 +11435,7 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
 
        status = mdb_txn_begin((MDB_env *) view->new_zone_dbenv, 0,
                               flags, &txn);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(ns_g_lctx,
                              NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
                              ISC_LOG_WARNING, "mdb_txn_begin: %s",
@@ -11393,7 +11444,7 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
        }
 
        status = mdb_dbi_open(txn, NULL, 0, dbi);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(ns_g_lctx,
                      NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
                              ISC_LOG_WARNING, "mdb_dbi_open: %s",
@@ -11404,9 +11455,10 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
        *txnp = txn;
 
  cleanup:
-       if (status != 0) {
-               if (txn != NULL)
+       if (status != MDB_SUCCESS) {
+               if (txn != NULL) {
                        mdb_txn_abort(txn);
+               }
                return (ISC_R_FAILURE);
        }
 
@@ -11420,38 +11472,34 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
  */
 static void
 nzd_env_close(dns_view_t *view) {
-       if (view->new_zone_dbenv != NULL) {
-               const char *dbpath = NULL;
-               isc_boolean_t have_dbpath = ISC_FALSE;
-               char dbpath_copy[PATH_MAX];
-               char lockpath[PATH_MAX];
-               int ret;
+       const char *dbpath = NULL;
+       char dbpath_copy[PATH_MAX];
+       char lockpath[PATH_MAX];
+       int status, ret;
 
-               if (mdb_env_get_path(view->new_zone_dbenv, &dbpath) == 0) {
-                       have_dbpath = ISC_TRUE;
-                       snprintf(lockpath, sizeof(lockpath), "%s-lock",
-                                dbpath);
-                       strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy));
-               }
+       if (view->new_zone_dbenv == NULL) {
+               return;
+       }
 
-               mdb_env_close((MDB_env *) view->new_zone_dbenv);
-               view->new_zone_dbenv = NULL;
+       status = mdb_env_get_path(view->new_zone_dbenv, &dbpath);
+       INSIST(status == MDB_SUCCESS);
+       snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath);
+       strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy));
+       mdb_env_close((MDB_env *) view->new_zone_dbenv);
 
-               if (have_dbpath) {
-                       /*
-                        * Database files must be owned by the eventual user, not
-                        * by root.
-                        */
-                       ret = chown(dbpath_copy, ns_os_uid(), -1);
-                       UNUSED(ret);
+       /*
+        * Database files must be owned by the eventual user, not by root.
+        */
+       ret = chown(dbpath_copy, ns_os_uid(), -1);
+       UNUSED(ret);
 
-                       /*
-                        * Some platforms need the lockfile not to exist when we
-                        * reopen the environment.
-                        */
-                       (void) isc_file_remove(lockpath);
-               }
-       }
+       /*
+        * Some platforms need the lockfile not to exist when we reopen the
+        * environment.
+        */
+       (void) isc_file_remove(lockpath);
+
+       view->new_zone_dbenv = NULL;
 }
 
 static isc_result_t
@@ -11467,7 +11515,7 @@ nzd_env_reopen(dns_view_t *view) {
        nzd_env_close(view);
 
        status = mdb_env_create(&env);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                              "mdb_env_create failed: %s",
@@ -11477,7 +11525,7 @@ nzd_env_reopen(dns_view_t *view) {
 
        if (view->new_zone_mapsize != 0ULL) {
                status = mdb_env_set_mapsize(env, view->new_zone_mapsize);
-               if (status != 0) {
+               if (status != MDB_SUCCESS) {
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                                      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                                      "mdb_env_set_mapsize failed: %s",
@@ -11486,14 +11534,8 @@ nzd_env_reopen(dns_view_t *view) {
                }
        }
 
-       /*
-        * MDB_NOTLS is used to prevent problems after configuration is
-        * reloaded, due to the way LMDB's use of thread-local storage (TLS)
-        * interacts with the BIND9 thread model.
-        */
-       status = mdb_env_open(env, view->new_zone_db,
-                             MDB_NOSUBDIR|MDB_NOTLS|MDB_CREATE, 0600);
-       if (status != 0) {
+       status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
+       if (status != MDB_SUCCESS) {
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                              "mdb_env_open of '%s' failed: %s",
@@ -11522,10 +11564,12 @@ nzd_close(MDB_txn **txnp, isc_boolean_t commit) {
        if (*txnp != NULL) {
                if (commit) {
                        status = mdb_txn_commit(*txnp);
-                       if (status != 0)
+                       if (status != MDB_SUCCESS) {
                                result = ISC_R_FAILURE;
-               } else
+                       }
+               } else {
                        mdb_txn_abort(*txnp);
+               }
                *txnp = NULL;
        }
 
@@ -11543,11 +11587,12 @@ nzd_count(dns_view_t *view, int *countp) {
        REQUIRE(countp != NULL);
 
        result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto cleanup;
+       }
 
        status = mdb_stat(txn, dbi, &statbuf);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(ns_g_lctx,
                              NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
                              ISC_LOG_WARNING, "mdb_stat: %s",
@@ -11620,8 +11665,9 @@ migrate_nzf(dns_view_t *view) {
 
        zonelist = NULL;
        CHECK(cfg_map_get(nzf_config, "zone", &zonelist));
-       if (!cfg_obj_islist(zonelist))
+       if (!cfg_obj_islist(zonelist)) {
                CHECK(ISC_R_FAILURE);
+       }
 
        CHECK(nzd_open(view, 0, &txn, &dbi));
 
@@ -11672,7 +11718,7 @@ migrate_nzf(dns_view_t *view) {
                data.mv_size = isc_buffer_usedlength(text);
 
                status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
-               if (status != 0) {
+               if (status != MDB_SUCCESS) {
                        isc_log_write(ns_g_lctx,
                                      NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER,
@@ -11701,15 +11747,19 @@ migrate_nzf(dns_view_t *view) {
        }
 
  cleanup:
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                (void) nzd_close(&txn, ISC_FALSE);
-       else
+       } else {
                result = nzd_close(&txn, commit);
+       }
 
-       if (text != NULL)
+       if (text != NULL) {
                isc_buffer_free(&text);
-       if (nzf_config != NULL)
+       }
+
+       if (nzf_config != NULL) {
                cfg_obj_destroy(ns_g_addparser, &nzf_config);
+       }
 
        return (result);
 }
index 1c5406e07bba2002fda95696752cfaf6d8c471c7..0c24b49defb666ac7202ea43a2d07982e4a973d3 100644 (file)
@@ -16,6 +16,8 @@
 #include <stdlib.h>
 #include <lmdb.h>
 
+#include <dns/view.h>
+
 #include <isc/print.h>
 
 int
@@ -36,42 +38,44 @@ main (int argc, char *argv[]) {
        path = argv[1];
 
        status = mdb_env_create(&env);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                fprintf(stderr, "named-nzd2nzf: mdb_env_create: %s",
                        mdb_strerror(status));
                exit(1);
        }
 
-       status = mdb_env_open(env, path,
-                             MDB_RDONLY|MDB_NOTLS|MDB_NOSUBDIR, 0600);
-       if (status != 0) {
+       status = mdb_env_open(env, path, DNS_LMDB_FLAGS, 0600);
+       if (status != MDB_SUCCESS) {
                fprintf(stderr, "named-nzd2nzf: mdb_env_open: %s",
                        mdb_strerror(status));
                exit(1);
        }
 
        status = mdb_txn_begin(env, 0, MDB_RDONLY, &txn);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                fprintf(stderr, "named-nzd2nzf: mdb_txn_begin: %s",
                        mdb_strerror(status));
                exit(1);
        }
 
        status = mdb_dbi_open(txn, NULL, 0, &dbi);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                fprintf(stderr, "named-nzd2nzf: mdb_dbi_open: %s",
                        mdb_strerror(status));
                exit(1);
        }
 
        status = mdb_cursor_open(txn, dbi, &cursor);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                fprintf(stderr, "named-nzd2nzf: mdb_cursor_open: %s",
                        mdb_strerror(status));
                exit(1);
        }
 
-       while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
+       for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+            status == MDB_SUCCESS;
+            status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))
+       {
                if (key.mv_data == NULL || key.mv_size == 0 ||
                    data.mv_data == NULL || data.mv_size == 0)
                {
index 3d056edb4ef523cb331a9e15f5cad848b55436e1..8f8a824023395e5ac7c0052ae6035352fca85024 100644 (file)
@@ -232,6 +232,25 @@ struct dns_view {
 #define DNS_VIEWATTR_ADBSHUTDOWN       0x02
 #define DNS_VIEWATTR_REQSHUTDOWN       0x04
 
+#ifdef HAVE_LMDB
+#include <lmdb.h>
+/*
+ * MDB_NOTLS is used to prevent problems after configuration is reloaded, due
+ * to the way LMDB's use of thread-local storage (TLS) interacts with the BIND9
+ * thread model.
+ */
+#define DNS_LMDB_COMMON_FLAGS          (MDB_CREATE | MDB_NOSUBDIR | MDB_NOTLS)
+#ifndef __OpenBSD__
+#define DNS_LMDB_FLAGS                 (DNS_LMDB_COMMON_FLAGS)
+#else /* __OpenBSD__ */
+/*
+ * OpenBSD does not have a unified buffer cache, which requires both reads and
+ * writes to be performed using mmap().
+ */
+#define DNS_LMDB_FLAGS                 (DNS_LMDB_COMMON_FLAGS | MDB_WRITEMAP)
+#endif /* __OpenBSD__ */
+#endif /* HAVE_LMDB */
+
 isc_result_t
 dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
                const char *name, dns_view_t **viewp);
index 2558a6d431a6cb86c4b9ab5aeb7d265a35bee607..d9e9736362f491284cf433de470688fafb8adaf9 100644 (file)
@@ -514,8 +514,10 @@ destroy(dns_view_t *view) {
                view->new_zone_file = NULL;
        }
 #ifdef HAVE_LMDB
-       if (view->new_zone_dbenv != NULL)
+       if (view->new_zone_dbenv != NULL) {
                mdb_env_close((MDB_env *) view->new_zone_dbenv);
+               view->new_zone_dbenv = NULL;
+       }
        if (view->new_zone_db != NULL) {
                isc_mem_free(view->mctx, view->new_zone_db);
                view->new_zone_db = NULL;
@@ -2046,7 +2048,7 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
        }
 
        status = mdb_env_create(&env);
-       if (status != 0) {
+       if (status != MDB_SUCCESS) {
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                              "mdb_env_create failed: %s",
@@ -2056,24 +2058,18 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
 
        if (mapsize != 0ULL) {
                status = mdb_env_set_mapsize(env, mapsize);
-               view->new_zone_mapsize = mapsize;
-               if (status != 0) {
+               if (status != MDB_SUCCESS) {
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                                      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                                      "mdb_env_set_mapsize failed: %s",
                                      mdb_strerror(status));
                        CHECK(ISC_R_FAILURE);
                }
+               view->new_zone_mapsize = mapsize;
        }
 
-       /*
-        * MDB_NOTLS is used to prevent problems after configuration is
-        * reloaded, due to the way LMDB's use of thread-local storage (TLS)
-        * interacts with the BIND9 thread model.
-        */
-       status = mdb_env_open(env, view->new_zone_db,
-                             MDB_NOSUBDIR|MDB_NOTLS|MDB_CREATE, 0600);
-       if (status != 0) {
+       status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
+       if (status != MDB_SUCCESS) {
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
                              "mdb_env_open of '%s' failed: %s",
@@ -2100,8 +2096,9 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
                        isc_mem_free(view->mctx, view->new_zone_db);
                        view->new_zone_db = NULL;
                }
-               if (env != NULL)
+               if (env != NULL) {
                        mdb_env_close(env);
+               }
 #endif /* HAVE_LMDB */
                view->new_zone_config = NULL;
                view->cfg_destroy = NULL;