# HG changeset patch # User Timo Sirainen # Date 1083117639 -10800 # Node ID d11efbf1d3417c2da10ffb48c86e573bf70a67e3 # Parent 4aeb7357951a03fe5a164a0a2d9a3e9f99d4eae5 Added fcntl_lock_disable setting to allow indexes to work with NFS. Some other locking fixes. diff -r 4aeb7357951a -r d11efbf1d341 dovecot-example.conf --- a/dovecot-example.conf Wed Apr 28 04:21:42 2004 +0300 +++ b/dovecot-example.conf Wed Apr 28 05:00:39 2004 +0300 @@ -255,6 +255,10 @@ # which use separate caches for them, such as OpenBSD. #mmap_no_write = no +# Don't use fcntl() locking. Alternatives are dotlocking and other tricks +# which may be slower. Required for NFS. +#fcntl_locks_disable = no + # Copy mail to another folders using hard links. This is much faster than # actually copying the file. This is problematic only if something modifies # the mail in one folder but doesn't want it modified in the others. I don't diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-index-lock.c --- a/src/lib-index/mail-index-lock.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-index-lock.c Wed Apr 28 05:00:39 2004 +0300 @@ -76,6 +76,24 @@ } } +static int mail_index_lock_mprotect(struct mail_index *index, int lock_type) +{ + int prot; + + if (index->map != NULL && + !MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) { + prot = lock_type == F_UNLCK ? PROT_NONE : + lock_type == F_WRLCK ? (PROT_READ|PROT_WRITE) : + PROT_READ; + if (mprotect(index->map->mmap_base, + index->map->file_size, prot) < 0) { + mail_index_set_syscall_error(index, "mprotect()"); + return -1; + } + } + return 0; +} + static int mail_index_lock(struct mail_index *index, int lock_type, unsigned int timeout_secs, int update_index, unsigned int *lock_id_r) @@ -84,6 +102,15 @@ i_assert(lock_type == F_RDLCK || lock_type == F_WRLCK); + if (index->fcntl_locks_disable) { + /* FIXME: exclusive locking will rewrite the index file every + time. shouldn't really be needed.. reading doesn't require + locks then, though */ + if (lock_type == F_WRLCK) + return 0; + } else { + } + if (lock_type == F_WRLCK && index->lock_type == F_RDLCK) { /* drop shared locks */ i_assert(index->excl_lock_count == 0); @@ -148,16 +175,8 @@ *lock_id_r = index->lock_id + 1; } - if (index->map != NULL && - !MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) { - int prot = PROT_READ | (lock_type == F_WRLCK ? PROT_WRITE : 0); - if (mprotect(index->map->mmap_base, - index->map->file_size, prot) < 0) { - mail_index_set_syscall_error(index, "mprotect()"); - return -1; - } - } - + if (mail_index_lock_mprotect(index, lock_type) < 0) + return -1; return 1; } @@ -189,6 +208,8 @@ if (fd == -1) return -1; + (void)mail_index_lock_mprotect(index, F_RDLCK); + ret = write_full(fd, index->map->hdr, sizeof(*index->map->hdr)); if (ret < 0 || write_full(fd, index->map->records, index->map->records_count * @@ -300,7 +321,7 @@ mail_index_unlock(index, lock_id); - *lock_id_r = 0; + *lock_id_r = index->lock_id + 1; return mail_index_lock_exclusive_copy(index); } @@ -314,7 +335,6 @@ "file_try_lock()"); return -1; } - index->lock_id--; } if (fsync(index->fd) < 0) { @@ -367,7 +387,7 @@ } } else { /* exclusive lock */ - i_assert(lock_id == index->lock_id+1); + i_assert(lock_id == index->lock_id + 1); i_assert(index->excl_lock_count > 0); if (--index->excl_lock_count == 0) mail_index_excl_unlock_finish(index); @@ -376,15 +396,13 @@ if (index->shared_lock_count == 0 && index->excl_lock_count == 0) { index->lock_id += 2; index->lock_type = F_UNLCK; - 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) + (void)mail_index_lock_mprotect(index, F_UNLCK); + if (!index->fcntl_locks_disable) { + if (file_wait_lock(index->fd, F_UNLCK) < 0) { mail_index_set_syscall_error(index, - "mprotect()"); + "file_wait_lock()"); + } } - if (file_wait_lock(index->fd, F_UNLCK) < 0) - mail_index_set_syscall_error(index, "file_wait_lock()"); } } diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-index-private.h --- a/src/lib-index/mail-index-private.h Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-index-private.h Wed Apr 28 05:00:39 2004 +0300 @@ -1,6 +1,7 @@ #ifndef __MAIL_INDEX_PRIVATE_H #define __MAIL_INDEX_PRIVATE_H +#include "file-dotlock.h" #include "mail-index.h" struct mail_transaction_header; @@ -70,6 +71,7 @@ int lock_type, shared_lock_count, excl_lock_count; unsigned int lock_id, copy_lock_id; char *copy_lock_path; + struct dotlock dotlock; char *error; unsigned int nodiskspace:1; @@ -79,6 +81,7 @@ unsigned int log_locked:1; unsigned int mmap_disable:1; unsigned int mmap_no_write:1; + unsigned int fcntl_locks_disable:1; unsigned int readonly:1; unsigned int fsck:1; }; diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-index.c --- a/src/lib-index/mail-index.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-index.c Wed Apr 28 05:00:39 2004 +0300 @@ -575,6 +575,8 @@ (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0; index->mmap_no_write = (flags & MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE) != 0; + index->fcntl_locks_disable = + (flags & MAIL_INDEX_OPEN_FLAG_FCNTL_LOCKS_DISABLE) != 0; index->readonly = FALSE; index->filepath = i_strconcat(index->dir, "/", diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-index.h --- a/src/lib-index/mail-index.h Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-index.h Wed Apr 28 05:00:39 2004 +0300 @@ -24,8 +24,8 @@ OSes that don't have unified buffer cache (currently OpenBSD <= 3.5) */ MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE = 0x08, - /* Use only dotlocking, no fcntl() */ - MAIL_INDEX_OPEN_FLAG_USE_DOTLOCKS = 0x10 + /* Don't use fcntl() locking */ + MAIL_INDEX_OPEN_FLAG_FCNTL_LOCKS_DISABLE= 0x10 }; enum mail_index_header_compat_flags { diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-transaction-log-private.h --- a/src/lib-index/mail-transaction-log-private.h Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-transaction-log-private.h Wed Apr 28 05:00:39 2004 +0300 @@ -1,6 +1,7 @@ #ifndef __MAIL_TRANSACTION_LOG_VIEW_H #define __MAIL_TRANSACTION_LOG_VIEW_H +#include "file-dotlock.h" #include "mail-transaction-log.h" struct mail_transaction_log_file { @@ -12,6 +13,7 @@ char *filepath; int fd; int lock_type; + struct dotlock dotlock; ino_t st_ino; dev_t st_dev; diff -r 4aeb7357951a -r d11efbf1d341 src/lib-index/mail-transaction-log.c --- a/src/lib-index/mail-transaction-log.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-index/mail-transaction-log.c Wed Apr 28 05:00:39 2004 +0300 @@ -16,6 +16,11 @@ #include #include +/* this lock should never exist for a long time.. */ +#define LOG_DOTLOCK_TIMEOUT 30 +#define LOG_DOTLOCK_STALE_TIMEOUT 0 +#define LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT 120 + struct mail_transaction_add_ctx { struct mail_transaction_log *log; struct mail_index_view *view; @@ -117,6 +122,54 @@ } static int +mail_transaction_log_file_dotlock(struct mail_transaction_log_file *file, + int lock_type) +{ + int ret; + + if (lock_type == F_UNLCK) { + ret = file_unlock_dotlock(file->filepath, &file->dotlock); + if (ret < 0) { + mail_index_file_set_syscall_error(file->log->index, + file->filepath, "file_unlock_dotlock()"); + return -1; + } + file->lock_type = F_UNLCK; + + if (ret == 0) { + mail_index_set_error(file->log->index, + "Dotlock was lost for transaction log file %s", + file->filepath); + return -1; + } + return 0; + } + + ret = file_lock_dotlock(file->filepath, NULL, FALSE, + LOG_DOTLOCK_TIMEOUT, + LOG_DOTLOCK_STALE_TIMEOUT, + LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT, + NULL, NULL, &file->dotlock); + if (ret > 0) { + file->lock_type = F_WRLCK; + return 0; + } + if (ret < 0) { + mail_index_file_set_syscall_error(file->log->index, + file->filepath, + "file_lock_dotlock()"); + return -1; + } + + mail_index_set_error(file->log->index, + "Timeout while waiting for release of " + "dotlock for transaction log file %s", + file->filepath); + file->log->index->index_lock_timeout = TRUE; + return -1; +} + +static int mail_transaction_log_file_lock(struct mail_transaction_log_file *file, int lock_type) { @@ -128,6 +181,9 @@ i_assert(file->lock_type == F_UNLCK); } + if (file->log->index->fcntl_locks_disable) + return mail_transaction_log_file_dotlock(file, lock_type); + ret = file_wait_lock_full(file->fd, lock_type, DEFAULT_LOCK_TIMEOUT, NULL, NULL); if (ret > 0) { @@ -233,8 +289,9 @@ unsigned int lock_id; int fd, fd2, ret; - /* this lock should never exist for a long time.. */ - fd = file_dotlock_open(path, NULL, 30, 0, 120, NULL, NULL); + fd = file_dotlock_open(path, NULL, LOG_DOTLOCK_TIMEOUT, + LOG_DOTLOCK_STALE_TIMEOUT, + LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT, NULL, NULL); if (fd == -1) { mail_index_file_set_syscall_error(index, path, "file_dotlock_open()"); diff -r 4aeb7357951a -r d11efbf1d341 src/lib-storage/index/index-storage.c --- a/src/lib-storage/index/index-storage.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/lib-storage/index/index-storage.c Wed Apr 28 05:00:39 2004 +0300 @@ -316,6 +316,8 @@ index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE; if (getenv("MMAP_NO_WRITE") != NULL) index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE; + if (getenv("FCNTL_LOCKS_DISABLE") != NULL) + index_flags |= MAIL_INDEX_OPEN_FLAG_FCNTL_LOCKS_DISABLE; do { ibox = i_new(struct index_mailbox, 1); diff -r 4aeb7357951a -r d11efbf1d341 src/master/mail-process.c --- a/src/master/mail-process.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/master/mail-process.c Wed Apr 28 05:00:39 2004 +0300 @@ -265,6 +265,8 @@ env_put("MMAP_DISABLE=1"); if (set->mmap_no_write) env_put("MMAP_NO_WRITE=1"); + if (set->fcntl_locks_disable) + env_put("FCNTL_LOCKS_DISABLE=1"); if (set->maildir_copy_with_hardlinks) env_put("MAILDIR_COPY_WITH_HARDLINKS=1"); if (set->maildir_check_content_changes) diff -r 4aeb7357951a -r d11efbf1d341 src/master/master-settings.c --- a/src/master/master-settings.c Wed Apr 28 04:21:42 2004 +0300 +++ b/src/master/master-settings.c Wed Apr 28 05:00:39 2004 +0300 @@ -90,6 +90,7 @@ DEF(SET_BOOL, mail_read_mmaped), DEF(SET_BOOL, mmap_disable), DEF(SET_BOOL, mmap_no_write), + DEF(SET_BOOL, fcntl_locks_disable), DEF(SET_BOOL, maildir_copy_with_hardlinks), DEF(SET_BOOL, maildir_check_content_changes), DEF(SET_STR, mbox_locks), @@ -214,6 +215,7 @@ #else MEMBER(mmap_no_write) FALSE, #endif + MEMBER(fcntl_locks_disable) FALSE, MEMBER(maildir_copy_with_hardlinks) FALSE, MEMBER(maildir_check_content_changes) FALSE, MEMBER(mbox_locks) "dotlock fcntl", diff -r 4aeb7357951a -r d11efbf1d341 src/master/master-settings.h --- a/src/master/master-settings.h Wed Apr 28 04:21:42 2004 +0300 +++ b/src/master/master-settings.h Wed Apr 28 05:00:39 2004 +0300 @@ -65,6 +65,7 @@ int mail_read_mmaped; int mmap_disable; int mmap_no_write; + int fcntl_locks_disable; int maildir_copy_with_hardlinks; int maildir_check_content_changes; const char *mbox_locks;