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;
 };