]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
race condition fixes
authorTimo Sirainen <tss@iki.fi>
Mon, 24 May 2004 02:47:23 +0000 (05:47 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 24 May 2004 02:47:23 +0000 (05:47 +0300)
--HG--
branch : HEAD

src/lib-storage/index/maildir/maildir-sync.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/index/maildir/maildir-uidlist.h

index 782e80898df3c518f78e574fbb4dba496d4903ca..80c3136d7e7fd51cb5359bf5ef3d62fc24256493 100644 (file)
@@ -629,15 +629,33 @@ static int maildir_sync_index(struct maildir_sync_context *ctx)
 
                if (seq > hdr->messages_count) {
                        if (uid < hdr->next_uid) {
-                               /* message not in index, but next_uid header
-                                  is updated? shouldn't really happen.. */
-                               mail_storage_set_critical(ibox->box.storage,
-                                       "Maildir sync: UID < next_uid "
-                                       "(%u < %u, file = %s)",
-                                       uid, hdr->next_uid, filename);
-                               mail_index_mark_corrupted(ibox->index);
-                               ret = -1;
-                               break;
+                               /* most likely a race condition: we read the
+                                  maildir, then someone else expunged messages
+                                  and committed changes to index. so, this
+                                  message shouldn't actually exist. mark it
+                                  racy and check in next sync.
+
+                                  the difference between this and the later
+                                  check is that this one happens when messages
+                                  are expunged from the end */
+                               if ((uflags &
+                                    MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
+                                       mail_storage_set_critical(
+                                               ibox->box.storage,
+                                               "Maildir sync: UID < next_uid "
+                                               "(%u < %u, file = %s)",
+                                               uid, hdr->next_uid, filename);
+                                       mail_index_mark_corrupted(ibox->index);
+                                       ret = -1;
+                                       break;
+                               }
+                               ibox->dirty_cur_time = ioloop_time;
+                               maildir_uidlist_add_flags(ibox->uidlist,
+                                       filename,
+                                       MAILDIR_UIDLIST_REC_FLAG_RACING);
+
+                               seq--;
+                               continue;
                        }
 
                        mail_index_append(trans, uid, &seq);
@@ -661,20 +679,9 @@ static int maildir_sync_index(struct maildir_sync_context *ctx)
                        /* most likely a race condition: we read the
                           maildir, then someone else expunged messages and
                           committed changes to index. so, this message
-                          shouldn't actually exist. check to be sure.
-
-                          FIXME: we could avoid this stat() and just mark
-                          this check in the uidlist and check it at next
-                          sync.. */
-                       struct stat st;
-                       const char *str;
-
-                       t_push();
-                       str = t_strdup_printf("%s/%s",
-                               (uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) ?
-                               ctx->new_dir : ctx->cur_dir, filename);
-                       if (stat(str, &st) == 0) {
-                               t_pop();
+                          shouldn't actually exist. mark it racy and check
+                          in next sync. */
+                       if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
                                mail_storage_set_critical(ibox->box.storage,
                                        "Maildir sync: UID inserted in the "
                                        "middle of mailbox "
@@ -683,8 +690,11 @@ static int maildir_sync_index(struct maildir_sync_context *ctx)
                                mail_index_mark_corrupted(ibox->index);
                                ret = -1;
                                break;
-                       }
-                       t_pop();
+                        }
+
+                       ibox->dirty_cur_time = ioloop_time;
+                       maildir_uidlist_add_flags(ibox->uidlist, filename,
+                               MAILDIR_UIDLIST_REC_FLAG_RACING);
 
                        seq--;
                        continue;
index a1f169300950b175b610a44c5b1169629ec5ca4a..7d519c5a3b17f4e27d51a6303aa38fcfb3239219 100644 (file)
@@ -848,6 +848,18 @@ int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx)
        return ret;
 }
 
+void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist,
+                              const char *filename,
+                              enum maildir_uidlist_rec_flag flags)
+{
+       struct maildir_uidlist_rec *rec;
+
+       rec = hash_lookup(uidlist->files, filename);
+       i_assert(rec != NULL);
+
+       rec->flags |= flags;
+}
+
 struct maildir_uidlist_iter_ctx *
 maildir_uidlist_iter_init(struct maildir_uidlist *uidlist)
 {
index c08ac9a6ca06697fc0320d62e0c2f6c9c311acad..63a0fa0be0696c9973c6aa9c3bbd3df711d7dbc9 100644 (file)
@@ -7,7 +7,8 @@ enum maildir_uidlist_rec_flag {
        MAILDIR_UIDLIST_REC_FLAG_NEW_DIR        = 0x01,
        MAILDIR_UIDLIST_REC_FLAG_MOVED          = 0x02,
        MAILDIR_UIDLIST_REC_FLAG_RECENT         = 0x04,
-       MAILDIR_UIDLIST_REC_FLAG_NONSYNCED      = 0x08
+       MAILDIR_UIDLIST_REC_FLAG_NONSYNCED      = 0x08,
+       MAILDIR_UIDLIST_REC_FLAG_RACING         = 0x10
 };
 
 int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist);
@@ -47,6 +48,10 @@ int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx,
 int maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx);
 int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx);
 
+void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist,
+                              const char *filename,
+                              enum maildir_uidlist_rec_flag flags);
+
 /* List all maildir files. */
 struct maildir_uidlist_iter_ctx *
 maildir_uidlist_iter_init(struct maildir_uidlist *uidlist);