From: Timo Sirainen Date: Sat, 1 May 2004 16:08:15 +0000 (+0300) Subject: handle losing index file X-Git-Tag: 1.1.alpha1~4164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93b29720c5141f787bd1861796867e4595c9d084;p=thirdparty%2Fdovecot%2Fcore.git handle losing index file --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-lock.c b/src/lib-index/mail-index-lock.c index 15a38f3017..5a1c1bcd23 100644 --- a/src/lib-index/mail-index-lock.c +++ b/src/lib-index/mail-index-lock.c @@ -100,8 +100,15 @@ static int mail_index_has_changed(struct mail_index *index) if (fstat(index->fd, &st1) < 0) return mail_index_set_syscall_error(index, "fstat()"); - if (stat(index->filepath, &st2) < 0) - return mail_index_set_syscall_error(index, "stat()"); + if (stat(index->filepath, &st2) < 0) { + mail_index_set_syscall_error(index, "stat()"); + if (errno != ENOENT) + return -1; + + /* lost it? recreate */ + (void)mail_index_reset(index); + return -1; + } if (st1.st_ino != st2.st_ino || !CMP_DEV_T(st1.st_dev, st2.st_dev)) { diff --git a/src/lib-index/mail-index-private.h b/src/lib-index/mail-index-private.h index b6dbef10ba..fcc9d8a667 100644 --- a/src/lib-index/mail-index-private.h +++ b/src/lib-index/mail-index-private.h @@ -87,7 +87,6 @@ void mail_index_header_init(struct mail_index_header *hdr); int mail_index_write_header(struct mail_index *index, const struct mail_index_header *hdr); -int mail_index_create(struct mail_index *index, struct mail_index_header *hdr); int mail_index_try_open_only(struct mail_index *index); int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r); int mail_index_create_tmp_file(struct mail_index *index, const char **path_r); @@ -129,7 +128,6 @@ int mail_index_sync_get_rec(struct mail_index_view *view, const void *data, size_t *data_offset); void mail_index_set_inconsistent(struct mail_index *index); -int mail_index_mark_corrupted(struct mail_index *index); int mail_index_set_error(struct mail_index *index, const char *fmt, ...) __attr_format__(2, 3); diff --git a/src/lib-index/mail-index-reset.c b/src/lib-index/mail-index-reset.c index c5d0415602..ec608fcd2d 100644 --- a/src/lib-index/mail-index-reset.c +++ b/src/lib-index/mail-index-reset.c @@ -6,28 +6,60 @@ #include "mail-index-private.h" #include "mail-transaction-log.h" -int mail_index_reset(struct mail_index *index) +static int mail_index_mark_corrupted(struct mail_index *index) { struct mail_index_header hdr; - if (mail_index_mark_corrupted(index) < 0) + if (index->readonly) + return 0; + + /* make sure we can write the header */ + if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) { + if (mprotect(index->map->mmap_base, sizeof(hdr), + PROT_READ | PROT_WRITE) < 0) { + mail_index_set_syscall_error(index, "mprotect()"); + return -1; + } + } + + hdr = *index->hdr; + hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED; + if (mail_index_write_header(index, &hdr) < 0) return -1; + if (fsync(index->fd) < 0) + return mail_index_set_syscall_error(index, "fsync()"); + + mail_index_set_inconsistent(index); + return 0; +} + +int mail_index_reset(struct mail_index *index) +{ + struct mail_index_header hdr; + uint32_t file_seq; + uoff_t file_offset; + int log_locked; + mail_index_header_init(&hdr); if (hdr.indexid == index->indexid) hdr.indexid++; - // FIXME: close it? .. - if (mail_index_create(index, &hdr) < 0) + if (mail_index_mark_corrupted(index) < 0) return -1; - /* reopen transaction log - FIXME: doesn't work, we have log views - open.. */ - mail_transaction_log_close(index->log); - index->log = mail_transaction_log_open_or_create(index); - if (index->log == NULL) { - /* FIXME: creates potential crashes.. */ + log_locked = index->log_locked; + if (log_locked) + mail_transaction_log_sync_unlock(index->log); + mail_index_close(index); + + if (mail_index_open(index, MAIL_INDEX_OPEN_FLAG_CREATE) < 0) return -1; + + if (log_locked) { + if (mail_transaction_log_sync_lock(index->log, + &file_seq, &file_offset) < 0) + return -1; } return 0; diff --git a/src/lib-index/mail-index-view.c b/src/lib-index/mail-index-view.c index 979736b1ff..6884855db9 100644 --- a/src/lib-index/mail-index-view.c +++ b/src/lib-index/mail-index-view.c @@ -83,7 +83,7 @@ int mail_index_view_lock_head(struct mail_index_view *view, int update_index) int mail_index_view_lock(struct mail_index_view *view) { - if (view->inconsistent) + if (mail_index_view_is_inconsistent(view)) return -1; if (view->map != view->index->map) { @@ -116,6 +116,8 @@ uint32_t mail_index_view_get_message_count(struct mail_index_view *view) int mail_index_view_is_inconsistent(struct mail_index_view *view) { + if (view->index->indexid != view->indexid) + view->inconsistent = TRUE; return view->inconsistent; } diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index e865a7d04a..672c7f04b8 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -399,7 +399,8 @@ int mail_index_create_tmp_file(struct mail_index *index, const char **path_r) return fd; } -int mail_index_create(struct mail_index *index, struct mail_index_header *hdr) +static int mail_index_create(struct mail_index *index, + struct mail_index_header *hdr) { const char *path; uint32_t seq; @@ -518,8 +519,8 @@ int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r) return ret; } -static int -mail_index_open2(struct mail_index *index, enum mail_index_open_flags flags) +static int mail_index_open_files(struct mail_index *index, + enum mail_index_open_flags flags) { struct mail_index_header hdr; unsigned int lock_id = 0; @@ -573,7 +574,7 @@ int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags) index->filepath = i_strconcat(index->dir, "/", index->prefix, NULL); - ret = mail_index_open2(index, flags); + ret = mail_index_open_files(index, flags); if (ret <= 0) break; @@ -654,35 +655,6 @@ void mail_index_set_inconsistent(struct mail_index *index) index->indexid = 0; } -int mail_index_mark_corrupted(struct mail_index *index) -{ - struct mail_index_header hdr; - - if (index->readonly || index->hdr == NULL || - (index->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) - return 0; - - /* make sure we can write the header */ - if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) { - if (mprotect(index->map->mmap_base, sizeof(hdr), - PROT_READ | PROT_WRITE) < 0) { - mail_index_set_syscall_error(index, "mprotect()"); - return -1; - } - } - - hdr = *index->hdr; - hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED; - if (mail_index_write_header(index, &hdr) < 0) - return -1; - - if (fsync(index->fd) < 0) - return mail_index_set_syscall_error(index, "fsync()"); - - mail_index_set_inconsistent(index); - return 0; -} - int mail_index_set_syscall_error(struct mail_index *index, const char *function) { diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c index 630b8de7cd..b91c1b3dcf 100644 --- a/src/lib-index/mail-transaction-log-view.c +++ b/src/lib-index/mail-transaction-log-view.c @@ -45,6 +45,15 @@ mail_transaction_log_view_open(struct mail_transaction_log *log) void mail_transaction_log_view_close(struct mail_transaction_log_view *view) { + struct mail_transaction_log_view **p; + + for (p = &view->log->views; *p != NULL; p = &(*p)->next) { + if (*p == view) { + *p = view->next; + break; + } + } + mail_transaction_log_view_unset(view); if (view->data_buf != NULL) buffer_free(view->data_buf); @@ -52,6 +61,14 @@ void mail_transaction_log_view_close(struct mail_transaction_log_view *view) i_free(view); } +void mail_transaction_log_views_close(struct mail_transaction_log *log) +{ + struct mail_transaction_log_view *view; + + for (view = log->views; view != NULL; view = view->next) + view->log = NULL; +} + int mail_transaction_log_view_set(struct mail_transaction_log_view *view, uint32_t min_file_seq, uoff_t min_file_offset, @@ -70,6 +87,9 @@ mail_transaction_log_view_set(struct mail_transaction_log_view *view, i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header)); i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header)); + if (view->log == NULL) + return -1; + ret = mail_transaction_log_file_find(view->log, min_file_seq, &file); if (ret <= 0) { if (ret == 0 && diff --git a/src/lib-index/mail-transaction-log.c b/src/lib-index/mail-transaction-log.c index 45d9c4ca61..5f34130fa4 100644 --- a/src/lib-index/mail-transaction-log.c +++ b/src/lib-index/mail-transaction-log.c @@ -127,8 +127,9 @@ mail_transaction_log_open_or_create(struct mail_index *index) void mail_transaction_log_close(struct mail_transaction_log *log) { - i_assert(log->views == NULL); + mail_transaction_log_views_close(log); + log->index->log = NULL; i_free(log); } @@ -683,7 +684,8 @@ int mail_transaction_log_file_map(struct mail_transaction_log_file *file, if (st.st_size == file->hdr.used_size && file->buffer_offset <= start_offset && end_offset == (uoff_t)-1) { /* we've seen the whole file.. do we have all of it mapped? */ - size = buffer_get_used_size(file->buffer); + size = file->buffer == NULL ? 0 : + buffer_get_used_size(file->buffer); if (file->buffer_offset + size == file->hdr.used_size) return 1; } @@ -709,13 +711,13 @@ int mail_transaction_log_file_map(struct mail_transaction_log_file *file, if (start_offset < sizeof(file->hdr)) { mail_transaction_log_file_set_corrupted(file, - "offset (%"PRIuUOFF_T"u) < header size (%"PRIuSIZE_T")", + "offset (%"PRIuUOFF_T") < header size (%"PRIuSIZE_T")", start_offset, sizeof(file->hdr)); return -1; } if (end_offset > file->hdr.used_size) { mail_transaction_log_file_set_corrupted(file, - "offset (%"PRIuUOFF_T"u) > used_size (%u)", + "offset (%"PRIuUOFF_T") > used_size (%u)", end_offset, file->hdr.used_size); return -1; } diff --git a/src/lib-index/mail-transaction-log.h b/src/lib-index/mail-transaction-log.h index d99d3f1a79..d0a9cb295e 100644 --- a/src/lib-index/mail-transaction-log.h +++ b/src/lib-index/mail-transaction-log.h @@ -94,6 +94,8 @@ mail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view, int mail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view); +void mail_transaction_log_views_close(struct mail_transaction_log *log); + /* Write data to transaction log. This is atomic operation. Sequences in updates[] and expunges[] are relative to given view, they're modified to real ones. */