From: Vladimír Čunát Date: Wed, 19 Aug 2020 08:23:04 +0000 (+0200) Subject: lib/cache check_health(): also detect size changes X-Git-Tag: v5.1.3~1^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd845d5f7c3664db0089cd00e2130f16cf96378c;p=thirdparty%2Fknot-resolver.git lib/cache check_health(): also detect size changes This is important for GC - otherwise the usage computation would be wrong after another process changed size (without replacing the file). --- diff --git a/lib/cache/cdb_lmdb.c b/lib/cache/cdb_lmdb.c index 81708ee5c..c955b3bfb 100644 --- a/lib/cache/cdb_lmdb.c +++ b/lib/cache/cdb_lmdb.c @@ -48,6 +48,7 @@ struct lmdb_env /* Cached part of struct stat for data.mdb. */ dev_t st_dev; ino_t st_ino; + off_t st_size; const char *mdb_data_path; /**< path to data.mdb, for convenience */ }; @@ -309,6 +310,10 @@ static int cdb_open_env(struct lmdb_env *env, const char *path, size_t mapsize, } env->st_dev = st.st_dev; env->st_ino = st.st_ino; + env->st_size = st.st_size; + if (env->st_size != env->mapsize) + kr_log_verbose("[cache] suspicious size of cache file: %zu != %zu\n", + (size_t)env->st_size, env->mapsize); /* Open the database. */ MDB_txn *txn = NULL; @@ -436,7 +441,15 @@ static int cdb_check_health(knot_db_t *db, struct kr_cdb_stats *stats) // FIXME: if the file doesn't exist? } if (st.st_dev == env->st_dev && st.st_ino == env->st_ino) { - return kr_ok(); + if (st.st_size == env->st_size) + return kr_ok(); + kr_log_info("[cache] detected size change by another process: %zu -> %zu\n", + (size_t)env->st_size, (size_t)st.st_size); + int ret = cdb_commit(db, stats); + if (!ret) ret = lmdb_error(mdb_env_set_mapsize(env->env, st.st_size)); + if (!ret) env->mapsize = st.st_size; + env->st_size = st.st_size; // avoid retrying in cycle even if it failed + return kr_error(ret); } kr_log_verbose("[cache] cache file has been replaced, reopening\n"); int ret = reopen_env(env, stats); diff --git a/utils/cache_gc/db.h b/utils/cache_gc/db.h index 74d876359..44cfbec29 100644 --- a/utils/cache_gc/db.h +++ b/utils/cache_gc/db.h @@ -9,6 +9,8 @@ int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db, knot_db_t ** libknot_db); +/** A wrapper around kr_cdb_api::check_health that keeps libknot_db up to date. + * \return zero or negative error code. */ int kr_gc_cache_check_health(struct kr_cache *kres_db, knot_db_t ** libknot_db); void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t * knot_db); diff --git a/utils/cache_gc/main.c b/utils/cache_gc/main.c index a2c05489f..736ade321 100644 --- a/utils/cache_gc/main.c +++ b/utils/cache_gc/main.c @@ -8,6 +8,7 @@ #include "lib/defines.h" #include "lib/utils.h" #include +#include #include "kresconfig.h" #include "kr_cache_gc.h" @@ -148,7 +149,8 @@ int main(int argc, char *argv[]) } // ENOENT: kresd may not be started yet or cleared the cache now - if (ret && ret != KNOT_ENOENT) { + // MDB_MAP_RESIZED: GC bailed out but on next iteration it should be OK + if (ret && ret != KNOT_ENOENT && ret != kr_error(MDB_MAP_RESIZED)) { printf("Error (%s)\n", knot_strerror(ret)); exit_code = 10; break;