From: Timo Sirainen Date: Wed, 28 Apr 2004 01:21:42 +0000 (+0300) Subject: locking fixes, mmap_disable=yes fixes X-Git-Tag: 1.1.alpha1~4187 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c1d45cada20777e1973579d40d0ebe43f89bb053;p=thirdparty%2Fdovecot%2Fcore.git locking fixes, mmap_disable=yes fixes --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-lock.c b/src/lib-index/mail-index-lock.c index b7400b2d37..4cc057ec44 100644 --- a/src/lib-index/mail-index-lock.c +++ b/src/lib-index/mail-index-lock.c @@ -241,6 +241,8 @@ static int mail_index_lock_exclusive_copy(struct mail_index *index) index->excl_lock_count++; if (mail_index_reopen(index, fd) < 0) { + /* FIXME: do this without another reopen which drops locks + and causes potential crashes */ i_assert(index->excl_lock_count == 1); i_free(index->copy_lock_path); index->copy_lock_path = NULL; @@ -304,6 +306,17 @@ int mail_index_lock_exclusive(struct mail_index *index, static int mail_index_copy_lock_finish(struct mail_index *index) { + if (index->shared_lock_count > 0) { + /* leave ourself shared locked. */ + if (file_try_lock(index->fd, F_RDLCK) <= 0) { + mail_index_file_set_syscall_error(index, + index->copy_lock_path, + "file_try_lock()"); + return -1; + } + index->lock_id--; + } + if (fsync(index->fd) < 0) { mail_index_file_set_syscall_error(index, index->copy_lock_path, "fsync()"); @@ -318,40 +331,34 @@ static int mail_index_copy_lock_finish(struct mail_index *index) i_free(index->copy_lock_path); index->copy_lock_path = NULL; - - index->shared_lock_count = 0; - index->lock_id += 2; - index->lock_type = F_UNLCK; return 0; } -void mail_index_unlock(struct mail_index *index, unsigned int lock_id) +static void mail_index_excl_unlock_finish(struct mail_index *index) { - if (index->copy_lock_path != NULL || - (index->map != NULL && index->map->write_to_disk)) { + if (index->map != NULL && index->map->write_to_disk) { i_assert(index->log_locked); - i_assert(index->excl_lock_count > 0); - i_assert(lock_id == index->lock_id+1); - if (--index->excl_lock_count == 0) { - if (index->map != NULL && index->map->write_to_disk) { - if (index->copy_lock_path != NULL) { - /* new mapping replaces the old */ - (void)unlink(index->copy_lock_path); - i_free(index->copy_lock_path); - index->copy_lock_path = NULL; - } - if (mail_index_copy(index) < 0) { - mail_index_set_inconsistent(index); - return; - } - } - if (mail_index_copy_lock_finish(index) < 0) - mail_index_set_inconsistent(index); + if (index->copy_lock_path != NULL) { + /* new mapping replaces the old */ + (void)unlink(index->copy_lock_path); + i_free(index->copy_lock_path); + index->copy_lock_path = NULL; } - return; + if (mail_index_copy(index) < 0) + mail_index_set_inconsistent(index); } + if (index->copy_lock_path != NULL) { + i_assert(index->log_locked); + + if (mail_index_copy_lock_finish(index) < 0) + mail_index_set_inconsistent(index); + } +} + +void mail_index_unlock(struct mail_index *index, unsigned int lock_id) +{ if ((lock_id & 1) == 0) { /* shared lock */ if (mail_index_is_locked(index, lock_id)) { @@ -362,13 +369,15 @@ void mail_index_unlock(struct mail_index *index, unsigned int lock_id) /* exclusive lock */ i_assert(lock_id == index->lock_id+1); i_assert(index->excl_lock_count > 0); - index->excl_lock_count--; + if (--index->excl_lock_count == 0) + mail_index_excl_unlock_finish(index); } if (index->shared_lock_count == 0 && index->excl_lock_count == 0) { index->lock_id += 2; index->lock_type = F_UNLCK; - if (index->map != NULL) { + if (index->map != NULL && + !MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) { if (mprotect(index->map->mmap_base, index->map->file_size, PROT_NONE) < 0) mail_index_set_syscall_error(index, diff --git a/src/lib-index/mail-index-sync-update.c b/src/lib-index/mail-index-sync-update.c index 6ee908475a..84c787d168 100644 --- a/src/lib-index/mail-index-sync-update.c +++ b/src/lib-index/mail-index-sync-update.c @@ -263,6 +263,9 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx) memcpy(map->mmap_base, &ctx.hdr, sizeof(ctx.hdr)); if (msync(map->mmap_base, map->file_used_size, MS_SYNC) < 0) return mail_index_set_syscall_error(index, "msync()"); + } else { + map->hdr_copy = ctx.hdr; + map->hdr = &map->hdr_copy; } return ret; diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index 65b976bff8..1439177757 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -313,7 +313,7 @@ int mail_index_map(struct mail_index *index, int force) map->log_file_seq = map->hdr->log_file_seq; map->log_file_offset = map->hdr->log_file_offset; - index->hdr = map->mmap_base; + index->hdr = map->hdr; index->map = map; return 1; } diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c index b330a2ef25..62c68c5cb1 100644 --- a/src/lib-index/mail-transaction-log-view.c +++ b/src/lib-index/mail-transaction-log-view.c @@ -151,13 +151,11 @@ mail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view, { va_list va; - i_assert(view->file != NULL); - view->broken = TRUE; va_start(va, fmt); t_push(); - mail_transaction_log_file_set_corrupted(view->file, "%s", + mail_transaction_log_file_set_corrupted(view->log->head, "%s", t_strdup_vprintf(fmt, va)); t_pop(); va_end(va); diff --git a/src/lib-index/mail-transaction-log.c b/src/lib-index/mail-transaction-log.c index b4850b75d4..c75cac8871 100644 --- a/src/lib-index/mail-transaction-log.c +++ b/src/lib-index/mail-transaction-log.c @@ -102,7 +102,8 @@ mail_transaction_log_open_or_create(struct mail_index *index) log->head->hdr.file_seq != index->hdr->log_file_seq) { /* 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 */ + check again - FIXME: missing error handling. + FIXME: index->hdr check crashes if we created the log */ (void)mail_transaction_log_check_file_seq(log); } return log; @@ -178,6 +179,7 @@ mail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file, } if (ret < 0) { + // FIXME: handle ESTALE mail_index_file_set_syscall_error(file->log->index, file->filepath, "pread()"); return -1; @@ -542,6 +544,9 @@ mail_transaction_log_file_read(struct mail_transaction_log_file *file, } size = file->hdr.used_size - file->buffer_offset - size; + if (size == 0) + return 1; + data = buffer_append_space_unsafe(file->buffer, size); ret = pread(file->fd, data, size, offset);