]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
sdbox: Create missing mail directory on resync if index directory exists
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 11 Jul 2017 11:14:47 +0000 (14:14 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 12 Jul 2017 21:45:23 +0000 (00:45 +0300)
This problem should be visible only with ITERINDEX enabled.

src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/index-storage.h

index 6df07c2ba134108e69d87f986a76041e0c1f0726..eb6281e65f1403be8373c336d3bdce57fc78cc57 100644 (file)
@@ -107,8 +107,7 @@ static int sdbox_sync_index_rebuild_dir(struct index_rebuild_context *ctx,
                                /* alt directory doesn't exist, ignore */
                                return 0;
                        }
-                       mailbox_set_deleted(ctx->box);
-                       return -1;
+                       return index_mailbox_fix_inconsistent_existence(ctx->box, path);
                }
                mail_storage_set_critical(storage,
                        "opendir(%s) failed: %m", path);
index 7735516c40c28469402ce42580a24808e6b5b87b..6b0482f76dd003a837add1633c8ef1945a189a08 100644 (file)
@@ -1134,3 +1134,35 @@ void index_storage_save_abort_last(struct mail_save_context *ctx, uint32_t seq)
           specific record, so we'll reset the whole cache transaction. */
        mail_cache_transaction_reset(ctx->transaction->cache_trans);
 }
+
+int index_mailbox_fix_inconsistent_existence(struct mailbox *box,
+                                            const char *path)
+{
+       const char *index_path;
+       struct stat st;
+
+       /* Could be a race condition or could be because ITERINDEX is used
+          and the index directory exists, but the storage directory doesn't.
+          Handle the existence inconsistency by creating this directory if
+          the index directory exists (don't bother checking if ITERINDEX is
+          set or not - it doesn't matter since either both dirs should exist
+          or not). */
+       if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
+                               &index_path) < 0)
+               return -1;
+
+       if (strcmp(index_path, path) == 0) {
+               /* there's no separate index path - mailbox was just deleted */
+       } else if (stat(index_path, &st) == 0) {
+               /* inconsistency - create also the mail directory */
+               return mailbox_mkdir(box, path, MAILBOX_LIST_PATH_TYPE_MAILBOX);
+       } else if (errno == ENOENT) {
+               /* race condition - mailbox was just deleted */
+       } else {
+               mail_storage_set_critical(box->storage,
+                       "stat(%s) failed: %m", index_path);
+               return -1;
+       }
+       mailbox_set_deleted(box);
+       return -1;
+}
index f3d86fa5f18323316c71788a261e989718ff90c4..b245117b2fa9ee84821420113eb78b0fac5b8f9d 100644 (file)
@@ -82,6 +82,8 @@ int index_storage_mailbox_delete_dir(struct mailbox *box, bool mailbox_deleted);
 int index_storage_mailbox_rename(struct mailbox *src, struct mailbox *dest);
 
 int index_mailbox_update_last_temp_file_scan(struct mailbox *box);
+int index_mailbox_fix_inconsistent_existence(struct mailbox *box,
+                                            const char *path);
 
 bool index_storage_is_readonly(struct mailbox *box);
 bool index_storage_is_inconsistent(struct mailbox *box);