]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storge: Call mail_storage.list_index_corrupted() when needed
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 24 Nov 2016 15:52:01 +0000 (17:52 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 25 Nov 2016 13:31:19 +0000 (15:31 +0200)
The callback is called whenever mailbox list index appears to be corrupted
with LAYOUT=index. The storage is responsible for adding to the index any
mailboxes that are missing.

src/lib-storage/list/mailbox-list-index-notify.c
src/lib-storage/list/mailbox-list-index-sync.c
src/lib-storage/list/mailbox-list-index.c
src/lib-storage/list/mailbox-list-index.h

index d19982142e6fe2de360c10a4999a5a195fc4f844..952d8f433f1d783971fb86d1046395d19e36e963 100644 (file)
@@ -778,6 +778,9 @@ int mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
 
        if (!inotify->initialized)
                mailbox_list_index_notify_read_init(inotify);
+       if (mailbox_list_index_handle_corruption(notify->list) < 0)
+               return -1;
+
        while (mailbox_list_index_notify_try_next(inotify)) {
                if ((inotify->notify_rec.events & inotify->notify.mask) != 0) {
                        *rec_r = &inotify->notify_rec;
index 411bdf9415c3023f09a526591d2e2c9fe0c6f301..5eedd4f2d7dae13090cc97c564e58e34a73ffb4f 100644 (file)
@@ -230,9 +230,11 @@ int mailbox_list_index_sync_begin(struct mailbox_list *list,
        struct mail_index_view *view;
        struct mail_index_transaction *trans;
        const struct mail_index_header *hdr;
+       bool fix_attempted = FALSE;
 
        i_assert(!ilist->syncing);
 
+retry:
        if (mailbox_list_index_index_open(list) < 0)
                return -1;
 
@@ -248,6 +250,14 @@ int mailbox_list_index_sync_begin(struct mailbox_list *list,
                mail_index_sync_rollback(&index_sync_ctx);
                return -1;
        }
+       if (ilist->call_corruption_callback && !fix_attempted) {
+               /* unlock and resync the index */
+               mail_index_sync_rollback(&index_sync_ctx);
+               if (mailbox_list_index_handle_corruption(list) < 0)
+                       return -1;
+               fix_attempted = TRUE;
+               goto retry;
+       }
 
        sync_ctx = i_new(struct mailbox_list_index_sync_context, 1);
        sync_ctx->list = list;
index a56603c0589a0d1c0efa4f3f49bd2a41a49b16e9..f27972e32ca423b8821c741bb865776296ec095c 100644 (file)
@@ -413,6 +413,8 @@ int mailbox_list_index_parse(struct mailbox_list *list,
                /* nothing changed */
                return 0;
        }
+       if ((hdr->flags & MAIL_INDEX_HDR_FLAG_FSCKD) != 0)
+               ilist->call_corruption_callback = TRUE;
 
        mailbox_list_index_reset(ilist);
        ilist->sync_log_file_seq = hdr->log_file_seq;
@@ -425,6 +427,7 @@ int mailbox_list_index_parse(struct mailbox_list *list,
                        mail_index_mark_corrupted(ilist->index);
                        return -1;
                }
+               ilist->call_corruption_callback = TRUE;
                ilist->corrupted_names_or_parents = TRUE;
        }
        if (mailbox_list_index_parse_records(ilist, view, &error) < 0) {
@@ -437,6 +440,7 @@ int mailbox_list_index_parse(struct mailbox_list *list,
                }
                /* FIXME: find any missing mailboxes, add them and write the
                   index back. */
+               ilist->call_corruption_callback = TRUE;
                ilist->corrupted_names_or_parents = TRUE;
        }
        return 0;
@@ -500,7 +504,8 @@ int mailbox_list_index_refresh_force(struct mailbox_list *list)
                ret = mailbox_list_index_parse(list, view, FALSE);
        }
        mail_index_view_close(&view);
-       return ret;
+
+       return mailbox_list_index_handle_corruption(list);
 }
 
 static void mailbox_list_index_refresh_timeout(struct mailbox_list *list)
@@ -548,6 +553,51 @@ void mailbox_list_index_refresh_later(struct mailbox_list *list)
        }
 }
 
+int mailbox_list_index_handle_corruption(struct mailbox_list *list)
+{
+       struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
+       struct mail_storage *const *storagep;
+       int ret = 0;
+
+       if (!ilist->call_corruption_callback)
+               return 0;
+
+       /* make sure we don't recurse */
+       if (ilist->handling_corruption)
+               return 0;
+       ilist->handling_corruption = TRUE;
+
+       array_foreach(&list->ns->all_storages, storagep) {
+               if ((*storagep)->v.list_index_corrupted != NULL) {
+                       if ((*storagep)->v.list_index_corrupted(*storagep) < 0)
+                               ret = -1;
+                       else {
+                               /* FIXME: implement a generic handler that
+                                  just lists mailbox directories in filesystem
+                                  and adds the missing ones to the index. */
+                       }
+               }
+       }
+       if (ret == 0)
+               ret = mailbox_list_index_set_uncorrupted(list);
+       ilist->handling_corruption = FALSE;
+       return ret;
+}
+
+int mailbox_list_index_set_uncorrupted(struct mailbox_list *list)
+{
+       struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
+       struct mailbox_list_index_sync_context *sync_ctx;
+
+       ilist->call_corruption_callback = FALSE;
+
+       if (mailbox_list_index_sync_begin(list, &sync_ctx) < 0)
+               return -1;
+
+       mail_index_unset_fscked(sync_ctx->trans);
+       return mailbox_list_index_sync_end(&sync_ctx, TRUE);
+}
+
 static void mailbox_list_index_deinit(struct mailbox_list *list)
 {
        struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
index 3697d67b8368c0a45d52e5addd211c4d683f974f..e1dbdeb3a988e8b8a89cc4bf78315ac805c465a1 100644 (file)
@@ -117,6 +117,8 @@ struct mailbox_list_index {
        unsigned int has_backing_store:1;
        unsigned int index_last_check_changed:1;
        unsigned int corrupted_names_or_parents:1;
+       unsigned int handling_corruption:1;
+       unsigned int call_corruption_callback:1;
 };
 
 struct mailbox_list_index_iterate_context {
@@ -156,6 +158,8 @@ int mailbox_list_index_refresh(struct mailbox_list *list);
 /* Refresh the index regardless of when the last refresh was done. */
 int mailbox_list_index_refresh_force(struct mailbox_list *list);
 void mailbox_list_index_refresh_later(struct mailbox_list *list);
+int mailbox_list_index_handle_corruption(struct mailbox_list *list);
+int mailbox_list_index_set_uncorrupted(struct mailbox_list *list);
 
 struct mailbox_list_index_node *
 mailbox_list_index_node_find_sibling(struct mailbox_list_index_node *node,