changeset 5529:fd13f04e1fda HEAD

Give "mbox file was modified while we were syncing" error only if we detect some problems in the mbox file. The check can't be trusted with NFS.
author Timo Sirainen <tss@iki.fi>
date Fri, 06 Apr 2007 21:13:16 +0300
parents bad62bc7bafc
children eaea98799f5a
files src/lib-storage/index/mbox/mbox-sync-private.h src/lib-storage/index/mbox/mbox-sync-rewrite.c src/lib-storage/index/mbox/mbox-sync.c
diffstat 3 files changed, 44 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/mbox/mbox-sync-private.h	Fri Apr 06 12:30:03 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-private.h	Fri Apr 06 21:13:16 2007 +0300
@@ -141,10 +141,13 @@
 	unsigned int delay_writes:1;
 	unsigned int renumber_uids:1;
 	unsigned int moved_offsets:1;
+	unsigned int ext_modified:1;
 };
 
 int mbox_sync(struct mbox_mailbox *mbox, enum mbox_sync_flags flags);
 int mbox_sync_has_changed(struct mbox_mailbox *mbox, bool leave_dirty);
+void mbox_sync_set_critical(struct mbox_sync_context *sync_ctx,
+			    const char *fmt, ...) __attr_format__(2, 3);
 
 void mbox_sync_parse_next_mail(struct istream *input,
 			       struct mbox_sync_mail_context *ctx);
@@ -164,7 +167,7 @@
 				 struct mbox_sync_mail *mail,
 				 bool *keywords_changed_r);
 int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
-bool mbox_sync_file_is_ext_modified(struct mbox_sync_context *sync_ctx);
+void mbox_sync_file_update_ext_modified(struct mbox_sync_context *sync_ctx);
 void mbox_sync_file_updated(struct mbox_sync_context *sync_ctx, bool dirty);
 int mbox_move(struct mbox_sync_context *sync_ctx,
 	      uoff_t dest, uoff_t source, uoff_t size);
--- a/src/lib-storage/index/mbox/mbox-sync-rewrite.c	Fri Apr 06 12:30:03 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-rewrite.c	Fri Apr 06 21:13:16 2007 +0300
@@ -44,7 +44,7 @@
         if (ret == (off_t)size)
 		ret = 0;
 	else if (ret >= 0) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"mbox_move(%"PRIuUOFF_T", %"PRIuUOFF_T", %"PRIuUOFF_T
 			") moved only %"PRIuUOFF_T" bytes in mbox file %s",
 			dest, source, size, (uoff_t)ret, sync_ctx->mbox->path);
@@ -415,10 +415,10 @@
 		if (need_space != (uoff_t)-mails[idx].space) {
 			/* this check works only if we're doing the first
 			   write, or if the file size was changed externally */
-			if (mbox_sync_file_is_ext_modified(sync_ctx))
-				return -1;
+			mbox_sync_file_update_ext_modified(sync_ctx);
 
-			i_panic("mbox %s: seq=%u uid=%u uid_broken=%d "
+			mbox_sync_set_critical(sync_ctx,
+				"mbox %s: seq=%u uid=%u uid_broken=%d "
 				"originally needed %"PRIuUOFF_T
 				" bytes, now needs %"PRIuSIZE_T" bytes",
 				sync_ctx->mbox->path, seq, mails[idx].uid,
--- a/src/lib-storage/index/mbox/mbox-sync.c	Fri Apr 06 12:30:03 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Fri Apr 06 21:13:16 2007 +0300
@@ -62,10 +62,27 @@
 "If deleted, important folder data will be lost, and it will be re-created\n" \
 "with the data reset to initial values.\n"
 
+void mbox_sync_set_critical(struct mbox_sync_context *sync_ctx,
+			    const char *fmt, ...)
+{
+	va_list va;
+
+	if (sync_ctx->ext_modified) {
+		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+			"mbox file %s was modified while we were syncing, "
+			"check your locking settings", sync_ctx->mbox->path);
+	}
+
+	va_start(va, fmt);
+	mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+				  "%s", t_strdup_vprintf(fmt, va));
+	va_end(va);
+}
+
 int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
 {
 	if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"Unexpectedly lost From-line at offset %"PRIuUOFF_T
 			" from mbox file %s", from_offset,
 			sync_ctx->mbox->path);
@@ -74,13 +91,15 @@
 	return 0;
 }
 
-bool mbox_sync_file_is_ext_modified(struct mbox_sync_context *sync_ctx)
+void mbox_sync_file_update_ext_modified(struct mbox_sync_context *sync_ctx)
 {
 	struct stat st;
 
+	/* Do this even if ext_modified is already set. Expunging code relies
+	   on last_stat being updated. */
 	if (fstat(sync_ctx->write_fd, &st) < 0) {
 		mbox_set_syscall_error(sync_ctx->mbox, "fstat()");
-		return TRUE;
+		return;
 	}
 
 	if (st.st_size != sync_ctx->last_stat.st_size ||
@@ -91,15 +110,10 @@
 		 supported by the OS */
 	      || st.st_mtim.tv_nsec != sync_ctx->last_stat.st_mtim.tv_nsec
 #endif
-	     ))) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
-			"mbox file %s was modified while we were syncing, "
-			"check your locking settings", sync_ctx->mbox->path);
-		return TRUE;
-	}
+	     )))
+		sync_ctx->ext_modified = TRUE;
 
 	sync_ctx->last_stat = st;
-	return FALSE;
 }
 
 void mbox_sync_file_updated(struct mbox_sync_context *sync_ctx, bool dirty)
@@ -337,7 +351,7 @@
 
 	if (rec == NULL && uid < sync_ctx->idx_next_uid) {
 		/* this UID was already in index and it was expunged */
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"mbox sync: Expunged message reappeared in mailbox %s "
 			"(UID %u < %u, seq=%u, idx_msgs=%u)",
 			sync_ctx->mbox->path, uid, sync_ctx->idx_next_uid,
@@ -345,7 +359,7 @@
 		ret = 0; rec = NULL;
 	} else if (rec != NULL && rec->uid != uid) {
 		/* new UID in the middle of the mailbox - shouldn't happen */
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"mbox sync: UID inserted in the middle of mailbox %s "
 			"(%u > %u, seq=%u, idx_msgs=%u)", sync_ctx->mbox->path,
 			rec->uid, uid, sync_ctx->seq, messages_count);
@@ -633,7 +647,7 @@
 		return -1;
 	}
 	if (ret == 0) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"X-IMAPbase uid-last unexpectedly points outside "
 			"mbox file %s", sync_ctx->mbox->path);
 		return -1;
@@ -648,7 +662,7 @@
 	}
 
 	if (uid_last != sync_ctx->base_uid_last) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"X-IMAPbase uid-last unexpectedly lost in mbox file %s",
 			sync_ctx->mbox->path);
 		return -1;
@@ -888,9 +902,7 @@
 		extra_space = sync_ctx->space_diff;
 	}
 
-	if (mbox_sync_file_is_ext_modified(sync_ctx))
-		return -1;
-
+	mbox_sync_file_update_ext_modified(sync_ctx);
 	if (mbox_sync_rewrite(sync_ctx,
 			      last_seq == sync_ctx->seq ? mail_ctx : NULL,
 			      end_offset, move_diff, extra_space,
@@ -936,8 +948,7 @@
 		if (ret == 0) {
 			if (istream_raw_mbox_seek(mbox->mbox_stream,
 						  old_offset) < 0) {
-				mail_storage_set_critical(
-					&mbox->storage->storage,
+				mbox_sync_set_critical(sync_ctx,
 					"Error seeking back to original "
 					"offset %s in mbox file %s",
 					dec2str(old_offset), mbox->path);
@@ -994,8 +1005,7 @@
 
 		if (istream_raw_mbox_seek(sync_ctx->mbox->mbox_stream,
 					  st->st_size) < 0) {
-			mail_storage_set_critical(
-				&sync_ctx->mbox->storage->storage,
+			mbox_sync_set_critical(sync_ctx,
 				"Error seeking to end of mbox file %s",
 				sync_ctx->mbox->path);
 			return -1;
@@ -1107,8 +1117,7 @@
 			if (sync_ctx->mbox->mbox_sync_dirty)
 				return 0;
 
-			mail_storage_set_critical(
-				&sync_ctx->mbox->storage->storage,
+			mbox_sync_set_critical(sync_ctx,
 				"UIDs broken with partial sync in mbox file %s",
 				sync_ctx->mbox->path);
 
@@ -1225,9 +1234,7 @@
 		} else if (sync_ctx->expunged_space > 0) {
 			if (!expunged) {
 				/* move the body */
-				if (mbox_sync_file_is_ext_modified(sync_ctx))
-					return -1;
-
+				mbox_sync_file_update_ext_modified(sync_ctx);
 				if (mbox_move(sync_ctx,
 					      mail_ctx->body_offset -
 					      sync_ctx->expunged_space,
@@ -1330,7 +1337,7 @@
 	}
 	file_size = st->st_size;
 	if (file_size < sync_ctx->file_input->v_offset) {
-		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
+		mbox_sync_set_critical(sync_ctx,
 			"file size unexpectedly shrinked in mbox file %s "
 			"(%"PRIuUOFF_T" vs %"PRIuUOFF_T")",
 			sync_ctx->mbox->path, file_size,
@@ -1357,9 +1364,6 @@
 
 		i_assert(sync_ctx->space_diff < 0);
 
-		if (mbox_sync_file_is_ext_modified(sync_ctx))
-			return -1;
-
 		if (file_set_size(sync_ctx->write_fd,
 				  file_size + -sync_ctx->space_diff) < 0) {
 			mbox_set_syscall_error(sync_ctx->mbox,
@@ -1388,8 +1392,7 @@
 	if (sync_ctx->expunged_space > 0) {
 		i_assert(sync_ctx->write_fd != -1);
 
-		if (mbox_sync_file_is_ext_modified(sync_ctx))
-			return -1;
+		mbox_sync_file_update_ext_modified(sync_ctx);
 
 		/* copy trailer, then truncate the file */
 		file_size = sync_ctx->last_stat.st_size;
@@ -1540,6 +1543,7 @@
 	sync_ctx->space_diff = 0;
 
 	sync_ctx->dest_first_mail = TRUE;
+	sync_ctx->ext_modified = FALSE;
 }
 
 static int mbox_sync_do(struct mbox_sync_context *sync_ctx,