dovecot-1.2: Maildir saving: Fixed race condition bugs in uidlis...
dovecot at dovecot.org
dovecot at dovecot.org
Mon May 4 23:48:59 EEST 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/6770f46971af
changeset: 9016:6770f46971af
user: Timo Sirainen <tss at iki.fi>
date: Mon May 04 14:28:31 2009 -0400
description:
Maildir saving: Fixed race condition bugs in uidlist handling, causing files to be given new UIDs sometimes.
diffstat:
1 file changed, 18 insertions(+), 10 deletions(-)
src/lib-storage/index/maildir/maildir-uidlist.c | 28 ++++++++++++++---------
diffs (103 lines):
diff -r 05a98aaf0aaf -r 6770f46971af src/lib-storage/index/maildir/maildir-uidlist.c
--- 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 @@ struct maildir_uidlist {
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 @@ static int maildir_uidlist_lock_timeout(
}
uidlist->lock_count++;
+ uidlist->locked_refresh = FALSE;
if (refresh) {
/* make sure we have the latest changes before
@@ -212,6 +214,7 @@ void maildir_uidlist_unlock(struct maild
if (--uidlist->lock_count > 0)
return;
+ uidlist->locked_refresh = FALSE;
(void)file_dotlock_delete(&uidlist->dotlock);
}
@@ -814,6 +817,8 @@ int maildir_uidlist_refresh(struct maild
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 @@ maildir_uidlist_set_ext_real(struct mail
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 @@ static bool maildir_uidlist_want_compres
{
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,12 +1235,10 @@ static bool maildir_uidlist_want_recreat
{
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;
@@ -1290,7 +1298,7 @@ static int maildir_uidlist_sync_update(s
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 @@ void maildir_uidlist_sync_remove(struct
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 @@ void maildir_uidlist_sync_finish(struct
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;
More information about the dovecot-cvs
mailing list