]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/mmapped: fix persistence, expand comments docs-cache-kru-8qejro/deployments/7118
authorLukáš Ondráček <lukas.ondracek@nic.cz>
Wed, 2 Jul 2025 18:56:15 +0000 (20:56 +0200)
committerLukáš Ondráček <lukas.ondracek@nic.cz>
Wed, 2 Jul 2025 19:02:28 +0000 (21:02 +0200)
lib/mmapped.c
lib/mmapped.h

index dfcad9257512e3d704d3d3a0116a7b04542ef95d..9be98ff27e66d4717902678daee94ac6c87d4651 100644 (file)
@@ -58,7 +58,7 @@ int mmapped_init_reset(struct mmapped *mmapped, const char *mmap_file, size_t si
 
        kr_assert(size >= header_size);
 
-       if (ftruncate(mmapped->fd, 0) == -1 || ftruncate(mmapped->fd, size) == -1) {  // get all zeroed
+       if ((ftruncate(mmapped->fd, 0) == -1) || (ftruncate(mmapped->fd, size) == -1)) {  // get all zeroed
                int ret = kr_error(errno);
                kr_log_crit(SYSTEM, "Cannot change size of file %s containing shared data: %s\n",
                                mmap_file, strerror(errno));
@@ -85,6 +85,7 @@ int mmapped_init(struct mmapped *mmapped, const char *mmap_file, size_t size, vo
                                mmap_file, strerror(errno));
                return fail(mmapped, ret);
        }
+       mmapped->persistent = persistent;
 
        // try to acquire write lock; wait for shared lock otherwise
        if (fcntl_flock_whole(mmapped->fd, F_WRLCK, false)) {
@@ -110,9 +111,7 @@ int mmapped_init(struct mmapped *mmapped, const char *mmap_file, size_t size, vo
 
        // mmap
        mmapped->mem = mmap(NULL, mmapped->size, PROT_READ | PROT_WRITE, MAP_SHARED, mmapped->fd, 0);
-       if (mmapped->mem == MAP_FAILED) {
-               return fail(mmapped, 0);
-       }
+       if (mmapped->mem == MAP_FAILED) return fail(mmapped, 0);
 
        // check header
        if (memcmp(mmapped->mem, header, header_size) != 0) {
index 3609856a3b5438b7741ad7fb775125be24954cd8..39f40f63bc6a90f0f1c0c1b7b99443553de9d1fd 100644 (file)
@@ -29,9 +29,11 @@ struct mmapped {
  * calls mmap, verifies that header is byte-wise identical
  * and returns MMAPPED_EXISTING, possibly ORed with MMAPPED_PENDING based on the lock type.
  *
- * On header mismatch, either the outcome is the same as in the first case (if write flock was acquired),
+ * On header or size mismatch, either the outcome is the same as in the first case (if write flock was acquired),
  * or kr_error(ENOTRECOVERABLE) is returned;
- * on a system error, kr_error(errno) is returned. */
+ * on a system error, kr_error(errno) is returned.
+ *
+ * If size is set to zero, only using existing data is allowed. */
 KR_EXPORT
 int mmapped_init(struct mmapped *mmapped, const char *mmap_file, size_t size, void *header, size_t header_size, bool persistent);
 
@@ -50,41 +52,74 @@ int mmapped_init_reset(struct mmapped *mmapped, const char *mmap_file, size_t si
 KR_EXPORT
 int mmapped_init_finish(struct mmapped *mmapped);
 
-/* Free mmapped memory and, unless the underlying file is used by other processes, truncate it to zero size. */
+/* Free mmapped memory and,
+ * unless the underlying file is used by other processes or persistence is requested, truncate it to zero size. */
 KR_EXPORT
 void mmapped_deinit(struct mmapped *mmapped);
 
 
+/* Detailed description of init return states:
+       mmapped_init:
+               PENDING:  (size > 0 only)
+                       new memory initialized, header copied there; first process with exclusive lock
+                       finish initialization and call _init_finish
+               EXISTING | PENDING:  (persistent case only)
+                       using existing data with equal header; first process with exclusive lock
+                       possibly perform other checks / modifications and call _init_finish
+                               or call _init_reset
+               EXISTING:
+                       using existing data with equal header; shared lock
+                       success; no further action required (but _init_finish possible)
+               kr_error(ENOTRECOVERABLE):
+                       file header is not valid and
+                               exclusive lock cannot be acquired or
+                               reset is not allowed (size == 0)
+               system error (<0)
+       mmapped_init_reset:
+               PENDING:
+                       new memory initialized, header copied; still exclusive lock
+               kr_error(ENOTRECOVERABLE):
+                       exclusive lock not acquired or
+                       reset is not allowed (size == 0)
+               system error (<0)
+       mmapped_init_finish:
+               0:
+                       lock degraded to shared (or was already)
+                       success; no further action required
+               system error (<0)
+*/
+
+
+/* Example usage, based on state flags returned by above functions:
 
-/* -- example usage, persistent case --
-       mmapped_init
-       if (>=0 && EXISTING) {
-               if (!valid) {
-                       mmapped_init_reset
+       persistent case:
+               mmapped_init
+               if (>=0 && EXISTING) {
+                       if (!valid) {
+                               mmapped_init_reset   // -> continue with init/fail below
+                       } else {
+                               mmapped_init_finish  // required only if PENDING
+                       }
                }
-               mmapped_init_finish
-       }
-       if (>=0 && !EXISTING && PENDING) {  //  == PENDING
-               // init
-               mmapped_init_finish
-       }
-       if (>=0 && !EXISTING && !PENDING) { //  == 0
+               if (>=0 && !EXISTING && PENDING) {  //  == PENDING
+                       ... // init
+                       mmapped_init_finish
+               }
+               if (<0) fail + return
+               assert(==0) // if both _finish above were used
                // done
-       }
-*/
 
-/* -- example usage, non-persistent case --
-       mmapped_init
-       if (>=0 && EXISTING) {              //  == EXISTING
-               if (!valid) {
-                       // fail
+       non-persistent case:
+               mmapped_init
+               if (>=0 && EXISTING) {              //  == EXISTING
+                       if (!valid) fail + return
+                       mmapped_init_finish  // not required
+               } else if (>=0 && PENDING) {        //  == PENDING
+                       ... // init
+                       mmapped_init_finish
                }
-               mmapped_init_finish  // not needed
-       } else if (>=0 && PENDING) {        //  == PENDING
-               // init
-               mmapped_init_finish
-       }
-       if (<0) fail
-       // done
+               if (<0) fail + return
+               assert(==0) // no other outcome if both _finish above were used
+               // done
 */