}
static int
-mdbox_storage_rebuild_scan_prepare(struct mdbox_storage_rebuild_context *ctx)
+mdbox_storage_rebuild_scan_prepare(struct mdbox_storage_rebuild_context *ctx,
+ struct mailbox *fsckd_box,
+ enum mdbox_rebuild_reason reason,
+ const char **reason_string_r)
{
const void *data;
size_t data_size;
if (mdbox_map_atomic_lock(ctx->atomic, "mdbox storage rebuild") < 0)
return -1;
+ if ((reason & MDBOX_REBUILD_REASON_FORCED) != 0)
+ *reason_string_r = "Rebuild forced";
+ else if ((reason & MDBOX_REBUILD_REASON_CORRUPTED) != 0)
+ *reason_string_r = "Storage was marked corrupted";
+ else if ((reason & MDBOX_REBUILD_REASON_MAP_FSCKD) != 0)
+ *reason_string_r = "dovecot.index.map was fsck'd";
+ else if ((reason & MDBOX_REBUILD_REASON_MAILBOX_FSCKD) != 0) {
+ *reason_string_r = t_strdup_printf(
+ "Mailbox %s index was fsck'd", fsckd_box->vname);
+ } else {
+ i_unreached();
+ }
+
/* fsck the map just in case its UIDs are broken */
if (mail_index_fsck(ctx->storage->map->index) < 0) {
mail_storage_set_index_error(&ctx->storage->storage.storage,
return 1;
}
-static int mdbox_storage_rebuild_scan(struct mdbox_storage_rebuild_context *ctx)
+static int mdbox_storage_rebuild_scan(struct mdbox_storage_rebuild_context *ctx,
+ const char *reason)
{
- i_warning("mdbox %s: rebuilding indexes", ctx->storage->storage_dir);
+ i_warning("mdbox %s: rebuilding indexes: %s",
+ ctx->storage->storage_dir, reason);
if (mdbox_storage_rebuild_scan_dir(ctx, ctx->storage->storage_dir,
FALSE) < 0)
static int
mdbox_storage_rebuild_in_context(struct mdbox_storage *storage,
- struct mdbox_map_atomic_context *atomic)
+ struct mdbox_map_atomic_context *atomic,
+ struct mailbox *fsckd_box,
+ enum mdbox_rebuild_reason rebuild_reason)
{
struct mdbox_storage_rebuild_context *ctx;
+ const char *reason_string;
int ret;
if (dbox_verify_alt_storage(storage->map->root_list) < 0) {
}
ctx = mdbox_storage_rebuild_init(storage, atomic);
- if ((ret = mdbox_storage_rebuild_scan_prepare(ctx)) > 0) {
+ if ((ret = mdbox_storage_rebuild_scan_prepare(ctx, fsckd_box,
+ rebuild_reason,
+ &reason_string)) > 0) {
struct event_reason *reason = event_reason_begin("mdbox:rebuild");
- ret = mdbox_storage_rebuild_scan(ctx);
+ ret = mdbox_storage_rebuild_scan(ctx, reason_string);
event_reason_end(&reason);
}
mdbox_storage_rebuild_deinit(ctx);
return ret;
}
-int mdbox_storage_rebuild(struct mdbox_storage *storage)
+int mdbox_storage_rebuild(struct mdbox_storage *storage,
+ struct mailbox *fsckd_box,
+ enum mdbox_rebuild_reason reason)
{
struct mdbox_map_atomic_context *atomic;
int ret;
atomic = mdbox_map_atomic_begin(storage->map);
- ret = mdbox_storage_rebuild_in_context(storage, atomic);
+ ret = mdbox_storage_rebuild_in_context(storage, atomic,
+ fsckd_box, reason);
mdbox_map_atomic_set_success(atomic);
mdbox_map_atomic_unset_fscked(atomic);
if (mdbox_map_atomic_finish(&atomic) < 0)
#ifndef MDBOX_STORAGE_REBUILD_H
#define MDBOX_STORAGE_REBUILD_H
-struct mdbox_map_atomic_context;
+enum mdbox_rebuild_reason {
+ /* Storage was marked as corrupted earlier */
+ MDBOX_REBUILD_REASON_CORRUPTED = BIT(0),
+ /* Mailbox index was marked fsck'd */
+ MDBOX_REBUILD_REASON_MAILBOX_FSCKD = BIT(1),
+ /* dovecot.map.index was marked fsck'd */
+ MDBOX_REBUILD_REASON_MAP_FSCKD = BIT(2),
+ /* Forced rebuild (e.g. doveadm force-resync) */
+ MDBOX_REBUILD_REASON_FORCED = BIT(3),
+};
-int mdbox_storage_rebuild(struct mdbox_storage *storage);
+int mdbox_storage_rebuild(struct mdbox_storage *storage,
+ struct mailbox *fsckd_box,
+ enum mdbox_rebuild_reason reason);
#endif
mail_index_get_header(mbox->box.view);
struct mdbox_sync_context *sync_ctx;
struct mdbox_map_atomic_context *atomic;
+ enum mdbox_rebuild_reason rebuild_reason = 0;
bool corrupted, storage_rebuilt = FALSE;
int ret;
- 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(mbox->storage) < 0)
+ if (mbox->storage->corrupted)
+ rebuild_reason |= MDBOX_REBUILD_REASON_CORRUPTED;
+ if ((hdr->flags & MAIL_INDEX_HDR_FLAG_FSCKD) != 0)
+ rebuild_reason |= MDBOX_REBUILD_REASON_MAILBOX_FSCKD;
+ if (mdbox_map_is_fscked(mbox->storage->map))
+ rebuild_reason |= MDBOX_REBUILD_REASON_MAP_FSCKD;
+ if ((flags & MDBOX_SYNC_FLAG_FORCE_REBUILD) != 0)
+ rebuild_reason |= MDBOX_REBUILD_REASON_FORCED;
+ if (rebuild_reason != 0) {
+ if (mdbox_storage_rebuild(mbox->storage, &mbox->box,
+ rebuild_reason) < 0)
return -1;
mailbox_recent_flags_reset(&mbox->box);
storage_rebuilt = TRUE;