[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