]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added fcntl_lock_disable setting to allow indexes to work with NFS. Some
authorTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2004 02:00:39 +0000 (05:00 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2004 02:00:39 +0000 (05:00 +0300)
other locking fixes.

--HG--
branch : HEAD

dovecot-example.conf
src/lib-index/mail-index-lock.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index.c
src/lib-index/mail-index.h
src/lib-index/mail-transaction-log-private.h
src/lib-index/mail-transaction-log.c
src/lib-storage/index/index-storage.c
src/master/mail-process.c
src/master/master-settings.c
src/master/master-settings.h

index 9dea0ded5d28093c98b194f6ad2314c7b7a708c8..9a4dece6c34186e4fa88ad51b331c84b6a207a12 100644 (file)
 # 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
index 4cc057ec448f5bd4a023a6cbef1cdc1d5746149e..098dfa642deabcff998f4062cde05e192ff21a56 100644 (file)
@@ -76,6 +76,24 @@ static int mail_index_has_changed(struct mail_index *index)
        }
 }
 
+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 @@ static int mail_index_lock(struct mail_index *index, int lock_type,
 
        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 @@ static int mail_index_lock(struct mail_index *index, int lock_type,
                *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 @@ static int mail_index_copy(struct mail_index *index)
        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 @@ int mail_index_lock_exclusive(struct mail_index *index,
 
        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 @@ static int mail_index_copy_lock_finish(struct mail_index *index)
                                                          "file_try_lock()");
                        return -1;
                }
-               index->lock_id--;
        }
 
        if (fsync(index->fd) < 0) {
@@ -367,7 +387,7 @@ void mail_index_unlock(struct mail_index *index, unsigned int lock_id)
                }
        } 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 @@ void mail_index_unlock(struct mail_index *index, unsigned int lock_id)
        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()");
        }
 }
 
index bc8aac73fa499514900de872a0af02b5a7290789..d99bef075e816c8e5dc288dff64cebbc3f597856 100644 (file)
@@ -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 @@ struct mail_index {
        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 @@ struct mail_index {
        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;
 };
index 14391777575aeeeca976f317f86c0ccd0f2cbbd6..cc0119ee89e453ea92ba35f21cd048fbafc168fd 100644 (file)
@@ -575,6 +575,8 @@ int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
                        (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, "/",
index 78fa542fb4e344f44f511fb01ab5e2104077e77b..02d813a77f25636e8d2096e834f9d39d41f9df71 100644 (file)
@@ -24,8 +24,8 @@ enum mail_index_open_flags {
           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 {
index 801ace6c07a83f3ebd8a0f0803afe6d3f48d3551..5cc8529dbf9d476ec5f421a1ab86000b563e4bd7 100644 (file)
@@ -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 @@ struct mail_transaction_log_file {
        char *filepath;
        int fd;
        int lock_type;
+       struct dotlock dotlock;
 
        ino_t st_ino;
        dev_t st_dev;
index c75cac8871e25bab233503ddc90a8b41da42bdf1..7c2e2cf75118be239a83745761e64ff3a8f23dca 100644 (file)
 #include <stddef.h>
 #include <sys/stat.h>
 
+/* 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;
@@ -116,6 +121,54 @@ void mail_transaction_log_close(struct mail_transaction_log *log)
        i_free(log);
 }
 
+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 @@ mail_transaction_log_file_lock(struct mail_transaction_log_file *file,
                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 @@ static int mail_transaction_log_file_create(struct mail_transaction_log *log,
        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()");
index dcc574029f40f49bd0d6920853df96fc4be9dc67..a5646c5fd723e667df69410bd4edaa3d4832be26 100644 (file)
@@ -316,6 +316,8 @@ index_storage_mailbox_init(struct index_storage *storage, struct mailbox *box,
                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);
index 0fe2c5a1c5506d4fbfb4988d4e5376343bbecc2b..7b42a2fa5488543c166ce851a3d221dbc4d9c15b 100644 (file)
@@ -265,6 +265,8 @@ int create_mail_process(struct login_group *group, int socket,
                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)
index 58b0bfff69e8d4bb28c03fa9fa189f69c7c24b77..5730887ce793eda10ab52985ff0a3b363977c9da 100644 (file)
@@ -90,6 +90,7 @@ static struct setting_def setting_defs[] = {
        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 @@ struct settings default_settings = {
 #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",
index 31c3095e4690c2234e2b6e438a00ac25b01c1466..d6ca4109c58adcdae30c3f8e7a3a56eebd5f0650 100644 (file)
@@ -65,6 +65,7 @@ struct settings {
        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;