]> 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)
committerGitLab <gitlab@git.dovecot.net>
Fri, 25 Nov 2016 13:25:14 +0000 (15:25 +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 73b513e5a250d529f7ab6a28b3f887c20c36e01b..379582fc9574b67a54850256740131ae9f1658a7 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 b52e4097d98bd03e5a910613b9a479b98a67faec..fdb5b0b943c1d885b2f974f0b1458840d539205a 100644 (file)
@@ -231,9 +231,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;
 
@@ -249,6 +251,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 0e097a9a989c97833fa125745ae49d22abacad2d..00bcd9cba12b52dc527efb730774e3a2909ee115 100644 (file)
@@ -117,6 +117,8 @@ struct mailbox_list_index {
        bool has_backing_store:1;
        bool index_last_check_changed:1;
        bool corrupted_names_or_parents:1;
+       bool handling_corruption:1;
+       bool 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,