changeset 10678:9740c4858a57 HEAD

Mailbox deletion: Fixed race condition where a mailbox couldn't get deleted.
author Timo Sirainen <tss@iki.fi>
date Tue, 09 Feb 2010 17:35:14 +0200
parents 93fe3aa23bdb
children 3712e2dcc856
files 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
diffstat 12 files changed, 39 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-index/mail-index-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -774,11 +774,13 @@
         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 @@
 		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
--- a/src/lib-index/mail-index.h	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-index/mail-index.h	Tue Feb 09 17:35:14 2010 +0200
@@ -143,7 +143,9 @@
 	   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 {
--- a/src/lib-storage/index/cydir/cydir-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -116,9 +116,8 @@
 	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;
 
--- a/src/lib-storage/index/dbox-multi/mdbox-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -185,7 +185,7 @@
 {
 	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 @@
 	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)
--- a/src/lib-storage/index/dbox-single/sdbox-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -166,7 +166,7 @@
 {
 	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 @@
 	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)
--- a/src/lib-storage/index/index-storage.h	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/index-storage.h	Tue Feb 09 17:35:14 2010 +0200
@@ -104,6 +104,7 @@
 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 *
--- a/src/lib-storage/index/index-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/index-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -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)
 {
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Tue Feb 09 17:35:14 2010 +0200
@@ -219,11 +219,10 @@
 	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) {
--- a/src/lib-storage/index/mbox/mbox-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -1792,9 +1792,7 @@
 		}
 	}
 
-	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;
 
--- a/src/lib-storage/index/raw/raw-sync.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/index/raw/raw-sync.c	Tue Feb 09 17:35:14 2010 +0200
@@ -16,10 +16,9 @@
 
 	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);
--- a/src/lib-storage/mail-storage-private.h	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/mail-storage-private.h	Tue Feb 09 17:35:14 2010 +0200
@@ -256,6 +256,8 @@
 	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 {
--- a/src/lib-storage/mail-storage.c	Tue Feb 09 04:52:29 2010 +0200
+++ b/src/lib-storage/mail-storage.c	Tue Feb 09 17:35:14 2010 +0200
@@ -615,6 +615,7 @@
 		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 @@
 			return -1;
 	}
 	ret = box->v.delete(box);
+
+	box->deleting = FALSE;
 	mailbox_close(box);
 	return ret;
 }