Mercurial > dovecot > original-hg > dovecot-1.1
changeset 8261:6bbe27c32cb8 HEAD
Maildir saving: Fixed race condition bugs in uidlist handling, causing files to be given new UIDs sometimes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 04 May 2009 14:28:31 -0400 |
parents | 6f8c536d76d0 |
children | 003bebac2c76 |
files | src/lib-storage/index/maildir/maildir-uidlist.c |
diffstat | 1 files changed, 18 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Mon May 04 12:33:27 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon May 04 14:28:31 2009 -0400 @@ -91,6 +91,7 @@ unsigned int initial_hdr_read:1; unsigned int initial_sync:1; unsigned int retry_rewind:1; + unsigned int locked_refresh:1; }; struct maildir_uidlist_sync_ctx { @@ -171,6 +172,7 @@ } uidlist->lock_count++; + uidlist->locked_refresh = FALSE; if (refresh) { /* make sure we have the latest changes before @@ -212,6 +214,7 @@ if (--uidlist->lock_count > 0) return; + uidlist->locked_refresh = FALSE; (void)file_dotlock_delete(&uidlist->dotlock); } @@ -808,6 +811,8 @@ if (ret >= 0) { uidlist->initial_read = TRUE; uidlist->initial_hdr_read = TRUE; + if (UIDLIST_IS_LOCKED(uidlist)) + uidlist->locked_refresh = TRUE; } return ret; } @@ -1015,7 +1020,10 @@ rec->extensions = p_malloc(uidlist->record_pool, buf->used); memcpy(rec->extensions, buf->data, buf->used); - uidlist->recreate = TRUE; + if (rec->uid != (uint32_t)-1) { + /* message already exists in uidlist, need to recreate it */ + uidlist->recreate = TRUE; + } } void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid, @@ -1206,8 +1214,10 @@ { unsigned int min_rewrite_count; - if (!ctx->uidlist->initial_read) + if (!ctx->uidlist->locked_refresh) return FALSE; + if (ctx->uidlist->recreate) + return TRUE; min_rewrite_count = (ctx->uidlist->read_records_count + ctx->new_files_count) * @@ -1219,13 +1229,11 @@ { struct maildir_uidlist *uidlist = ctx->uidlist; - if (uidlist->recreate || - ctx->finish_change_counter != uidlist->change_counter) + if (!uidlist->locked_refresh) + return FALSE; + if (ctx->finish_change_counter != uidlist->change_counter) return TRUE; - if (!uidlist->initial_read) - return FALSE; - if (uidlist->fd == -1 || uidlist->version != UIDLIST_VERSION) return TRUE; return maildir_uidlist_want_compress(ctx); @@ -1284,7 +1292,7 @@ if ((uoff_t)st.st_size != file_size) { i_warning("%s: file size changed unexpectedly after write", uidlist->path); - } else { + } else if (uidlist->locked_refresh) { uidlist->fd_size = st.st_size; uidlist->last_read_offset = st.st_size; maildir_uidlist_update_hdr(uidlist, &st); @@ -1494,6 +1502,7 @@ unsigned int idx; i_assert(ctx->partial); + i_assert(ctx->uidlist->locked_refresh); rec = hash_lookup(ctx->uidlist->files, filename); i_assert(rec != NULL); @@ -1630,8 +1639,7 @@ ctx->uidlist->initial_sync = TRUE; i_assert(ctx->locked || !ctx->changed); - if ((ctx->changed || ctx->uidlist->recreate || - maildir_uidlist_want_compress(ctx)) && + if ((ctx->changed || maildir_uidlist_want_compress(ctx)) && !ctx->failed && ctx->locked) T_BEGIN { if (maildir_uidlist_sync_update(ctx) < 0) ctx->failed = TRUE;