dovecot-1.1: Relative (%) limits in quota rules and warnings wor...

dovecot at dovecot.org dovecot at dovecot.org
Tue Feb 26 16:18:45 EET 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/9e4c26471b19
changeset: 7294:9e4c26471b19
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Feb 26 16:21:05 2008 +0200
description:
Relative (%) limits in quota rules and warnings work now if the backend
specifies or changes the limits (e.g. Maildir++ maildirsize file)

diffstat:

6 files changed, 150 insertions(+), 100 deletions(-)
src/plugins/quota/quota-dict.c    |    2 
src/plugins/quota/quota-dirsize.c |    2 
src/plugins/quota/quota-fs.c      |   37 +++++++-----
src/plugins/quota/quota-maildir.c |   86 +++++++++++++---------------
src/plugins/quota/quota-private.h |   10 +--
src/plugins/quota/quota.c         |  113 +++++++++++++++++++++++++------------

diffs (truncated from 513 to 300 lines):

diff -r f78b83bf16b7 -r 9e4c26471b19 src/plugins/quota/quota-dict.c
--- a/src/plugins/quota/quota-dict.c	Tue Feb 26 15:11:34 2008 +0200
+++ b/src/plugins/quota/quota-dict.c	Tue Feb 26 16:21:05 2008 +0200
@@ -96,7 +96,7 @@ dict_quota_count(struct dict_quota_root 
 
 static int
 dict_quota_get_resource(struct quota_root *_root, const char *name,
-			uint64_t *value_r, uint64_t *limit ATTR_UNUSED)
+			uint64_t *value_r)
 {
 	struct dict_quota_root *root = (struct dict_quota_root *)_root;
 	bool want_bytes;
diff -r f78b83bf16b7 -r 9e4c26471b19 src/plugins/quota/quota-dirsize.c
--- a/src/plugins/quota/quota-dirsize.c	Tue Feb 26 15:11:34 2008 +0200
+++ b/src/plugins/quota/quota-dirsize.c	Tue Feb 26 16:21:05 2008 +0200
@@ -180,7 +180,7 @@ get_quota_root_usage(struct quota_root *
 
 static int
 dirsize_quota_get_resource(struct quota_root *_root, const char *name,
-			   uint64_t *value_r, uint64_t *limit ATTR_UNUSED)
+			   uint64_t *value_r)
 {
 	int ret;
 
diff -r f78b83bf16b7 -r 9e4c26471b19 src/plugins/quota/quota-fs.c
--- a/src/plugins/quota/quota-fs.c	Tue Feb 26 15:11:34 2008 +0200
+++ b/src/plugins/quota/quota-fs.c	Tue Feb 26 16:21:05 2008 +0200
@@ -549,14 +549,14 @@ fs_quota_get_one_resource(struct fs_quot
 
 static int
 fs_quota_get_resource(struct quota_root *_root, const char *name,
-		      uint64_t *value_r, uint64_t *limit_r)
+		      uint64_t *value_r)
 {
 	struct fs_quota_root *root = (struct fs_quota_root *)_root;
+	uint64_t limit = 0;
 	bool bytes;
 	int ret;
 
 	*value_r = 0;
-	*limit_r = 0;
 
 	if (root->mount == NULL ||
 	    (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) != 0 &&
@@ -566,22 +566,29 @@ fs_quota_get_resource(struct quota_root 
 
 #ifdef HAVE_RQUOTA
 	if (strcmp(root->mount->type, "nfs") == 0) {
-		int ret;
-
 		T_BEGIN {
-			ret = do_rquota(root, bytes, value_r, limit_r);
+			ret = do_rquota(root, bytes, value_r, &limit);
 		} T_END;
+	} else
+#endif
+	{
+		ret = fs_quota_get_one_resource(root, FALSE, bytes,
+						value_r, &limit);
+		if (ret == 0) {
+			/* fallback to group quota */
+			ret = fs_quota_get_one_resource(root, TRUE, bytes,
+							value_r, &limit);
+		}
+	}
+	if (ret <= 0)
 		return ret;
-	}
-#endif
-
-	ret = fs_quota_get_one_resource(root, FALSE, bytes,
-					value_r, limit_r);
-	if (ret != 0)
-		return ret;
-
-	/* fallback to group quota */
-	return fs_quota_get_one_resource(root, TRUE, bytes, value_r, limit_r);
+
+	/* update limit */
+	if (bytes)
+		_root->default_rule.bytes_limit = limit;
+	else
+		_root->default_rule.count_limit = limit;
+	return 1;
 }
 
 static int 
diff -r f78b83bf16b7 -r 9e4c26471b19 src/plugins/quota/quota-maildir.c
--- a/src/plugins/quota/quota-maildir.c	Tue Feb 26 15:11:34 2008 +0200
+++ b/src/plugins/quota/quota-maildir.c	Tue Feb 26 16:21:05 2008 +0200
@@ -23,8 +23,6 @@ struct maildir_quota_root {
 	struct quota_root root;
 
 	const char *maildirsize_path;
-	uint64_t message_bytes_limit;
-	uint64_t message_count_limit;
 
 	uint64_t total_bytes;
 	uint64_t total_count;
@@ -208,6 +206,7 @@ maildirs_check_have_changed(struct mail_
 
 static int maildirsize_write(struct maildir_quota_root *root, const char *path)
 {
+	const struct quota_rule *rule = &root->root.default_rule;
 	struct dotlock *dotlock;
 	string_t *str;
 	int fd;
@@ -229,15 +228,15 @@ static int maildirsize_write(struct mail
 	}
 
 	str = t_str_new(128);
-	if (root->message_bytes_limit != (uint64_t)-1) {
+	if (rule->bytes_limit != 0) {
 		str_printfa(str, "%lluS",
-			    (unsigned long long)root->message_bytes_limit);
-	}
-	if (root->message_count_limit != (uint64_t)-1) {
+			    (unsigned long long)rule->bytes_limit);
+	}
+	if (rule->count_limit != 0) {
 		if (str_len(str) > 0)
 			str_append_c(str, ',');
 		str_printfa(str, "%lluC",
-			    (unsigned long long)root->message_count_limit);
+			    (unsigned long long)rule->count_limit);
 	}
 	str_printfa(str, "\n%llu %llu\n",
 		    (unsigned long long)root->total_bytes,
@@ -352,8 +351,8 @@ maildir_parse_limit(const char *str, uin
 	char *pos;
 	bool ret = TRUE;
 
-	*bytes_r = (uint64_t)-1;
-	*count_r = (uint64_t)-1;
+	*bytes_r = 0;
+	*count_r = 0;
 
 	/* 0 values mean unlimited */
 	for (limit = t_strsplit(str, ","); *limit != NULL; limit++) {
@@ -382,6 +381,7 @@ static int maildirsize_parse(struct mail
 static int maildirsize_parse(struct maildir_quota_root *root,
 			     int fd, const char *const *lines)
 {
+	struct quota_rule *rule = &root->root.default_rule;
 	uint64_t message_bytes_limit, message_count_limit;
 	long long bytes_diff, total_bytes;
 	int count_diff, total_count;
@@ -394,15 +394,24 @@ static int maildirsize_parse(struct mail
 	(void)maildir_parse_limit(lines[0], &message_bytes_limit,
 				  &message_count_limit);
 
-	if (!root->master_message_limits) {
-		/* we don't know the limits, use whatever the file says */
-		root->message_bytes_limit = message_bytes_limit;
-		root->message_count_limit = message_count_limit;
-	} else if (root->message_bytes_limit != message_bytes_limit ||
-		   root->message_count_limit != message_count_limit) {
+	/* truncate too high limits to signed 64bit int range */
+	if (message_bytes_limit >= (1ULL << 63))
+		message_bytes_limit = (1ULL << 63) - 1;
+	if (message_count_limit >= (1ULL << 63))
+		message_count_limit = (1ULL << 63) - 1;
+
+	if (rule->bytes_limit == (int64_t)message_bytes_limit &&
+	    rule->count_limit == (int64_t)message_count_limit) {
+		/* limits haven't changed */
+	} else if (root->master_message_limits) {
 		/* we know the limits and they've changed.
 		   the file must be rewritten. */
 		return 0;
+	} else {
+		/* we're using limits from the file. */
+		rule->bytes_limit = message_bytes_limit;
+		rule->count_limit = message_count_limit;
+		quota_root_recalculate_relative_rules(&root->root);
 	}
 
 	if (*lines == NULL) {
@@ -425,8 +434,8 @@ static int maildirsize_parse(struct mail
 		return -1;
 	}
 
-	if ((uint64_t)total_bytes > root->message_bytes_limit ||
-	    (uint64_t)total_count > root->message_count_limit) {
+	if (total_bytes > rule->bytes_limit ||
+	    total_count > rule->count_limit) {
 		/* we're over quota. don't trust these values if the file
 		   contains more than the initial summary line, or if the file
 		   is older than 15 minutes. */
@@ -540,26 +549,23 @@ static int maildirsize_read(struct maild
 	return ret;
 }
 
-static void maildirquota_init_limits(struct maildir_quota_root *root)
-{
+static bool maildirquota_limits_init(struct maildir_quota_root *root)
+{
+	if (root->limits_initialized)
+		return root->maildirsize_path != NULL;
 	root->limits_initialized = TRUE;
 
+	/* these limits must be checked before the maildirsize is read the
+	   first time. if master limits aren't used, the default rule limits
+	   will be zero initially, but they'll be updated after the file is
+	   read. */
 	if (root->root.default_rule.bytes_limit != 0 ||
-	    root->root.default_rule.count_limit != 0) {
+	    root->root.default_rule.count_limit != 0)
 		root->master_message_limits = TRUE;
-		root->message_bytes_limit = root->root.default_rule.bytes_limit;
-		root->message_count_limit = root->root.default_rule.count_limit;
-	}
-}
-
-static bool maildirquota_limits_init(struct maildir_quota_root *root)
-{
-	if (!root->limits_initialized) {
-		maildirquota_init_limits(root);
-		if (root->maildirsize_path == NULL) {
-			i_warning("quota maildir: No maildir storages, "
-				  "ignoring quota.");
-		}
+
+	if (root->maildirsize_path == NULL) {
+		i_warning("quota maildir: No maildir storages, "
+			  "ignoring quota.");
 	}
 	return root->maildirsize_path != NULL;
 }
@@ -575,8 +581,8 @@ static int maildirquota_refresh(struct m
 		ret = maildirsize_read(root);
 	} T_END;
 	if (ret == 0) {
-		if (root->message_bytes_limit == (uint64_t)-1 &&
-		    root->message_count_limit == (uint64_t)-1) {
+		if (root->root.default_rule.bytes_limit == 0 &&
+		    root->root.default_rule.count_limit == 0) {
 			/* no quota */
 			return 0;
 		}
@@ -620,8 +626,6 @@ static struct quota_root *maildir_quota_
 
 	root = i_new(struct maildir_quota_root, 1);
 	root->fd = -1;
-	root->message_bytes_limit = (uint64_t)-1;
-	root->message_count_limit = (uint64_t)-1;
 	return &root->root;
 }
 
@@ -703,7 +707,7 @@ maildir_quota_root_get_resources(struct 
 
 static int
 maildir_quota_get_resource(struct quota_root *_root, const char *name,
-			   uint64_t *value_r, uint64_t *limit_r)
+			   uint64_t *value_r)
 {
 	struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
 
@@ -712,14 +716,8 @@ maildir_quota_get_resource(struct quota_
 
 	if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0) {
 		*value_r = root->total_bytes;
-		if (!root->master_message_limits &&
-		    root->message_bytes_limit != (uint64_t)-1)
-			*limit_r = root->message_bytes_limit;
 	} else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0) {
 		*value_r = root->total_count;
-		if (!root->master_message_limits &&
-		    root->message_count_limit != (uint64_t)-1)
-			*limit_r = root->message_count_limit;
 	} else
 		return 0;
 	return 1;
diff -r f78b83bf16b7 -r 9e4c26471b19 src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h	Tue Feb 26 15:11:34 2008 +0200
+++ b/src/plugins/quota/quota-private.h	Tue Feb 26 16:21:05 2008 +0200
@@ -23,11 +23,12 @@ struct quota_rule {
 	char *mailbox_name;
 
 	int64_t bytes_limit, count_limit;
+	/* relative to default_rule */
+	unsigned int bytes_percent, count_percent;
 };
 
 struct quota_warning_rule {
-	uint64_t bytes_limit;
-	uint64_t count_limit;
+	struct quota_rule rule;
 
 	char *command;
 };
@@ -45,10 +46,8 @@ struct quota_backend_vfuncs {
 			      struct mail_storage *storage);
 
 	const char *const *(*get_resources)(struct quota_root *root);
-	/* the limit is set by default, so it shouldn't normally need to
-	   be changed. */
 	int (*get_resource)(struct quota_root *root, const char *name,
-			    uint64_t *value_r, uint64_t *limit);
+			    uint64_t *value_r);


More information about the dovecot-cvs mailing list