]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mail storages can now be shared between namespaces.
authorTimo Sirainen <tss@iki.fi>
Wed, 3 Jun 2009 20:45:23 +0000 (16:45 -0400)
committerTimo Sirainen <tss@iki.fi>
Wed, 3 Jun 2009 20:45:23 +0000 (16:45 -0400)
--HG--
branch : HEAD

15 files changed:
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/dbox/dbox-storage-rebuild.c
src/lib-storage/index/dbox/dbox-storage.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/raw/raw-storage.c
src/lib-storage/index/shared/shared-storage.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/lib-storage/mail-user.h
src/lib-storage/mailbox-list.c
src/plugins/convert/convert-storage.c
src/plugins/virtual/virtual-storage.c

index 6b4b74f99f69ebb7d532fe219ab7cb33035f54b9..62953595f06ec8d7cd7a13d5d13b1ebd641e6f65 100644 (file)
@@ -26,8 +26,6 @@ extern struct mailbox cydir_mailbox;
 static MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static void cydir_list_init(struct mailbox_list *list);
-
 static struct mail_storage *cydir_storage_alloc(void)
 {
        struct cydir_storage *storage;
@@ -40,15 +38,6 @@ static struct mail_storage *cydir_storage_alloc(void)
        return &storage->storage;
 }
 
-static int
-cydir_storage_create(struct mail_storage *_storage ATTR_UNUSED,
-                    struct mail_namespace *ns,
-                    const char **error_r ATTR_UNUSED)
-{
-       cydir_list_init(ns->list);
-       return 0;
-}
-
 static void
 cydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
                                struct mailbox_list_settings *set)
@@ -336,7 +325,8 @@ static void cydir_class_deinit(void)
        cydir_transaction_class_deinit();
 }
 
-static void cydir_list_init(struct mailbox_list *list)
+static void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+                                  struct mailbox_list *list)
 {
        struct cydir_mailbox_list *mlist;
 
@@ -351,15 +341,16 @@ static void cydir_list_init(struct mailbox_list *list)
 
 struct mail_storage cydir_storage = {
        MEMBER(name) CYDIR_STORAGE_NAME,
-       MEMBER(mailbox_is_file) FALSE,
+       MEMBER(class_flags) 0,
 
        {
                NULL,
                cydir_class_init,
                cydir_class_deinit,
                cydir_storage_alloc,
-               cydir_storage_create,
+               NULL,
                index_storage_destroy,
+               cydir_storage_add_list,
                cydir_storage_get_list_settings,
                NULL,
                cydir_mailbox_open,
index b33e6e007c7e2e4877d31b0eef57709351ad6ff4..a63dcd8fb449aaaf2bb4bc965fc050c5043c5a01 100644 (file)
@@ -469,20 +469,13 @@ static int rebuild_mailboxes(struct dbox_storage_rebuild_context *ctx)
 {
        struct mail_user *user = ctx->storage->storage.user;
        struct mail_namespace *ns;
-       const char *rebuild_dir, *ns_dir;
 
-       rebuild_dir = ctx->storage->storage_dir;
        for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-               if (strcmp(ns->storage->name, "dbox") != 0)
-                       continue;
-
-               ns_dir = mailbox_list_get_path(ns->list, NULL,
-                                              MAILBOX_LIST_PATH_TYPE_DIR);
-               if (strcmp(ns_dir, rebuild_dir) != 0)
-                       continue;
-
-               if (rebuild_namespace_mailboxes(ctx, ns) < 0)
-                       return -1;
+               if (ns->storage == &ctx->storage->storage &&
+                   ns->alias_for == NULL) {
+                       if (rebuild_namespace_mailboxes(ctx, ns) < 0)
+                               return -1;
+               }
        }
        return 0;
 }
index c07310031e41882bc091a505f49a6aa975e142ab..fe09be85513ff4417490671540375954a9f5571e 100644 (file)
@@ -39,9 +39,6 @@ extern struct mailbox dbox_mailbox;
 static MODULE_CONTEXT_DEFINE_INIT(dbox_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static void dbox_list_init(struct mailbox_list *list,
-                          const struct dbox_settings *set);
-
 static struct mail_storage *dbox_storage_alloc(void)
 {
        struct dbox_storage *storage;
@@ -69,7 +66,8 @@ dbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
                return -1;
        }
 
-       dbox_list_init(ns->list, storage->set);
+       _storage->unique_root_dir =
+               p_strdup(_storage->pool, ns->list->set.root_dir);
 
        dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
        storage->storage_dir = p_strconcat(_storage->pool, dir,
@@ -162,6 +160,7 @@ dbox_open(struct dbox_storage *storage, struct mailbox_list *list,
        mbox->ibox.box = dbox_mailbox;
        mbox->ibox.box.pool = pool;
        mbox->ibox.box.storage = _storage;
+       mbox->ibox.box.list = list;
        mbox->ibox.mail_vfuncs = &dbox_mail_vfuncs;
        mbox->ibox.index = index;
        mbox->ibox.keep_index_backups = TRUE;
@@ -720,14 +719,14 @@ static void dbox_class_deinit(void)
        dbox_transaction_class_deinit();
 }
 
-static void dbox_list_init(struct mailbox_list *list,
-                          const struct dbox_settings *set)
+static void dbox_storage_add_list(struct mail_storage *storage,
+                                 struct mailbox_list *list)
 {
        struct dbox_mailbox_list *mlist;
 
        mlist = p_new(list->pool, struct dbox_mailbox_list, 1);
        mlist->module_ctx.super = list->v;
-       mlist->set = set;
+       mlist->set = mail_storage_get_driver_settings(storage);
 
        list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
        list->v.delete_mailbox = dbox_list_delete_mailbox;
@@ -739,7 +738,7 @@ static void dbox_list_init(struct mailbox_list *list,
 
 struct mail_storage dbox_storage = {
        MEMBER(name) DBOX_STORAGE_NAME,
-       MEMBER(mailbox_is_file) FALSE,
+       MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT, /* FIXME: for multi-dbox only.. */
 
        {
                 dbox_get_setting_parser_info,
@@ -748,6 +747,7 @@ struct mail_storage dbox_storage = {
                dbox_storage_alloc,
                dbox_storage_create,
                dbox_storage_destroy,
+               dbox_storage_add_list,
                dbox_storage_get_list_settings,
                NULL,
                dbox_mailbox_open,
index 442bd63411ad497077423d5b1c0a0f6fdeb7b44b..574ad31b2b019008d1b95f0894436c9d125f0c6f 100644 (file)
@@ -44,9 +44,6 @@ static MODULE_CONTEXT_DEFINE_INIT(maildir_mailbox_list_module,
                                  &mailbox_list_module_register);
 static const char *maildir_subdirs[] = { "cur", "new", "tmp" };
 
-static void maildir_list_init(struct mailbox_list *list,
-                             const struct maildir_settings *set);
-
 static bool maildir_is_internal_name(const char *name)
 {
        return strcmp(name, "cur") == 0 ||
@@ -114,7 +111,6 @@ maildir_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
        const char *dir;
 
        storage->set = mail_storage_get_driver_settings(_storage);
-       maildir_list_init(list, storage->set);
 
        storage->maildir_list_ext_id = (uint32_t)-1;
        storage->temp_prefix = mailbox_list_get_temp_prefix(list);
@@ -1007,14 +1003,14 @@ static void maildir_class_deinit(void)
        maildir_transaction_class_deinit();
 }
 
-static void maildir_list_init(struct mailbox_list *list,
-                             const struct maildir_settings *set)
+static void maildir_storage_add_list(struct mail_storage *storage,
+                                    struct mailbox_list *list)
 {
        struct maildir_mailbox_list *mlist;
 
        mlist = p_new(list->pool, struct maildir_mailbox_list, 1);
        mlist->module_ctx.super = list->v;
-       mlist->set = set;
+       mlist->set = mail_storage_get_driver_settings(storage);
 
        if (strcmp(list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0) {
                list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
@@ -1032,7 +1028,7 @@ static void maildir_list_init(struct mailbox_list *list,
 
 struct mail_storage maildir_storage = {
        MEMBER(name) MAILDIR_STORAGE_NAME,
-       MEMBER(mailbox_is_file) FALSE,
+       MEMBER(class_flags) 0,
 
        {
                 maildir_get_setting_parser_info,
@@ -1041,6 +1037,7 @@ struct mail_storage maildir_storage = {
                maildir_storage_alloc,
                maildir_storage_create,
                index_storage_destroy,
+               maildir_storage_add_list,
                maildir_storage_get_list_settings,
                maildir_storage_autodetect,
                maildir_mailbox_open,
index 2a8c7a4bfc1a0d2f4000b859d585079c2e8a9d90..2e3b5e4815c7ddc8f6a5d81c4047591421ce9f27 100644 (file)
@@ -73,9 +73,6 @@ extern struct mailbox mbox_mailbox;
 static MODULE_CONTEXT_DEFINE_INIT(mbox_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static void mbox_list_init(struct mailbox_list *list,
-                          const struct mbox_settings *set);
-
 int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
 {
        i_assert(function != NULL);
@@ -134,7 +131,6 @@ mbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
        const char *dir;
 
        storage->set = mail_storage_get_driver_settings(_storage);
-       mbox_list_init(ns->list, storage->set);
 
        dir = mailbox_list_get_path(ns->list, NULL,
                                    MAILBOX_LIST_PATH_TYPE_INDEX);
@@ -841,14 +837,14 @@ static void mbox_class_deinit(void)
        mbox_transaction_class_deinit();
 }
 
-static void mbox_list_init(struct mailbox_list *list,
-                          const struct mbox_settings *set)
+static void mbox_storage_add_list(struct mail_storage *storage,
+                                 struct mailbox_list *list)
 {
        struct mbox_mailbox_list *mlist;
 
        mlist = p_new(list->pool, struct mbox_mailbox_list, 1);
        mlist->module_ctx.super = list->v;
-       mlist->set = set;
+       mlist->set = mail_storage_get_driver_settings(storage);
 
        if (strcmp(list->name, MAILBOX_LIST_NAME_FS) == 0 &&
            *list->set.maildir_name == '\0') {
@@ -865,7 +861,7 @@ static void mbox_list_init(struct mailbox_list *list,
 
 struct mail_storage mbox_storage = {
        MEMBER(name) MBOX_STORAGE_NAME,
-       MEMBER(mailbox_is_file) TRUE,
+       MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE,
 
        {
                 mbox_get_setting_parser_info,
@@ -874,6 +870,7 @@ struct mail_storage mbox_storage = {
                mbox_storage_alloc,
                mbox_storage_create,
                index_storage_destroy,
+               mbox_storage_add_list,
                mbox_storage_get_list_settings,
                mbox_storage_autodetect,
                mbox_mailbox_open,
index 686c647c9913378ac5971162e1a77c2d4a7dd67f..9b088ba571b6d183618ed4e8b2638dbf7d26d9f2 100644 (file)
@@ -16,8 +16,6 @@ struct raw_mailbox_list {
 extern struct mail_storage raw_storage;
 extern struct mailbox raw_mailbox;
 
-static void raw_list_init(struct mailbox_list *list);
-
 static struct mail_storage *raw_storage_alloc(void)
 {
        struct raw_storage *storage;
@@ -30,14 +28,6 @@ static struct mail_storage *raw_storage_alloc(void)
        return &storage->storage;
 }
 
-static int
-raw_storage_create(struct mail_storage *_storage ATTR_UNUSED,
-                  struct mail_namespace *ns, const char **error_r ATTR_UNUSED)
-{
-       raw_list_init(ns->list);
-       return 0;
-}
-
 static void
 raw_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
                              struct mailbox_list_settings *set)
@@ -196,7 +186,8 @@ static void raw_class_deinit(void)
        raw_transaction_class_deinit();
 }
 
-static void raw_list_init(struct mailbox_list *list)
+static void raw_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+                                struct mailbox_list *list)
 {
        list->v.iter_is_mailbox = raw_list_iter_is_mailbox;
        list->v.delete_mailbox = raw_list_delete_mailbox;
@@ -204,15 +195,16 @@ static void raw_list_init(struct mailbox_list *list)
 
 struct mail_storage raw_storage = {
        MEMBER(name) RAW_STORAGE_NAME,
-       MEMBER(mailbox_is_file) TRUE,
+       MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE,
 
        {
                NULL,
                raw_class_init,
                raw_class_deinit,
                raw_storage_alloc,
-               raw_storage_create,
+               NULL,
                index_storage_destroy,
+               raw_storage_add_list,
                raw_storage_get_list_settings,
                NULL,
                raw_mailbox_open,
index fdc0ddcab21eb1a87052d178f4167bfba97f031a..e624daff9e934f6863ac62eee54ef34b5e463c4f 100644 (file)
@@ -48,7 +48,7 @@ shared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
                                       driver, NULL);
                return -1;
        }
-       _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
+       _storage->class_flags = storage->storage_class->class_flags;
 
        wildcardp = strchr(ns->prefix, '%');
        if (wildcardp == NULL) {
@@ -313,7 +313,7 @@ shared_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
 
 struct mail_storage shared_storage = {
        MEMBER(name) SHARED_STORAGE_NAME,
-       MEMBER(mailbox_is_file) FALSE, /* unknown at this point */
+       MEMBER(class_flags) 0, /* unknown at this point */
 
        {
                NULL,
@@ -322,6 +322,7 @@ struct mail_storage shared_storage = {
                shared_storage_alloc,
                shared_storage_create,
                index_storage_destroy,
+               NULL,
                shared_storage_get_list_settings,
                NULL,
                NULL,
index f35512b77a09ac1fc11a8f973e4e95eb88a82b01..3541ae6d08abfce4a8b9792c6c07c095e4dc434a 100644 (file)
@@ -4,7 +4,7 @@
 #include "array.h"
 #include "str.h"
 #include "file-lock.h"
-#include "mail-storage.h"
+#include "mail-storage-private.h"
 #include "mail-storage-settings.h"
 #include "mail-namespace.h"
 
@@ -18,6 +18,9 @@ void mail_namespace_add_storage(struct mail_namespace *ns,
        /* currently we support only a single storage */
        i_assert(ns->storage == NULL);
        ns->storage = storage;
+
+       if (storage->v.add_list != NULL)
+               storage->v.add_list(storage, ns->list);
 }
 
 void mail_namespace_finish_list_init(struct mail_namespace *ns,
@@ -42,7 +45,7 @@ void mail_namespace_finish_list_init(struct mail_namespace *ns,
 static void mail_namespace_free(struct mail_namespace *ns)
 {
        if (ns->storage != NULL)
-               mail_storage_destroy(&ns->storage);
+               mail_storage_unref(&ns->storage);
        if (ns->list != NULL)
                mailbox_list_destroy(&ns->list);
 
@@ -359,8 +362,6 @@ void mail_namespace_destroy(struct mail_namespace *ns)
                }
        }
 
-       if (ns->storage != NULL)
-               mail_storage_destroy(&ns->storage);
        mail_namespace_free(ns);
 }
 
index 18a9db0f9ba0f60146fba2bcc73a279f70d8239a..62d1446e195a0e28a30aeb1bdf6baf50cdc5ea8d 100644 (file)
@@ -35,6 +35,8 @@ struct mail_storage_vfuncs {
        int (*create)(struct mail_storage *storage, struct mail_namespace *ns,
                      const char **error_r);
        void (*destroy)(struct mail_storage *storage);
+       void (*add_list)(struct mail_storage *storage,
+                        struct mailbox_list *list);
 
        void (*get_list_settings)(const struct mail_namespace *ns,
                                  struct mailbox_list_settings *set);
@@ -58,14 +60,24 @@ union mail_storage_module_context {
        struct mail_storage_module_register *reg;
 };
 
+enum mail_storage_class_flags {
+       /* mailboxes are files, not directories */
+       MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE = 0x01,
+       /* root_dir points to a unique directory */
+       MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT     = 0x02
+};
+
 struct mail_storage {
        const char *name;
-       bool mailbox_is_file;
+       enum mail_storage_class_flags class_flags;
 
         struct mail_storage_vfuncs v;
 
 /* private: */
        pool_t pool;
+       struct mail_storage *prev, *next;
+       int refcount;
+       const char *unique_root_dir;
 
        char *error_string;
        enum mail_error error;
index fffb516ffc6bfa8d2236a20c3768f5285993159a..babdd39a291c3d8d3a994c526126830ca28b01ff 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "llist.h"
 #include "mkdir-parents.h"
 #include "var-expand.h"
 #include "mail-index-private.h"
@@ -196,6 +197,23 @@ mail_storage_create_root(struct mailbox_list *list,
        }
 }
 
+static struct mail_storage *
+mail_storage_find(struct mail_user *user,
+                 const struct mail_storage *storage_class,
+                 const struct mailbox_list_settings *set)
+{
+       struct mail_storage *storage = user->storages;
+
+       for (; storage != NULL; storage = storage->next) {
+               if (strcmp(storage->name, storage_class->name) == 0 &&
+                   ((storage->class_flags &
+                     MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0 ||
+                    strcmp(storage->unique_root_dir, set->root_dir) == 0))
+                       return storage;
+       }
+       return NULL;
+}
+
 int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        enum mail_storage_flags flags, const char **error_r)
 {
@@ -254,7 +272,16 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        return -1;
        }
 
+       storage = mail_storage_find(ns->user, storage_class, &list_set);
+       if (storage != NULL) {
+               /* using an existing storage */
+               storage->refcount++;
+               mail_namespace_add_storage(ns, storage);
+               return 0;
+       }
+
        storage = storage_class->v.alloc();
+       storage->refcount = 1;
        storage->storage_class = storage_class;
        storage->user = ns->user;
        storage->set = ns->mail_set;
@@ -264,7 +291,8 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                p_new(storage->pool, struct mail_storage_callbacks, 1);
        p_array_init(&storage->module_contexts, storage->pool, 5);
 
-       if (storage->v.create(storage, ns, error_r) < 0) {
+       if (storage->v.create != NULL &&
+           storage->v.create(storage, ns, error_r) < 0) {
                *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
                pool_unref(&storage->pool);
                return -1;
@@ -274,18 +302,29 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                hook_mail_storage_created(storage);
        } T_END;
 
+       DLLIST_PREPEND(&ns->user->storages, storage);
         mail_namespace_add_storage(ns, storage);
        return 0;
 }
 
-void mail_storage_destroy(struct mail_storage **_storage)
+void mail_storage_ref(struct mail_storage *storage)
+{
+       storage->refcount++;
+}
+
+void mail_storage_unref(struct mail_storage **_storage)
 {
        struct mail_storage *storage = *_storage;
 
-       i_assert(storage != NULL);
+       i_assert(storage->refcount > 0);
 
        *_storage = NULL;
 
+       if (--storage->refcount > 0)
+               return;
+
+       DLLIST_REMOVE(&storage->user->storages, storage);
+
        storage->v.destroy(storage);
        i_free(storage->error_string);
        pool_unref(&storage->pool);
@@ -403,7 +442,8 @@ const char *mail_storage_get_last_error(struct mail_storage *storage,
 
 bool mail_storage_is_mailbox_file(struct mail_storage *storage)
 {
-       return storage->mailbox_is_file;
+       return (storage->class_flags &
+               MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
 }
 
 bool mail_storage_set_error_from_errno(struct mail_storage *storage)
index 40bfe5475894dc7ad6c36bb7fbd52253195eb0f4..5ef20a63bd78ec6c868f7fbc4f63cb5fb5699726 100644 (file)
@@ -259,7 +259,8 @@ struct mail_storage *mail_storage_find_class(const char *name);
    exists. The storage is put into ns->storage. */
 int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        enum mail_storage_flags flags, const char **error_r);
-void mail_storage_destroy(struct mail_storage **storage);
+void mail_storage_ref(struct mail_storage *storage);
+void mail_storage_unref(struct mail_storage **storage);
 
 /* Returns the mail storage settings. */
 const struct mail_storage_settings *
index 2315c9ac85cf3a8ae94e7eda68d98a495f6fcccf..b7d15d352abc397e53130e162d523b61b1bdd889 100644 (file)
@@ -28,6 +28,7 @@ struct mail_user {
        const struct mail_user_settings *unexpanded_set;
        struct mail_user_settings *set;
        struct mail_namespace *namespaces;
+       struct mail_storage *storages;
 
        /* Module-specific contexts. See mail_storage_module_id. */
        ARRAY_DEFINE(module_contexts, union mail_user_module_context *);
index 56249324b9d89f9c3dff8617eea6b9a3e6327acf..45715b670d4e1cf09fceb7b3f521e468703789bd 100644 (file)
@@ -851,7 +851,8 @@ bool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
 const char *mailbox_list_get_last_error(struct mailbox_list *list,
                                        enum mail_error *error_r)
 {
-       *error_r = list->error;
+       if (error_r != NULL)
+               *error_r = list->error;
 
        return list->error_string != NULL ? list->error_string :
                "Unknown internal list error";
index 9c8631d582d9a44f1927f2989137301acda5387c..14408fa15361b62f4a038c5667246c4e8afeb850 100644 (file)
@@ -441,7 +441,7 @@ int convert_storage(const char *source_data,
 
        /* just in case if another process just had converted the mailbox,
           reopen the source storage */
-       mail_storage_destroy(&source_ns->storage);
+       mail_storage_unref(&source_ns->storage);
        if (mail_storage_create(source_ns, NULL,
                                MAIL_STORAGE_FLAG_NO_AUTOCREATE, &error) < 0) {
                /* No need for conversion anymore. */
index 31532c7b1f76786c314b41d02abc79adebe0d31a..73987ca8d89007752bdd0db9e98c19bca715a0ab 100644 (file)
@@ -34,8 +34,6 @@ struct virtual_storage_module virtual_storage_module =
 static MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static void virtual_list_init(struct mailbox_list *list);
-
 void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
 {
        const char *str;
@@ -64,16 +62,6 @@ static struct mail_storage *virtual_storage_alloc(void)
        return &storage->storage;
 }
 
-static int
-virtual_storage_create(struct mail_storage *_storage ATTR_UNUSED,
-                      struct mail_namespace *ns,
-                      const char **error_r ATTR_UNUSED)
-{
-       ns->flags |= NAMESPACE_FLAG_NOQUOTA;
-       virtual_list_init(ns->list);
-       return 0;
-}
-
 static void
 virtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
                                  struct mailbox_list_settings *set)
@@ -560,13 +548,16 @@ static void virtual_class_deinit(void)
        virtual_transaction_class_deinit();
 }
 
-static void virtual_list_init(struct mailbox_list *list)
+static void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+                                    struct mailbox_list *list)
 {
        struct virtual_mailbox_list *mlist;
 
        mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
        mlist->module_ctx.super = list->v;
 
+       list->ns->flags |= NAMESPACE_FLAG_NOQUOTA;
+
        list->v.iter_is_mailbox = virtual_list_iter_is_mailbox;
        list->v.delete_mailbox = virtual_list_delete_mailbox;
 
@@ -575,15 +566,16 @@ static void virtual_list_init(struct mailbox_list *list)
 
 struct mail_storage virtual_storage = {
        MEMBER(name) VIRTUAL_STORAGE_NAME,
-       MEMBER(mailbox_is_file) FALSE,
+       MEMBER(class_flags) 0,
 
        {
                NULL,
                virtual_class_init,
                virtual_class_deinit,
                virtual_storage_alloc,
-               virtual_storage_create,
+               NULL,
                index_storage_destroy,
+               virtual_storage_add_list,
                virtual_storage_get_list_settings,
                NULL,
                virtual_mailbox_open,