]> 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)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Wed, 12 Jul 2017 05:36:15 +0000 (08:36 +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 55904b5c228ed195a1363641637942bceb99e4ce..43b9c97c429d652865028f7fd0038093b71c0c51 100644 (file)
@@ -1185,3 +1185,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 9218e1ac65515853bfc16d8f2a8f11cafbd259e7..17240bd1b72b37ebdfc3064ce5c8b59b23aa93fb 100644 (file)
@@ -81,6 +81,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);