dovecot-2.2: lib-storage: Fixed some race condition crashes with...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Oct 7 18:36:30 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/96f79038038f
changeset: 17910:96f79038038f
user: Timo Sirainen <tss at iki.fi>
date: Tue Oct 07 21:35:44 2014 +0300
description:
lib-storage: Fixed some race condition crashes with LAYOUT=index
diffstat:
src/lib-storage/list/mailbox-list-index-backend.c | 90 +++++++++++++++-------
src/lib-storage/list/mailbox-list-index.c | 13 ++-
src/lib-storage/list/mailbox-list-index.h | 4 +
3 files changed, 76 insertions(+), 31 deletions(-)
diffs (193 lines):
diff -r 2b84c33d5d11 -r 96f79038038f src/lib-storage/list/mailbox-list-index-backend.c
--- a/src/lib-storage/list/mailbox-list-index-backend.c Tue Oct 07 20:29:16 2014 +0300
+++ b/src/lib-storage/list/mailbox-list-index-backend.c Tue Oct 07 21:35:44 2014 +0300
@@ -66,8 +66,8 @@
}
static int
-index_list_get_node(struct index_mailbox_list *list, const char *name,
- struct mailbox_list_index_node **node_r)
+index_list_get_refreshed_node(struct index_mailbox_list *list, const char *name,
+ struct mailbox_list_index_node **node_r)
{
struct mailbox_list_index_node *node;
@@ -81,6 +81,33 @@
return 1;
}
+static int
+index_list_get_refreshed_node_seq(struct index_mailbox_list *list,
+ struct mail_index_view *view,
+ const char *name,
+ struct mailbox_list_index_node **node_r,
+ uint32_t *seq_r)
+{
+ unsigned int i;
+ int ret;
+
+ *node_r = NULL;
+ *seq_r = 0;
+
+ for (i = 0; i < 2; i++) {
+ if ((ret = index_list_get_refreshed_node(list, name, node_r)) <= 0)
+ return ret;
+ if (mail_index_lookup_seq(view, (*node_r)->uid, seq_r))
+ return 1;
+ /* mailbox was just expunged. refreshing should notice it. */
+ if (mailbox_list_index_refresh_force(&list->list) < 0)
+ return -1;
+ }
+ i_panic("mailbox list index: refreshing doesn't lose expunged uid=%u",
+ (*node_r)->uid);
+ return -1;
+}
+
static const char *
index_get_guid_path(struct mailbox_list *_list, const char *root_dir,
const guid_128_t mailbox_guid)
@@ -124,22 +151,35 @@
if (!mailbox_list_set_get_root_path(&_list->set, type, &root_dir))
return 0;
- if ((ret = index_list_get_node(list, name, &node)) <= 0) {
- if (ret == 0) {
- mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+ if (ilist->sync_ctx != NULL) {
+ /* we could get here during sync from
+ index_list_mailbox_create_selectable() */
+ view = ilist->sync_ctx->view;
+ node = mailbox_list_index_lookup(&list->list, name);
+ if (node == NULL) {
+ seq = 0;
+ ret = 0;
+ } else if (mail_index_lookup_seq(view, node->uid, &seq)) {
+ ret = 1;
+ } else {
+ i_panic("mailbox list index: lost uid=%u", node->uid);
}
- return -1;
+ } else {
+ view = mail_index_view_open(ilist->index);
+ ret = index_list_get_refreshed_node_seq(list, view, name, &node, &seq);
+ if (ret < 0) {
+ mail_index_view_close(&view);
+ return -1;
+ }
}
- /* 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,
- &status, mailbox_guid) ||
- guid_128_is_empty(mailbox_guid)) {
+ i_assert(ret == 0 || seq != 0);
+ if (ret == 0) {
+ mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+ ret = -1;
+ } else if (!mailbox_list_index_status(_list, view, seq, 0,
+ &status, mailbox_guid) ||
+ guid_128_is_empty(mailbox_guid)) {
mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
ret = -1;
@@ -188,7 +228,7 @@
*existence_r = MAILBOX_EXISTENCE_NONE;
- if ((ret = index_list_get_node(list, name, &node)) < 0)
+ if ((ret = index_list_get_refreshed_node(list, name, &node)) < 0)
return -1;
if (ret == 0)
return 0;
@@ -435,16 +475,12 @@
const void *data;
bool expunged;
uint32_t seq;
- int ret;
if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
return -1;
- if ((ret = index_list_get_node(list, name, &node)) < 0) {
- (void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
- return -1;
- }
- if (ret == 0) {
+ node = mailbox_list_index_lookup(&list->list, name);
+ if (node == NULL) {
(void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
mailbox_list_set_error(&list->list, MAIL_ERROR_NOTFOUND,
T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
@@ -552,7 +588,6 @@
const void *data;
bool created, expunged;
uint32_t oldseq, newseq;
- int ret;
if (_oldlist != _newlist) {
mailbox_list_set_error(_oldlist, MAIL_ERROR_NOTPOSSIBLE,
@@ -563,11 +598,8 @@
if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
return -1;
- if ((ret = index_list_get_node(list, oldname, &oldnode)) < 0) {
- (void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
- return -1;
- }
- if (ret == 0) {
+ oldnode = mailbox_list_index_lookup(&list->list, oldname);
+ if (oldnode == NULL) {
(void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
mailbox_list_set_error(&list->list, MAIL_ERROR_NOTFOUND,
T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
diff -r 2b84c33d5d11 -r 96f79038038f src/lib-storage/list/mailbox-list-index.c
--- a/src/lib-storage/list/mailbox-list-index.c Tue Oct 07 20:29:16 2014 +0300
+++ b/src/lib-storage/list/mailbox-list-index.c Tue Oct 07 21:35:44 2014 +0300
@@ -362,8 +362,6 @@
int mailbox_list_index_refresh(struct mailbox_list *list)
{
struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
- struct mail_index_view *view;
- int ret;
if (ilist->syncing)
return 0;
@@ -376,6 +374,17 @@
return 0;
}
+ return mailbox_list_index_refresh_force(list);
+}
+
+int mailbox_list_index_refresh_force(struct mailbox_list *list)
+{
+ struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
+ struct mail_index_view *view;
+ int ret;
+
+ i_assert(!ilist->syncing);
+
ilist->last_refresh_timeval = ioloop_timeval;
if (mailbox_list_index_index_open(list) < 0)
return -1;
diff -r 2b84c33d5d11 -r 96f79038038f src/lib-storage/list/mailbox-list-index.h
--- a/src/lib-storage/list/mailbox-list-index.h Tue Oct 07 20:29:16 2014 +0300
+++ b/src/lib-storage/list/mailbox-list-index.h Tue Oct 07 21:35:44 2014 +0300
@@ -142,7 +142,11 @@
int mailbox_list_index_index_open(struct mailbox_list *list);
bool mailbox_list_index_need_refresh(struct mailbox_list_index *ilist,
struct mail_index_view *view);
+/* Refresh the index, but only if it hasn't been refreshed "recently"
+ (= within this same ioloop run) */
int mailbox_list_index_refresh(struct mailbox_list *list);
+/* Refresh the index regardless of when the last refresh was done. */
+int mailbox_list_index_refresh_force(struct mailbox_list *list);
void mailbox_list_index_refresh_later(struct mailbox_list *list);
struct mailbox_list_index_node *
More information about the dovecot-cvs
mailing list