dovecot-1.3: Implemented support for per-namespace quotas. Can b...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Apr 17 04:58:28 EEST 2009
details: http://hg.dovecot.org/dovecot-1.3/rev/f9c07af22f91
changeset: 9129:f9c07af22f91
user: Timo Sirainen <tss at iki.fi>
date: Thu Apr 16 21:56:54 2009 -0400
description:
Implemented support for per-namespace quotas. Can be used with public namespaces.
diffstat:
9 files changed, 151 insertions(+), 16 deletions(-)
src/plugins/quota/quota-count.c | 3 +
src/plugins/quota/quota-dict.c | 22 ++++++++++---
src/plugins/quota/quota-dirsize.c | 3 +
src/plugins/quota/quota-maildir.c | 33 ++++++++++++++++++-
src/plugins/quota/quota-plugin.c | 5 ++
src/plugins/quota/quota-plugin.h | 1
src/plugins/quota/quota-private.h | 8 ++++
src/plugins/quota/quota-storage.c | 62 ++++++++++++++++++++++++++++++++++---
src/plugins/quota/quota.c | 30 ++++++++++++++---
diffs (truncated from 356 to 300 lines):
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-count.c
--- a/src/plugins/quota/quota-count.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-count.c Thu Apr 16 21:56:54 2009 -0400
@@ -102,6 +102,9 @@ int quota_count(struct quota_root *root,
storages = array_get(&root->quota->storages, &count);
for (i = 0; i < count; i++) {
+ if (!quota_root_is_storage_visible(root, storages[i]))
+ continue;
+
ret = quota_count_storage(root, storages[i], bytes_r, count_r);
if (ret < 0)
break;
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-dict.c
--- a/src/plugins/quota/quota-dict.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-dict.c Thu Apr 16 21:56:54 2009 -0400
@@ -4,6 +4,7 @@
#include "str.h"
#include "dict.h"
#include "mail-user.h"
+#include "mail-namespace.h"
#include "quota-private.h"
#include <stdlib.h>
@@ -41,12 +42,25 @@ static int dict_quota_init(struct quota_
username = t_strdup_until(args, p);
args = p+1;
- if (strncmp(args, "noenforcing:", 12) == 0) {
+ do {
/* FIXME: pretty ugly in here. the parameters should have
been designed to be extensible. do it in a future version */
- _root->no_enforcing = TRUE;
- args += 12;
- }
+ if (strncmp(args, "noenforcing:", 12) == 0) {
+ _root->no_enforcing = TRUE;
+ args += 12;
+ continue;
+ }
+ if (strncmp(args, "ns=", 3) == 0) {
+ p = strchr(args, ':');
+ if (p == NULL)
+ break;
+
+ _root->ns_prefix = p_strdup_until(_root->pool,
+ args + 3, p);
+ args = p + 1;
+ continue;
+ }
+ } while (0);
if (*username == '\0')
username = _root->quota->user->username;
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-dirsize.c
--- a/src/plugins/quota/quota-dirsize.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-dirsize.c Thu Apr 16 21:56:54 2009 -0400
@@ -158,6 +158,9 @@ get_quota_root_usage(struct quota_root *
t_array_init(&paths, 8);
storages = array_get(&root->quota->storages, &count);
for (i = 0; i < count; i++) {
+ if (!quota_root_is_storage_visible(root, storages[i]))
+ continue;
+
path = mail_storage_get_mailbox_path(storages[i], "", &is_file);
quota_count_path_add(&paths, path, FALSE);
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-maildir.c
--- a/src/plugins/quota/quota-maildir.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-maildir.c Thu Apr 16 21:56:54 2009 -0400
@@ -378,6 +378,9 @@ static int maildirsize_recalculate(struc
/* count mails from all storages */
storages = array_get(&root->root.quota->storages, &count);
for (i = 0; i < count; i++) {
+ if (!quota_root_is_storage_visible(&root->root, storages[i]))
+ continue;
+
if (maildirsize_recalculate_storage(root, storages[i]) < 0) {
ret = -1;
break;
@@ -387,6 +390,10 @@ static int maildirsize_recalculate(struc
if (ret == 0) {
/* check if any of the directories have changed */
for (i = 0; i < count; i++) {
+ if (!quota_root_is_storage_visible(&root->root,
+ storages[i]))
+ continue;
+
ret = maildirs_check_have_changed(root, storages[i],
root->recalc_last_stamp);
if (ret != 0)
@@ -686,6 +693,26 @@ static struct quota_root *maildir_quota_
return &root->root;
}
+static int maildir_quota_init(struct quota_root *_root, const char *args)
+{
+ const char *const *tmp;
+
+ if (args == NULL)
+ return 0;
+
+ for (tmp = t_strsplit(args, ":"); *tmp != NULL; tmp++) {
+ if (strcmp(*tmp, "noenforcing") == 0)
+ _root->no_enforcing = TRUE;
+ else if (strncmp(*tmp, "ns=", 3) == 0)
+ _root->ns_prefix = p_strdup(_root->pool, *tmp + 3);
+ else {
+ i_error("maildir quota: Invalid parameter: %s", *tmp);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static void maildir_quota_deinit(struct quota_root *_root)
{
struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
@@ -739,7 +766,9 @@ maildir_quota_storage_added(struct quota
roots = array_get_modifiable("a->roots, &count);
for (i = 0; i < count; i++) {
- if (roots[i]->backend.name == quota_backend_maildir.name)
+ if (roots[i]->backend.name == quota_backend_maildir.name &&
+ (roots[i]->ns_prefix == NULL ||
+ roots[i]->ns == storage->ns))
maildir_quota_root_storage_added(roots[i], storage);
}
}
@@ -805,7 +834,7 @@ struct quota_backend quota_backend_maild
{
maildir_quota_alloc,
- NULL,
+ maildir_quota_init,
maildir_quota_deinit,
maildir_quota_parse_rule,
maildir_quota_storage_added,
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-plugin.c
--- a/src/plugins/quota/quota-plugin.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-plugin.c Thu Apr 16 21:56:54 2009 -0400
@@ -14,6 +14,7 @@ void (*quota_next_hook_mail_user_created
void (*quota_next_hook_mail_user_created)(struct mail_user *user);
void (*quota_next_hook_mail_storage_created)(struct mail_storage *storage);
void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
+void (*quota_next_hook_mail_namespaces_created)(struct mail_namespace *namespaces);
const char *quota_plugin_version = PACKAGE_VERSION;
@@ -27,6 +28,9 @@ void quota_plugin_init(void)
quota_next_hook_mailbox_list_created = hook_mailbox_list_created;
hook_mailbox_list_created = quota_mailbox_list_created;
+
+ quota_next_hook_mail_namespaces_created = hook_mail_namespaces_created;
+ hook_mail_namespaces_created = quota_mail_namespaces_created;
}
void quota_plugin_deinit(void)
@@ -34,4 +38,5 @@ void quota_plugin_deinit(void)
hook_mail_user_created = quota_next_hook_mail_user_created;
hook_mail_storage_created = quota_next_hook_mail_storage_created;
hook_mailbox_list_created = quota_next_hook_mailbox_list_created;
+ hook_mail_namespaces_created = quota_next_hook_mail_namespaces_created;
}
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-plugin.h
--- a/src/plugins/quota/quota-plugin.h Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-plugin.h Thu Apr 16 21:56:54 2009 -0400
@@ -24,6 +24,7 @@ void quota_mail_user_created(struct mail
void quota_mail_user_created(struct mail_user *user);
void quota_mail_storage_created(struct mail_storage *storage);
void quota_mailbox_list_created(struct mailbox_list *list);
+void quota_mail_namespaces_created(struct mail_namespace *namespaces);
void quota_plugin_init(void);
void quota_plugin_deinit(void);
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-private.h Thu Apr 16 21:56:54 2009 -0400
@@ -96,6 +96,12 @@ struct quota_root {
struct quota *quota;
struct quota_backend backend;
+ /* this quota root applies only to this namespace. it may also be
+ a public namespace without an owner. */
+ struct mail_namespace *ns;
+ /* this is set in quota init(), because namespaces aren't known yet */
+ const char *ns_prefix;
+
/* initially the same as set->default_rule.*_limit, but some backends
may change these by reading the limits elsewhere (e.g. Maildir++,
FS quota) */
@@ -133,6 +139,8 @@ void quota_remove_user_storage(struct ma
struct quota *quota_get_mail_user_quota(struct mail_user *user);
+bool quota_root_is_storage_visible(struct quota_root *root,
+ struct mail_storage *storage);
struct quota_rule *
quota_root_rule_find(struct quota_root_settings *root_set, const char *name);
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota-storage.c
--- a/src/plugins/quota/quota-storage.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota-storage.c Thu Apr 16 21:56:54 2009 -0400
@@ -523,7 +523,9 @@ void quota_mail_storage_created(struct m
qstorage);
/* register to owner's quota roots */
- quota = quota_get_mail_user_quota(storage->ns->owner);
+ quota = storage->ns->owner != NULL ?
+ quota_get_mail_user_quota(storage->ns->owner) :
+ quota_get_mail_user_quota(storage->ns->user);
quota_add_user_storage(quota, storage);
}
@@ -531,12 +533,43 @@ void quota_mail_storage_created(struct m
quota_next_hook_mail_storage_created(storage);
}
+static struct quota_root *
+quota_find_root_for_ns(struct quota *quota, struct mail_namespace *ns)
+{
+ struct quota_root *const *roots;
+ unsigned int i, count;
+
+ roots = array_get("a->roots, &count);
+ for (i = 0; i < count; i++) {
+ if (roots[i]->ns_prefix != NULL &&
+ strcmp(roots[i]->ns_prefix, ns->prefix) == 0)
+ return roots[i];
+ }
+ return NULL;
+}
+
void quota_mailbox_list_created(struct mailbox_list *list)
{
struct quota_mailbox_list *qlist;
-
- if (list->ns->owner != NULL &&
- (list->ns->flags & NAMESPACE_FLAG_INTERNAL) == 0) {
+ struct quota *quota;
+ struct quota_root *root;
+ bool add;
+
+ if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0)
+ add = FALSE;
+ else if (list->ns->owner == NULL) {
+ /* see if we have a quota explicitly defined for
+ this namespace */
+ quota = quota_get_mail_user_quota(list->ns->user);
+ root = quota_find_root_for_ns(quota, list->ns);
+ add = root != NULL;
+ if (root != NULL)
+ root->ns = list->ns;
+ } else {
+ add = TRUE;
+ }
+
+ if (add) {
qlist = p_new(list->pool, struct quota_mailbox_list, 1);
qlist->module_ctx.super = list->v;
list->v.delete_mailbox = quota_mailbox_list_delete;
@@ -546,3 +579,24 @@ void quota_mailbox_list_created(struct m
if (quota_next_hook_mailbox_list_created != NULL)
quota_next_hook_mailbox_list_created(list);
}
+
+void quota_mail_namespaces_created(struct mail_namespace *namespaces)
+{
+ struct quota *quota;
+ struct quota_root *const *roots;
+ unsigned int i, count;
+
+ quota = quota_get_mail_user_quota(namespaces->user);
+ roots = array_get("a->roots, &count);
+ for (i = 0; i < count; i++) {
+ if (roots[i]->ns_prefix == NULL || roots[i]->ns != NULL)
+ continue;
+
+ roots[i]->ns = mail_namespace_find_prefix(namespaces,
+ roots[i]->ns_prefix);
+ if (roots[i]->ns == NULL) {
+ i_error("maildir quota: Unknown namespace: %s",
+ roots[i]->ns_prefix);
+ }
+ }
+}
diff -r be738988c8ab -r f9c07af22f91 src/plugins/quota/quota.c
--- a/src/plugins/quota/quota.c Thu Apr 16 21:55:45 2009 -0400
+++ b/src/plugins/quota/quota.c Thu Apr 16 21:56:54 2009 -0400
@@ -595,8 +595,9 @@ void quota_remove_user_storage(struct ma
struct mail_storage *const *storages;
unsigned int i, count;
- quota = storage->ns->owner == NULL ? NULL :
- quota_get_mail_user_quota(storage->ns->owner);
+ quota = storage->ns->owner != NULL ?
+ quota_get_mail_user_quota(storage->ns->owner) :
+ quota_get_mail_user_quota(storage->ns->user);
if (quota == NULL) {
More information about the dovecot-cvs
mailing list