Mercurial > dovecot > core-2.2
changeset 20628:c5438de8fc7f
quota: If quota lookup updates vsize header, lock it earlier to avoid a deadlock.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 10 Aug 2016 19:15:56 +0300 |
parents | 464988cb3980 |
children | e23e2b702622 |
files | src/plugins/quota/quota-private.h src/plugins/quota/quota-storage.c src/plugins/quota/quota.c |
diffstat | 3 files changed, 14 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/quota/quota-private.h Wed Aug 10 19:13:09 2016 +0300 +++ b/src/plugins/quota/quota-private.h Wed Aug 10 19:15:56 2016 +0300 @@ -210,5 +210,6 @@ uint64_t bytes_before, uint64_t bytes_current, uint64_t count_before, uint64_t count_current); bool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size); +int quota_transaction_set_limits(struct quota_transaction_context *ctx); #endif
--- a/src/plugins/quota/quota-storage.c Wed Aug 10 19:13:09 2016 +0300 +++ b/src/plugins/quota/quota-storage.c Wed Aug 10 19:15:56 2016 +0300 @@ -230,6 +230,9 @@ } ctx->dest_mail = qt->tmp_mail; } + /* get quota before copying any mails. this avoids .vsize.lock + deadlocks with backends that lock mails for expunging/copying. */ + (void)quota_transaction_set_limits(qt); if (qbox->module_ctx.super.copy(ctx, mail) < 0) return -1; @@ -284,6 +287,9 @@ } ctx->dest_mail = qt->tmp_mail; } + /* get quota before copying any mails. this avoids .vsize.lock + deadlocks with backends that lock mails for expunging/copying. */ + (void)quota_transaction_set_limits(qt); return qbox->module_ctx.super.save_begin(ctx, input); }
--- a/src/plugins/quota/quota.c Wed Aug 10 19:13:09 2016 +0300 +++ b/src/plugins/quota/quota.c Wed Aug 10 19:15:56 2016 +0300 @@ -783,7 +783,7 @@ return ctx; } -static int quota_transaction_set_limits(struct quota_transaction_context *ctx) +int quota_transaction_set_limits(struct quota_transaction_context *ctx) { struct quota_root *const *roots; const char *mailbox_name; @@ -792,6 +792,8 @@ bool use_grace, ignored; int ret; + if (ctx->limits_set) + return 0; ctx->limits_set = TRUE; mailbox_name = mailbox_get_vname(ctx->box); /* use quota_grace only for LDA/LMTP */ @@ -1101,10 +1103,8 @@ uoff_t size; int ret; - if (!ctx->limits_set) { - if (quota_transaction_set_limits(ctx) < 0) - return -1; - } + if (quota_transaction_set_limits(ctx) < 0) + return -1; if (ctx->no_quota_updates) return 1; @@ -1142,10 +1142,8 @@ if (ctx->failed) return -1; - if (!ctx->limits_set) { - if (quota_transaction_set_limits(ctx) < 0) - return -1; - } + if (quota_transaction_set_limits(ctx) < 0) + return -1; if (ctx->no_quota_updates) return 1; /* this is a virtual function mainly for trash plugin and similar,