]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
gc: don't re-open cache so often
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 24 Feb 2020 17:32:26 +0000 (18:32 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 28 Feb 2020 14:58:53 +0000 (15:58 +0100)
Re-opening the cache causes fsync - every interval (1s by default).
Normally that isn't noticeable, but on encrypted ZFS it causes
high CPU consumption (even when "idle").

grahamc first reported this and Mic92 tested the patch helps. Thanks!
https://gitter.im/CZ-NIC/knot-resolver?at=5e4ea2343ca8a67fb808e349

NEWS
utils/cache_gc/kr_cache_gc.c
utils/cache_gc/main.c

diff --git a/NEWS b/NEWS
index 6442664093bb0c66dc05cc9617155146f242fa00..10a89f3930c519170b633a8470c1024ae0be90be 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Knot Resolver 5.x.y (2020-0m-0d)
+================================
+
+Improvements
+------------
+- cache garbage collector: reduce filesystem operations when idle (!946)
+
+
 Knot Resolver 5.0.1 (2020-02-05)
 ================================
 
index 3c750c1f641d9666cc1d54fe021c9bfd144a4044..5913d29b0d6b2bcce82c3c69bc015c1e01fbd448 100644 (file)
@@ -144,12 +144,24 @@ int cb_delete_categories(const knot_db_val_t * key, gc_record_info_t * info,
 
 int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
 {
-       struct kr_cache kres_db = { 0 };
-       knot_db_t *db = NULL;
-
-       int ret = kr_gc_cache_open(cfg->cache_path, &kres_db, &db);
-       if (ret) {
-               return ret;
+       // statically open cache, its clean up and initialization
+       static bool is_open = false;
+       static struct kr_cache kres_db = { 0 };
+       static knot_db_t *db = NULL;
+       if (!cfg) {
+               if (is_open) {
+                       kr_gc_cache_close(&kres_db, db);
+                       is_open = false;
+               }
+               return 0;
+       }
+       if (!is_open) {
+               int ret = kr_gc_cache_open(cfg->cache_path, &kres_db, &db);
+               if (ret) {
+                       return ret;
+               } else {
+                       is_open = true;
+               }
        }
 
        const size_t db_size = knot_db_lmdb_get_mapsize(db);
@@ -170,7 +182,6 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
                       db_size);
        }
        if (cfg->dry_run || !large_usage) {
-               kr_gc_cache_close(&kres_db, db);
                return KNOT_EOK;
        }
 
@@ -180,9 +191,8 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
        gc_timer_start(&timer_analyze);
        ctx_compute_categories_t cats = { { 0 }
        };
-       ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
+       int ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
        if (ret != KNOT_EOK) {
-               kr_gc_cache_close(&kres_db, db);
                return ret;
        }
 
@@ -222,7 +232,6 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
        ret = kr_gc_cache_iter(db, cb_delete_categories, &to_del);
        if (ret != KNOT_EOK) {
                entry_dynarray_deep_free(&to_del.to_delete);
-               kr_gc_cache_close(&kres_db, db);
                return ret;
        }
        printf
@@ -243,7 +252,6 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
                printf("Error starting R/W DB transaction (%s).\n",
                       knot_strerror(ret));
                entry_dynarray_deep_free(&to_del.to_delete);
-               kr_gc_cache_close(&kres_db, db);
                return ret;
        }
 
@@ -302,7 +310,9 @@ finish:
        rrtype_dynarray_free(&deleted_rrtypes);
        entry_dynarray_deep_free(&to_del.to_delete);
 
+       // OK, let's close it in this case.
        kr_gc_cache_close(&kres_db, db);
+       is_open = false;
 
        return ret;
 }
index 6037a3f0662ad1c5a5285889b49d773be9140ca9..5384562537136cef6a6a4c8feef1a9fd5b474aff 100644 (file)
@@ -116,16 +116,20 @@ int main(int argc, char *argv[])
                return 1;
        }
 
+       int exit_code = 0;
        do {
                int ret = kr_cache_gc(&cfg);
                // ENOENT: kresd may not be started yet or cleared the cache now
                if (ret && ret != -ENOENT) {
                        printf("Error (%s)\n", knot_strerror(ret));
-                       return 10;
+                       exit_code = 10;
+                       break;
                }
 
                usleep(cfg.gc_interval);
        } while (cfg.gc_interval > 0 && !killed);
+       // clean up any state
+       kr_cache_gc(NULL);
 
-       return 0;
+       return exit_code;
 }