]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Delay calculating percentage-based quota limits
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 15 Aug 2024 12:33:51 +0000 (15:33 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:00 +0000 (10:40 +0200)
This simplifies the following changes.

src/plugins/quota/quota-fs.c
src/plugins/quota/quota-private.h
src/plugins/quota/quota-util.c
src/plugins/quota/quota.c

index 5995a4e2c4a9a21ac6a459a2d99d83f033e33669..56562c5329ad0bc3359c584486b06b2d8bdd30e2 100644 (file)
@@ -940,11 +940,6 @@ fs_quota_get_resource(struct quota_root *_root, const char *name,
                /* update limit */
                _root->bytes_limit = bytes_limit;
                _root->count_limit = count_limit;
-
-               /* limits have changed, so we'll need to recalculate
-                  relative quota rules */
-               quota_root_recalculate_relative_rules(_root->backend.event,
-                       _root->set, bytes_limit, count_limit);
        }
        return QUOTA_GET_RESULT_LIMITED;
 }
index b9c32ab59296531f40505963c70aee8e9ecbac1f..d4f38a91a780a52a526605d1e02d7d0017982209 100644 (file)
@@ -188,10 +188,6 @@ bool quota_root_is_namespace_visible(struct quota_root *root,
 struct quota_rule *
 quota_root_rule_find(struct quota_root_settings *root_set, const char *name);
 
-void quota_root_recalculate_relative_rules(struct event *event,
-                                          struct quota_root_settings *root_set,
-                                          int64_t bytes_limit,
-                                          int64_t count_limit);
 /* Returns 1 if values were returned successfully, 0 if we're recursing into
    the same function, -1 if error. */
 int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r,
@@ -200,7 +196,8 @@ int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r,
 int quota_root_parse_grace(struct event *event,
                           struct quota_root_settings *root_set,
                           const char *value, const char **error_r);
-bool quota_warning_match(const struct quota_warning_rule *w,
+bool quota_warning_match(struct quota_root *root,
+                        const struct quota_warning_rule *w,
                         uint64_t bytes_before, uint64_t bytes_current,
                         uint64_t count_before, uint64_t count_current,
                         const char **reason_r);
index c4803efa29dfeb0425905996106bbabb79fa5325..a4050be8eaf713aecee1e3cc1703e5611c526dfc 100644 (file)
@@ -100,40 +100,6 @@ static int quota_limit_parse(struct quota_root_settings *root_set,
        return 0;
 }
 
-static void
-quota_rule_recalculate_relative_rules(struct quota_rule *rule,
-                                     int64_t bytes_limit, int64_t count_limit)
-{
-       if (rule->bytes_percent != 0)
-               rule->bytes_limit = bytes_limit * rule->bytes_percent / 100;
-       if (rule->count_percent != 0)
-               rule->count_limit = count_limit * rule->count_percent / 100;
-}
-
-void quota_root_recalculate_relative_rules(struct event *event,
-                                          struct quota_root_settings *root_set,
-                                          int64_t bytes_limit,
-                                          int64_t count_limit)
-{
-       struct quota_rule *rule;
-       struct quota_warning_rule *warning_rule;
-
-       array_foreach_modifiable(&root_set->rules, rule) {
-               quota_rule_recalculate_relative_rules(rule, bytes_limit,
-                                                     count_limit);
-       }
-
-       array_foreach_modifiable(&root_set->warning_rules, warning_rule) {
-               quota_rule_recalculate_relative_rules(&warning_rule->rule,
-                                                     bytes_limit, count_limit);
-       }
-
-       e_debug(event,
-               "Quota root %s: Recalculated relative rules with "
-               "bytes=%lld count=%lld.", root_set->name,
-               (long long)bytes_limit, (long long)count_limit);
-}
-
 static int
 quota_rule_parse_limits(struct event *event,
                        struct quota_root_settings *root_set,
@@ -260,9 +226,6 @@ int quota_root_add_rule(struct event *event, pool_t pool,
                                    relative_rule, error_r) < 0)
                ret = -1;
 
-       quota_root_recalculate_relative_rules(event, root_set,
-                                             root_set->default_rule.bytes_limit,
-                                             root_set->default_rule.count_limit);
        const char *rule_plus =
                rule == &root_set->default_rule ? "" : "+";
 
@@ -319,9 +282,6 @@ int quota_root_add_warning_rule(struct event *event, pool_t pool,
        warning->rule = rule;
        warning->reverse = reverse;
 
-       quota_root_recalculate_relative_rules(event, root_set,
-                                             root_set->default_rule.bytes_limit,
-                                             root_set->default_rule.count_limit);
        e_debug(event, "Quota warning: bytes=%"PRId64"%s "
                "messages=%"PRId64"%s reverse=%s command=%s",
                warning->rule.bytes_limit,
@@ -352,34 +312,41 @@ int quota_root_parse_grace(struct event *event,
        return 0;
 }
 
-bool quota_warning_match(const struct quota_warning_rule *w,
+bool quota_warning_match(struct quota_root *root,
+                        const struct quota_warning_rule *w,
                         uint64_t bytes_before, uint64_t bytes_current,
                         uint64_t count_before, uint64_t count_current,
                         const char **reason_r)
 {
 #define QUOTA_EXCEEDED(before, current, limit) \
        ((before) < (uint64_t)(limit) && (current) >= (uint64_t)(limit))
+       uint64_t bytes_limit = w->rule.bytes_percent == 0 ?
+               w->rule.bytes_limit :
+               root->bytes_limit * w->rule.bytes_percent / 100;
+       uint64_t count_limit = w->rule.count_percent == 0 ?
+               w->rule.count_limit :
+               root->count_limit * w->rule.count_percent / 100;
        if (!w->reverse) {
                /* over quota (default) */
-               if (QUOTA_EXCEEDED(bytes_before, bytes_current, w->rule.bytes_limit)) {
+               if (QUOTA_EXCEEDED(bytes_before, bytes_current, bytes_limit)) {
                        *reason_r = t_strdup_printf("bytes=%"PRIu64" -> %"PRIu64" over limit %"PRId64,
-                               bytes_before, bytes_current, w->rule.bytes_limit);
+                               bytes_before, bytes_current, bytes_limit);
                        return TRUE;
                }
-               if (QUOTA_EXCEEDED(count_before, count_current, w->rule.count_limit)) {
+               if (QUOTA_EXCEEDED(count_before, count_current, count_limit)) {
                        *reason_r = t_strdup_printf("count=%"PRIu64" -> %"PRIu64" over limit %"PRId64,
-                               count_before, count_current, w->rule.count_limit);
+                               count_before, count_current, count_limit);
                        return TRUE;
                }
        } else {
-               if (QUOTA_EXCEEDED(bytes_current, bytes_before, w->rule.bytes_limit)) {
+               if (QUOTA_EXCEEDED(bytes_current, bytes_before, bytes_limit)) {
                        *reason_r = t_strdup_printf("bytes=%"PRIu64" -> %"PRIu64" below limit %"PRId64,
-                               bytes_before, bytes_current, w->rule.bytes_limit);
+                               bytes_before, bytes_current, bytes_limit);
                        return TRUE;
                }
-               if (QUOTA_EXCEEDED(count_current, count_before, w->rule.count_limit)) {
+               if (QUOTA_EXCEEDED(count_current, count_before, count_limit)) {
                        *reason_r = t_strdup_printf("count=%"PRIu64" -> %"PRIu64" below limit %"PRId64,
-                               count_before, count_current, w->rule.count_limit);
+                               count_before, count_current, count_limit);
                        return TRUE;
                }
        }
index fa5776fb9c95c7a5c0965a541eda00442adc7a1e..115d64c9c3d1d3713258ab423ac54a8f4213ea10 100644 (file)
@@ -467,8 +467,14 @@ quota_root_get_rule_limits(struct quota_root *root, const char *mailbox_name,
 
        if (rule != NULL) {
                if (!rule->ignore) {
-                       bytes_limit += rule->bytes_limit;
-                       count_limit += rule->count_limit;
+                       if (rule->bytes_percent != 0)
+                               bytes_limit += bytes_limit * rule->bytes_percent / 100;
+                       else
+                               bytes_limit += rule->bytes_limit;
+                       if (rule->count_percent != 0)
+                               count_limit += count_limit * rule->count_percent / 100;
+                       else
+                               count_limit += rule->count_limit;
                } else {
                        bytes_limit = 0;
                        count_limit = 0;
@@ -1033,7 +1039,7 @@ static void quota_warnings_execute(struct quota_transaction_context *ctx,
        else
                count_before = (int64_t)count_current - ctx->count_used;
        for (i = 0; i < count; i++) {
-               if (quota_warning_match(&warnings[i],
+               if (quota_warning_match(root, &warnings[i],
                                        bytes_before, bytes_current,
                                        count_before, count_current,
                                        &reason)) {