changeset 10656:9d3b5cbef222 HEAD

Moved mail_index lookup cache from lib-storage to lib-index. Removed some code duplication as a result.
author Timo Sirainen <tss@iki.fi>
date Sun, 07 Feb 2010 04:50:40 +0200
parents fc0ac73f0b36
children e7f066508299
files src/lib-index/Makefile.am src/lib-index/mail-index-alloc-cache.c src/lib-index/mail-index-alloc-cache.h src/lib-index/mail-index.c src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h 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-storage.c src/lib-storage/mailbox-list.c src/plugins/virtual/virtual-storage.c
diffstat 16 files changed, 247 insertions(+), 251 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/Makefile.am	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-index/Makefile.am	Sun Feb 07 04:50:40 2010 +0200
@@ -14,6 +14,7 @@
 	mail-cache-transaction.c \
 	mail-cache-sync-update.c \
         mail-index.c \
+        mail-index-alloc-cache.c \
         mail-index-dummy-view.c \
         mail-index-fsck.c \
         mail-index-lock.c \
@@ -48,6 +49,7 @@
 	mail-cache.h \
 	mail-cache-private.h \
 	mail-index.h \
+        mail-index-alloc-cache.h \
         mail-index-modseq.h \
 	mail-index-private.h \
         mail-index-strmap.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-alloc-cache.c	Sun Feb 07 04:50:40 2010 +0200
@@ -0,0 +1,203 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "module-context.h"
+#include "eacces-error.h"
+#include "mail-index-private.h"
+#include "mail-index-alloc-cache.h"
+
+#define MAIL_INDEX_ALLOC_CACHE_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, mail_index_alloc_cache_index_module)
+
+/* How many seconds to keep index opened for reuse after it's been closed */
+#define INDEX_CACHE_TIMEOUT 10
+/* How many closed indexes to keep */
+#define INDEX_CACHE_MAX 3
+
+struct mail_index_alloc_cache_list {
+	union mail_index_module_context module_ctx;
+	struct mail_index_alloc_cache_list *next;
+
+	struct mail_index *index;
+	char *mailbox_path;
+	int refcount;
+
+	dev_t index_dir_dev;
+	ino_t index_dir_ino;
+
+	time_t destroy_time;
+};
+
+static MODULE_CONTEXT_DEFINE_INIT(mail_index_alloc_cache_index_module,
+				  &mail_index_module_register);
+static struct mail_index_alloc_cache_list *indexes = NULL;
+static struct timeout *to_index = NULL;
+
+static struct mail_index_alloc_cache_list *
+mail_index_alloc_cache_add(struct mail_index *index,
+			   const char *mailbox_path, struct stat *st)
+{
+	struct mail_index_alloc_cache_list *list;
+
+	list = i_new(struct mail_index_alloc_cache_list, 1);
+	list->refcount = 1;
+	list->index = index;
+
+	list->mailbox_path = i_strdup(mailbox_path);
+	list->index_dir_dev = st->st_dev;
+	list->index_dir_ino = st->st_ino;
+
+	list->next = indexes;
+	indexes = list;
+
+	MODULE_CONTEXT_SET(index, mail_index_alloc_cache_index_module, list);
+	return list;
+}
+
+static void
+mail_index_alloc_cache_list_free(struct mail_index_alloc_cache_list *list)
+{
+	mail_index_free(&list->index);
+	i_free(list->mailbox_path);
+	i_free(list);
+}
+
+struct mail_index *
+mail_index_alloc_cache_get(const char *mailbox_path,
+			   const char *index_dir, const char *prefix)
+{
+	struct mail_index_alloc_cache_list **indexp, *rec, *match;
+	struct stat st, st2;
+	unsigned int destroy_count;
+
+	/* compare index_dir inodes so we don't break even with symlinks.
+	   if index_dir doesn't exist yet or if using in-memory indexes, just
+	   compare mailbox paths */
+	memset(&st, 0, sizeof(st));
+	if (index_dir == NULL) {
+		/* in-memory indexes */
+	} else if (stat(index_dir, &st) < 0) {
+		if (errno == ENOENT) {
+			/* it'll be created later */
+		} else if (errno == EACCES) {
+			i_error("%s", eacces_error_get("stat", index_dir));
+		} else {
+			i_error("stat(%s) failed: %m", index_dir);
+		}
+	}
+
+	destroy_count = 0; match = NULL;
+	for (indexp = &indexes; *indexp != NULL;) {
+		rec = *indexp;
+
+		if (match != NULL) {
+			/* already found the index. we're just going through
+			   the rest of them to drop 0 refcounts */
+		} else if (index_dir != NULL && rec->index_dir_ino != 0) {
+			if (st.st_ino == rec->index_dir_ino &&
+			    CMP_DEV_T(st.st_dev, rec->index_dir_dev)) {
+				/* make sure the directory still exists.
+				   it might have been renamed and we're trying
+				   to access it via its new path now. */
+				if (stat(rec->index->dir, &st2) < 0 ||
+				    st2.st_ino != st.st_ino ||
+				    !CMP_DEV_T(st2.st_dev, st.st_dev))
+					rec->destroy_time = 0;
+				else
+					match = rec;
+			}
+		} else {
+			if (strcmp(mailbox_path, rec->mailbox_path) == 0)
+				match = rec;
+		}
+
+		if (rec->refcount == 0 && rec != match) {
+			if (rec->destroy_time <= ioloop_time ||
+			    destroy_count >= INDEX_CACHE_MAX) {
+				*indexp = rec->next;
+				mail_index_alloc_cache_list_free(rec);
+				continue;
+			} else {
+				destroy_count++;
+			}
+		}
+
+                indexp = &(*indexp)->next;
+	}
+
+	if (match == NULL) {
+		struct mail_index *index = mail_index_alloc(index_dir, prefix);
+		match = mail_index_alloc_cache_add(index, mailbox_path, &st);
+	} else {
+		match->refcount++;
+	}
+	i_assert(match->index != NULL);
+	return match->index;
+}
+
+static void destroy_unrefed(bool all)
+{
+	struct mail_index_alloc_cache_list **list, *rec;
+
+	for (list = &indexes; *list != NULL;) {
+		rec = *list;
+
+		if (rec->refcount == 0 &&
+		    (all || rec->destroy_time <= ioloop_time)) {
+			*list = rec->next;
+			mail_index_alloc_cache_list_free(rec);
+		} else {
+			list = &(*list)->next;
+		}
+	}
+
+	if (indexes == NULL && to_index != NULL)
+		timeout_remove(&to_index);
+}
+
+static void index_removal_timeout(void *context ATTR_UNUSED)
+{
+	destroy_unrefed(FALSE);
+}
+
+void mail_index_alloc_cache_unref(struct mail_index *index)
+{
+	struct mail_index_alloc_cache_list *list;
+
+	for (list = indexes; list != NULL; list = list->next) {
+		if (list->index == index)
+			break;
+	}
+
+	i_assert(list != NULL);
+	i_assert(list->refcount > 0);
+
+	list->refcount--;
+	list->destroy_time = ioloop_time + INDEX_CACHE_TIMEOUT;
+	if (to_index == NULL) {
+		to_index = timeout_add(INDEX_CACHE_TIMEOUT*1000/2,
+				       index_removal_timeout, NULL);
+	}
+}
+
+void mail_index_alloc_cache_destroy_unrefed(void)
+{
+	destroy_unrefed(TRUE);
+}
+
+void mail_index_alloc_cache_index_opened(struct mail_index *index)
+{
+	struct mail_index_alloc_cache_list *list =
+		MAIL_INDEX_ALLOC_CACHE_CONTEXT(index);
+	struct stat st;
+
+	if (list != NULL && list->index_dir_ino == 0 &&
+	    !MAIL_INDEX_IS_IN_MEMORY(index)) {
+		/* newly created index directory. update its stat. */
+		if (stat(index->dir, &st) == 0) {
+			list->index_dir_ino = st.st_ino;
+			list->index_dir_dev = st.st_dev;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-alloc-cache.h	Sun Feb 07 04:50:40 2010 +0200
@@ -0,0 +1,15 @@
+#ifndef MAIL_INDEX_ALLOC_CACHE_H
+#define MAIL_INDEX_ALLOC_CACHE_H
+
+/* If using in-memory indexes, give index_dir=NULL. */
+struct mail_index *
+mail_index_alloc_cache_get(const char *mailbox_path,
+			   const char *index_dir, const char *prefix);
+void mail_index_alloc_cache_unref(struct mail_index *index);
+
+void mail_index_alloc_cache_destroy_unrefed(void);
+
+/* internal: */
+void mail_index_alloc_cache_index_opened(struct mail_index *index);
+
+#endif
--- a/src/lib-index/mail-index.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-index/mail-index.c	Sun Feb 07 04:50:40 2010 +0200
@@ -11,6 +11,7 @@
 #include "nfs-workarounds.h"
 #include "read-full.h"
 #include "write-full.h"
+#include "mail-index-alloc-cache.h"
 #include "mail-index-private.h"
 #include "mail-index-view-private.h"
 #include "mail-index-sync-private.h"
@@ -527,6 +528,7 @@
 
 	i_assert(index->map != NULL);
 	index->opened = TRUE;
+	mail_index_alloc_cache_index_opened(index);
 	return 1;
 }
 
--- a/src/lib-storage/index/cydir/cydir-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -202,12 +202,6 @@
 	struct stat st;
 	const char *src;
 
-	/* Make sure the indexes are closed before trying to delete the
-	   directory that contains them. It can still fail with some NFS
-	   implementations if indexes are opened by another session, but
-	   that can't really be helped. */
-	index_storage_destroy_unrefed();
-
 	/* delete the index and control directories */
 	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
@@ -309,7 +303,7 @@
 		NULL,
 		cydir_storage_alloc,
 		NULL,
-		index_storage_destroy,
+		NULL,
 		cydir_storage_add_list,
 		cydir_storage_get_list_settings,
 		NULL,
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -97,7 +97,6 @@
 	mdbox_files_free(storage);
 	dbox_map_deinit(&storage->map);
 	array_free(&storage->open_files);
-	index_storage_destroy(_storage);
 }
 
 struct mailbox *
@@ -358,12 +357,6 @@
 	const char *trash_dest;
 	int ret;
 
-	/* Make sure the indexes are closed before trying to delete the
-	   directory that contains them. It can still fail with some NFS
-	   implementations if indexes are opened by another session, but
-	   that can't really be helped. */
-	index_storage_destroy_unrefed();
-
 	/* delete the index and control directories */
 	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -237,12 +237,6 @@
 	const char *trash_dest;
 	int ret;
 
-	/* Make sure the indexes are closed before trying to delete the
-	   directory that contains them. It can still fail with some NFS
-	   implementations if indexes are opened by another session, but
-	   that can't really be helped. */
-	index_storage_destroy_unrefed();
-
 	/* delete the index and control directories */
 	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
@@ -291,7 +285,7 @@
                 NULL,
 		sdbox_storage_alloc,
 		NULL,
-		index_storage_destroy,
+		NULL,
 		sdbox_storage_add_list,
 		dbox_storage_get_list_settings,
 		NULL,
--- a/src/lib-storage/index/index-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/index-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -7,6 +7,7 @@
 #include "str.h"
 #include "imap-parser.h"
 #include "mkdir-parents.h"
+#include "mail-index-alloc-cache.h"
 #include "mail-index-private.h"
 #include "mail-index-modseq.h"
 #include "mailbox-list-private.h"
@@ -19,58 +20,8 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-/* How many seconds to keep index opened for reuse after it's been closed */
-#define INDEX_CACHE_TIMEOUT 10
-/* How many closed indexes to keep */
-#define INDEX_CACHE_MAX 3
-
 #define LOCK_NOTIFY_INTERVAL 30
 
-struct index_list {
-	union mail_index_module_context module_ctx;
-	struct index_list *next;
-
-	struct mail_index *index;
-	char *mailbox_path;
-	int refcount;
-
-	dev_t index_dir_dev;
-	ino_t index_dir_ino;
-
-	time_t destroy_time;
-};
-
-static struct index_list *indexes = NULL;
-static struct timeout *to_index = NULL;
-
-static struct index_list *
-index_storage_add(struct mail_index *index,
-		  const char *mailbox_path, struct stat *st)
-{
-	struct index_list *list;
-
-	list = i_new(struct index_list, 1);
-	list->refcount = 1;
-	list->index = index;
-
-	list->mailbox_path = i_strdup(mailbox_path);
-	list->index_dir_dev = st->st_dev;
-	list->index_dir_ino = st->st_ino;
-
-	list->next = indexes;
-	indexes = list;
-
-	MODULE_CONTEXT_SET(index, mail_storage_mail_index_module, list);
-	return list;
-}
-
-static void index_list_free(struct index_list *list)
-{
-	mail_index_free(&list->index);
-	i_free(list->mailbox_path);
-	i_free(list);
-}
-
 int index_list_create_missing_index_dir(struct mailbox_list *list,
 					const char *name)
 {
@@ -113,159 +64,20 @@
 	return 0;
 }
 
-static const char *
-get_index_dir(struct mailbox_list *list, const char *name,
-	      enum mailbox_flags flags, struct stat *st_r)
-{
-	const char *index_dir;
-
-	index_dir = (flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ? "" :
-		mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
-	if (*index_dir == '\0') {
-		/* disabled */
-		return NULL;
-	}
-
-	if (stat(index_dir, st_r) < 0) {
-		if (errno == ENOENT) {
-			/* it'll be created later */
-			memset(st_r, 0, sizeof(*st_r));
-			return index_dir;
-		}
-		if (errno == EACCES) {
-			mailbox_list_set_critical(list, "%s",
-				mail_error_eacces_msg("stat", index_dir));
-			return NULL;
-		}
-
-		mailbox_list_set_critical(list, "stat(%s) failed: %m",
-					  index_dir);
-		return NULL;
-	}
-	return index_dir;
-}
-
 static struct mail_index *
 index_storage_alloc(struct mailbox_list *list, const char *name,
 		    enum mailbox_flags flags, const char *prefix)
 {
-	struct index_list **indexp, *rec, *match;
-	struct stat st, st2;
 	const char *index_dir, *mailbox_path;
-	int destroy_count;
 
 	mailbox_path = mailbox_list_get_path(list, name,
 					     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	index_dir = get_index_dir(list, name, flags, &st);
-
-	if (index_dir == NULL)
-		memset(&st, 0, sizeof(st));
-
-	/* compare index_dir inodes so we don't break even with symlinks.
-	   if index_dir doesn't exist yet or if using in-memory indexes, just
-	   compare mailbox paths */
-	destroy_count = 0; match = NULL;
-	for (indexp = &indexes; *indexp != NULL;) {
-		rec = *indexp;
-
-		if (match != NULL) {
-			/* already found the index. we're just going through
-			   the rest of them to drop 0 refcounts */
-		} else if (index_dir != NULL && rec->index_dir_ino != 0) {
-			if (st.st_ino == rec->index_dir_ino &&
-			    CMP_DEV_T(st.st_dev, rec->index_dir_dev)) {
-				/* make sure the directory still exists.
-				   it might have been renamed and we're trying
-				   to access it via its new path now. */
-				if (stat(rec->index->dir, &st2) < 0 ||
-				    st2.st_ino != st.st_ino ||
-				    !CMP_DEV_T(st2.st_dev, st.st_dev))
-					rec->destroy_time = 0;
-				else
-					match = rec;
-			}
-		} else {
-			if (strcmp(mailbox_path, rec->mailbox_path) == 0)
-				match = rec;
-		}
-
-		if (rec->refcount == 0 && rec != match) {
-			if (rec->destroy_time <= ioloop_time ||
-			    destroy_count >= INDEX_CACHE_MAX) {
-				*indexp = rec->next;
-				index_list_free(rec);
-				continue;
-			} else {
-				destroy_count++;
-			}
-		}
-
-                indexp = &(*indexp)->next;
-	}
+	index_dir = (flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ? "" :
+		mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
+	if (*index_dir == '\0')
+		index_dir = NULL;
 
-	if (match == NULL) {
-		match = index_storage_add(mail_index_alloc(index_dir, prefix),
-					  mailbox_path, &st);
-	} else {
-		match->refcount++;
-	}
-	i_assert(match->index != NULL);
-	return match->index;
-}
-
-static void destroy_unrefed(bool all)
-{
-	struct index_list **list, *rec;
-
-	for (list = &indexes; *list != NULL;) {
-		rec = *list;
-
-		if (rec->refcount == 0 &&
-		    (all || rec->destroy_time <= ioloop_time)) {
-			*list = rec->next;
-			index_list_free(rec);
-		} else {
-			list = &(*list)->next;
-		}
-	}
-
-	if (indexes == NULL && to_index != NULL)
-		timeout_remove(&to_index);
-}
-
-static void index_removal_timeout(void *context ATTR_UNUSED)
-{
-	destroy_unrefed(FALSE);
-}
-
-void index_storage_unref(struct mail_index *index)
-{
-	struct index_list *list;
-
-	for (list = indexes; list != NULL; list = list->next) {
-		if (list->index == index)
-			break;
-	}
-
-	i_assert(list != NULL);
-	i_assert(list->refcount > 0);
-
-	list->refcount--;
-	list->destroy_time = ioloop_time + INDEX_CACHE_TIMEOUT;
-	if (to_index == NULL) {
-		to_index = timeout_add(INDEX_CACHE_TIMEOUT*1000/2,
-				       index_removal_timeout, NULL);
-	}
-}
-
-void index_storage_destroy_unrefed(void)
-{
-	destroy_unrefed(TRUE);
-}
-
-void index_storage_destroy(struct mail_storage *storage ATTR_UNUSED)
-{
-	index_storage_destroy_unrefed();
+	return mail_index_alloc_cache_get(mailbox_path, index_dir, prefix);
 }
 
 static void set_cache_decisions(const char *set, const char *fields,
@@ -374,12 +186,9 @@
 int index_storage_mailbox_open(struct mailbox *box)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *)box;
-	struct index_list *list = MAIL_STORAGE_CONTEXT(ibox->index);
 	enum file_lock_method lock_method =
 		box->storage->set->parsed_lock_method;
 	enum mail_index_open_flags index_flags;
-	const char *index_dir;
-	struct stat st;
 	int ret;
 
 	i_assert(!box->opened);
@@ -401,16 +210,6 @@
 		return -1;
 	}
 
-	index_dir = mailbox_list_get_path(box->list, box->name,
-					  MAILBOX_LIST_PATH_TYPE_INDEX);
-	if (list->index_dir_ino == 0 && *index_dir != '\0') {
-		/* newly created index directory. update its stat. */
-		if (stat(index_dir, &st) == 0) {
-			list->index_dir_ino = st.st_ino;
-			list->index_dir_dev = st.st_dev;
-		}
-	}
-
 	ret = mail_index_open(ibox->index, index_flags, lock_method);
 	if (ret <= 0 || ibox->move_to_memory) {
 		if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
@@ -526,7 +325,7 @@
 	if (ibox->box.input != NULL)
 		i_stream_unref(&ibox->box.input);
 	if (ibox->index != NULL)
-		index_storage_unref(ibox->index);
+		mail_index_alloc_cache_unref(ibox->index);
 	if (array_is_created(&ibox->recent_flags))
 		array_free(&ibox->recent_flags);
 	i_free(ibox->cache_fields);
--- a/src/lib-storage/index/index-storage.h	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/index-storage.h	Sun Feb 07 04:50:40 2010 +0200
@@ -73,10 +73,6 @@
 			       unsigned int secs_left);
 void index_storage_lock_notify_reset(struct index_mailbox *ibox);
 
-void index_storage_unref(struct mail_index *index);
-void index_storage_destroy_unrefed(void);
-void index_storage_destroy(struct mail_storage *storage ATTR_UNUSED);
-
 void index_storage_mailbox_alloc(struct index_mailbox *ibox, const char *name,
 				 struct istream *input,
 				 enum mailbox_flags flags,
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -705,12 +705,6 @@
 
 	mailbox_get_guid(list, name, mailbox_guid);
 
-	/* Make sure the indexes are closed before trying to delete the
-	   directory that contains them. It can still fail with some NFS
-	   implementations if indexes are opened by another session, but
-	   that can't really be helped. */
-	index_storage_destroy_unrefed();
-
 	/* delete the index and control directories */
 	if (mlist->super.delete_mailbox(list, name) < 0)
 		return -1;
@@ -1034,7 +1028,7 @@
                 maildir_get_setting_parser_info,
 		maildir_storage_alloc,
 		maildir_storage_create,
-		index_storage_destroy,
+		NULL,
 		maildir_storage_add_list,
 		maildir_storage_get_list_settings,
 		maildir_storage_autodetect,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -757,7 +757,6 @@
 	}
 
 	/* delete index / control files first */
-	index_storage_destroy_unrefed();
 	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
 
@@ -858,7 +857,7 @@
                 mbox_get_setting_parser_info,
 		mbox_storage_alloc,
 		mbox_storage_create,
-		index_storage_destroy,
+		NULL,
 		mbox_storage_add_list,
 		mbox_storage_get_list_settings,
 		mbox_storage_autodetect,
--- a/src/lib-storage/index/raw/raw-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/raw/raw-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -178,7 +178,7 @@
 		NULL,
 		raw_storage_alloc,
 		NULL,
-		index_storage_destroy,
+		NULL,
 		raw_storage_add_list,
 		raw_storage_get_list_settings,
 		NULL,
--- a/src/lib-storage/index/shared/shared-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/shared/shared-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -296,7 +296,7 @@
 		NULL,
 		shared_storage_alloc,
 		shared_storage_create,
-		index_storage_destroy,
+		NULL,
 		NULL,
 		shared_storage_get_list_settings,
 		NULL,
--- a/src/lib-storage/mail-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/mail-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -8,6 +8,7 @@
 #include "mkdir-parents.h"
 #include "var-expand.h"
 #include "mail-index-private.h"
+#include "mail-index-alloc-cache.h"
 #include "mailbox-list-private.h"
 #include "mail-storage-private.h"
 #include "mail-storage-settings.h"
@@ -328,6 +329,8 @@
 		storage->v.destroy(storage);
 	i_free(storage->error_string);
 	pool_unref(&storage->pool);
+
+	mail_index_alloc_cache_destroy_unrefed();
 }
 
 void mail_storage_clear_error(struct mail_storage *storage)
--- a/src/lib-storage/mailbox-list.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/mailbox-list.c	Sun Feb 07 04:50:40 2010 +0200
@@ -15,6 +15,7 @@
 #include "unlink-directory.h"
 #include "imap-match.h"
 #include "imap-utf7.h"
+#include "mail-index-alloc-cache.h"
 #include "mailbox-log.h"
 #include "mailbox-tree.h"
 #include "mail-storage-private.h"
@@ -744,6 +745,13 @@
 				       "INBOX can't be deleted.");
 		return -1;
 	}
+
+	/* Make sure the indexes are closed before trying to delete the
+	   directory that contains them. It can still fail with some NFS
+	   implementations if indexes are opened by another session, but
+	   that can't really be helped. */
+	mail_index_alloc_cache_destroy_unrefed();
+
 	return list->v.delete_mailbox(list, name);
 }
 
--- a/src/plugins/virtual/virtual-storage.c	Sun Feb 07 03:25:32 2010 +0200
+++ b/src/plugins/virtual/virtual-storage.c	Sun Feb 07 04:50:40 2010 +0200
@@ -382,12 +382,6 @@
 	struct stat st;
 	const char *src;
 
-	/* Make sure the indexes are closed before trying to delete the
-	   directory that contains them. It can still fail with some NFS
-	   implementations if indexes are opened by another session, but
-	   that can't really be helped. */
-	index_storage_destroy_unrefed();
-
 	/* delete the index and control directories */
 	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
@@ -569,7 +563,7 @@
 		NULL,
 		virtual_storage_alloc,
 		NULL,
-		index_storage_destroy,
+		NULL,
 		virtual_storage_add_list,
 		virtual_storage_get_list_settings,
 		NULL,