dovecot-2.2: lib-index: If header is corrupted after syncing, lo...
dovecot at dovecot.org
dovecot at dovecot.org
Sun May 10 09:31:47 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/69630e6048fd
changeset: 18627:69630e6048fd
user: Timo Sirainen <tss at iki.fi>
date: Sun May 10 12:28:09 2015 +0300
description:
lib-index: If header is corrupted after syncing, log the reason why.
diffstat:
src/lib-index/mail-index-map-hdr.c | 102 ++++++++++++++++++++++----------
src/lib-index/mail-index-map-read.c | 22 +++++-
src/lib-index/mail-index-private.h | 10 ++-
src/lib-index/mail-index-sync-update.c | 8 +-
4 files changed, 100 insertions(+), 42 deletions(-)
diffs (299 lines):
diff -r fddd3dbdf987 -r 69630e6048fd src/lib-index/mail-index-map-hdr.c
--- a/src/lib-index/mail-index-map-hdr.c Sun May 10 12:05:06 2015 +0300
+++ b/src/lib-index/mail-index-map-hdr.c Sun May 10 12:28:09 2015 +0300
@@ -167,7 +167,7 @@
bool mail_index_check_header_compat(struct mail_index *index,
const struct mail_index_header *hdr,
- uoff_t file_size)
+ uoff_t file_size, const char **error_r)
{
enum mail_index_header_compat_flags compat_flags = 0;
@@ -176,35 +176,34 @@
#endif
if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
- /* major version change - handle silently(?) */
+ /* major version change */
+ *error_r = t_strdup_printf("Major version changed (%u != %u)",
+ hdr->major_version, MAIL_INDEX_MAJOR_VERSION);
return FALSE;
}
if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
/* we've already complained about it */
+ *error_r = "Header's corrupted flag is set";
return FALSE;
}
if (hdr->compat_flags != compat_flags) {
/* architecture change */
- mail_index_set_error(index, "Rebuilding index file %s: "
- "CPU architecture changed",
- index->filepath);
+ *error_r = "CPU architecture changed";
return FALSE;
}
if (hdr->base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
hdr->header_size < hdr->base_header_size) {
- mail_index_set_error(index, "Corrupted index file %s: "
- "Corrupted header sizes (base %u, full %u)",
- index->filepath, hdr->base_header_size,
- hdr->header_size);
+ *error_r = t_strdup_printf(
+ "Corrupted header sizes (base %u, full %u)",
+ hdr->base_header_size, hdr->header_size);
return FALSE;
}
if (hdr->header_size > file_size) {
- mail_index_set_error(index, "Corrupted index file %s: "
- "Corrupted header size (%u > %"PRIuUOFF_T")",
- index->filepath, hdr->header_size,
- file_size);
+ *error_r = t_strdup_printf(
+ "Header size is larger than file (%u > %"PRIuUOFF_T")",
+ hdr->header_size, file_size);
return FALSE;
}
@@ -218,7 +217,6 @@
index->indexid = hdr->indexid;
mail_transaction_log_indexid_changed(index->log);
}
-
return TRUE;
}
@@ -233,33 +231,51 @@
}
}
-int mail_index_map_check_header(struct mail_index_map *map)
+int mail_index_map_check_header(struct mail_index_map *map,
+ const char **error_r)
{
struct mail_index *index = map->index;
const struct mail_index_header *hdr = &map->hdr;
- if (!mail_index_check_header_compat(index, hdr, (uoff_t)-1))
+ if (!mail_index_check_header_compat(index, hdr, (uoff_t)-1, error_r))
return -1;
/* following some extra checks that only take a bit of CPU */
if (hdr->record_size < sizeof(struct mail_index_record)) {
- mail_index_set_error(index, "Corrupted index file %s: "
- "record_size too small: %u < %"PRIuSIZE_T,
- index->filepath, hdr->record_size,
- sizeof(struct mail_index_record));
+ *error_r = t_strdup_printf(
+ "record_size too small (%u < %"PRIuSIZE_T")",
+ hdr->record_size, sizeof(struct mail_index_record));
return -1;
}
- if (hdr->uid_validity == 0 && hdr->next_uid != 1)
+ if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
+ *error_r = t_strdup_printf(
+ "uidvalidity=0, but next_uid=%u", hdr->next_uid);
return 0;
- if (hdr->next_uid == 0)
+ }
+ if (hdr->next_uid == 0) {
+ *error_r = "next_uid=0";
return 0;
- if (hdr->messages_count > map->rec_map->records_count)
+ }
+ if (hdr->messages_count > map->rec_map->records_count) {
+ *error_r = t_strdup_printf(
+ "messages_count is higher in header than record map (%u > %u)",
+ hdr->messages_count, map->rec_map->records_count);
return 0;
+ }
- if (hdr->seen_messages_count > hdr->messages_count ||
- hdr->deleted_messages_count > hdr->messages_count)
+ if (hdr->seen_messages_count > hdr->messages_count) {
+ *error_r = t_strdup_printf(
+ "seen_messages_count %u > messages_count %u",
+ hdr->seen_messages_count, hdr->messages_count);
return 0;
+ }
+ if (hdr->deleted_messages_count > hdr->messages_count) {
+ *error_r = t_strdup_printf(
+ "deleted_messages_count %u > messages_count %u",
+ hdr->deleted_messages_count, hdr->messages_count);
+ return 0;
+ }
switch (hdr->minor_version) {
case 0:
/* upgrade silently from v1.0 */
@@ -279,11 +295,28 @@
map->hdr.unused_old_sync_size = 0;
map->hdr.unused_old_sync_stamp = 0;
}
- if (hdr->first_recent_uid == 0 ||
- hdr->first_recent_uid > hdr->next_uid ||
- hdr->first_unseen_uid_lowwater > hdr->next_uid ||
- hdr->first_deleted_uid_lowwater > hdr->next_uid)
+ if (hdr->first_recent_uid == 0) {
+ *error_r = "first_recent_uid=0";
return 0;
+ }
+ if (hdr->first_recent_uid > hdr->next_uid) {
+ *error_r = t_strdup_printf(
+ "first_recent_uid %u > next_uid %u",
+ hdr->first_recent_uid, hdr->next_uid);
+ return 0;
+ }
+ if (hdr->first_unseen_uid_lowwater > hdr->next_uid) {
+ *error_r = t_strdup_printf(
+ "first_unseen_uid_lowwater %u > next_uid %u",
+ hdr->first_unseen_uid_lowwater, hdr->next_uid);
+ return 0;
+ }
+ if (hdr->first_deleted_uid_lowwater > hdr->next_uid) {
+ *error_r = t_strdup_printf(
+ "first_deleted_uid_lowwater %u > next_uid %u",
+ hdr->first_deleted_uid_lowwater, hdr->next_uid);
+ return 0;
+ }
if (hdr->messages_count > 0) {
/* last message's UID must be smaller than next_uid.
@@ -291,9 +324,16 @@
const struct mail_index_record *rec;
rec = MAIL_INDEX_REC_AT_SEQ(map, hdr->messages_count);
- if (rec->uid == 0 || rec->uid >= hdr->next_uid)
+ if (rec->uid == 0) {
+ *error_r = "last message has uid=0";
+ return -1;
+ }
+ if (rec->uid >= hdr->next_uid) {
+ *error_r = t_strdup_printf(
+ "last message uid %u >= next_uid %u",
+ rec->uid, hdr->next_uid);
return 0;
+ }
}
-
return 1;
}
diff -r fddd3dbdf987 -r 69630e6048fd src/lib-index/mail-index-map-read.c
--- a/src/lib-index/mail-index-map-read.c Sun May 10 12:05:06 2015 +0300
+++ b/src/lib-index/mail-index-map-read.c Sun May 10 12:28:09 2015 +0300
@@ -31,6 +31,7 @@
struct mail_index *index = map->index;
struct mail_index_record_map *rec_map = map->rec_map;
const struct mail_index_header *hdr;
+ const char *error;
i_assert(rec_map->mmap_base == NULL);
@@ -66,9 +67,11 @@
return 0;
}
- if (!mail_index_check_header_compat(index, hdr, rec_map->mmap_size)) {
+ if (!mail_index_check_header_compat(index, hdr, rec_map->mmap_size, &error)) {
/* Can't use this file */
- return 0;
+ mail_index_set_error(index, "Corrupted index file %s: %s",
+ index->filepath, error);
+ return -1;
}
rec_map->mmap_used_size = hdr->header_size +
@@ -126,6 +129,7 @@
struct mail_index *index = map->index;
const struct mail_index_header *hdr;
unsigned char read_buf[IO_BLOCK_SIZE];
+ const char *error;
const void *buf;
void *data = NULL;
ssize_t ret;
@@ -146,9 +150,11 @@
if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
(ret > 0 || pos >= hdr->base_header_size)) {
- if (!mail_index_check_header_compat(index, hdr, file_size)) {
+ if (!mail_index_check_header_compat(index, hdr, file_size, &error)) {
/* Can't use this file */
- return 0;
+ mail_index_set_error(index, "Corrupted index file %s: %s",
+ index->filepath, error);
+ return -1;
}
initial_buf_pos = pos;
@@ -295,6 +301,7 @@
struct stat st;
uoff_t file_size;
bool use_mmap, unusable = FALSE;
+ const char *error;
int ret, try;
ret = mail_index_reopen_if_changed(index);
@@ -339,7 +346,12 @@
for (try = 0; ret > 0; try++) {
/* make sure the header is ok before using this mapping */
- ret = mail_index_map_check_header(new_map);
+ ret = mail_index_map_check_header(new_map, &error);
+ if (ret < 0) {
+ mail_index_set_error(index,
+ "Corrupted index file %s: %s",
+ index->filepath, error);
+ }
if (ret > 0) T_BEGIN {
if (mail_index_map_parse_extensions(new_map) < 0)
ret = 0;
diff -r fddd3dbdf987 -r 69630e6048fd src/lib-index/mail-index-private.h
--- a/src/lib-index/mail-index-private.h Sun May 10 12:05:06 2015 +0300
+++ b/src/lib-index/mail-index-private.h Sun May 10 12:28:09 2015 +0300
@@ -307,10 +307,16 @@
uint32_t *first_seq_r,
uint32_t *last_seq_r);
-int mail_index_map_check_header(struct mail_index_map *map);
+/* Returns 1 on success, 0 on non-critical errors we want to silently fix,
+ -1 if map isn't usable. The caller is responsible for logging the errors
+ if -1 is returned. */
+int mail_index_map_check_header(struct mail_index_map *map,
+ const char **error_r);
+/* Returns 1 if header is usable, 0 or -1 if not. The caller should log an
+ error if -1 is returned, but not if 0 is returned. */
bool mail_index_check_header_compat(struct mail_index *index,
const struct mail_index_header *hdr,
- uoff_t file_size);
+ uoff_t file_size, const char **error_r);
int mail_index_map_parse_extensions(struct mail_index_map *map);
int mail_index_map_parse_keywords(struct mail_index_map *map);
diff -r fddd3dbdf987 -r 69630e6048fd src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c Sun May 10 12:05:06 2015 +0300
+++ b/src/lib-index/mail-index-sync-update.c Sun May 10 12:28:09 2015 +0300
@@ -911,7 +911,7 @@
const void *tdata;
uint32_t prev_seq;
uoff_t start_offset, prev_offset;
- const char *reason;
+ const char *reason, *error;
int ret;
bool had_dirty, reset;
@@ -1075,10 +1075,10 @@
i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
- if (mail_index_map_check_header(map) <= 0) {
+ if (mail_index_map_check_header(map, &error) <= 0) {
mail_index_set_error(index,
- "Synchronization corrupted index header: %s",
- index->filepath);
+ "Synchronization corrupted index header %s: %s",
+ index->filepath, error);
(void)mail_index_fsck(index);
map = index->map;
} else if (sync_map_ctx.errors) {
More information about the dovecot-cvs
mailing list