const char *value, const char **error_r);
bool quota_warning_match(const struct quota_warning_rule *w,
uint64_t bytes_before, uint64_t bytes_current,
- uint64_t count_before, uint64_t count_current);
+ uint64_t count_before, uint64_t count_current,
+ const char **reason_r);
bool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size);
int quota_transaction_set_limits(struct quota_transaction_context *ctx);
bool quota_warning_match(const struct quota_warning_rule *w,
uint64_t bytes_before, uint64_t bytes_current,
- uint64_t count_before, uint64_t count_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))
if (!w->reverse) {
/* over quota (default) */
- return QUOTA_EXCEEDED(bytes_before, bytes_current, w->rule.bytes_limit) ||
- QUOTA_EXCEEDED(count_before, count_current, w->rule.count_limit);
+ if (QUOTA_EXCEEDED(bytes_before, bytes_current, w->rule.bytes_limit)) {
+ *reason_r = t_strdup_printf("bytes=%llu -> %llu over limit %llu",
+ (unsigned long long)bytes_before,
+ (unsigned long long)bytes_current,
+ (unsigned long long)w->rule.bytes_limit);
+ return TRUE;
+ }
+ if (QUOTA_EXCEEDED(count_before, count_current, w->rule.count_limit)) {
+ *reason_r = t_strdup_printf("count=%llu -> %llu over limit %llu",
+ (unsigned long long)count_before,
+ (unsigned long long)count_current,
+ (unsigned long long)w->rule.count_limit);
+ return TRUE;
+ }
} else {
- return QUOTA_EXCEEDED(bytes_current, bytes_before, w->rule.bytes_limit) ||
- QUOTA_EXCEEDED(count_current, count_before, w->rule.count_limit);
+ if (QUOTA_EXCEEDED(bytes_current, bytes_before, w->rule.bytes_limit)) {
+ *reason_r = t_strdup_printf("bytes=%llu -> %llu below limit %llu",
+ (unsigned long long)bytes_before,
+ (unsigned long long)bytes_current,
+ (unsigned long long)w->rule.bytes_limit);
+ return TRUE;
+ }
+ if (QUOTA_EXCEEDED(count_current, count_before, w->rule.count_limit)) {
+ *reason_r = t_strdup_printf("count=%llu -> %llu below limit %llu",
+ (unsigned long long)count_before,
+ (unsigned long long)count_current,
+ (unsigned long long)w->rule.count_limit);
+ return TRUE;
+ }
}
+ return FALSE;
}
bool quota_transaction_is_over(struct quota_transaction_context *ctx,
}
static void quota_warning_execute(struct quota_root *root, const char *cmd,
- const char *last_arg)
+ const char *last_arg, const char *reason)
{
const char *socket_path, *const *args, *error, *scheme, *ptr;
restrict_access_init(&set.restrict_set);
if (root->quota->set->debug)
- i_debug("quota: Executing warning: %s", cmd);
+ i_debug("quota: Executing warning: %s (because %s)", cmd, reason);
args = t_strsplit_spaces(cmd, " ");
if (last_arg != NULL) {
unsigned int i, count;
uint64_t bytes_current, bytes_before, bytes_limit;
uint64_t count_current, count_before, count_limit;
+ const char *reason;
warnings = array_get_modifiable(&root->set->warning_rules, &count);
if (count == 0)
for (i = 0; i < count; i++) {
if (quota_warning_match(&warnings[i],
bytes_before, bytes_current,
- count_before, count_current)) {
- quota_warning_execute(root, warnings[i].command, NULL);
+ count_before, count_current,
+ &reason)) {
+ quota_warning_execute(root, warnings[i].command,
+ NULL, reason);
break;
}
}
if (cur_overquota != root->quota_over_flag_status) {
name = t_strconcat(root->set->set_name, "_over_script", NULL);
overquota_script = mail_user_plugin_getenv(root->quota->user, name);
- if (overquota_script != NULL)
- quota_warning_execute(root, overquota_script, root->quota_over_flag);
+ if (overquota_script != NULL) {
+ quota_warning_execute(root, overquota_script,
+ root->quota_over_flag,
+ "quota_over_flag mismatch");
+ }
}
}