]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Renamed fsync_disable to mail_fsync=optimized|always|never.
authorTimo Sirainen <tss@iki.fi>
Fri, 25 Jun 2010 15:21:49 +0000 (16:21 +0100)
committerTimo Sirainen <tss@iki.fi>
Fri, 25 Jun 2010 15:21:49 +0000 (16:21 +0100)
--HG--
branch : HEAD

32 files changed:
doc/example-config/conf.d/10-mail.conf
src/config/old-set-parser.c
src/config/settings-get.pl
src/lib-index/mail-cache-compress.c
src/lib-index/mail-cache-transaction.c
src/lib-index/mail-cache.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index-write.c
src/lib-index/mail-index.c
src/lib-index/mail-index.h
src/lib-index/mail-transaction-log-append.c
src/lib-index/mail-transaction-log-file.c
src/lib-index/mail-transaction-log-private.h
src/lib-index/mail-transaction-log.c
src/lib-index/mailbox-list-index-sync.c
src/lib-index/mailbox-list-index.c
src/lib-storage/index/cydir/cydir-save.c
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/dbox-common/dbox-file.c
src/lib-storage/index/dbox-multi/mdbox-map.c
src/lib-storage/index/dbox-multi/mdbox-save.c
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-single/sdbox-save.c
src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/maildir/maildir-save.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/index/mbox/mbox-save.c
src/lib-storage/mail-storage-settings.c
src/lib-storage/mail-storage-settings.h
src/lib/Makefile.am
src/lib/fsync-mode.h [new file with mode: 0644]

index 67193adae347e6bfed1e7ed4c678b0756a3f947f..5fffaaf1b048c3b5fcbcce07c2e69e780e5076bf 100644 (file)
 # since version 3, so this should be safe to use nowadays by default.
 #dotlock_use_excl = yes
 
-# Don't use fsync() or fdatasync() calls. This makes the performance better
-# at the cost of potential data loss if the server (or the file server)
-# goes down.
-#fsync_disable = no
+# When to use fsync() or fdatasync() calls:
+#   optimized (default): Whenever necessary to avoid losing important data
+#   always: Useful with e.g. NFS when write()s are delayed
+#   never: Never use it (best performance, but crashes can lose data)
+#mail_fsync = optimized
 
 # Mail storage exists in NFS. Set this to yes to make Dovecot flush NFS caches
 # whenever needed. If you're using only a single mail server this isn't needed.
index 8095e89f011e3ce7fbd41f1a555c4a6e3f5bab7c..244e91020afc5ac8ff85fa84c1c68fac274730be 100644 (file)
@@ -130,6 +130,14 @@ old_settings_handle_root(struct config_parser_context *ctx,
                set_rename(ctx, key, "ssl", value);
                return TRUE;
        }
+       if (strcmp(key, "fsync_disable") == 0) {
+               if (strcasecmp(value, "yes") == 0)
+                       value = "never";
+               else if (strcasecmp(value, "no") == 0)
+                       value = "optimized";
+               set_rename(ctx, key, "mail_fsync", value);
+               return TRUE;
+       }
        if (strcmp(key, "dbox_rotate_size") == 0) {
                set_rename(ctx, key, "mdbox_rotate_size", value);
                return TRUE;
index 58a6c1522c77b3250ae4425f90066c04c0db60f8..61c26743379c7b49d478df235eb580a0a103d44c 100755 (executable)
@@ -5,6 +5,7 @@ print '#include "lib.h"'."\n";
 print '#include "array.h"'."\n";
 print '#include "var-expand.h"'."\n";
 print '#include "file-lock.h"'."\n";
+print '#include "fsync-mode.h"'."\n";
 print '#include "settings-parser.h"'."\n";
 print '#include "all-settings.h"'."\n";
 print '#include <stddef.h>'."\n";
index 35129b41a919d98feb8c1c87c210f540334457ad..86311d823e539d97671d610d2e5f736973fe7834 100644 (file)
@@ -297,7 +297,7 @@ mail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
 
        o_stream_destroy(&output);
 
-       if ((cache->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+       if (cache->index->fsync_mode == FSYNC_MODE_ALWAYS) {
                if (fdatasync(fd) < 0) {
                        mail_cache_set_syscall_error(cache, "fdatasync()");
                        array_free(ext_offsets);
index ff1befba45f9212861a968e9b1cb1d7c86891949..149724504afb01101a2fd1a08ce0c5b85cadef2c 100644 (file)
@@ -836,7 +836,7 @@ mail_cache_header_fields_write(struct mail_cache_transaction_ctx *ctx,
        if (mail_cache_write(cache, buffer->data, size, offset) < 0)
                return -1;
 
-       if ((cache->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+       if (cache->index->fsync_mode == FSYNC_MODE_ALWAYS) {
                if (fdatasync(cache->fd) < 0) {
                        mail_cache_set_syscall_error(cache, "fdatasync()");
                        return -1;
index 77fb4f7f1615e6c26a4d79e374cec4527d3bd410..9c8c749ff912e1c7655cec6ea0f390164f4c954f 100644 (file)
@@ -657,7 +657,7 @@ int mail_cache_unlock(struct mail_cache *cache)
                mail_cache_update_need_compress(cache);
        }
 
-       if ((cache->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+       if (cache->index->fsync_mode == FSYNC_MODE_ALWAYS) {
                if (fdatasync(cache->fd) < 0)
                        mail_cache_set_syscall_error(cache, "fdatasync()");
        }
index f31ee057bd8035943acf825aab47385cb0fb3d16..8d6c58535e547f3ef868fdf082877cc43d3eecdb 100644 (file)
@@ -172,6 +172,7 @@ struct mail_index {
 
        unsigned int open_count;
        enum mail_index_open_flags flags;
+       enum fsync_mode fsync_mode;
        enum mail_index_sync_type fsync_mask;
        mode_t mode;
        gid_t gid;
index b4d5e011474831ad4aaf366068fed4775a714f7e..659ee1748cceace685cb4fa1045536dbe6912278 100644 (file)
@@ -78,8 +78,7 @@ static int mail_index_recreate(struct mail_index *index)
        }
        o_stream_destroy(&output);
 
-       if (ret == 0 &&
-           (index->flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) == 0) {
+       if (ret == 0 && index->fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync(fd) < 0) {
                        mail_index_file_set_syscall_error(index, path,
                                                          "fdatasync()");
@@ -245,7 +244,7 @@ void mail_index_write(struct mail_index *index, bool want_rotate)
                ret = mail_index_write_map_over(index);
                if (ret < 0)
                        mail_index_set_syscall_error(index, "pwrite_full()");
-               else if ((index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+               else if (index->fsync_mode == FSYNC_MODE_ALWAYS) {
                        ret = fdatasync(index->fd);
                        if (ret < 0) {
                                mail_index_set_syscall_error(index,
index 667bde56678e00bb38948be8f74474bf9797fb2b..9b56a274ac18939d16f51e11f36bbd87d332d324 100644 (file)
@@ -84,10 +84,12 @@ void mail_index_free(struct mail_index **_index)
        i_free(index);
 }
 
-void mail_index_set_fsync_types(struct mail_index *index,
-                               enum mail_index_sync_type fsync_mask)
+void mail_index_set_fsync_mode(struct mail_index *index,
+                              enum fsync_mode mode,
+                              enum mail_index_sync_type mask)
 {
-       index->fsync_mask = fsync_mask;
+       index->fsync_mode = mode;
+       index->fsync_mask = mask;
 }
 
 void mail_index_set_permissions(struct mail_index *index,
@@ -519,8 +521,8 @@ int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
        index->readonly = (flags & MAIL_INDEX_OPEN_FLAG_READONLY) != 0;
 
        if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
-           (flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0)
-               i_fatal("nfs flush requires fsync_disable=no");
+           index->fsync_mode != FSYNC_MODE_ALWAYS)
+               i_fatal("nfs flush requires mail_fsync=always");
        if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
            (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0)
                i_fatal("nfs flush requires mmap_disable=yes");
index dddde3542d5161c2e9d9b695c07b468fe8295da1..c59d03d97551330542cdd821f435a93dac4e9d80 100644 (file)
@@ -2,6 +2,7 @@
 #define MAIL_INDEX_H
 
 #include "file-lock.h"
+#include "fsync-mode.h"
 #include "mail-types.h"
 #include "seq-range-array.h"
 
@@ -17,8 +18,6 @@ enum mail_index_open_flags {
        MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE       = 0x04,
        /* Rely on O_EXCL when creating dotlocks */
        MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL   = 0x10,
-       /* Don't fsync() or fdatasync() */
-       MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE      = 0x20,
        /* Flush NFS attr/data/write cache when necessary */
        MAIL_INDEX_OPEN_FLAG_NFS_FLUSH          = 0x40,
        /* Open the index read-only */
@@ -207,10 +206,10 @@ struct mail_index_view_sync_ctx;
 struct mail_index *mail_index_alloc(const char *dir, const char *prefix);
 void mail_index_free(struct mail_index **index);
 
-/* Specify the transaction types that are fsynced after writing.
-   Default is to fsync nothing. */
-void mail_index_set_fsync_types(struct mail_index *index,
-                               enum mail_index_sync_type fsync_mask);
+/* Specify how often to do fsyncs. If mode is FSYNC_MODE_OPTIMIZED, the mask
+   can be used to specify which transaction types to fsync. */
+void mail_index_set_fsync_mode(struct mail_index *index, enum fsync_mode mode,
+                              enum mail_index_sync_type mask);
 void mail_index_set_permissions(struct mail_index *index,
                                mode_t mode, gid_t gid, const char *gid_origin);
 /* Set locking method and maximum time to wait for a lock (-1U = default). */
index 3dc13e08ed5e3ac441825c7cbf59032856423b35..cf099bfb3665a366cc2b9d27fcfb87ddaac3cc24 100644 (file)
@@ -109,8 +109,8 @@ static int log_buffer_write(struct mail_transaction_log_append_ctx *ctx)
        }
 
        if ((ctx->want_fsync &&
-            (file->log->flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) == 0) ||
-           (file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+            file->log->index->fsync_mode != FSYNC_MODE_NEVER) ||
+           file->log->index->fsync_mode == FSYNC_MODE_ALWAYS) {
                if (fdatasync(file->fd) < 0) {
                        mail_index_file_set_syscall_error(ctx->log->index,
                                                          file->filepath,
index cb6a55588783cb8d2352e645be7290979802c4ac..ca761d209bf3064db0151e421345460efa03cb95 100644 (file)
@@ -548,7 +548,7 @@ mail_transaction_log_file_create2(struct mail_transaction_log_file *file,
        int fd, ret;
        bool rename_existing;
 
-       if ((file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+       if (file->log->nfs_flush) {
                /* although we check also mtime and file size below, it's done
                   only to fix broken log files. we don't bother flushing
                   attribute cache just for that. */
@@ -614,9 +614,9 @@ mail_transaction_log_file_create2(struct mail_transaction_log_file *file,
        if (write_full(new_fd, &file->hdr, sizeof(file->hdr)) < 0)
                return log_file_set_syscall_error(file, "write_full()");
 
-       if ((file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
+       if (file->log->index->fsync_mode == FSYNC_MODE_ALWAYS) {
                /* the header isn't important, so don't bother calling
-                  fdatasync() unless NFS is used */
+                  fdatasync() unless it's required */
                if (fdatasync(new_fd) < 0)
                        return log_file_set_syscall_error(file, "fdatasync()");
        }
@@ -1333,8 +1333,6 @@ static int
 mail_transaction_log_file_read(struct mail_transaction_log_file *file,
                               uoff_t start_offset, bool nfs_flush)
 {
-       bool index_nfs_flush =
-               (file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
        int ret;
 
        i_assert(file->mmap_base == NULL);
@@ -1344,7 +1342,7 @@ mail_transaction_log_file_read(struct mail_transaction_log_file *file,
           that we really should have read more, flush the cache and try again.
           if file is locked, the attribute cache was already flushed when
           refreshing the log. */
-       if (index_nfs_flush && nfs_flush) {
+       if (file->log->nfs_flush && nfs_flush) {
                if (!file->locked)
                        nfs_flush_attr_cache_unlocked(file->filepath);
                else {
@@ -1369,7 +1367,7 @@ mail_transaction_log_file_read(struct mail_transaction_log_file *file,
        if ((ret = mail_transaction_log_file_read_more(file)) <= 0)
                return ret;
 
-       if (index_nfs_flush && !nfs_flush &&
+       if (file->log->nfs_flush && !nfs_flush &&
            mail_transaction_log_file_need_nfs_flush(file)) {
                /* we didn't read enough data. flush and try again. */
                return mail_transaction_log_file_read(file, start_offset, TRUE);
@@ -1556,7 +1554,7 @@ int mail_transaction_log_file_map(struct mail_transaction_log_file *file,
                start_offset = file->sync_offset;
        }
 
-       if ((file->log->flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0)
+       if ((file->log->index->flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0)
                ret = mail_transaction_log_file_map_mmap(file, start_offset);
        else {
                mail_transaction_log_file_munmap(file);
index c92c2758ff6a3a10be7d23fa3f3e6a2fa6027b02..cf6285469607c364b05206d70e06ec0ebe4ca0a8 100644 (file)
@@ -80,7 +80,6 @@ struct mail_transaction_log_file {
 struct mail_transaction_log {
        struct mail_index *index;
         struct mail_transaction_log_view *views;
-       enum mail_index_open_flags flags;
        char *filepath, *filepath2;
 
        /* files is a linked list of all the opened log files. the list is
@@ -94,6 +93,8 @@ struct mail_transaction_log {
        unsigned int dotlock_count;
         struct dotlock_settings dotlock_settings, new_dotlock_settings;
        struct dotlock *dotlock;
+
+       unsigned int nfs_flush:1;
 };
 
 void
index 7be2a762fd4bf926b0fdac3a36a303e13a8146b4..c4e411efe698d3a3a8791addff1e1b6c495e94d5 100644 (file)
@@ -80,15 +80,12 @@ int mail_transaction_log_open(struct mail_transaction_log *log)
                                    MAIL_TRANSACTION_LOG_SUFFIX, NULL);
        log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
 
-       log->flags = log->index->flags;
+       log->nfs_flush =
+               (log->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
        log->dotlock_settings.use_excl_lock =
-               (log->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
-       log->dotlock_settings.nfs_flush =
-               (log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
-       log->new_dotlock_settings.use_excl_lock =
-               (log->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
-       log->new_dotlock_settings.nfs_flush =
-               (log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
+               (log->index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
+       log->dotlock_settings.nfs_flush = log->nfs_flush;
+       log->new_dotlock_settings = log->dotlock_settings;
 
        if (log->open_file != NULL)
                mail_transaction_log_file_free(&log->open_file);
@@ -299,7 +296,7 @@ mail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush)
        if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head))
                return 0;
 
-       if (nfs_flush && (log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0)
+       if (nfs_flush && log->nfs_flush)
                nfs_flush_file_handle_cache(log->filepath);
        if (nfs_safe_stat(log->filepath, &st) < 0) {
                if (errno != ENOENT) {
@@ -386,8 +383,7 @@ int mail_transaction_log_find_file(struct mail_transaction_log *log,
                if (mail_transaction_log_refresh(log, FALSE) < 0)
                        return -1;
                if (file_seq > log->head->hdr.file_seq) {
-                       if (!nfs_flush ||
-                           (log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) == 0)
+                       if (!nfs_flush || !log->nfs_flush)
                                return 0;
                        /* try again, this time flush attribute cache */
                        if (mail_transaction_log_refresh(log, TRUE) < 0)
index d09672e7cb9527b502408b00b2dd25ee4157cd1f..6acc86fa13d96e773ff1b9391bc4173ee253a4b3 100644 (file)
@@ -875,8 +875,7 @@ mailbox_list_index_sync_write(struct mailbox_list_index_sync_ctx *ctx)
                        ret = -1;
                }
                if (ret == 0 &&
-                   (ctx->index->mail_index->flags &
-                    MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
+                   ctx->index->mail_index->fsync_mode == FSYNC_MODE_ALWAYS &&
                    fdatasync(ctx->index->fd) < 0) {
                        mailbox_list_index_set_syscall_error(ctx->index,
                                                             "fdatasync()");
index d7d0898419b28259aec11e21d29156d5210c59c7..23ac6e96c5199fdbbd92c12ba07fc05837d7f6fa 100644 (file)
@@ -274,7 +274,7 @@ int mailbox_list_index_file_create(struct mailbox_list_index *index,
                return -1;
        }
 
-       if ((index->mail_index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
+       if (index->mail_index->fsync_mode == FSYNC_MODE_ALWAYS &&
            fdatasync(fd) < 0) {
                mailbox_list_index_set_syscall_error(index, "fdatasync()");
                (void)file_dotlock_delete(&dotlock);
index a86b3b7c362d497103d2afcd02a56a31569ea0e0..4015dfc7f657eb3a1ae5261b72e8f25c5623ea36 100644 (file)
@@ -171,7 +171,7 @@ int cydir_save_finish(struct mail_save_context *_ctx)
                ctx->failed = TRUE;
        }
 
-       if (!storage->set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fsync(ctx->fd) < 0) {
                        mail_storage_set_critical(storage,
                                                  "fsync(%s) failed: %m", path);
index 8b6c46bbe7d02e5d58c1f8b29548aef21e3080e0..0132486487dd0d9629c87c2ccab6fa214a1f0805 100644 (file)
@@ -55,9 +55,10 @@ cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
 
        index_storage_mailbox_alloc(&mbox->box, name, flags,
                                    CYDIR_INDEX_PREFIX);
-       mail_index_set_fsync_types(mbox->box.index,
-                                  MAIL_INDEX_SYNC_TYPE_APPEND |
-                                  MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+       mail_index_set_fsync_mode(mbox->box.index,
+                                 storage->set->parsed_fsync_mode,
+                                 MAIL_INDEX_SYNC_TYPE_APPEND |
+                                 MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = cydir_transaction_save_commit_pre;
index 3a61fbf7c33ea31fc19de42e9879bdfdc1726653..fcdeed50ae72523ec3ac974ecdab20e603ab19d7 100644 (file)
@@ -520,6 +520,8 @@ void dbox_file_append_rollback(struct dbox_file_append_context **_ctx)
 
 int dbox_file_append_flush(struct dbox_file_append_context *ctx)
 {
+       struct mail_storage *storage = &ctx->file->storage->storage;
+
        if (ctx->last_flush_offset == ctx->output->offset)
                return 0;
 
@@ -528,7 +530,7 @@ int dbox_file_append_flush(struct dbox_file_append_context *ctx)
                return -1;
        }
 
-       if (!ctx->file->storage->storage.set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync(ctx->file->fd) < 0) {
                        dbox_file_set_syscall_error(ctx->file, "fdatasync()");
                        return -1;
@@ -678,6 +680,7 @@ const char *dbox_file_metadata_get(struct dbox_file *file,
 
 int dbox_file_move(struct dbox_file *file, bool alt_path)
 {
+       struct mail_storage *storage = &file->storage->storage;
        struct ostream *output;
        const char *dest_dir, *temp_path, *dest_path, *p;
        struct stat st;
@@ -716,30 +719,30 @@ int dbox_file_move(struct dbox_file *file, bool alt_path)
                ret = o_stream_flush(output);
        if (output->stream_errno != 0) {
                errno = output->stream_errno;
-               mail_storage_set_critical(&file->storage->storage,
-                                         "write(%s) failed: %m", temp_path);
+               mail_storage_set_critical(storage, "write(%s) failed: %m",
+                                         temp_path);
                ret = -1;
        } else if (file->input->stream_errno != 0) {
                errno = file->input->stream_errno;
                dbox_file_set_syscall_error(file, "ftruncate()");
                ret = -1;
        } else if (ret < 0) {
-               mail_storage_set_critical(&file->storage->storage,
+               mail_storage_set_critical(storage,
                        "o_stream_send_istream(%s, %s) "
                        "failed with unknown error",
                        temp_path, file->cur_path);
        }
        o_stream_unref(&output);
 
-       if (!file->storage->storage.set->fsync_disable && ret == 0) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER && ret == 0) {
                if (fsync(out_fd) < 0) {
-                       mail_storage_set_critical(&file->storage->storage,
+                       mail_storage_set_critical(storage,
                                "fsync(%s) failed: %m", temp_path);
                        ret = -1;
                }
        }
        if (close(out_fd) < 0) {
-               mail_storage_set_critical(&file->storage->storage,
+               mail_storage_set_critical(storage,
                        "close(%s) failed: %m", temp_path);
                ret = -1;
        }
@@ -752,14 +755,14 @@ int dbox_file_move(struct dbox_file *file, bool alt_path)
           destination file. the destination shouldn't exist, but if it does
           its contents should be the same (except for maybe older metadata) */
        if (rename(temp_path, dest_path) < 0) {
-               mail_storage_set_critical(&file->storage->storage,
+               mail_storage_set_critical(storage,
                        "rename(%s, %s) failed: %m", temp_path, dest_path);
                (void)unlink(temp_path);
                return -1;
        }
-       if (!file->storage->storage.set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync_path(dest_dir) < 0) {
-                       mail_storage_set_critical(&file->storage->storage,
+                       mail_storage_set_critical(storage,
                                "fdatasync(%s) failed: %m", dest_dir);
                        (void)unlink(dest_path);
                        return -1;
@@ -779,7 +782,7 @@ int dbox_file_move(struct dbox_file *file, bool alt_path)
        /* file was successfully moved - reopen it */
        dbox_file_close(file);
        if (dbox_file_open(file, &deleted) <= 0) {
-               mail_storage_set_critical(&file->storage->storage,
+               mail_storage_set_critical(storage,
                        "dbox_file_move(%s): reopening file failed", dest_path);
                return -1;
        }
index 046f638127338f011e09c5644e36f569b8b7615a..c831037847b6970d4e41e52413b5c47bc7fcd263 100644 (file)
@@ -57,6 +57,8 @@ mdbox_map_init(struct mdbox_storage *storage, struct mailbox_list *root_list,
        map->set = storage->set;
        map->path = i_strdup(path);
        map->index = mail_index_alloc(path, MDBOX_GLOBAL_INDEX_PREFIX);
+       mail_index_set_fsync_mode(map->index,
+               MAP_STORAGE(map)->set->parsed_fsync_mode, 0);
        mail_index_set_lock_method(map->index,
                MAP_STORAGE(map)->set->parsed_lock_method,
                mail_storage_get_lock_timeout(MAP_STORAGE(map), -1U));
index 0211d0c402ec9110b40d2e876b0331624db03b6f..87e3f1222fce5fe1fc2ca087d0bef86e40bf836c 100644 (file)
@@ -310,6 +310,7 @@ void mdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
                                        struct mail_index_transaction_commit_result *result)
 {
        struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
+       struct mail_storage *storage = _ctx->transaction->box->storage;
 
        _ctx->transaction = NULL; /* transaction is already freed */
 
@@ -326,9 +327,10 @@ void mdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
        }
        mdbox_map_append_free(&ctx->append_ctx);
 
-       if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync_path(ctx->mbox->box.path) < 0) {
-                       i_error("fdatasync_path(%s) failed: %m",
+                       mail_storage_set_critical(storage,
+                               "fdatasync_path(%s) failed: %m",
                                ctx->mbox->box.path);
                }
        }
index 12148f3697fc626b3aad4d48ecfc0ca084a7d4df..cb727b3e2d5aaef25aa241c82f7f60ea67d06d28 100644 (file)
@@ -99,9 +99,10 @@ mdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.mail_vfuncs = &mdbox_mail_vfuncs;
 
        index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
-       mail_index_set_fsync_types(mbox->box.index,
-                                  MAIL_INDEX_SYNC_TYPE_APPEND |
-                                  MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+       mail_index_set_fsync_mode(mbox->box.index,
+                                 storage->set->parsed_fsync_mode,
+                                 MAIL_INDEX_SYNC_TYPE_APPEND |
+                                 MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = mdbox_transaction_save_commit_pre;
index 1ff094caa1ed0430ce3a092a3b9d8475091fd568..491fe6267f38f98e898ff7b65b51fcb15d0442e2 100644 (file)
@@ -266,6 +266,7 @@ void sdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
                                        struct mail_index_transaction_commit_result *result)
 {
        struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
+       struct mail_storage *storage = _ctx->transaction->box->storage;
 
        _ctx->transaction = NULL; /* transaction is already freed */
 
@@ -280,9 +281,10 @@ void sdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
        if (sdbox_sync_finish(&ctx->sync_ctx, TRUE) < 0)
                ctx->ctx.failed = TRUE;
 
-       if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync_path(ctx->mbox->box.path) < 0) {
-                       i_error("fdatasync_path(%s) failed: %m",
+                       mail_storage_set_critical(storage,
+                               "fdatasync_path(%s) failed: %m",
                                ctx->mbox->box.path);
                }
        }
index 4150c60bd8b11bae93316bf8176fde95bd07e332..3d5ea02c685623dc809efe3b90dd01e3487c2d12 100644 (file)
@@ -62,9 +62,10 @@ sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.mail_vfuncs = &sdbox_mail_vfuncs;
 
        index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
-       mail_index_set_fsync_types(mbox->box.index,
-                                  MAIL_INDEX_SYNC_TYPE_APPEND |
-                                  MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+       mail_index_set_fsync_mode(mbox->box.index,
+                                 storage->set->parsed_fsync_mode,
+                                 MAIL_INDEX_SYNC_TYPE_APPEND |
+                                 MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = sdbox_transaction_save_commit_pre;
index ca67f08479125f5d172e1b4febd9b5c5a87f60e4..356cd799a2156eb7e4f6e731c095668f8b57a434 100644 (file)
@@ -287,6 +287,8 @@ void index_storage_mailbox_alloc(struct mailbox *box, const char *name,
        mail_index_set_permissions(box->index, box->file_create_mode,
                                   box->file_create_gid,
                                   box->file_create_gid_origin);
+       mail_index_set_fsync_mode(box->index,
+                                 box->storage->set->parsed_fsync_mode, 0);
        mail_index_set_lock_method(box->index,
                box->storage->set->parsed_lock_method,
                mail_storage_get_lock_timeout(box->storage, -1U));
index 163e5f7681cdad85dcc6d36d4eac2b251c82af2f..2f715d9d3f9af5abee1be9a149af4d9db57ce771 100644 (file)
@@ -549,7 +549,8 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx)
        output_errno = _ctx->output->stream_errno;
        o_stream_destroy(&_ctx->output);
 
-       if (!storage->set->fsync_disable && !ctx->failed) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER &&
+           !ctx->failed) {
                if (fsync(ctx->fd) < 0) {
                        if (!mail_storage_set_error_from_errno(storage)) {
                                mail_storage_set_critical(storage,
@@ -675,7 +676,7 @@ static int maildir_transaction_fsync_dirs(struct maildir_save_context *ctx,
 {
        struct mail_storage *storage = &ctx->mbox->storage->storage;
 
-       if (storage->set->fsync_disable)
+       if (storage->set->parsed_fsync_mode == FSYNC_MODE_NEVER)
                return 0;
 
        if (new_changed) {
index d373e98ef9c5b7c1fae203b7b1b568e3575a1b16..d5fc2531161e9986c037baf2022663d9cf63530c 100644 (file)
@@ -1296,7 +1296,7 @@ static int maildir_uidlist_write_fd(struct maildir_uidlist *uidlist, int fd,
                return -1;
        }
 
-       if (!storage->set->fsync_disable) {
+       if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync(fd) < 0) {
                        mail_storage_set_critical(storage,
                                "fdatasync(%s) failed: %m", path);
index f9a3891489635fd6bb32eb4e5825d5ae78348165..9911ec4bb26b29aa1e1b1fbff7617761418966d7 100644 (file)
@@ -781,7 +781,7 @@ int mbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
                o_stream_flush(ctx->output);
        }
        if (mbox->mbox_fd != -1 && !mbox->mbox_writeonly &&
-           !mbox->storage->storage.set->fsync_disable) {
+           mbox->storage->storage.set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
                if (fdatasync(mbox->mbox_fd) < 0) {
                        mbox_set_syscall_error(mbox, "fdatasync()");
                        mbox_save_truncate(ctx);
index f58f2699aad41dbe45c84c9e00c6e5f357af04c4..d67df15623541412c948cdd9771c01316680778d 100644 (file)
@@ -30,7 +30,7 @@ static const struct setting_define mail_storage_setting_defines[] = {
        DEF(SET_UINT, mail_max_keyword_length),
        DEF(SET_TIME, mail_max_lock_timeout),
        DEF(SET_BOOL, mail_save_crlf),
-       DEF(SET_BOOL, fsync_disable),
+       DEF(SET_ENUM, mail_fsync),
        DEF(SET_BOOL, mmap_disable),
        DEF(SET_BOOL, dotlock_use_excl),
        DEF(SET_BOOL, mail_nfs_storage),
@@ -54,7 +54,7 @@ const struct mail_storage_settings mail_storage_default_settings = {
        .mail_max_keyword_length = 50,
        .mail_max_lock_timeout = 0,
        .mail_save_crlf = FALSE,
-       .fsync_disable = FALSE,
+       .mail_fsync = "optimized:never:always",
        .mmap_disable = FALSE,
        .dotlock_use_excl = FALSE,
        .mail_nfs_storage = FALSE,
@@ -239,8 +239,6 @@ mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
 {
        enum mail_index_open_flags index_flags = 0;
 
-       if (set->fsync_disable)
-               index_flags |= MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE;
 #ifndef MMAP_CONFLICTS_WRITE
        if (set->mmap_disable)
 #endif
@@ -291,12 +289,25 @@ static bool mail_storage_settings_check(void *_set, pool_t pool ATTR_UNUSED,
        bool uidl_format_ok;
        char c;
 
+       if (strcmp(set->mail_fsync, "optimized") == 0)
+               set->parsed_fsync_mode = FSYNC_MODE_OPTIMIZED;
+       else if (strcmp(set->mail_fsync, "never") == 0)
+               set->parsed_fsync_mode = FSYNC_MODE_NEVER;
+       else if (strcmp(set->mail_fsync, "always") == 0)
+               set->parsed_fsync_mode = FSYNC_MODE_ALWAYS;
+       else {
+               *error_r = t_strdup_printf("Unknown mail_fsync: %s",
+                                          set->mail_fsync);
+               return FALSE;
+       }
+
        if (set->mail_nfs_index && !set->mmap_disable) {
                *error_r = "mail_nfs_index=yes requires mmap_disable=yes";
                return FALSE;
        }
-       if (set->mail_nfs_index && set->fsync_disable) {
-               *error_r = "mail_nfs_index=yes requires fsync_disable=no";
+       if (set->mail_nfs_index &&
+           set->parsed_fsync_mode != FSYNC_MODE_ALWAYS) {
+               *error_r = "mail_nfs_index=yes requires mail_fsync=always";
                return FALSE;
        }
 
index c4465fb617aa8a4f0b07c351f07df2e8c510fa68..aeb6b36ef12be98f27903353059cf58674c7b843 100644 (file)
@@ -2,6 +2,7 @@
 #define MAIL_STORAGE_SETTINGS_H
 
 #include "file-lock.h"
+#include "fsync-mode.h"
 
 #define MAIL_STORAGE_SET_DRIVER_NAME "MAIL"
 
@@ -17,7 +18,7 @@ struct mail_storage_settings {
        unsigned int mail_max_keyword_length;
        unsigned int mail_max_lock_timeout;
        bool mail_save_crlf;
-       bool fsync_disable;
+       const char *mail_fsync;
        bool mmap_disable;
        bool dotlock_use_excl;
        bool mail_nfs_storage;
@@ -30,6 +31,7 @@ struct mail_storage_settings {
        const char *pop3_uidl_format;
 
        enum file_lock_method parsed_lock_method;
+       enum fsync_mode parsed_fsync_mode;
 };
 
 struct mail_namespace_settings {
index 78f626f80c32e4ef180b1b5e65e4fc9ad6fcc925..61754327b72e3f07c98a1671727936ebf4c6e0a0 100644 (file)
@@ -144,6 +144,7 @@ headers = \
        file-dotlock.h \
        file-lock.h \
        file-set-size.h \
+       fsync-mode.h \
        hash.h \
        hash2.h \
        hex-binary.h \
diff --git a/src/lib/fsync-mode.h b/src/lib/fsync-mode.h
new file mode 100644 (file)
index 0000000..5873614
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef FSYNC_MODE_H
+#define FSYNC_MODE_H
+
+enum fsync_mode {
+       /* fsync when it's necessary for data safety. */
+       FSYNC_MODE_OPTIMIZED = 0,
+       /* never fsync (in case of a crash can lose data) */
+       FSYNC_MODE_NEVER,
+       /* fsync after all writes. this is necessary with NFS to avoid
+          write failures being delayed until file is close(). */
+       FSYNC_MODE_ALWAYS
+};
+
+#endif