]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: mail_cache_*lock() - Handle syscall errors correctly
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 30 Mar 2020 12:13:56 +0000 (15:13 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 15 Apr 2020 09:41:42 +0000 (12:41 +0300)
If reading a cache file failed because of some temporary syscall error, it
was treated the same as if the cache was corrupted. This could have
caused compression to lose cached data.

src/lib-index/mail-cache.c

index c3cab5f6dc0a1072bae62b75d610eb746ecff8ff..25759488cd807f380b1e8fdc742e40aabbbf364f 100644 (file)
@@ -699,14 +699,21 @@ mail_cache_lock_full(struct mail_cache *cache, bool nonblock)
           index. */
        i_assert(!cache->index->mapping || cache->index->log_sync_locked);
 
-       if (!cache->opened)
-               (void)mail_cache_open_and_verify(cache);
-
-       if (MAIL_CACHE_IS_UNUSABLE(cache) ||
-           MAIL_INDEX_IS_IN_MEMORY(cache->index) ||
+       if (MAIL_INDEX_IS_IN_MEMORY(cache->index) ||
            cache->index->readonly)
                return 0;
 
+       /* Make sure at least some cache file is opened. Usually it's the
+          latest one, so delay until it's locked to check whether a newer
+          cache file exists. */
+       if ((ret = mail_cache_open_and_verify(cache)) < 0)
+               return -1;
+       if (ret == 0) {
+               /* Cache doesn't exist or it was just found to be corrupted and
+                  was unlinked. Cache compression will create it back. */
+               return 0;
+       }
+
        for (;;) {
                if (mail_cache_lock_file(cache, nonblock) <= 0)
                        return -1;
@@ -715,9 +722,9 @@ mail_cache_lock_full(struct mail_cache *cache, bool nonblock)
                        /* locked the latest file */
                        break;
                }
-               if (mail_cache_reopen(cache) <= 0) {
+               if ((ret = mail_cache_reopen(cache)) <= 0) {
                        i_assert(cache->file_lock == NULL);
-                       return -1;
+                       return ret;
                }
                i_assert(cache->file_lock == NULL);
                /* okay, so it was just compressed. try again. */