Mercurial > dovecot > original-hg > dovecot-1.2
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,