[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-save.c, 1.55, 1.56

cras at dovecot.org cras at dovecot.org
Fri Jul 22 13:15:00 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv19398

Modified Files:
	maildir-save.c 
Log Message:
Fix potential deadlocking while saving messages.



Index: maildir-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- maildir-save.c	12 Jul 2005 12:45:06 -0000	1.55
+++ maildir-save.c	22 Jul 2005 10:14:58 -0000	1.56
@@ -33,6 +33,7 @@
 	struct maildir_mailbox *mbox;
 	struct mail_index_transaction *trans;
 	struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
+	struct maildir_index_sync_context *sync_ctx;
 
 	const char *tmpdir, *newdir, *curdir;
 	struct maildir_filename *files;
@@ -309,7 +310,6 @@
 
 static const char *
 maildir_get_updated_filename(struct maildir_save_context *ctx,
-			     struct maildir_index_sync_context *sync_ctx,
 			     struct maildir_filename *mf)
 {
 	if (mf->flags == MAIL_RECENT && mf->keywords_count == 0)
@@ -317,13 +317,12 @@
 
 	buffer_update_const_data(ctx->keywords_buffer, mf + 1,
 				 mf->keywords_count * sizeof(unsigned int));
-	return maildir_filename_set_flags(sync_ctx, mf->basename,
+	return maildir_filename_set_flags(ctx->sync_ctx, mf->basename,
 					  mf->flags, &ctx->keywords_array);
 }
 
 static void
 maildir_save_commit_abort(struct maildir_save_context *ctx,
-			  struct maildir_index_sync_context *sync_ctx,
 			  struct maildir_filename *pos)
 {
 	struct maildir_filename *mf;
@@ -332,7 +331,7 @@
 	/* try to unlink the mails already moved */
 	for (mf = ctx->files; mf != pos; mf = mf->next) {
 		t_push();
-		dest = maildir_get_updated_filename(ctx, sync_ctx, mf);
+		dest = maildir_get_updated_filename(ctx, mf);
 		if (dest != NULL)
 			path = t_strdup_printf("%s/%s", ctx->curdir, dest);
 		else {
@@ -348,7 +347,6 @@
 
 int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx)
 {
-	struct maildir_index_sync_context *sync_ctx;
 	struct maildir_filename *mf;
 	uint32_t first_uid, last_uid;
 	enum maildir_uidlist_rec_flag flags;
@@ -357,17 +355,17 @@
 
 	i_assert(ctx->output == NULL);
 
-	sync_ctx = maildir_sync_index_begin(ctx->mbox);
-	if (sync_ctx == NULL) {
-		maildir_save_commit_abort(ctx, sync_ctx, ctx->files);
+	ctx->sync_ctx = maildir_sync_index_begin(ctx->mbox);
+	if (ctx->sync_ctx == NULL) {
+		maildir_save_commit_abort(ctx, ctx->files);
 		return -1;
 	}
 
 	ret = maildir_uidlist_lock(ctx->mbox->uidlist);
 	if (ret <= 0) {
 		/* error or timeout - our transaction is broken */
-		maildir_sync_index_abort(sync_ctx);
-		maildir_save_commit_abort(ctx, sync_ctx, ctx->files);
+		maildir_sync_index_abort(ctx->sync_ctx);
+		maildir_save_commit_abort(ctx, ctx->files);
 		return -1;
 	}
 
@@ -386,13 +384,13 @@
 	ret = 0;
 	for (mf = ctx->files; mf != NULL; mf = mf->next) {
 		t_push();
-		dest = maildir_get_updated_filename(ctx, sync_ctx, mf);
+		dest = maildir_get_updated_filename(ctx, mf);
 		fname = dest != NULL ? dest : mf->basename;
 
 		if (maildir_file_move(ctx, mf->basename, dest) < 0 ||
 		    maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
 					      fname, flags) < 0) {
-			maildir_save_commit_abort(ctx, sync_ctx, mf);
+			maildir_save_commit_abort(ctx, mf);
 			t_pop();
 			ret = -1;
 			break;
@@ -413,7 +411,6 @@
 		ctx->uidlist_sync_ctx = NULL;
 	}
 
-	maildir_sync_index_abort(sync_ctx);
 	return ret;
 }
 
@@ -422,6 +419,10 @@
 	/* can't do anything anymore if we fail */
 	(void)maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
 
+	/* to avoid deadlocks uidlist must not be left locked without index
+	   being locked, so we can't put call to save_commit_pre(). */
+	maildir_sync_index_abort(ctx->sync_ctx);
+
 	pool_unref(ctx->pool);
 }
 



More information about the dovecot-cvs mailing list