]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Mailbox deletion: Fixed race condition where a mailbox couldn't get deleted.
authorTimo Sirainen <tss@iki.fi>
Tue, 9 Feb 2010 15:35:14 +0000 (17:35 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 9 Feb 2010 15:35:14 +0000 (17:35 +0200)
--HG--
branch : HEAD

12 files changed:
src/lib-index/mail-index-sync.c
src/lib-index/mail-index.h
src/lib-storage/index/cydir/cydir-sync.c
src/lib-storage/index/dbox-multi/mdbox-sync.c
src/lib-storage/index/dbox-single/sdbox-sync.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/index-sync.c
src/lib-storage/index/maildir/maildir-sync-index.c
src/lib-storage/index/mbox/mbox-sync.c
src/lib-storage/index/raw/raw-sync.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c

index e6aa104b0ad21b1fb366012081f220bf43106794..710f946fba1a8113f5f16466d939bb155397ce24 100644 (file)
@@ -774,11 +774,13 @@ int mail_index_sync_commit(struct mail_index_sync_ctx **_ctx)
         struct mail_index_sync_ctx *ctx = *_ctx;
        struct mail_index *index = ctx->index;
        uint32_t next_uid;
-       bool want_rotate, index_undeleted;
+       bool want_rotate, index_undeleted, delete_index;
        int ret = 0;
 
        index_undeleted = ctx->ext_trans->index_undeleted;
-       if (index->index_delete_requested && !index_undeleted) {
+       delete_index = index->index_delete_requested && !index_undeleted &&
+               (ctx->flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) != 0;
+       if (delete_index) {
                /* finish this sync by marking the index deleted */
                mail_index_set_deleted(ctx->ext_trans);
        }
@@ -806,12 +808,12 @@ int mail_index_sync_commit(struct mail_index_sync_ctx **_ctx)
                return -1;
        }
 
-       if (index_undeleted) {
+       if (delete_index)
+               index->index_deleted = TRUE;
+       else if (index_undeleted) {
                index->index_deleted = FALSE;
                index->index_delete_requested = FALSE;
        }
-       if (index->index_delete_requested)
-               index->index_deleted = TRUE;
 
        /* refresh the mapping with newly committed external transactions
           and the synced expunges. sync using file handler here so that the
index f2c857cae37dc70555e4fd4b9159c4db1311d8c4..41fc63014e814443c71fbc448f268df2fe7ccf7b 100644 (file)
@@ -143,7 +143,9 @@ enum mail_index_sync_flags {
           return 0 in mail_index_sync_begin() */
        MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES    = 0x08,
        /* Create the transaction with FSYNC flag */
-       MAIL_INDEX_SYNC_FLAG_FSYNC              = 0x10
+       MAIL_INDEX_SYNC_FLAG_FSYNC              = 0x10,
+       /* If we see "delete index" request transaction, finish it */
+       MAIL_INDEX_SYNC_FLAG_DELETING_INDEX     = 0x20
 };
 
 enum mail_index_view_sync_flags {
index a693e6957be3c0b0e476a51b058a97deb47ce616..e8897bf8b6854285de88c4041e492a1cc40d3631 100644 (file)
@@ -116,9 +116,8 @@ int cydir_sync_begin(struct cydir_mailbox *mbox,
        ctx = i_new(struct cydir_sync_context, 1);
        ctx->mbox = mbox;
 
-       sync_flags = MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
-       if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       sync_flags = index_storage_get_sync_flags(&mbox->box) |
+               MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
        if (!force)
                sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
 
index d72f9096371d5624a6e24f71ecdc22d1013b4e8d..dbe71bfd1b948e57f90494c5c39716832ede5fdd 100644 (file)
@@ -185,7 +185,7 @@ int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags,
 {
        struct mail_storage *storage = mbox->box.storage;
        struct mdbox_sync_context *ctx;
-       enum mail_index_sync_flags sync_flags = 0;
+       enum mail_index_sync_flags sync_flags;
        unsigned int i;
        int ret;
        bool rebuild, storage_rebuilt = FALSE;
@@ -203,8 +203,7 @@ int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags,
        ctx->mbox = mbox;
        ctx->flags = flags;
 
-       if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       sync_flags = index_storage_get_sync_flags(&mbox->box);
        if (!rebuild && (flags & MDBOX_SYNC_FLAG_FORCE) == 0)
                sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
        if ((flags & MDBOX_SYNC_FLAG_FSYNC) != 0)
index 7714271d1f4a66e714897dd2da2d8ade6291b0fe..3886debd7ce18f77cfd368bd1a46f431873c0c8e 100644 (file)
@@ -166,7 +166,7 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
 {
        struct mail_storage *storage = mbox->box.storage;
        struct sdbox_sync_context *ctx;
-       enum mail_index_sync_flags sync_flags = 0;
+       enum mail_index_sync_flags sync_flags;
        unsigned int i;
        int ret;
        bool rebuild;
@@ -178,8 +178,7 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
        ctx->mbox = mbox;
        ctx->flags = flags;
 
-       if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       sync_flags = index_storage_get_sync_flags(&mbox->box);
        if (!rebuild && (flags & SDBOX_SYNC_FLAG_FORCE) == 0)
                sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
        if ((flags & SDBOX_SYNC_FLAG_FSYNC) != 0)
index 7731c6a9e3ccf64cf2bc9a528019878ad4761d1b..ccc9969453cf87b77695120eb88eeacc220b092c 100644 (file)
@@ -104,6 +104,7 @@ void index_mailbox_reset_uidvalidity(struct mailbox *box);
 void index_mailbox_check_add(struct mailbox *box, const char *path);
 void index_mailbox_check_remove_all(struct mailbox *box);
 
+enum mail_index_sync_flags index_storage_get_sync_flags(struct mailbox *box);
 bool index_mailbox_want_full_sync(struct mailbox *box,
                                  enum mailbox_sync_flags flags);
 struct mailbox_sync_context *
index 30e7cb518b6f148bd529caf900e1fdcea3ff67ab..325d7adf9f672dd35fc0527c769b2e4e95ba57f7 100644 (file)
@@ -6,6 +6,17 @@
 #include "array.h"
 #include "index-sync-private.h"
 
+enum mail_index_sync_flags index_storage_get_sync_flags(struct mailbox *box)
+{
+       enum mail_index_sync_flags sync_flags = 0;
+
+       if ((box->flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
+               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       if (box->deleting)
+               sync_flags |= MAIL_INDEX_SYNC_FLAG_DELETING_INDEX;
+       return sync_flags;
+}
+
 bool index_mailbox_want_full_sync(struct mailbox *box,
                                  enum mailbox_sync_flags flags)
 {
index 4c7e6b93cb121c397bb48ea29f0f6cdf2e147003..2b3dd1c8f31d02c7e70a6a97425bd9748aef71bd 100644 (file)
@@ -219,11 +219,10 @@ int maildir_sync_index_begin(struct maildir_mailbox *mbox,
        struct mail_index_transaction *trans;
        enum mail_index_sync_flags sync_flags;
 
-       sync_flags = 0;
+       sync_flags = index_storage_get_sync_flags(&mbox->box);
        /* don't drop recent messages if we're saving messages */
-       if ((_box->flags & MAILBOX_FLAG_KEEP_RECENT) == 0 &&
-           maildir_sync_ctx != NULL)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       if (maildir_sync_ctx == NULL)
+               sync_flags &= ~MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
 
        if (mail_index_sync_begin(_box->index, &sync_ctx, &view,
                                  &trans, sync_flags) < 0) {
index 6efb86d7d54c80a3cc149a4bfe6dd7367d3665f3..cf226acb559980d568d50fe38076a4a5af139487 100644 (file)
@@ -1792,9 +1792,7 @@ again:
                }
        }
 
-       sync_flags = 0;
-       if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
+       sync_flags = index_storage_get_sync_flags(&mbox->box);
        if ((flags & MBOX_SYNC_REWRITE) != 0)
                sync_flags |= MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
 
index 4c7d88bf6d27cce83e34eaf7c9e3d829e359911d..a758022c68ad69adad30766be6c16374b0f5d785 100644 (file)
@@ -16,10 +16,9 @@ static int raw_sync(struct raw_mailbox *mbox)
 
        i_assert(!mbox->synced);
 
-       sync_flags = MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY |
+       sync_flags = index_storage_get_sync_flags(&mbox->box) |
+               MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY |
                MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
-       if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
-               sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
 
        ret = mail_index_sync_begin(mbox->box.index, &index_sync_ctx,
                                    &sync_view, &trans, sync_flags);
index f1cde503d9dac44a7d6449f060eba4fceaa34bb5..61e68ad38e17925b619ee0b59ec9bd2538464b8b 100644 (file)
@@ -256,6 +256,8 @@ struct mailbox {
        unsigned int mailbox_deleted:1;
        /* we've discovered there aren't enough permissions to modify mailbox */
        unsigned int backend_readonly:1;
+       /* Mailbox is being deleted */
+       unsigned int deleting:1;
 };
 
 struct mail_vfuncs {
index 4490b820da12bbbefcbf57771589aca764707462..d0fff9373b5f9f95d4876efa6745c11ead6a8b8c 100644 (file)
@@ -615,6 +615,7 @@ int mailbox_delete(struct mailbox *box)
                return -1;
        }
 
+       box->deleting = TRUE;
        if (mailbox_open(box) < 0) {
                (void)mail_storage_get_last_error(box->storage, &error);
                if (error != MAIL_ERROR_NOTFOUND)
@@ -625,6 +626,8 @@ int mailbox_delete(struct mailbox *box)
                        return -1;
        }
        ret = box->v.delete(box);
+
+       box->deleting = FALSE;
        mailbox_close(box);
        return ret;
 }