dovecot: Handle losing index file better. Handle fsck better.

dovecot at dovecot.org dovecot at dovecot.org
Thu Jun 28 01:52:05 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/e59892590a02
changeset: 5820:e59892590a02
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jun 28 01:48:59 2007 +0300
description:
Handle losing index file better. Handle fsck better.

diffstat:

8 files changed, 48 insertions(+), 19 deletions(-)
src/lib-index/mail-index-fsck.c         |    9 +++++++--
src/lib-index/mail-index-private.h      |    8 +++++---
src/lib-index/mail-index-sync-private.h |    1 +
src/lib-index/mail-index-sync-update.c  |    4 ++++
src/lib-index/mail-index-sync.c         |   23 ++++++++++++++++++++---
src/lib-index/mail-index-view-sync.c    |    2 +-
src/lib-index/mail-index-write.c        |    5 ++++-
src/lib-index/mail-index.c              |   15 ++++++---------

diffs (204 lines):

diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-fsck.c
--- a/src/lib-index/mail-index-fsck.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-fsck.c	Thu Jun 28 01:48:59 2007 +0300
@@ -47,6 +47,11 @@ mail_index_fsck_map(struct mail_index *i
 					      &file_offset);
 	}
 
+	/* Remember the log head position. If we go back in the index's head
+	   offset, ignore errors in the log up to this offset. */
+	index->fsck_log_head_file_seq = file_seq;
+	index->fsck_log_head_file_offset = file_offset;
+
 	/* locking already does the most important sanity checks for header */
 	hdr = map->hdr;
 
@@ -55,8 +60,7 @@ mail_index_fsck_map(struct mail_index *i
 
 	hdr.flags &= ~MAIL_INDEX_HDR_FLAG_FSCK;
 
-	if (hdr.log_file_seq != file_seq) {
-		hdr.log_file_seq = file_seq;
+	if (hdr.log_file_seq < file_seq) {
 		hdr.log_file_head_offset = hdr.log_file_tail_offset =
 			sizeof(struct mail_transaction_log_header);
 	} else {
@@ -65,6 +69,7 @@ mail_index_fsck_map(struct mail_index *i
 		if (hdr.log_file_tail_offset > hdr.log_file_head_offset)
 			hdr.log_file_tail_offset = hdr.log_file_head_offset;
 	}
+	hdr.log_file_seq = file_seq;
 
 	hdr.messages_count = 0;
 	hdr.recent_messages_count = 0;
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-private.h
--- a/src/lib-index/mail-index-private.h	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-private.h	Thu Jun 28 01:48:59 2007 +0300
@@ -161,13 +161,17 @@ struct mail_index {
 	struct mail_index_map *map;
 	uint32_t indexid;
 	/* last_read_log_file_* contains the seq/offsets we last read from
-	   the main index file's headers. these are used ro figure out when
+	   the main index file's headers. these are used to figure out when
 	   the main index file should be updated, and if we can update it
 	   by writing on top of it or if we need to recreate it. */
 	uint32_t last_read_log_file_seq;
 	uint32_t last_read_log_file_head_offset;
 	uint32_t last_read_log_file_tail_offset;
 	struct stat last_read_stat;
+
+	/* transaction log head seq/offset when we last fscked */
+	uint32_t fsck_log_head_file_seq;
+	uoff_t fsck_log_head_file_offset;
 
 	int lock_type, shared_lock_count, excl_lock_count;
 	unsigned int lock_id;
@@ -281,8 +285,6 @@ void mail_index_view_transaction_ref(str
 void mail_index_view_transaction_ref(struct mail_index_view *view);
 void mail_index_view_transaction_unref(struct mail_index_view *view);
 
-void mail_index_set_inconsistent(struct mail_index *index);
-
 int mail_index_set_error(struct mail_index *index, const char *fmt, ...)
 	__attr_format__(2, 3);
 /* "%s failed with index file %s: %m" */
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-sync-private.h
--- a/src/lib-index/mail-index-sync-private.h	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-sync-private.h	Thu Jun 28 01:48:59 2007 +0300
@@ -38,6 +38,7 @@ struct mail_index_sync_map_ctx {
 	unsigned int expunge_handlers_set:1;
 	unsigned int expunge_handlers_used:1;
 	unsigned int cur_ext_ignore:1;
+	unsigned int errors:1;
 };
 
 extern struct mail_transaction_map_functions mail_index_map_sync_funcs;
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c	Thu Jun 28 01:48:59 2007 +0300
@@ -814,6 +814,10 @@ int mail_index_sync_map(struct mail_inde
 
 	/*FIXME:if (mail_index_map_msync(index, map) < 0)
 		ret = -1;*/
+	if (sync_map_ctx.errors) {
+		/* avoid the same syncing errors the next time */
+		mail_index_write(index, FALSE);
+	}
 
 	/* restore refcount before closing the view. this is necessary also
 	   if map got cloned, because view closing would otherwise destroy it */
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-sync.c
--- a/src/lib-index/mail-index-sync.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-sync.c	Thu Jun 28 01:48:59 2007 +0300
@@ -321,7 +321,6 @@ mail_index_sync_set_log_view(struct mail
 		mail_index_set_error(view->index,
 			"Unexpected transaction log desync with index %s",
 			view->index->filepath);
-		mail_index_set_inconsistent(view->index);
 		return -1;
 	}
 	return 0;
@@ -396,8 +395,17 @@ int mail_index_sync_begin(struct mail_in
 	   the end of the transaction log */
 	if (mail_index_sync_set_log_view(ctx->view, hdr->log_file_seq,
 					 hdr->log_file_tail_offset) < 0) {
-                mail_index_sync_rollback(&ctx);
-		return -1;
+		/* if a log file is missing, there's nothing we can do except
+		   to skip over it. fix the problem with fsck and try again. */
+		mail_index_sync_rollback(&ctx);
+		if (mail_index_fsck(index) <= 0) {
+			mail_index_unlock(index, lock_id);
+			mail_transaction_log_sync_unlock(index->log);
+			return -1;
+		}
+		return mail_index_sync_begin(index, ctx_r, view_r, trans_r,
+					     log_file_seq, log_file_offset,
+					     flags);
 	}
 
 	/* we need to have all the transactions sorted to optimize
@@ -690,8 +698,17 @@ void mail_index_sync_set_corrupted(struc
 	uint32_t seq;
 	uoff_t offset;
 
+	ctx->errors = TRUE;
+
 	mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
 					       &seq, &offset);
+
+	if (seq < ctx->view->index->fsck_log_head_file_seq ||
+	    (seq == ctx->view->index->fsck_log_head_file_seq &&
+	     offset < ctx->view->index->fsck_log_head_file_offset)) {
+		/* be silent */
+		return;
+	}
 
 	va_start(va, fmt);
 	t_push();
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-view-sync.c
--- a/src/lib-index/mail-index-view-sync.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-view-sync.c	Thu Jun 28 01:48:59 2007 +0300
@@ -104,7 +104,7 @@ static int view_sync_set_log_view_range(
 			mail_index_set_error(view->index,
 				"Transaction log got desynced for index %s",
 				view->index->filepath);
-			mail_index_set_inconsistent(view->index);
+			view->inconsistent = TRUE;
 		}
 		return -1;
 	}
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index-write.c
--- a/src/lib-index/mail-index-write.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index-write.c	Thu Jun 28 01:48:59 2007 +0300
@@ -194,7 +194,10 @@ void mail_index_write(struct mail_index 
 	} else {
 		if (mail_index_write_map_over(index) < 0) {
 			mail_index_set_syscall_error(index, "pwrite_full()");
-			mail_index_set_inconsistent(index);
+			/* hopefully didn't break badly */
+			mail_index_unlock(index, lock_id);
+			mail_index_move_to_memory(index);
+			return;
 		}
 		mail_index_unlock(index, lock_id);
 	}
diff -r 4ea31bf18a56 -r e59892590a02 src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c	Thu Jun 28 01:03:18 2007 +0300
+++ b/src/lib-index/mail-index.c	Thu Jun 28 01:48:59 2007 +0300
@@ -364,9 +364,11 @@ mail_index_try_open(struct mail_index *i
 
 	if (ret == 0) {
 		/* it's corrupted - recreate it */
-		if (close(index->fd) < 0)
-			mail_index_set_syscall_error(index, "close()");
-		index->fd = -1;
+		if (index->fd != -1) {
+			if (close(index->fd) < 0)
+				mail_index_set_syscall_error(index, "close()");
+			index->fd = -1;
+		}
 	}
 	return ret;
 }
@@ -618,11 +620,6 @@ int mail_index_set_error(struct mail_ind
 	return -1;
 }
 
-void mail_index_set_inconsistent(struct mail_index *index)
-{
-	index->indexid = 0;
-}
-
 int mail_index_move_to_memory(struct mail_index *index)
 {
 	struct mail_index_map *map;
@@ -667,7 +664,7 @@ int mail_index_move_to_memory(struct mai
 
 void mail_index_mark_corrupted(struct mail_index *index)
 {
-	mail_index_set_inconsistent(index);
+	index->indexid = 0;
 
 	index->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
 	if (unlink(index->filepath) < 0 && errno != ENOENT && errno != ESTALE)


More information about the dovecot-cvs mailing list