From: Timo Sirainen Date: Mon, 13 Apr 2009 22:23:37 +0000 (-0400) Subject: maildir: When saving messages, in some race conditions we might have written a duplic... X-Git-Tag: 2.0.alpha1~953 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=15cc66ca72982a43e3bfa58f307adc57e9caa52d;p=thirdparty%2Fdovecot%2Fcore.git maildir: When saving messages, in some race conditions we might have written a duplicate UID. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index 9fdd5c46df..d00d08574b 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -555,6 +555,11 @@ int mail_index_set_error(struct mail_index *index, const char *fmt, ...) return -1; } +bool mail_index_is_in_memory(struct mail_index *index) +{ + return MAIL_INDEX_IS_IN_MEMORY(index); +} + int mail_index_move_to_memory(struct mail_index *index) { struct mail_index_map *map; diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index fa25f9e3d9..1ab8090797 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -206,6 +206,8 @@ int mail_index_open_or_create(struct mail_index *index, enum file_lock_method lock_method); void mail_index_close(struct mail_index *index); +/* Returns TRUE if index is currently in memory. */ +bool mail_index_is_in_memory(struct mail_index *index); /* Move the index into memory. Returns 0 if ok, -1 if error occurred. */ int mail_index_move_to_memory(struct mail_index *index); /* Returns TRUE if index is currently in memory. */ diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index b8bddef275..5f8d128a2b 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -820,10 +820,14 @@ int maildir_uidlist_refresh(struct maildir_uidlist *uidlist) int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist) { const struct maildir_index_header *mhdr = &uidlist->mbox->maildir_hdr; + struct mail_index *index = uidlist->mbox->ibox.index; + struct mail_index_view *view; const struct mail_index_header *hdr; struct stat st; int ret; + i_assert(UIDLIST_IS_LOCKED(uidlist)); + if (uidlist->fd != -1) return maildir_uidlist_refresh(uidlist); @@ -832,12 +836,17 @@ int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist) if (st.st_size == mhdr->uidlist_size && st.st_mtime == (time_t)mhdr->uidlist_mtime && - ST_NTIMES_EQUAL(ST_MTIME_NSEC(st), mhdr->uidlist_mtime_nsecs)) { - /* index is up-to-date */ - hdr = mail_index_get_header(uidlist->mbox->ibox.view); + ST_NTIMES_EQUAL(ST_MTIME_NSEC(st), mhdr->uidlist_mtime_nsecs) && + (!mail_index_is_in_memory(index) || st.st_mtime < ioloop_time-1)) { + /* index is up-to-date. look up the uidvalidity and next-uid + from it. we'll need to create a new view temporarily to + make sure we get the latest values. */ + view = mail_index_view_open(index); + hdr = mail_index_get_header(view); uidlist->uid_validity = hdr->uid_validity; uidlist->next_uid = hdr->next_uid; uidlist->initial_hdr_read = TRUE; + mail_index_view_close(&view); return 1; } else { return maildir_uidlist_refresh(uidlist);