Skip to content

Commit

Permalink
lib-storge: Call mail_storage.list_index_corrupted() when needed
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sirainen committed Nov 25, 2016
1 parent 243d0d9 commit a81c40f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/lib-storage/list/mailbox-list-index-notify.c
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions src/lib-storage/list/mailbox-list-index-sync.c
Expand Up @@ -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;

Expand All @@ -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;
Expand Down
52 changes: 51 additions & 1 deletion src/lib-storage/list/mailbox-list-index.c
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions src/lib-storage/list/mailbox-list-index.h
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit a81c40f

Please sign in to comment.