Mercurial > dovecot > original-hg > dovecot-1.2
changeset 9016:6770f46971af 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 | 05a98aaf0aaf |
children | 0aa17f3e4a6d |
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:32:59 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); } @@ -814,6 +817,8 @@ if (ret >= 0) { uidlist->initial_read = TRUE; uidlist->initial_hdr_read = TRUE; + if (UIDLIST_IS_LOCKED(uidlist)) + uidlist->locked_refresh = TRUE; } return ret; } @@ -1021,7 +1026,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, @@ -1212,8 +1220,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) * @@ -1225,13 +1235,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); @@ -1290,7 +1298,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); @@ -1525,6 +1533,7 @@ unsigned int idx; i_assert(ctx->partial); + i_assert(ctx->uidlist->locked_refresh); rec = hash_table_lookup(ctx->uidlist->files, filename); i_assert(rec != NULL); @@ -1661,8 +1670,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;