dovecot-2.0: Fixed opening mailbox when index directory didn't a...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jun 15 23:10:34 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/7a63279e95ba
changeset: 9469:7a63279e95ba
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jun 15 16:10:26 2009 -0400
description:
Fixed opening mailbox when index directory didn't already exist.

diffstat:

1 file changed, 60 insertions(+), 37 deletions(-)
src/lib-storage/index/index-storage.c |   97 ++++++++++++++++++++-------------

diffs (216 lines):

diff -r 653183a81b6c -r 7a63279e95ba src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c	Mon Jun 15 14:28:55 2009 -0400
+++ b/src/lib-storage/index/index-storage.c	Mon Jun 15 16:10:26 2009 -0400
@@ -26,6 +26,7 @@
 #define LOCK_NOTIFY_INTERVAL 30
 
 struct index_list {
+	union mail_index_module_context module_ctx;
 	struct index_list *next;
 
 	struct mail_index *index;
@@ -41,8 +42,9 @@ static struct index_list *indexes = NULL
 static struct index_list *indexes = NULL;
 static struct timeout *to_index = NULL;
 
-static void index_storage_add(struct mail_index *index,
-			      const char *mailbox_path, struct stat *st)
+static struct index_list *
+index_storage_add(struct mail_index *index,
+		  const char *mailbox_path, struct stat *st)
 {
 	struct index_list *list;
 
@@ -56,6 +58,9 @@ static void index_storage_add(struct mai
 
 	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)
@@ -65,39 +70,39 @@ static void index_list_free(struct index
 	i_free(list);
 }
 
-static int create_index_dir(struct mailbox_list *list, const char *name)
+static int create_missing_index_dir(struct mailbox *box)
 {
 	const char *root_dir, *index_dir, *p, *parent_dir;
 	mode_t mode, parent_mode;
 	gid_t gid, parent_gid;
 	int n = 0;
 
-	root_dir = mailbox_list_get_path(list, name,
+	root_dir = mailbox_list_get_path(box->list, box->name,
 					 MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	index_dir = mailbox_list_get_path(list, name,
+	index_dir = mailbox_list_get_path(box->list, box->name,
 					  MAILBOX_LIST_PATH_TYPE_INDEX);
 	if (strcmp(index_dir, root_dir) == 0 || *index_dir == '\0')
 		return 0;
 
-	mailbox_list_get_dir_permissions(list, name, &mode, &gid);
+	mailbox_list_get_dir_permissions(box->list, box->name, &mode, &gid);
 	while (mkdir_chown(index_dir, mode, (uid_t)-1, gid) < 0) {
 		if (errno == EEXIST)
 			break;
 
 		p = strrchr(index_dir, '/');
 		if (errno != ENOENT || p == NULL || ++n == 2) {
-			mailbox_list_set_critical(list,
+			mail_storage_set_critical(box->storage,
 				"mkdir(%s) failed: %m", index_dir);
 			return -1;
 		}
 		/* create the parent directory first */
-		mailbox_list_get_dir_permissions(list, NULL,
+		mailbox_list_get_dir_permissions(box->list, NULL,
 						 &parent_mode, &parent_gid);
 		parent_dir = t_strdup_until(index_dir, p);
 		if (mkdir_parents_chown(parent_dir, parent_mode,
 					(uid_t)-1, parent_gid) < 0 &&
 		    errno != EEXIST) {
-			mailbox_list_set_critical(list,
+			mail_storage_set_critical(box->storage,
 				"mkdir(%s) failed: %m", parent_dir);
 			return -1;
 		}
@@ -120,11 +125,9 @@ get_index_dir(struct mailbox_list *list,
 
 	if (stat(index_dir, st_r) < 0) {
 		if (errno == ENOENT) {
-			/* try to create it */
-			if (create_index_dir(list, name) < 0)
-				return NULL;
-			if (stat(index_dir, st_r) == 0)
-				return index_dir;
+			/* it'll be created later */
+			memset(st_r, 0, sizeof(*st_r));
+			return index_dir;
 		}
 		if (errno == EACCES) {
 			mailbox_list_set_critical(list, "%s",
@@ -143,13 +146,11 @@ index_storage_alloc(struct mailbox_list 
 index_storage_alloc(struct mailbox_list *list, const char *name,
 		    enum mailbox_flags flags, const char *prefix)
 {
-	struct index_list **indexp, *rec;
-	struct mail_index *index;
+	struct index_list **indexp, *rec, *match;
 	struct stat st, st2;
 	const char *index_dir, *mailbox_path;
 	int destroy_count;
 
-	// FIXME: failure handling when dirs don't exist yet?
 	mailbox_path = mailbox_list_get_path(list, name,
 					     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	index_dir = get_index_dir(list, name, flags, &st);
@@ -158,13 +159,17 @@ index_storage_alloc(struct mailbox_list 
 		memset(&st, 0, sizeof(st));
 
 	/* compare index_dir inodes so we don't break even with symlinks.
-	   for in-memory indexes compare just mailbox paths */
-	destroy_count = 0; index = NULL;
+	   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 (index_dir != NULL) {
-			if (index == NULL && st.st_ino == rec->index_dir_ino &&
+		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
@@ -173,17 +178,12 @@ index_storage_alloc(struct mailbox_list 
 				    st2.st_ino != st.st_ino ||
 				    !CMP_DEV_T(st2.st_dev, st.st_dev))
 					rec->destroy_time = 0;
-				else {
-					rec->refcount++;
-					index = rec->index;
-				}
+				else
+					match = rec;
 			}
 		} else {
-			if (index == NULL && st.st_ino == 0 &&
-			    strcmp(mailbox_path, rec->mailbox_path) == 0) {
-				rec->refcount++;
-				index = rec->index;
-			}
+			if (strcmp(mailbox_path, rec->mailbox_path) == 0)
+				match = rec;
 		}
 
 		if (rec->refcount == 0) {
@@ -200,12 +200,13 @@ index_storage_alloc(struct mailbox_list 
                 indexp = &(*indexp)->next;
 	}
 
-	if (index == NULL) {
-		index = mail_index_alloc(index_dir, prefix);
-		index_storage_add(index, mailbox_path, &st);
-	}
-
-	return index;
+	if (match == NULL) {
+		match = index_storage_add(mail_index_alloc(index_dir, prefix),
+					  mailbox_path, &st);
+	} else {
+		match->refcount++;
+	}
+	return match->index;
 }
 
 static void destroy_unrefed(bool all)
@@ -369,9 +370,12 @@ int index_storage_mailbox_open(struct ma
 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;
 	gid_t dir_gid;
 	int ret;
 
@@ -394,8 +398,27 @@ int index_storage_mailbox_open(struct ma
 		index_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
 	if (ibox->keep_index_backups)
 		index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS;
-	if (ibox->index_never_in_memory)
+	if (ibox->index_never_in_memory) {
 		index_flags |= MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY;
+		if (mail_index_is_in_memory(ibox->index)) {
+			mail_storage_set_critical(box->storage,
+				"Couldn't create index file");
+			return -1;
+		}
+	}
+
+	if (create_missing_index_dir(box) < 0)
+		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) {


More information about the dovecot-cvs mailing list