This fixes a bug caused by
883a3022992d0f832f0aff21572caeb7c63b7668 where
dovecot.index.log file wasn't rotated as often as it was supposed to be. It
also could have caused dovecot.index to be rewritten much more often than
it was supposed to be.
The buggy commit was correct that the tail_offset wasn't updated previously
to the dovecot.index.log file after changes. However, I didn't realize that
the tail_offset was internally still updated and required by this rotation
check to work correctly.
The fix works by relaxing the tail_offset==head_offset requirement for
rotation. It's enough that all the changes are synced, which can be checked
from mail_index_sync_ctx.fully_synced. Any changes after tail_offset are
then supposed to be external transactions, which aren't synced anyway, so
rotation is allowed.
}
}
- want_rotate = mail_transaction_log_want_rotate(index->log);
+ /* Log rotation is allowed only if everything was synced. Note that
+ tail_offset might not equal head_offset here, because
+ mail_index_sync_update_mailbox_offset() doesn't always update
+ tail_offset to skip over other committed external transactions.
+ However, it's still safe to do the rotation because external
+ transactions don't require syncing. */
+ want_rotate = ctx->fully_synced &&
+ mail_transaction_log_want_rotate(index->log);
if (ret == 0 &&
(want_rotate || mail_index_sync_want_index_write(index))) {
index->need_recreate = FALSE;
return;
/* rotate the .log before writing index, so the index will point to
- the latest log. */
- if (want_rotate &&
- hdr->log_file_seq == index->log->head->hdr.file_seq &&
- hdr->log_file_tail_offset == hdr->log_file_head_offset) {
+ the latest log. Note that it's the caller's responsibility to make
+ sure that the .log can be safely rotated (i.e. everything has been
+ synced). */
+ if (want_rotate) {
if (mail_transaction_log_rotate(index->log, FALSE) == 0) {
struct mail_transaction_log_file *file =
index->log->head;