From: Timo Sirainen Date: Thu, 15 Aug 2024 12:33:51 +0000 (+0300) Subject: quota: Delay calculating percentage-based quota limits X-Git-Tag: 2.4.0~403 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f33c6430118dd9ee5bfbd0bffb4eeaef0a4eb3a1;p=thirdparty%2Fdovecot%2Fcore.git quota: Delay calculating percentage-based quota limits This simplifies the following changes. --- diff --git a/src/plugins/quota/quota-fs.c b/src/plugins/quota/quota-fs.c index 5995a4e2c4..56562c5329 100644 --- a/src/plugins/quota/quota-fs.c +++ b/src/plugins/quota/quota-fs.c @@ -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; } diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index b9c32ab592..d4f38a91a7 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -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); diff --git a/src/plugins/quota/quota-util.c b/src/plugins/quota/quota-util.c index c4803efa29..a4050be8ea 100644 --- a/src/plugins/quota/quota-util.c +++ b/src/plugins/quota/quota-util.c @@ -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; } } diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index fa5776fb9c..115d64c9c3 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -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)) {