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;
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;
/* 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;
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) {
}
/* 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;
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)
}
}
+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);
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 {
/* 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,