]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Change quota_backend_vfuncs.namespace_added() to take root parameter
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 19 Aug 2024 10:11:10 +0000 (13:11 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:00 +0000 (10:40 +0200)
The quota-fs mountpoint handling was also simplified.

src/plugins/quota/quota-count.c
src/plugins/quota/quota-fs.c
src/plugins/quota/quota-imapc.c
src/plugins/quota/quota-maildir.c
src/plugins/quota/quota-private.h
src/plugins/quota/quota.c

index 507d19cbf38ce13b42c98f96da6443e5a38d0eea..8045b29126b0a0ca93801b3fa4e3e68a23e55d7d 100644 (file)
@@ -126,12 +126,10 @@ quota_mailbox_iter_next(struct quota_mailbox_iter *iter)
 
        if (iter->iter == NULL) {
                namespaces = array_get(&iter->root->namespaces, &count);
-               do {
-                       if (iter->ns_idx >= count)
-                               return NULL;
+               if (iter->ns_idx >= count)
+                       return NULL;
 
-                       iter->ns = namespaces[iter->ns_idx++];
-               } while (!quota_root_is_namespace_visible(iter->root, iter->ns));
+               iter->ns = namespaces[iter->ns_idx++];
                iter->iter = mailbox_list_iter_init(iter->ns->list, "*",
                        MAILBOX_LIST_ITER_SKIP_ALIASES |
                        MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
index 56562c5329ad0bc3359c584486b06b2d8bdd30e2..b2005902a5ce48c7706c40024d448ca79f81bc4b 100644 (file)
@@ -6,6 +6,7 @@
 #include "array.h"
 #include "str.h"
 #include "hostpid.h"
+#include "llist.h"
 #include "mountpoint.h"
 #include "quota-private.h"
 #include "quota-fs.h"
@@ -63,6 +64,7 @@
 
 struct fs_quota_mountpoint {
        int refcount;
+       struct fs_quota_mountpoint *prev, *next;
 
        char *mount_path;
        char *device_path;
@@ -73,6 +75,8 @@ struct fs_quota_mountpoint {
        int fd;
        char *path;
 #endif
+
+       bool initialized:1;
 };
 
 struct fs_quota_root {
@@ -93,6 +97,8 @@ struct fs_quota_root {
 
 extern struct quota_backend quota_backend_fs;
 
+struct fs_quota_mountpoint *quota_fs_mountpoints = NULL;
+
 static struct quota_root *fs_quota_alloc(void)
 {
        struct fs_quota_root *root;
@@ -151,6 +157,7 @@ static void fs_quota_mountpoint_free(struct fs_quota_mountpoint *mount)
        if (--mount->refcount > 0)
                return;
 
+       DLLIST_REMOVE(&quota_fs_mountpoints, mount);
 #ifdef FS_QUOTA_SOLARIS
        i_close_fd_path(&mount->fd, mount->path);
        i_free(mount->path);
@@ -182,6 +189,14 @@ static struct fs_quota_mountpoint *fs_quota_mountpoint_get(const char *dir)
        if (ret <= 0)
                return NULL;
 
+       for (mount = quota_fs_mountpoints; mount != NULL; mount = mount->next) {
+               if (strcmp(mount->device_path, point.device_path) == 0 &&
+                   strcmp(mount->mount_path, point.mount_path) == 0) {
+                       mount->refcount++;
+                       return mount;
+               }
+       }
+
        mount = i_new(struct fs_quota_mountpoint, 1);
        mount->refcount = 1;
        mount->device_path = point.device_path;
@@ -191,6 +206,7 @@ static struct fs_quota_mountpoint *fs_quota_mountpoint_get(const char *dir)
 #ifdef FS_QUOTA_SOLARIS
        mount->fd = -1;
 #endif
+       DLLIST_PREPEND(&quota_fs_mountpoints, mount);
 
        if (mount_type_is_nfs(mount)) {
                if (strchr(mount->device_path, ':') == NULL) {
@@ -204,39 +220,18 @@ static struct fs_quota_mountpoint *fs_quota_mountpoint_get(const char *dir)
        return mount;
 }
 
-#define QUOTA_ROOT_MATCH(root, mount) \
-       ((root)->root.backend.name == quota_backend_fs.name && \
-        ((root)->storage_mount_path == NULL || \
-         strcmp((root)->storage_mount_path, (mount)->mount_path) == 0))
-
-static struct fs_quota_root *
-fs_quota_root_find_mountpoint(struct quota *quota,
-                             const struct fs_quota_mountpoint *mount)
-{
-       struct quota_root *const *roots;
-       struct fs_quota_root *empty = NULL;
-       unsigned int i, count;
-
-       roots = array_get(&quota->roots, &count);
-       for (i = 0; i < count; i++) {
-               struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
-               if (QUOTA_ROOT_MATCH(root, mount)) {
-                       if (root->mount == NULL)
-                               empty = root;
-                       else if (strcmp(root->mount->mount_path,
-                                       mount->mount_path) == 0)
-                               return root;
-               }
-       }
-       return empty;
-}
-
 static void
-fs_quota_mount_init(struct fs_quota_root *root,
-                   struct fs_quota_mountpoint *mount, const char *dir)
+fs_quota_mount_init(struct fs_quota_root *root, const char *dir)
 {
-       struct quota_root *const *roots;
-       unsigned int i, count;
+       struct fs_quota_mountpoint *mount = fs_quota_mountpoint_get(dir);
+       if (mount == NULL)
+               return;
+       if (mount->initialized) {
+               /* already initialized */
+               root->mount = mount;
+               return;
+       }
+       mount->initialized = TRUE;
 
 #ifdef FS_QUOTA_SOLARIS
 #ifdef HAVE_RQUOTA
@@ -258,63 +253,23 @@ fs_quota_mount_init(struct fs_quota_root *root,
        e_debug(root->root.backend.event, "fs quota block device = %s", mount->device_path);
        e_debug(root->root.backend.event, "fs quota mount point = %s", mount->mount_path);
        e_debug(root->root.backend.event, "fs quota mount type = %s", mount->type);
-
-       /* if there are more unused quota roots, copy this mount to them */
-       roots = array_get(&root->root.quota->roots, &count);
-       for (i = 0; i < count; i++) {
-               root = (struct fs_quota_root *)roots[i];
-               if (QUOTA_ROOT_MATCH(root, mount) && root->mount == NULL) {
-                       mount->refcount++;
-                       root->mount = mount;
-               }
-       }
 }
 
-static void fs_quota_add_missing_mounts(struct quota *quota)
-{
-       struct fs_quota_mountpoint *mount;
-       struct quota_root *const *roots;
-       unsigned int i, count;
-
-       roots = array_get(&quota->roots, &count);
-       for (i = 0; i < count; i++) {
-               struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
-
-               if (root->root.backend.name != quota_backend_fs.name ||
-                   root->storage_mount_path == NULL || root->mount != NULL)
-                       continue;
-
-               mount = fs_quota_mountpoint_get(root->storage_mount_path);
-               if (mount != NULL) {
-                       fs_quota_mount_init(root, mount,
-                                           root->storage_mount_path);
-               }
-       }
-}
-
-static void fs_quota_namespace_added(struct quota *quota,
+static void fs_quota_namespace_added(struct quota_root *_root,
                                     struct mail_namespace *ns)
 {
-       struct fs_quota_mountpoint *mount;
-       struct fs_quota_root *root;
+       struct fs_quota_root *root = (struct fs_quota_root *)_root;
        const char *dir;
 
-       if (!mailbox_list_get_root_path(ns->list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
-                                       &dir))
-               mount = NULL;
-       else
-               mount = fs_quota_mountpoint_get(dir);
-       if (mount != NULL) {
-               root = fs_quota_root_find_mountpoint(quota, mount);
-               if (root != NULL && root->mount == NULL)
-                       fs_quota_mount_init(root, mount, dir);
-               else
-                       fs_quota_mountpoint_free(mount);
-       }
+       if (root->mount != NULL)
+               return;
 
-       /* we would actually want to do this only once after all quota roots
-          are created, but there's no way to do this right now */
-       fs_quota_add_missing_mounts(quota);
+       if (root->storage_mount_path != NULL)
+               fs_quota_mount_init(root, root->storage_mount_path);
+       else if (mailbox_list_get_root_path(ns->list,
+                                           MAILBOX_LIST_PATH_TYPE_MAILBOX,
+                                           &dir))
+               fs_quota_mount_init(root, dir);
 }
 
 static const char *const *
index 99629ed0d0f1ca833d025909167525444b0af03a..10950b044c923eb5d17d0f5d759a79e2248b4f61 100644 (file)
@@ -86,16 +86,6 @@ static void imapc_quota_deinit(struct quota_root *_root)
        i_free(_root);
 }
 
-static void
-imapc_quota_root_namespace_added(struct quota_root *_root,
-                                struct mail_namespace *ns)
-{
-       struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
-
-       if (root->imapc_ns == NULL)
-               root->imapc_ns = ns;
-}
-
 static struct imapc_quota_refresh *
 imapc_quota_root_refresh_find(struct imapc_storage_client *client)
 {
@@ -417,19 +407,13 @@ static int imapc_quota_refresh(struct imapc_quota_root *root,
 }
 
 static void
-imapc_quota_namespace_added(struct quota *quota, struct mail_namespace *ns)
+imapc_quota_namespace_added(struct quota_root *_root, struct mail_namespace *ns)
 {
-       struct quota_root **roots;
-       unsigned int i, count;
-
-       roots = array_get_modifiable(&quota->roots, &count);
-       for (i = 0; i < count; i++) {
-               if (roots[i]->backend.name == quota_backend_imapc.name &&
-                   ((roots[i]->ns_prefix == NULL &&
-                     ns->type == MAIL_NAMESPACE_TYPE_PRIVATE) ||
-                    roots[i]->ns == ns))
-                       imapc_quota_root_namespace_added(roots[i], ns);
-       }
+       struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
+
+       if (root->imapc_ns == NULL ||
+           root->imapc_ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
+               root->imapc_ns = ns;
 }
 
 static const char *const *
index db00d817309ddc0ecb6d55e80bd17e2806972053..8f92c8884dc17d8190324ad8499e8c21d7282999 100644 (file)
@@ -378,9 +378,6 @@ static int maildirsize_recalculate(struct maildir_quota_root *root,
        /* count mails from all namespaces */
        namespaces = array_get(&root->root.namespaces, &count);
        for (i = 0; i < count; i++) {
-               if (!quota_root_is_namespace_visible(&root->root, namespaces[i]))
-                       continue;
-
                if (maildirsize_recalculate_namespace(root, namespaces[i], error_r) < 0) {
                        ret = -1;
                        break;
@@ -390,10 +387,6 @@ static int maildirsize_recalculate(struct maildir_quota_root *root,
        if (ret == 0) {
                /* check if any of the directories have changed */
                for (i = 0; i < count; i++) {
-                       if (!quota_root_is_namespace_visible(&root->root,
-                                                          namespaces[i]))
-                               continue;
-
                        ret = maildirs_check_have_changed(root, namespaces[i],
                                                root->recalc_last_stamp,
                                                error_r);
@@ -759,31 +752,16 @@ static void maildir_quota_deinit(struct quota_root *_root)
 }
 
 static void
-maildir_quota_root_namespace_added(struct quota_root *_root,
-                                  struct mail_namespace *ns)
+maildir_quota_namespace_added(struct quota_root *_root,
+                             struct mail_namespace *ns)
 {
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
 
-       if (root->maildirsize_ns == NULL)
+       if (root->maildirsize_ns == NULL ||
+           root->maildirsize_ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
                root->maildirsize_ns = ns;
 }
 
-static void
-maildir_quota_namespace_added(struct quota *quota, struct mail_namespace *ns)
-{
-       struct quota_root **roots;
-       unsigned int i, count;
-
-       roots = array_get_modifiable(&quota->roots, &count);
-       for (i = 0; i < count; i++) {
-               if (roots[i]->backend.name == quota_backend_maildir.name &&
-                   ((roots[i]->ns_prefix == NULL &&
-                     ns->type == MAIL_NAMESPACE_TYPE_PRIVATE) ||
-                    roots[i]->ns == ns))
-                       maildir_quota_root_namespace_added(roots[i], ns);
-       }
-}
-
 static const char *const *
 maildir_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
 {
index 98ca47df2fc50903ee6355a3014871a2939b7505..738c3230fd9e661a78e9a75e23a1e9cad951cc1d 100644 (file)
@@ -53,7 +53,7 @@ struct quota_backend_vfuncs {
        void (*deinit)(struct quota_root *root);
 
        /* called once for each namespace */
-       void (*namespace_added)(struct quota *quota,
+       void (*namespace_added)(struct quota_root *root,
                                struct mail_namespace *ns);
 
        const char *const *(*get_resources)(struct quota_root *root);
index 0ca5ea51a1a96466245ade483267815f07cab244..b30ea59e4418da8edeb60e342e8db42bb50d6c6f 100644 (file)
@@ -536,6 +536,8 @@ void quota_add_user_namespace(struct quota *quota, struct mail_namespace *ns)
        struct quota_root *root;
 
        array_foreach_elem(&quota->roots, root) {
+               if (!quota_root_is_namespace_visible(root, ns))
+                       continue;
                /* first check if there already exists a namespace with the
                   exact same path. we don't want to count them twice. */
                if (quota_is_duplicate_namespace(root, ns))
@@ -544,7 +546,7 @@ void quota_add_user_namespace(struct quota *quota, struct mail_namespace *ns)
                array_push_back(&root->namespaces, &ns);
 
                if (root->backend.v.namespace_added != NULL)
-                       root->backend.v.namespace_added(quota, ns);
+                       root->backend.v.namespace_added(root, ns);
        }
 }