# HG changeset patch # User Timo Sirainen # Date 1470845756 -10800 # Node ID c5438de8fc7f8e5d9d591d5f7a32b27e631559e1 # Parent 464988cb39802ec179703380d35a51d0c9ac1e30 quota: If quota lookup updates vsize header, lock it earlier to avoid a deadlock. diff -r 464988cb3980 -r c5438de8fc7f src/plugins/quota/quota-private.h --- 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 diff -r 464988cb3980 -r c5438de8fc7f src/plugins/quota/quota-storage.c --- 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); } diff -r 464988cb3980 -r c5438de8fc7f src/plugins/quota/quota.c --- 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,