]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Make quota_try_alloc() suitable for moving/replacing messages
authorStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 13 Nov 2018 21:50:46 +0000 (22:50 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 26 Feb 2025 10:45:00 +0000 (10:45 +0000)
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c
src/plugins/quota/quota.h
src/plugins/trash/trash-plugin.c

index 030937748c6adc4cf7f04efcb9064a494687a29b..d96fd4908eda8f469d10ff23a3ccd195bdb75ca2 100644 (file)
@@ -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;
index 4ec91f0afe30dfea59530b28c0685b3e4bc6e578..c8355d3e82ee518a23ddd92dbd14c308981c4d95 100644 (file)
@@ -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;
 }
 
index 386196993478160c6f80cfef170e7f6f6e7807ec..466255c265b82193d2849fef35817c87d5445512 100644 (file)
@@ -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,
index 3c4cfb641b16db62c165eb60c915bbf9a165aa80..6f6b0055bba27e7f0ea854ce3173aabb0f5de853 100644 (file)
@@ -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,