From 3f91e60401495a4046c73992fabaa5e77200a451 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 9 Feb 2010 17:35:14 +0200 Subject: [PATCH] Mailbox deletion: Fixed race condition where a mailbox couldn't get deleted. --HG-- branch : HEAD --- src/lib-index/mail-index-sync.c | 12 +++++++----- src/lib-index/mail-index.h | 4 +++- src/lib-storage/index/cydir/cydir-sync.c | 5 ++--- src/lib-storage/index/dbox-multi/mdbox-sync.c | 5 ++--- src/lib-storage/index/dbox-single/sdbox-sync.c | 5 ++--- src/lib-storage/index/index-storage.h | 1 + src/lib-storage/index/index-sync.c | 11 +++++++++++ src/lib-storage/index/maildir/maildir-sync-index.c | 7 +++---- src/lib-storage/index/mbox/mbox-sync.c | 4 +--- src/lib-storage/index/raw/raw-sync.c | 5 ++--- src/lib-storage/mail-storage-private.h | 2 ++ src/lib-storage/mail-storage.c | 3 +++ 12 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c index e6aa104b0a..710f946fba 100644 --- a/src/lib-index/mail-index-sync.c +++ b/src/lib-index/mail-index-sync.c @@ -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 diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index f2c857cae3..41fc63014e 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -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 { diff --git a/src/lib-storage/index/cydir/cydir-sync.c b/src/lib-storage/index/cydir/cydir-sync.c index a693e6957b..e8897bf8b6 100644 --- a/src/lib-storage/index/cydir/cydir-sync.c +++ b/src/lib-storage/index/cydir/cydir-sync.c @@ -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; diff --git a/src/lib-storage/index/dbox-multi/mdbox-sync.c b/src/lib-storage/index/dbox-multi/mdbox-sync.c index d72f909637..dbe71bfd1b 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-sync.c +++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c @@ -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) diff --git a/src/lib-storage/index/dbox-single/sdbox-sync.c b/src/lib-storage/index/dbox-single/sdbox-sync.c index 7714271d1f..3886debd7c 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync.c @@ -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) diff --git a/src/lib-storage/index/index-storage.h b/src/lib-storage/index/index-storage.h index 7731c6a9e3..ccc9969453 100644 --- a/src/lib-storage/index/index-storage.h +++ b/src/lib-storage/index/index-storage.h @@ -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 * diff --git a/src/lib-storage/index/index-sync.c b/src/lib-storage/index/index-sync.c index 30e7cb518b..325d7adf9f 100644 --- a/src/lib-storage/index/index-sync.c +++ b/src/lib-storage/index/index-sync.c @@ -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) { diff --git a/src/lib-storage/index/maildir/maildir-sync-index.c b/src/lib-storage/index/maildir/maildir-sync-index.c index 4c7e6b93cb..2b3dd1c8f3 100644 --- a/src/lib-storage/index/maildir/maildir-sync-index.c +++ b/src/lib-storage/index/maildir/maildir-sync-index.c @@ -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) { diff --git a/src/lib-storage/index/mbox/mbox-sync.c b/src/lib-storage/index/mbox/mbox-sync.c index 6efb86d7d5..cf226acb55 100644 --- a/src/lib-storage/index/mbox/mbox-sync.c +++ b/src/lib-storage/index/mbox/mbox-sync.c @@ -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; diff --git a/src/lib-storage/index/raw/raw-sync.c b/src/lib-storage/index/raw/raw-sync.c index 4c7d88bf6d..a758022c68 100644 --- a/src/lib-storage/index/raw/raw-sync.c +++ b/src/lib-storage/index/raw/raw-sync.c @@ -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); diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index f1cde503d9..61e68ad38e 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -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 { diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 4490b820da..d0fff9373b 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -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; } -- 2.47.3