changeset 21137:6bdcc7190a55

LAYOUT=index: Don't write corrupted mailbox names to box-name header. This way when opening a mailbox the box-name header isn't overwritten by a corrupted name. Keep track of the corrupted names with MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME flag in list index records. The flag isn't removed until the mailbox is renamed.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 16 Nov 2016 03:06:31 +0200
parents 0346bbd0fdc1
children b24657e6abe7
files src/lib-storage/list/mailbox-list-index-backend.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
diffstat 4 files changed, 25 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Wed Nov 16 03:01:22 2016 +0200
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Wed Nov 16 03:06:31 2016 +0200
@@ -456,6 +456,15 @@
 	return 0;
 }
 
+static bool mailbox_has_corrupted_name(struct mailbox *box)
+{
+	struct mailbox_list_index_node *node;
+
+	node = mailbox_list_index_lookup(box->list, box->name);
+	return node != NULL &&
+		(node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0;
+}
+
 static int index_list_mailbox_open(struct mailbox *box)
 {
 	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
@@ -491,7 +500,7 @@
 	if (name_hdr_size == box_name_len &&
 	    memcmp(box_zerosep_name, name_hdr, box_name_len) == 0) {
 		/* Same mailbox name */
-	} else {
+	} else if (!mailbox_has_corrupted_name(box)) {
 		/* Mailbox name changed - update */
 		struct mail_index_transaction *trans =
 			mail_index_transaction_begin(box->view, 0);
@@ -699,6 +708,13 @@
 	oldrec.name_id = newrec.name_id;
 	oldrec.parent_uid = newrec.parent_uid;
 
+	if ((newnode->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0) {
+		/* mailbox is renamed - clear away the corruption flag so the
+		   new name will be written to the mailbox index header. */
+		newnode->flags &= ~MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME;
+		mail_index_update_flags(sync_ctx->trans, oldseq, MODIFY_REMOVE,
+					MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME);
+	}
 	mail_index_update_ext(sync_ctx->trans, oldseq,
 			      sync_ctx->ilist->ext_id, &oldrec, NULL);
 	mail_index_expunge(sync_ctx->trans, newseq);
--- a/src/lib-storage/list/mailbox-list-index-sync.c	Wed Nov 16 03:01:22 2016 +0200
+++ b/src/lib-storage/list/mailbox-list-index-sync.c	Wed Nov 16 03:06:31 2016 +0200
@@ -377,6 +377,11 @@
 				      sync_ctx->ilist->ext_id, &irec, NULL);
 		node->corrupted_parent = FALSE;
 	}
+	if ((node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0) {
+		/* rely on lib-index to drop unnecessary updates */
+		mail_index_update_flags(sync_ctx->trans, seq, MODIFY_ADD,
+					MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME);
+	}
 }
 
 static void
--- a/src/lib-storage/list/mailbox-list-index.c	Wed Nov 16 03:01:22 2016 +0200
+++ b/src/lib-storage/list/mailbox-list-index.c	Wed Nov 16 03:06:31 2016 +0200
@@ -233,6 +233,7 @@
 	name = p_strdup_printf(ilist->mailbox_pool, "unknown-%s",
 			       guid_128_to_string(guid));
 	node->name = name;
+	node->flags |= MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME;
 
 	hash_table_insert(ilist->mailbox_names,
 			  POINTER_CAST(node->name_id), name);
@@ -372,6 +373,7 @@
 			/* we have only the mailbox list index and this node
 			   may have a different GUID, so rename it. */
 			guid_128_generate(guid);
+			node->flags |= MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME;
 			node->name = p_strdup_printf(ilist->mailbox_pool,
 						     "%s-duplicate-%s", node->name,
 						     guid_128_to_string(guid));
--- a/src/lib-storage/list/mailbox-list-index.h	Wed Nov 16 03:01:22 2016 +0200
+++ b/src/lib-storage/list/mailbox-list-index.h	Wed Nov 16 03:06:31 2016 +0200
@@ -43,6 +43,7 @@
 	MAILBOX_LIST_INDEX_FLAG_NONEXISTENT = MAIL_DELETED,
 	MAILBOX_LIST_INDEX_FLAG_NOSELECT = MAIL_DRAFT,
 	MAILBOX_LIST_INDEX_FLAG_NOINFERIORS = MAIL_ANSWERED,
+	MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME = MAIL_SEEN,
 
 	/* set during syncing for mailboxes that still exist */
 	MAILBOX_LIST_INDEX_FLAG_SYNC_EXISTS = MAIL_FLAGGED