From: Timo Sirainen Date: Sat, 5 Oct 2019 12:46:47 +0000 (+0300) Subject: lib-index: Fix checking if log file can be rotated X-Git-Tag: 2.3.8~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4b7da11ff7d8c7ff7f95c6032ddd064373faf5e7;p=thirdparty%2Fdovecot%2Fcore.git lib-index: Fix checking if log file can be rotated 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. --- diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c index 641ab7be6f..55d56ca355 100644 --- a/src/lib-index/mail-index-sync.c +++ b/src/lib-index/mail-index-sync.c @@ -949,7 +949,14 @@ int mail_index_sync_commit(struct mail_index_sync_ctx **_ctx) } } - 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; diff --git a/src/lib-index/mail-index-write.c b/src/lib-index/mail-index-write.c index 0c3bfcdd54..473c4e1805 100644 --- a/src/lib-index/mail-index-write.c +++ b/src/lib-index/mail-index-write.c @@ -126,10 +126,10 @@ void mail_index_write(struct mail_index *index, bool want_rotate) 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;