]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
locking fixes, mmap_disable=yes fixes
authorTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2004 01:21:42 +0000 (04:21 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2004 01:21:42 +0000 (04:21 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-lock.c
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index.c
src/lib-index/mail-transaction-log-view.c
src/lib-index/mail-transaction-log.c

index b7400b2d37963108c7c7848399a9b656d732f992..4cc057ec448f5bd4a023a6cbef1cdc1d5746149e 100644 (file)
@@ -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,
index 6ee908475a7ce2d9f36cbf4289fe3cfbf7b7ceb1..84c787d168bdd6987dc5061657e45baa0d99e39b 100644 (file)
@@ -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;
index 65b976bff82ae28c3c85ab4666f37aafeccc703f..14391777575aeeeca976f317f86c0ccd0f2cbbd6 100644 (file)
@@ -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;
 }
index b330a2ef253507f66127046413e2e5ddf24da3ad..62c68c5cb172553dcca053a55d63b2c66b3c912f 100644 (file)
@@ -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);
index b4850b75d475afd286152fed77a647e4d94f5660..c75cac8871e25bab233503ddc90a8b41da42bdf1 100644 (file)
@@ -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);