dovecot-2.2: LAYOUT=index: Fixed race condition during mailbox c...

dovecot at dovecot.org dovecot at dovecot.org
Fri Oct 11 18:55:10 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/ab341f7509b5
changeset: 16842:ab341f7509b5
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Oct 11 18:54:36 2013 +0300
description:
LAYOUT=index: Fixed race condition during mailbox creation.

diffstat:

 src/lib-storage/list/mailbox-list-index-backend.c |  33 ++++++++++++----------
 src/lib-storage/list/mailbox-list-index-sync.c    |   4 ++
 src/lib-storage/list/mailbox-list-index.h         |   1 +
 3 files changed, 23 insertions(+), 15 deletions(-)

diffs (141 lines):

diff -r 4b0a736bc40c -r ab341f7509b5 src/lib-storage/list/mailbox-list-index-backend.c
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Fri Oct 11 12:31:48 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Fri Oct 11 18:54:36 2013 +0300
@@ -136,7 +136,10 @@
 		}
 		return -1;
 	}
-	view = mail_index_view_open(ilist->index);
+	/* we could get here during sync from
+	   index_list_mailbox_create_selectable() */
+	view = ilist->sync_ctx == NULL ? mail_index_view_open(ilist->index) :
+		ilist->sync_ctx->view;
 	if (!mail_index_lookup_seq(view, node->uid, &seq))
 		i_panic("mailbox list index: lost uid=%u", node->uid);
 	if (!mailbox_list_index_status(_list, view, seq, 0,
@@ -149,7 +152,8 @@
 		*path_r = index_get_guid_path(_list, root_dir, mailbox_guid);
 		ret = 1;
 	}
-	mail_index_view_close(&view);
+	if (ilist->sync_ctx == NULL)
+		mail_index_view_close(&view);
 	return ret;
 }
 
@@ -234,20 +238,23 @@
 }
 
 static int
-index_list_mailbox_create_selectable(struct index_mailbox_list *list,
-				     const char *name, guid_128_t mailbox_guid)
+index_list_mailbox_create_selectable(struct mailbox *box,
+				     const struct mailbox_update *update)
 {
+	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
+	struct index_mailbox_list *list =
+		(struct index_mailbox_list *)box->list;
 	struct mailbox_list_index_sync_context *sync_ctx;
 	struct mailbox_list_index_record rec;
 	struct mailbox_list_index_node *node;
 	const void *data;
-	bool expunged, created;
+	bool expunged, created, success;
 	uint32_t seq;
 
 	if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
 		return -1;
 
-	seq = mailbox_list_index_sync_name(sync_ctx, name, &node, &created);
+	seq = mailbox_list_index_sync_name(sync_ctx, box->name, &node, &created);
 	if (!created &&
 	    (node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
 			    MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
@@ -266,11 +273,12 @@
 	node->flags = 0;
 	mail_index_update_flags(sync_ctx->trans, seq, MODIFY_REPLACE, 0);
 
-	memcpy(rec.guid, mailbox_guid, sizeof(rec.guid));
+	memcpy(rec.guid, update->mailbox_guid, sizeof(rec.guid));
 	mail_index_update_ext(sync_ctx->trans, seq, sync_ctx->ilist->ext_id,
 			      &rec, NULL);
 
-	if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0)
+	success = ibox->module_ctx.super.create_box(box, update, FALSE) == 0;
+	if (mailbox_list_index_sync_end(&sync_ctx, success) < 0)
 		return -1;
 	return 1;
 }
@@ -279,7 +287,6 @@
 index_list_mailbox_create(struct mailbox *box,
 			  const struct mailbox_update *update, bool directory)
 {
-	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
 	struct index_mailbox_list *list =
 		(struct index_mailbox_list *)box->list;
 	struct mailbox_update new_update;
@@ -306,14 +313,11 @@
 			new_update = *update;
 		if (guid_128_is_empty(new_update.mailbox_guid))
 			guid_128_generate(new_update.mailbox_guid);
-		ret = index_list_mailbox_create_selectable(list, box->name,
-							   new_update.mailbox_guid);
+		ret = index_list_mailbox_create_selectable(box, &new_update);
 		if (ret < 0) {
 			mail_storage_copy_list_error(box->storage, box->list);
 			return -1;
 		}
-		/* the storage backend needs to use the same GUID */
-		update = &new_update;
 	} else {
 		ret = 0;
 	}
@@ -323,8 +327,7 @@
 				       "Mailbox already exists");
 		return -1;
 	}
-	return directory ? 0 :
-		ibox->module_ctx.super.create_box(box, update, directory);
+	return 0;
 }
 
 static int
diff -r 4b0a736bc40c -r ab341f7509b5 src/lib-storage/list/mailbox-list-index-sync.c
--- a/src/lib-storage/list/mailbox-list-index-sync.c	Fri Oct 11 12:31:48 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-index-sync.c	Fri Oct 11 18:54:36 2013 +0300
@@ -236,6 +236,8 @@
 	struct mail_index_transaction *trans;
 	const struct mail_index_header *hdr;
 
+	i_assert(!ilist->syncing);
+
 	if (mail_index_sync_begin(ilist->index, &index_sync_ctx, &view, &trans,
 				  MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES) < 0) {
 		mailbox_list_index_set_index_error(list);
@@ -269,6 +271,7 @@
 			&uid_validity, sizeof(uid_validity), TRUE);
 	}
 	sync_ctx->view = mail_index_transaction_open_updated_view(trans);
+	ilist->sync_ctx = sync_ctx;
 	ilist->syncing = TRUE;
 
 	*sync_ctx_r = sync_ctx;
@@ -370,6 +373,7 @@
 		ret = -1;
 	}
 	sync_ctx->ilist->syncing = FALSE;
+	sync_ctx->ilist->sync_ctx = NULL;
 	i_free(sync_ctx);
 	return ret;
 }
diff -r 4b0a736bc40c -r ab341f7509b5 src/lib-storage/list/mailbox-list-index.h
--- a/src/lib-storage/list/mailbox-list-index.h	Fri Oct 11 12:31:48 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-index.h	Fri Oct 11 18:54:36 2013 +0300
@@ -92,6 +92,7 @@
 	HASH_TABLE(void *, char *) mailbox_names;
 	uint32_t highest_name_id;
 
+	struct mailbox_list_index_sync_context *sync_ctx;
 	uint32_t sync_log_file_seq;
 	uoff_t sync_log_file_offset;
 	uint32_t sync_stamp;


More information about the dovecot-cvs mailing list