dovecot-2.0: Maildir saving: Fixed race condition bugs in uidlis...
dovecot at dovecot.org
dovecot at dovecot.org
Mon May 4 23:48:45 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/9b6ca1680cd2
changeset: 9206:9b6ca1680cd2
user: Timo Sirainen <tss at iki.fi>
date: Mon May 04 16:38:38 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 1cdee5c559ca -r 9b6ca1680cd2 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 16:38:38 2009 -0400
@@ -93,6 +93,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 {
@@ -173,6 +174,7 @@ static int maildir_uidlist_lock_timeout(
}
uidlist->lock_count++;
+ uidlist->locked_refresh = FALSE;
if (refresh) {
/* make sure we have the latest changes before
@@ -214,6 +216,7 @@ void maildir_uidlist_unlock(struct maild
if (--uidlist->lock_count > 0)
return;
+ uidlist->locked_refresh = FALSE;
(void)file_dotlock_delete(&uidlist->dotlock);
}
@@ -815,6 +818,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;
}
@@ -1022,7 +1027,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,
@@ -1213,8 +1221,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) *
@@ -1226,12 +1236,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;
@@ -1291,7 +1299,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);
@@ -1530,6 +1538,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);
@@ -1673,8 +1682,7 @@ void maildir_uidlist_sync_finish(struct
/* mbox=NULL means we're coming from dbox rebuilding code.
the dbox is already locked, so allow uidlist recreation */
i_assert(ctx->locked || !ctx->changed || ctx->uidlist->mbox == NULL);
- if ((ctx->changed || ctx->uidlist->recreate ||
- maildir_uidlist_want_compress(ctx)) &&
+ if ((ctx->changed || maildir_uidlist_want_compress(ctx)) &&
!ctx->failed && (ctx->locked || ctx->uidlist->mbox == NULL)) {
T_BEGIN {
if (maildir_uidlist_sync_update(ctx) < 0)
More information about the dovecot-cvs
mailing list