dovecot-1.1: maildir: When saving messages, in some race conditi...

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 14 01:23:43 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.1/rev/fe49fbf6da11
changeset: 8245:fe49fbf6da11
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Apr 13 18:23:37 2009 -0400
description:
maildir: When saving messages, in some race conditions we might have written a duplicate UID.

diffstat:

3 files changed, 19 insertions(+), 3 deletions(-)
src/lib-index/mail-index.c                      |    5 +++++
src/lib-index/mail-index.h                      |    2 ++
src/lib-storage/index/maildir/maildir-uidlist.c |   15 ++++++++++++---

diffs (66 lines):

diff -r 732acf7d13c1 -r fe49fbf6da11 src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c	Mon Apr 13 18:21:24 2009 -0400
+++ b/src/lib-index/mail-index.c	Mon Apr 13 18:23:37 2009 -0400
@@ -535,6 +535,11 @@ int mail_index_set_error(struct mail_ind
 	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 -r 732acf7d13c1 -r fe49fbf6da11 src/lib-index/mail-index.h
--- a/src/lib-index/mail-index.h	Mon Apr 13 18:21:24 2009 -0400
+++ b/src/lib-index/mail-index.h	Mon Apr 13 18:23:37 2009 -0400
@@ -185,6 +185,8 @@ int mail_index_open(struct mail_index *i
 		    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);
 
diff -r 732acf7d13c1 -r fe49fbf6da11 src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Apr 13 18:21:24 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Apr 13 18:23:37 2009 -0400
@@ -813,10 +813,14 @@ int maildir_uidlist_refresh_fast_init(st
 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);
 
@@ -825,12 +829,17 @@ int maildir_uidlist_refresh_fast_init(st
 
 	if ((uoff_t)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);


More information about the dovecot-cvs mailing list