Mercurial > dovecot > core-2.2
changeset 21131:a93530968d51
lib-storage: Fix invalid parents in LAYOUT=index
Previously it just kept complaining without fixing the errors.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 16 Nov 2016 01:03:20 +0200 |
parents | bb229dce59cc |
children | e3e79ca1689d |
files | 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 |
diffstat | 3 files changed, 66 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-index-sync.c Wed Nov 16 01:01:58 2016 +0200 +++ b/src/lib-storage/list/mailbox-list-index-sync.c Wed Nov 16 01:03:20 2016 +0200 @@ -353,6 +353,52 @@ } } +static void +mailbox_list_index_sync_update_corrupted_node(struct mailbox_list_index_sync_context *sync_ctx, + struct mailbox_list_index_node *node) +{ + struct mailbox_list_index_record irec; + uint32_t seq; + const void *data; + bool expunged; + + if (!mail_index_lookup_seq(sync_ctx->view, node->uid, &seq)) + return; + + if (node->corrupted_parent) { + mail_index_lookup_ext(sync_ctx->view, seq, + sync_ctx->ilist->ext_id, + &data, &expunged); + i_assert(data != NULL); + + memcpy(&irec, data, sizeof(irec)); + irec.parent_uid = node->parent == NULL ? 0 : node->parent->uid; + mail_index_update_ext(sync_ctx->trans, seq, + sync_ctx->ilist->ext_id, &irec, NULL); + node->corrupted_parent = FALSE; + } +} + +static void +mailbox_list_index_sync_update_corrupted_nodes(struct mailbox_list_index_sync_context *sync_ctx, + struct mailbox_list_index_node *node) +{ + for (; node != NULL; node = node->next) { + mailbox_list_index_sync_update_corrupted_node(sync_ctx, node); + mailbox_list_index_sync_update_corrupted_nodes(sync_ctx, node->children); + } +} + +static void +mailbox_list_index_sync_update_corrupted(struct mailbox_list_index_sync_context *sync_ctx) +{ + if (!sync_ctx->ilist->corrupted) + return; + + mailbox_list_index_sync_update_corrupted_nodes(sync_ctx, + sync_ctx->ilist->mailbox_tree); +} + int mailbox_list_index_sync_end(struct mailbox_list_index_sync_context **_sync_ctx, bool success) { @@ -361,8 +407,10 @@ *_sync_ctx = NULL; - if (success) + if (success) { + mailbox_list_index_sync_update_corrupted(sync_ctx); mailbox_list_index_sync_update_hdr(sync_ctx); + } mail_index_view_close(&sync_ctx->view); if (success) {
--- a/src/lib-storage/list/mailbox-list-index.c Wed Nov 16 01:01:58 2016 +0200 +++ b/src/lib-storage/list/mailbox-list-index.c Wed Nov 16 01:03:20 2016 +0200 @@ -258,7 +258,7 @@ struct mail_index_view *view, const char **error_r) { - struct mailbox_list_index_node *node; + struct mailbox_list_index_node *node, *parent; HASH_TABLE(struct mailbox_list_index_node *, struct mailbox_list_index_node *) duplicate_hash; const struct mail_index_record *rec; @@ -319,19 +319,22 @@ if (irec->parent_uid != 0) { /* node should have a parent */ - node->parent = mailbox_list_index_lookup_uid(ilist, - irec->parent_uid); - if (node->parent != NULL) { - node->next = node->parent->children; - node->parent->children = node; + parent = mailbox_list_index_lookup_uid(ilist, + irec->parent_uid); + if (parent == NULL) { + *error_r = t_strdup_printf( + "parent_uid=%u points to nonexistent record", + irec->parent_uid); + if (ilist->has_backing_store) + break; + /* just place it under the root */ + node->corrupted_parent = TRUE; + } else { + node->parent = parent; + node->next = parent->children; + parent->children = node; continue; } - *error_r = t_strdup_printf( - "parent_uid=%u points to nonexistent record", - irec->parent_uid); - if (ilist->has_backing_store) - break; - /* just place it under the root */ } if (hash_table_lookup(duplicate_hash, node) == NULL) hash_table_insert(duplicate_hash, node, node);
--- a/src/lib-storage/list/mailbox-list-index.h Wed Nov 16 01:01:58 2016 +0200 +++ b/src/lib-storage/list/mailbox-list-index.h Wed Nov 16 01:03:20 2016 +0200 @@ -80,6 +80,8 @@ uint32_t name_id, uid; enum mailbox_list_index_flags flags; + /* parent_uid is corrupted on disk - need to update it */ + bool corrupted_parent; const char *name; };