]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
cache: clear any stale readers when opening cache
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 28 Apr 2021 10:53:26 +0000 (12:53 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 28 Apr 2021 10:53:26 +0000 (12:53 +0200)
NEWS
lib/cache/cdb_lmdb.c

diff --git a/NEWS b/NEWS
index f5933b793dcf7cbbb79a7f85158fb110690505a1..813e6c89beabb30b893323b1ee309fc04163cb6b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Bugfixes
 - dnstap module: fix repeated configuration (!1168)
 - validator: fix SERVFAIL for some rare dynamic proofs (!1166)
 - fix SIGBUS on uncommon ARM machines (unaligned access; !1167, #426)
+- cache: better resilience on abnormal termination/restarts (!1172)
 
 
 Knot Resolver 5.3.1 (2021-03-31)
index 5f4db061c5aed36161b533e31db64b3834f2baae..706cd80e772ead35da4354a282f69cbc055b566d 100644 (file)
@@ -124,6 +124,18 @@ static int refresh_mapsize(struct lmdb_env *env)
        return kr_ok();
 }
 
+static void clear_stale_readers(struct lmdb_env *env)
+{
+       int cleared;
+       int ret = mdb_reader_check(env->env, &cleared);
+       if (ret != MDB_SUCCESS) {
+               kr_log_error("[cache] failed to clear stale reader locks: "
+                               "LMDB error %d %s\n", ret, mdb_strerror(ret));
+       } else if (cleared != 0) {
+               kr_log_info("[cache] cleared %d stale reader locks\n", cleared);
+       }
+}
+
 #define FLAG_RENEW (2*MDB_RDONLY)
 /** mdb_txn_begin or _renew + handle retries in some situations
  *
@@ -154,13 +166,7 @@ retry:
                if (ret == 0)
                        goto retry;
        } else if (unlikely(ret == MDB_READERS_FULL)) {
-               int cleared;
-               ret = mdb_reader_check(env->env, &cleared);
-               if (ret == MDB_SUCCESS)
-                       kr_log_info("[cache] cleared %d stale reader locks\n", cleared);
-               else
-                       kr_log_error("[cache] failed to clear stale reader locks: "
-                                       "LMDB error %d %s\n", ret, mdb_strerror(ret));
+               clear_stale_readers(env);
                goto retry;
        }
        return ret;
@@ -389,6 +395,11 @@ static int cdb_open_env(struct lmdb_env *env, const char *path, const size_t map
        ret = mdb_txn_commit(txn);
        if (ret != MDB_SUCCESS) goto error_mdb;
 
+       /* Stale RO transactions could have been left behind by a cashing process
+        * (e.g. one whose termination lead to spawning the current one).
+        * According to docs they might hold onto some space until we clear them. */
+       clear_stale_readers(env);
+
        return kr_ok();
 
 error_mdb: