From: Timo Sirainen Date: Mon, 3 Jul 2023 09:06:07 +0000 (+0300) Subject: mdbox: Move storage rebuild handling to mdbox_sync() X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6a32cd04084fa8fdf4f09f068e9d16426dedee46;p=thirdparty%2Fdovecot%2Fcore.git mdbox: Move storage rebuild handling to mdbox_sync() This simplifies the code, since it's the only place that can actually rebuild the storage. Also will be needed for following commit. --- diff --git a/src/lib-storage/index/dbox-multi/mdbox-save.c b/src/lib-storage/index/dbox-multi/mdbox-save.c index 268f77c721..6f1853915c 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-save.c +++ b/src/lib-storage/index/dbox-multi/mdbox-save.c @@ -286,6 +286,7 @@ int mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx) struct mailbox_transaction_context *_t = _ctx->transaction; const struct mail_index_header *hdr; uint32_t first_map_uid, last_map_uid; + bool corrupted; i_assert(ctx->ctx.finished); @@ -305,9 +306,12 @@ int mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx) up-to-date atomic->sync_view */ if (mdbox_sync_begin(ctx->mbox, MDBOX_SYNC_FLAG_NO_PURGE | MDBOX_SYNC_FLAG_FORCE | - MDBOX_SYNC_FLAG_FSYNC | - MDBOX_SYNC_FLAG_NO_REBUILD, ctx->atomic, - &ctx->sync_ctx) < 0) { + MDBOX_SYNC_FLAG_FSYNC, ctx->atomic, + &ctx->sync_ctx, &corrupted) < 0) { + if (corrupted) { + mailbox_set_critical(_t->box, + "mdbox: Can't rebuild corrupted storage while saving a mail"); + } mdbox_transaction_save_rollback(_ctx); return -1; } diff --git a/src/lib-storage/index/dbox-multi/mdbox-sync.c b/src/lib-storage/index/dbox-multi/mdbox-sync.c index 0c2d2d4ce5..8b2c55f522 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-sync.c +++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c @@ -226,30 +226,18 @@ static int mdbox_sync_try_begin(struct mdbox_sync_context *ctx, int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags, struct mdbox_map_atomic_context *atomic, - struct mdbox_sync_context **ctx_r) + struct mdbox_sync_context **ctx_r, bool *corrupted_r) { - const struct mail_index_header *hdr = - mail_index_get_header(mbox->box.view); struct mdbox_sync_context *ctx; const char *reason; enum mail_index_sync_flags sync_flags; int ret; - bool rebuild, storage_rebuilt = FALSE; *ctx_r = NULL; + *corrupted_r = FALSE; /* avoid race conditions with mailbox creation, don't check for dbox headers until syncing has locked the mailbox */ - rebuild = mbox->storage->corrupted || - (hdr->flags & MAIL_INDEX_HDR_FLAG_FSCKD) != 0 || - mdbox_map_is_fscked(mbox->storage->map) || - (flags & MDBOX_SYNC_FLAG_FORCE_REBUILD) != 0; - if (rebuild && (flags & MDBOX_SYNC_FLAG_NO_REBUILD) == 0) { - if (mdbox_storage_rebuild_in_context(mbox->storage, atomic) < 0) - return -1; - mailbox_recent_flags_reset(&mbox->box); - storage_rebuilt = TRUE; - } ctx = i_new(struct mdbox_sync_context, 1); ctx->mbox = mbox; @@ -257,7 +245,7 @@ int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags, ctx->atomic = atomic; sync_flags = index_storage_get_sync_flags(&mbox->box); - if (!rebuild && (flags & MDBOX_SYNC_FLAG_FORCE) == 0) + if ((flags & MDBOX_SYNC_FLAG_FORCE) == 0) sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES; if ((flags & MDBOX_SYNC_FLAG_FSYNC) != 0) sync_flags |= MAIL_INDEX_SYNC_FLAG_FSYNC; @@ -280,25 +268,9 @@ int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags, index_storage_expunging_deinit(&mbox->box); i_free_and_null(ctx); - if (ret < 0) - return -1; - - /* corrupted */ - if (storage_rebuilt) { - mailbox_set_critical(&mbox->box, - "mdbox: Storage keeps breaking"); - return -1; - } - - /* we'll need to rebuild storage. - try again from the beginning. */ - mdbox_storage_set_corrupted(mbox->storage); - if ((flags & MDBOX_SYNC_FLAG_NO_REBUILD) != 0) { - mailbox_set_critical(&mbox->box, - "mdbox: Can't rebuild storage"); - return -1; - } - return mdbox_sync_begin(mbox, flags, atomic, ctx_r); + if (ret == 0) + *corrupted_r = TRUE; + return -1; } index_storage_expunging_deinit(&mbox->box); @@ -342,12 +314,43 @@ int mdbox_sync_finish(struct mdbox_sync_context **_ctx, bool success) int mdbox_sync(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags) { + const struct mail_index_header *hdr = + mail_index_get_header(mbox->box.view); struct mdbox_sync_context *sync_ctx; struct mdbox_map_atomic_context *atomic; + bool corrupted, storage_rebuilt = FALSE; int ret; atomic = mdbox_map_atomic_begin(mbox->storage->map); - ret = mdbox_sync_begin(mbox, flags, atomic, &sync_ctx); + + if (mbox->storage->corrupted || + (hdr->flags & MAIL_INDEX_HDR_FLAG_FSCKD) != 0 || + mdbox_map_is_fscked(mbox->storage->map) || + (flags & MDBOX_SYNC_FLAG_FORCE_REBUILD) != 0) { + if (mdbox_storage_rebuild_in_context(mbox->storage, atomic) < 0) { + (void)mdbox_map_atomic_finish(&atomic); + return -1; + } + mailbox_recent_flags_reset(&mbox->box); + storage_rebuilt = TRUE; + flags |= MDBOX_SYNC_FLAG_FORCE; + } + + + ret = mdbox_sync_begin(mbox, flags, atomic, &sync_ctx, &corrupted); + if (corrupted) { + if (storage_rebuilt) { + mailbox_set_critical(&mbox->box, + "mdbox: Storage keeps breaking"); + return -1; + } + + /* we'll need to rebuild storage. + try again from the beginning. */ + mdbox_storage_set_corrupted(mbox->storage); + return mdbox_sync(mbox, flags); + } + if (ret == 0 && sync_ctx != NULL) ret = mdbox_sync_finish(&sync_ctx, TRUE); if (ret == 0) diff --git a/src/lib-storage/index/dbox-multi/mdbox-sync.h b/src/lib-storage/index/dbox-multi/mdbox-sync.h index a9bc5651f2..8f58bd01e0 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-sync.h +++ b/src/lib-storage/index/dbox-multi/mdbox-sync.h @@ -9,7 +9,6 @@ enum mdbox_sync_flags { MDBOX_SYNC_FLAG_FSYNC = 0x02, MDBOX_SYNC_FLAG_FORCE_REBUILD = 0x04, MDBOX_SYNC_FLAG_NO_PURGE = 0x08, - MDBOX_SYNC_FLAG_NO_REBUILD = 0x10 }; struct mdbox_sync_context { @@ -27,7 +26,7 @@ struct mdbox_sync_context { int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags, struct mdbox_map_atomic_context *atomic, - struct mdbox_sync_context **ctx_r); + struct mdbox_sync_context **ctx_r, bool *corrupted_r); int mdbox_sync_finish(struct mdbox_sync_context **ctx, bool success); int mdbox_sync(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags);