From: Timo Sirainen Date: Thu, 21 Oct 2010 15:33:28 +0000 (+0100) Subject: dbox: If alt path is lost, fail with an error rather than rebuilding indexes. X-Git-Tag: 2.0.6~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=763155262f295ab5e6c68244fd047d9b3edb0626;p=thirdparty%2Fdovecot%2Fcore.git dbox: If alt path is lost, fail with an error rather than rebuilding indexes. This could be simply because alt storage is unmounted at the time and rebuilding would just lose messages. If this error happens unintentionally, it's still possible to fix it with "doveadm force-resync". --- diff --git a/src/lib-storage/index/dbox-multi/mdbox-file.c b/src/lib-storage/index/dbox-multi/mdbox-file.c index 745c8672c3..a13b39f53c 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-file.c +++ b/src/lib-storage/index/dbox-multi/mdbox-file.c @@ -183,6 +183,32 @@ mdbox_file_init_new_alt(struct mdbox_storage *storage) return mdbox_file_init_full(storage, 0, TRUE); } +int mdbox_file_open(struct dbox_file *file, bool *deleted_r) +{ + struct mdbox_file *mfile = (struct mdbox_file *)file; + struct stat st; + int ret; + + if ((ret = dbox_file_open(file, deleted_r)) <= 0 || !*deleted_r) + return ret; + + /* file appears to be deleted. check if the alt path root even exists + to avoid reindexing errors if alt path isn't mounted currently */ + if (stat(mfile->storage->alt_storage_dir, &st) == 0) + return 1; + else if (errno == ENOENT) { + mail_storage_set_critical(&file->storage->storage, + "mdbox: User's alt path lost: %s", + mfile->storage->alt_storage_dir); + return -1; + } else { + mail_storage_set_critical(&file->storage->storage, + "stat(%s) failed: %m", mfile->storage->alt_storage_dir); + return -1; + } +} + + int mdbox_file_assign_file_id(struct mdbox_file *file, uint32_t file_id) { const char *old_path; diff --git a/src/lib-storage/index/dbox-multi/mdbox-file.h b/src/lib-storage/index/dbox-multi/mdbox-file.h index 9095cce745..7750de59c3 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-file.h +++ b/src/lib-storage/index/dbox-multi/mdbox-file.h @@ -16,6 +16,8 @@ mdbox_file_init(struct mdbox_storage *storage, uint32_t file_id); struct dbox_file * mdbox_file_init_new_alt(struct mdbox_storage *storage); +int mdbox_file_open(struct dbox_file *file, bool *deleted_r); + /* Assign file ID for a newly created file. */ int mdbox_file_assign_file_id(struct mdbox_file *file, uint32_t file_id); diff --git a/src/lib-storage/index/dbox-multi/mdbox-mail.c b/src/lib-storage/index/dbox-multi/mdbox-mail.c index da776836c6..c67843bf7f 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-mail.c +++ b/src/lib-storage/index/dbox-multi/mdbox-mail.c @@ -129,7 +129,7 @@ int mdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, if (!dbox_file_is_open(mail->open_file)) mail->imail.mail.stats_open_lookup_count++; - if (dbox_file_open(mail->open_file, &deleted) <= 0) + if (mdbox_file_open(mail->open_file, &deleted) <= 0) return -1; if (deleted) { /* either it's expunged now or moved to another file. */ diff --git a/src/lib-storage/index/dbox-multi/mdbox-purge.c b/src/lib-storage/index/dbox-multi/mdbox-purge.c index 33405d3684..8e5442c729 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-purge.c +++ b/src/lib-storage/index/dbox-multi/mdbox-purge.c @@ -658,7 +658,7 @@ int mdbox_purge(struct mail_storage *_storage) while (ret == 0 && seq_range_array_iter_nth(&iter, i++, &file_id)) T_BEGIN { file = mdbox_file_init(storage, file_id); - if (dbox_file_open(file, &deleted) > 0 && !deleted) { + if (mdbox_file_open(file, &deleted) > 0 && !deleted) { if (mdbox_file_purge(ctx, file) < 0) ret = -1; } else { diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c index 68c2efe0e3..e9541a4bd6 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c +++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c @@ -277,7 +277,7 @@ static int rebuild_add_file(struct mdbox_storage_rebuild_context *ctx, seq_range_array_add(&ctx->seen_file_ids, 0, file_id); file = mdbox_file_init(ctx->storage, file_id); - if ((ret = dbox_file_open(file, &deleted)) > 0 && !deleted) + if ((ret = mdbox_file_open(file, &deleted)) > 0 && !deleted) ret = rebuild_file_mails(ctx, file, file_id); if (ret == 0) i_error("mdbox rebuild: Failed to fix file %s/%s", dir, fname); @@ -614,7 +614,7 @@ static int rebuild_restore_msg(struct mdbox_storage_rebuild_context *ctx, /* first see if message contains the mailbox it was originally saved to */ file = mdbox_file_init(ctx->storage, msg->file_id); - ret = dbox_file_open(file, &deleted); + ret = mdbox_file_open(file, &deleted); if (ret > 0 && !deleted) ret = dbox_file_seek(file, msg->offset); if (ret > 0 && !deleted && dbox_file_metadata_read(file) > 0) { diff --git a/src/lib-storage/index/dbox-single/sdbox-file.c b/src/lib-storage/index/dbox-single/sdbox-file.c index be15a67ce0..6df975d7a6 100644 --- a/src/lib-storage/index/dbox-single/sdbox-file.c +++ b/src/lib-storage/index/dbox-single/sdbox-file.c @@ -73,6 +73,33 @@ void sdbox_file_free(struct dbox_file *file) dbox_file_free(file); } +int sdbox_file_open(struct dbox_file *file, bool *deleted_r) +{ + struct sdbox_file *sfile = (struct sdbox_file *)file; + struct stat st; + const char *alt_root; + int ret; + + if ((ret = dbox_file_open(file, deleted_r)) <= 0 || !*deleted_r) + return ret; + + /* file appears to be deleted. check if the alt path root even exists + to avoid reindexing errors if alt path isn't mounted currently */ + alt_root = mailbox_list_get_path(sfile->mbox->box.list, NULL, + MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX); + if (stat(alt_root, &st) == 0) + return 1; + else if (errno == ENOENT) { + mail_storage_set_critical(&file->storage->storage, + "sdbox: User's alt path lost: %s", alt_root); + return -1; + } else { + mail_storage_set_critical(&file->storage->storage, + "stat(%s) failed: %m", alt_root); + return -1; + } +} + int sdbox_file_get_attachments(struct dbox_file *file, const char **extrefs_r) { const char *line; @@ -82,7 +109,7 @@ int sdbox_file_get_attachments(struct dbox_file *file, const char **extrefs_r) *extrefs_r = NULL; /* read the metadata */ - ret = dbox_file_open(file, &deleted); + ret = sdbox_file_open(file, &deleted); if (ret > 0) { if (deleted) return 0; @@ -365,7 +392,7 @@ int sdbox_file_move(struct dbox_file *file, bool alt_path) /* file was successfully moved - reopen it */ dbox_file_close(file); - if (dbox_file_open(file, &deleted) <= 0) { + if (sdbox_file_open(file, &deleted) <= 0) { mail_storage_set_critical(storage, "dbox_file_move(%s): reopening file failed", dest_path); return -1; diff --git a/src/lib-storage/index/dbox-single/sdbox-file.h b/src/lib-storage/index/dbox-single/sdbox-file.h index 30eb4f4878..4a707cf9ba 100644 --- a/src/lib-storage/index/dbox-single/sdbox-file.h +++ b/src/lib-storage/index/dbox-single/sdbox-file.h @@ -19,6 +19,8 @@ struct dbox_file *sdbox_file_init(struct sdbox_mailbox *mbox, uint32_t uid); struct dbox_file *sdbox_file_create(struct sdbox_mailbox *mbox); void sdbox_file_free(struct dbox_file *file); +int sdbox_file_open(struct dbox_file *file, bool *deleted_r); + /* Get file's extrefs metadata. */ int sdbox_file_get_attachments(struct dbox_file *file, const char **extrefs_r); /* Returns attachment path for this file, given the source path. The result is diff --git a/src/lib-storage/index/dbox-single/sdbox-mail.c b/src/lib-storage/index/dbox-single/sdbox-mail.c index 0b573d910d..1c34d6a4e3 100644 --- a/src/lib-storage/index/dbox-single/sdbox-mail.c +++ b/src/lib-storage/index/dbox-single/sdbox-mail.c @@ -43,7 +43,7 @@ static bool sdbox_mail_file_set(struct dbox_mail *mail) mail->open_file->refcount++; /* it doesn't have input stream yet */ - ret = dbox_file_open(mail->open_file, &deleted); + ret = sdbox_file_open(mail->open_file, &deleted); i_assert(ret > 0); return TRUE; } @@ -63,7 +63,7 @@ int sdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, if (!sdbox_mail_file_set(mail)) { if (!dbox_file_is_open(mail->open_file)) mail->imail.mail.stats_open_lookup_count++; - if (dbox_file_open(mail->open_file, &deleted) <= 0) + if (sdbox_file_open(mail->open_file, &deleted) <= 0) return -1; if (deleted) { sdbox_mail_set_expunged(mail); diff --git a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c index b2f2e86f13..eb7bbcbcd6 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c @@ -32,7 +32,7 @@ static int sdbox_sync_add_file_index(struct dbox_sync_rebuild_context *ctx, bool deleted; int ret; - if ((ret = dbox_file_open(file, &deleted)) > 0) { + if ((ret = sdbox_file_open(file, &deleted)) > 0) { if (deleted) return 0; ret = dbox_file_seek(file, 0); diff --git a/src/lib-storage/index/dbox-single/sdbox-sync.c b/src/lib-storage/index/dbox-single/sdbox-sync.c index c3beab76c2..b31518a89c 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync.c @@ -18,7 +18,7 @@ dbox_sync_file_move_if_needed(struct dbox_file *file, if (move_to_alt != dbox_file_is_in_alt(file)) { /* move the file. if it fails, nothing broke so don't worry about it. */ - if (dbox_file_open(file, &deleted) > 0 && !deleted) + if (sdbox_file_open(file, &deleted) > 0 && !deleted) (void)sdbox_file_move(file, move_to_alt); } }