From: Stephan Bosch Date: Tue, 13 Nov 2018 21:50:46 +0000 (+0100) Subject: quota: Make quota_try_alloc() suitable for moving/replacing messages X-Git-Tag: 2.4.1~129 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cba9f033db57a092c038aebcc7bd521841cd2509;p=thirdparty%2Fdovecot%2Fcore.git quota: Make quota_try_alloc() suitable for moving/replacing messages --- diff --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index 030937748c..d96fd4908e 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -295,7 +295,7 @@ static int quota_check(struct mail_save_context *ctx, struct mailbox *src_box) } const char *error; - ret = quota_try_alloc(qt, ctx->dest_mail, NULL, &error); + ret = quota_try_alloc(qt, ctx->dest_mail, NULL, NULL, &error); switch (ret) { case QUOTA_ALLOC_RESULT_OK: return 0; diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index 4ec91f0afe..c8355d3e82 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -1117,10 +1117,13 @@ static void quota_alloc_with_size(struct quota_transaction_context *ctx, } enum quota_alloc_result -quota_try_alloc(struct quota_transaction_context *ctx, struct mail *mail, +quota_try_alloc(struct quota_transaction_context *ctx, + struct mail *mail, struct mail *expunged_mail, const struct quota_overrun **overruns_r, const char **error_r) { - uoff_t size; + struct mailbox *expunged_box = (expunged_mail == NULL ? NULL : + expunged_mail->box); + uoff_t size, expunged_size = 0; const char *error; enum quota_get_result error_res; @@ -1150,9 +1153,24 @@ quota_try_alloc(struct quota_transaction_context *ctx, struct mail *mail, mail->box->vname, mail->uid, error); return QUOTA_ALLOC_RESULT_TEMPFAIL; } + if (expunged_mail != NULL && + quota_get_mail_size(ctx, expunged_mail, &expunged_size) < 0) { + enum mail_error err; + error = mailbox_get_last_internal_error( + expunged_mail->box, &err); + + if (err != MAIL_ERROR_EXPUNGED) { + *error_r = t_strdup_printf( + "Failed to get mail size (box=%s, uid=%u): %s", + expunged_mail->box->vname, + expunged_mail->uid, error); + return QUOTA_ALLOC_RESULT_TEMPFAIL; + } + } enum quota_alloc_result ret = - quota_test_alloc(ctx, size, NULL, 0, overruns_r, error_r); + quota_test_alloc(ctx, size, expunged_box, expunged_size, + overruns_r, error_r); if (ret != QUOTA_ALLOC_RESULT_OK) return ret; /* with quota_try_alloc() we want to keep track of how many bytes @@ -1161,7 +1179,7 @@ quota_try_alloc(struct quota_transaction_context *ctx, struct mail *mail, quota_alloc() or quota_free_bytes() was already used within the same transaction, but that doesn't normally happen. */ ctx->auto_updating = FALSE; - quota_alloc_with_size(ctx, size, 0); + quota_alloc_with_size(ctx, size, expunged_size); return QUOTA_ALLOC_RESULT_OK; } diff --git a/src/plugins/quota/quota.h b/src/plugins/quota/quota.h index 3861969934..466255c265 100644 --- a/src/plugins/quota/quota.h +++ b/src/plugins/quota/quota.h @@ -120,9 +120,9 @@ void quota_transaction_rollback(struct quota_transaction_context **ctx); quota_overrun which indicates which roots have overruns and how much is used. */ enum quota_alloc_result -quota_try_alloc(struct quota_transaction_context *ctx, struct mail *mail, - const struct quota_overrun **overruns_r, const char **error_r) - ATTR_NULL(3); +quota_try_alloc(struct quota_transaction_context *ctx, + struct mail *mail, struct mail *expunged_mail, + const struct quota_overrun **overruns_r, const char **error_r); /* Like quota_try_alloc(), but don't actually allocate anything. */ enum quota_alloc_result quota_test_alloc(struct quota_transaction_context *ctx, uoff_t size, diff --git a/src/plugins/trash/trash-plugin.c b/src/plugins/trash/trash-plugin.c index 3c4cfb641b..6f6b0055bb 100644 --- a/src/plugins/trash/trash-plugin.c +++ b/src/plugins/trash/trash-plugin.c @@ -99,10 +99,12 @@ const char *trash_plugin_version = DOVECOT_ABI_VERSION; static MODULE_CONTEXT_DEFINE_INIT(trash_user_module, &mail_user_module_register); -static enum quota_alloc_result(*trash_next_quota_test_alloc)( - struct quota_transaction_context *ctx, uoff_t size, - struct mailbox *expunged_box, uoff_t expunged_size, - const struct quota_overrun **overruns_r, const char **error_r); +static enum quota_alloc_result +(*trash_next_quota_test_alloc)(struct quota_transaction_context *ctx, + uoff_t size, struct mailbox *expunged_box, + uoff_t expunged_size, + const struct quota_overrun **overruns_r, + const char **error_r); static void trash_clean_init(struct trash_clean *tclean,