Mercurial > dovecot > core-2.2
changeset 3173:d137899ea853 HEAD
We could have gone past the transaction log view's boundaries if log was
just rotated. Plus other transaction log cleanups, fixes and new asserts.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 05 Mar 2005 14:41:22 +0200 |
parents | b951764080cc |
children | 091821cac480 |
files | src/lib-index/mail-index.c src/lib-index/mail-transaction-log-append.c src/lib-index/mail-transaction-log-view.c src/lib-index/mail-transaction-log.c src/lib-index/mail-transaction-log.h |
diffstat | 5 files changed, 68 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-index.c Sat Mar 05 13:57:29 2005 +0200 +++ b/src/lib-index/mail-index.c Sat Mar 05 14:41:22 2005 +0200 @@ -732,7 +732,10 @@ mail_transaction_log_view_get_prev_pos(log_view, &prev_seq, &prev_offset); - index->map->hdr.log_file_seq = prev_seq; + i_assert(prev_seq <= max_seq && + (prev_seq != max_seq || prev_offset <= max_offset)); + + index->map->hdr.log_file_seq = prev_seq; index->map->hdr.log_file_int_offset = index->map->hdr.log_file_ext_offset = prev_offset;
--- a/src/lib-index/mail-transaction-log-append.c Sat Mar 05 13:57:29 2005 +0200 +++ b/src/lib-index/mail-transaction-log-append.c Sat Mar 05 14:41:22 2005 +0200 @@ -345,7 +345,7 @@ if (log->head->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_SIZE && (time_t)log->head->hdr.create_stamp < - ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_MIN_TIME) { + ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_TIME) { /* we might want to rotate, but check first that everything is synced in index. */ if (mail_index_lock_shared(log->index, TRUE, &lock_id) < 0) {
--- a/src/lib-index/mail-transaction-log-view.c Sat Mar 05 13:57:29 2005 +0200 +++ b/src/lib-index/mail-transaction-log-view.c Sat Mar 05 14:41:22 2005 +0200 @@ -91,24 +91,19 @@ if (min_file_seq == 0) { /* new index, transaction file not synced yet */ min_file_seq = 1; - min_file_offset = sizeof(struct mail_transaction_log_header); + min_file_offset = 0; if (max_file_seq == 0) { max_file_seq = min_file_seq; max_file_offset = min_file_offset; } - } else if (min_file_offset == 0) { - /* this could happen if internal transactions haven't yet been - committed but external are. just assume we're at the - beginning. */ - min_file_offset = sizeof(struct mail_transaction_log_header); - } + } if (min_file_seq == view->log->tail->hdr.prev_file_seq && min_file_offset == view->log->tail->hdr.prev_file_offset) { /* we can skip this */ min_file_seq = view->log->tail->hdr.file_seq; - min_file_offset = sizeof(struct mail_transaction_log_header); + min_file_offset = 0; if (min_file_seq > max_file_seq) { /* empty view */ @@ -127,13 +122,20 @@ return -1; } + if (min_file_offset == 0) { + /* this could happen if internal transactions haven't yet been + committed but external are. just assume we're at the + beginning. */ + min_file_offset = file->hdr.hdr_size; + if (max_file_offset == 0 && min_file_seq == max_file_seq) + max_file_offset = min_file_offset; + } + /* check these later than others as index file may have corrupted log_file_offset. we should have recreated the log file and skipped min_file_seq file above.. max_file_offset can be broken only if min_file_seq = max_file_seq. */ - i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header)); - i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header)); - + i_assert(min_file_offset >= file->hdr.hdr_size); i_assert(min_file_seq != max_file_seq || min_file_offset <= max_file_offset); @@ -167,9 +169,8 @@ end_offset = file->hdr.file_seq == max_file_seq ? max_file_offset : (uoff_t)-1; - ret = mail_transaction_log_file_map(file, - sizeof(struct mail_transaction_log_header), - end_offset); + ret = mail_transaction_log_file_map(file, file->hdr.hdr_size, + end_offset); if (ret == 0) { mail_index_set_error(view->log->index, "Lost transaction log file %s seq %u", @@ -211,6 +212,8 @@ view->max_file_offset = max_file_offset; view->type_mask = type_mask; view->broken = FALSE; + + i_assert(view->cur->hdr.file_seq == min_file_seq); return 0; } @@ -258,23 +261,27 @@ uint32_t hdr_size; size_t file_size; + if (view->cur == NULL) + return 0; + + view->prev_file_seq = view->cur->hdr.file_seq; + view->prev_file_offset = view->cur_offset; + for (;;) { file = view->cur; if (file == NULL) return 0; - view->prev_file_seq = file->hdr.file_seq; - view->prev_file_offset = view->cur_offset; - if (view->cur_offset != file->sync_offset) break; view->cur = file->next; - view->cur_offset = sizeof(struct mail_transaction_log_header); + view->cur_offset = file->hdr.hdr_size; } - if (view->cur_offset >= view->max_file_offset && - file->hdr.file_seq == view->max_file_seq) + if (file->hdr.file_seq > view->max_file_seq || + (view->cur_offset >= view->max_file_offset && + file->hdr.file_seq == view->max_file_seq)) return 0; data = buffer_get_data(file->buffer, &file_size);
--- a/src/lib-index/mail-transaction-log.c Sat Mar 05 13:57:29 2005 +0200 +++ b/src/lib-index/mail-transaction-log.c Sat Mar 05 14:41:22 2005 +0200 @@ -233,9 +233,12 @@ if (index->fd != -1 && INDEX_HAS_MISSING_LOGS(index, log->head)) { /* head log file isn't same as head index file - - shouldn't happen except in race conditions. lock them and - check again - FIXME: missing error handling. */ - (void)mail_transaction_log_check_file_seq(log); + shouldn't happen except in race conditions. + lock them and check again */ + if (mail_transaction_log_check_file_seq(log) < 0) { + mail_transaction_log_close(log); + return NULL; + } } return log; } @@ -256,6 +259,11 @@ static void mail_transaction_log_file_close(struct mail_transaction_log_file *file) { + if (file == file->log->head) + file->log->head = NULL; + if (file == file->log->tail) + file->log->tail = file->next; + mail_transaction_log_file_unlock(file); if (file->buffer != NULL) @@ -340,7 +348,8 @@ static int mail_transaction_log_file_create2(struct mail_transaction_log *log, const char *path, int fd, - dev_t dev, ino_t ino) + struct dotlock **dotlock, + dev_t dev, ino_t ino, uoff_t file_size) { struct mail_index *index = log->index; struct mail_transaction_log_header hdr; @@ -354,10 +363,11 @@ if ((ret = fstat(fd2, &st)) < 0) { mail_index_file_set_syscall_error(index, path, "fstat()"); - } else if (st.st_ino == ino && CMP_DEV_T(st.st_dev, dev)) { + } else if (st.st_ino == ino && CMP_DEV_T(st.st_dev, dev) && + (uoff_t)st.st_size == file_size) { /* same file, still broken */ } else { - (void)file_dotlock_delete(&log->dotlock); + (void)file_dotlock_delete(dotlock); return fd2; } @@ -400,31 +410,27 @@ return -1; } - fd2 = dup(fd); - if (fd2 < 0) { - mail_index_file_set_syscall_error(index, path, "dup()"); - return -1; - } - - if (file_dotlock_replace(&log->dotlock, 0) <= 0) + if (file_dotlock_replace(dotlock, + DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) <= 0) return -1; /* success */ - return fd2; + return fd; } static int mail_transaction_log_file_create(struct mail_transaction_log *log, - const char *path, dev_t dev, ino_t ino) + const char *path, + dev_t dev, ino_t ino, uoff_t file_size) { + struct dotlock *dotlock; mode_t old_mask; int fd, fd2; /* With dotlocking we might already have path.lock created, so this filename has to be different. */ old_mask = umask(log->index->mode ^ 0666); - fd = file_dotlock_open(&log->new_dotlock_settings, path, 0, - &log->dotlock); + fd = file_dotlock_open(&log->new_dotlock_settings, path, 0, &dotlock); umask(old_mask); if (fd == -1) { @@ -436,13 +442,14 @@ if (log->index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, log->index->gid) < 0) { mail_index_file_set_syscall_error(log->index, path, "fchown()"); - (void)file_dotlock_delete(&log->dotlock); + (void)file_dotlock_delete(&dotlock); return -1; } - fd2 = mail_transaction_log_file_create2(log, path, fd, dev, ino); + fd2 = mail_transaction_log_file_create2(log, path, fd, &dotlock, + dev, ino, file_size); if (fd2 < 0) { - (void)file_dotlock_delete(&log->dotlock); + (void)file_dotlock_delete(&dotlock); return -1; } return fd2; @@ -475,8 +482,8 @@ ret = mail_transaction_log_file_read_hdr(file); if (ret == 0) { /* corrupted header */ - fd = mail_transaction_log_file_create(log, path, - st.st_dev, st.st_ino); + fd = mail_transaction_log_file_create(log, path, st.st_dev, + st.st_ino, st.st_size); if (fd == -1) ret = -1; else if (fstat(fd, &st) < 0) { @@ -520,6 +527,8 @@ /* log replaced with file having same sequence as previous one. shouldn't happen unless previous log file was corrupted.. */ + file->next = (*p)->next; + (*p)->next = NULL; break; } } @@ -542,7 +551,7 @@ return NULL; } - fd = mail_transaction_log_file_create(log, path, 0, 0); + fd = mail_transaction_log_file_create(log, path, 0, 0, 0); if (fd == -1) return NULL; } @@ -563,9 +572,6 @@ *p = next; } } - - if (log->tail == NULL) - log->head = NULL; } int mail_transaction_log_rotate(struct mail_transaction_log *log, int lock) @@ -574,6 +580,8 @@ struct stat st; int fd; + i_assert(log->head->locked); + if (fstat(log->head->fd, &st) < 0) { mail_index_file_set_syscall_error(log->index, log->head->filepath, @@ -582,7 +590,7 @@ } fd = mail_transaction_log_file_create(log, log->head->filepath, - st.st_dev, st.st_ino); + st.st_dev, st.st_ino, st.st_size); if (fd == -1) return -1; @@ -609,19 +617,6 @@ return 0; } -static int mail_transaction_log_recreate(struct mail_transaction_log *log) -{ - unsigned int lock_id; - int ret; - - if (mail_index_lock_shared(log->index, TRUE, &lock_id) < 0) - return -1; - - ret = mail_transaction_log_rotate(log, FALSE); - mail_index_unlock(log->index, lock_id); - return ret; -} - static int mail_transaction_log_refresh(struct mail_transaction_log *log) { struct mail_transaction_log_file *file; @@ -632,10 +627,6 @@ MAIL_TRANSACTION_LOG_PREFIX, NULL); if (stat(path, &st) < 0) { mail_index_file_set_syscall_error(log->index, path, "stat()"); - if (errno == ENOENT && log->head->locked) { - /* lost? */ - return mail_transaction_log_recreate(log); - } return -1; }
--- a/src/lib-index/mail-transaction-log.h Sat Mar 05 13:57:29 2005 +0200 +++ b/src/lib-index/mail-transaction-log.h Sat Mar 05 14:41:22 2005 +0200 @@ -7,7 +7,7 @@ #define MAIL_TRANSACTION_LOG_PREFIX ".log" #define MAIL_TRANSACTION_LOG_ROTATE_SIZE (1024*128) -#define MAIL_TRANSACTION_LOG_ROTATE_MIN_TIME (60*5) +#define MAIL_TRANSACTION_LOG_ROTATE_TIME (60*5) struct mail_transaction_log_header { uint8_t major_version;