From: Timo Sirainen Date: Fri, 11 Oct 2013 15:54:36 +0000 (+0300) Subject: LAYOUT=index: Fixed race condition during mailbox creation. X-Git-Tag: 2.2.7~87 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ca31fc1a8e48281c6882796fa7d4372acc2f97e5;p=thirdparty%2Fdovecot%2Fcore.git LAYOUT=index: Fixed race condition during mailbox creation. --- diff --git a/src/lib-storage/list/mailbox-list-index-backend.c b/src/lib-storage/list/mailbox-list-index-backend.c index 535dc1dc73..e27a8016e5 100644 --- a/src/lib-storage/list/mailbox-list-index-backend.c +++ b/src/lib-storage/list/mailbox-list-index-backend.c @@ -136,7 +136,10 @@ index_list_get_path(struct mailbox_list *_list, const char *name, } 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 @@ index_list_get_path(struct mailbox_list *_list, const char *name, *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 @@ index_list_mailbox_create_dir(struct index_mailbox_list *list, const char *name) } 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 @@ index_list_mailbox_create_selectable(struct index_mailbox_list *list, 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 @@ static int 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 @@ index_list_mailbox_create(struct mailbox *box, 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 @@ index_list_mailbox_create(struct mailbox *box, "Mailbox already exists"); return -1; } - return directory ? 0 : - ibox->module_ctx.super.create_box(box, update, directory); + return 0; } static int diff --git a/src/lib-storage/list/mailbox-list-index-sync.c b/src/lib-storage/list/mailbox-list-index-sync.c index f34537f21e..c5817e51e5 100644 --- a/src/lib-storage/list/mailbox-list-index-sync.c +++ b/src/lib-storage/list/mailbox-list-index-sync.c @@ -236,6 +236,8 @@ int mailbox_list_index_sync_begin(struct mailbox_list *list, 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 @@ int mailbox_list_index_sync_begin(struct mailbox_list *list, &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 @@ int mailbox_list_index_sync_end(struct mailbox_list_index_sync_context **_sync_c ret = -1; } sync_ctx->ilist->syncing = FALSE; + sync_ctx->ilist->sync_ctx = NULL; i_free(sync_ctx); return ret; } diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h index ec2f9bdc5a..2668ced748 100644 --- a/src/lib-storage/list/mailbox-list-index.h +++ b/src/lib-storage/list/mailbox-list-index.h @@ -92,6 +92,7 @@ struct mailbox_list_index { 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;