Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5972:9fb9dc4d8df8 HEAD
Flush NFS caches when needed if MAIL_INDEX_OPEN_FLAG_NFS_FLUSH is enabled.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 12 Jul 2007 23:55:08 +0300 |
parents | 2bc25f61431f |
children | fe9da9c92cf4 |
files | src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache-sync-update.c src/lib-index/mail-cache.c src/lib-index/mail-hash.c src/lib-index/mail-index-lock.c src/lib-index/mail-index-map.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-file.c src/lib-index/mail-transaction-log.c src/lib-index/mailbox-list-index-sync.c src/lib-index/mailbox-list-index.c |
diffstat | 15 files changed, 179 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-compress.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-cache-compress.c Thu Jul 12 23:55:08 2007 +0300 @@ -257,6 +257,7 @@ return -1; } + mail_cache_flush_read_cache(cache, FALSE); ret = read_full(fd, &hdr, sizeof(hdr)); close_keep_errno(fd); @@ -287,6 +288,9 @@ unsigned int i, count; int fd, ret; + if (cache->fd != -1) + mail_cache_flush_read_cache(cache, TRUE); + /* get the latest info on fields */ if (mail_cache_header_fields_read(cache) < 0) return -1;
--- a/src/lib-index/mail-cache-private.h Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-cache-private.h Thu Jul 12 23:55:08 2007 +0300 @@ -200,6 +200,7 @@ /* Returns -1 if cache is / just got corrupted, 0 if ok. */ int mail_cache_unlock(struct mail_cache *cache); +void mail_cache_flush_read_cache(struct mail_cache *cache, bool just_locked); int mail_cache_write(struct mail_cache *cache, const void *data, size_t size, uoff_t offset);
--- a/src/lib-index/mail-cache-sync-update.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-cache-sync-update.c Thu Jul 12 23:55:08 2007 +0300 @@ -119,6 +119,7 @@ return 1; if (cache->file_cache != NULL) { + mail_cache_flush_read_cache(cache, FALSE); file_cache_invalidate(cache->file_cache, *new_cache_offset, (uoff_t)-1); } @@ -158,5 +159,6 @@ void mail_cache_sync_lost_handler(struct mail_index *index) { + mail_cache_flush_read_cache(index->cache, FALSE); file_cache_invalidate(index->cache->file_cache, 0, (uoff_t)-1); }
--- a/src/lib-index/mail-cache.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-cache.c Thu Jul 12 23:55:08 2007 +0300 @@ -77,6 +77,9 @@ if (cache->file_cache == NULL) return; + nfs_flush_attr_cache_fd(cache->filepath, cache->fd); + nfs_flush_read_cache(cache->filepath, cache->fd, F_UNLCK, FALSE); + file_cache_set_fd(cache->file_cache, cache->fd); if (fstat(cache->fd, &st) < 0) @@ -397,19 +400,44 @@ i_free(cache); } -static int mail_cache_lock_file(struct mail_cache *cache, int lock_type) +void mail_cache_flush_read_cache(struct mail_cache *cache, bool just_locked) { + if (!cache->index->nfs_flush) + return; + + /* Assume flock() is independent of fcntl() locks. This isn't true + with Linux 2.6 NFS, but with it there's no point in using flock() */ + if (cache->locked && + cache->index->lock_method == FILE_LOCK_METHOD_FCNTL) { + nfs_flush_read_cache(cache->filepath, cache->fd, + F_WRLCK, just_locked); + } else { + nfs_flush_read_cache(cache->filepath, cache->fd, + F_UNLCK, FALSE); + } +} + +static int mail_cache_lock_file(struct mail_cache *cache) +{ + int ret; + if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK) { i_assert(cache->file_lock == NULL); - return mail_index_lock_fd(cache->index, cache->filepath, - cache->fd, lock_type, - MAIL_INDEX_LOCK_SECS, - &cache->file_lock); + ret = mail_index_lock_fd(cache->index, cache->filepath, + cache->fd, F_WRLCK, + MAIL_INDEX_LOCK_SECS, + &cache->file_lock); } else { i_assert(cache->dotlock == NULL); - return file_dotlock_create(&cache->dotlock_settings, - cache->filepath, 0, &cache->dotlock); + ret = file_dotlock_create(&cache->dotlock_settings, + cache->filepath, 0, &cache->dotlock); } + + if (ret <= 0) + return ret; + + mail_cache_flush_read_cache(cache, TRUE); + return 1; } static void mail_cache_unlock_file(struct mail_cache *cache) @@ -454,7 +482,7 @@ } for (i = 0; i < 3; i++) { - ret = mail_cache_lock_file(cache, F_WRLCK); + ret = mail_cache_lock_file(cache); if (ret <= 0) break; cache->locked = TRUE; @@ -538,6 +566,11 @@ mail_cache_update_need_compress(cache); } + if (cache->index->nfs_flush) { + if (fdatasync(cache->fd) < 0) + mail_cache_set_syscall_error(cache, "fdatasync()"); + } + mail_cache_unlock_file(cache); return ret; }
--- a/src/lib-index/mail-hash.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-hash.c Thu Jul 12 23:55:08 2007 +0300 @@ -10,6 +10,7 @@ #include "read-full.h" #include "write-full.h" #include "mmap-util.h" +#include "nfs-workarounds.h" #include "mail-index-private.h" #include "mail-hash.h" @@ -273,6 +274,9 @@ hash->mmap_size = size; } + if (hash->index->nfs_flush) + nfs_flush_read_cache(hash->filepath, hash->fd, F_UNLCK, FALSE); + ret = pread_full(hash->fd, hash->mmap_base, size, 0); if (ret < 0) { mail_hash_set_syscall_error(hash, "pread_full()"); @@ -357,6 +361,9 @@ struct stat st; size_t size; + if (hash->index->nfs_flush) + nfs_flush_attr_cache_fd(hash->filepath, hash->fd); + if (fstat(hash->fd, &st) < 0) { mail_hash_set_syscall_error(hash, "fstat()"); return -1; @@ -644,7 +651,10 @@ if (hash->fd == -1) return mail_hash_reopen(hash); - if (stat(hash->filepath, &st) < 0) { + if (hash->index->nfs_flush) + nfs_flush_attr_cache(hash->filepath); + + if (nfs_safe_stat(hash->filepath, &st) < 0) { if (errno == ENOENT) return mail_hash_reopen(hash);
--- a/src/lib-index/mail-index-lock.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index-lock.c Thu Jul 12 23:55:08 2007 +0300 @@ -18,6 +18,7 @@ */ #include "lib.h" +#include "nfs-workarounds.h" #include "mail-index-private.h" int mail_index_lock_fd(struct mail_index *index, const char *path, int fd, @@ -117,13 +118,31 @@ return 1; } +static void mail_index_flush_read_cache(struct mail_index *index) +{ + if (!index->nfs_flush) + return; + + /* Assume flock() is independent of fcntl() locks. This isn't true + with Linux 2.6 NFS, but with it there's no point in using flock() */ + if (index->lock_method == FILE_LOCK_METHOD_FCNTL) { + nfs_flush_read_cache(index->filepath, index->fd, + index->lock_type, TRUE); + } else { + nfs_flush_read_cache(index->filepath, index->fd, + F_UNLCK, FALSE); + } +} + int mail_index_lock_shared(struct mail_index *index, unsigned int *lock_id_r) { int ret; ret = mail_index_lock(index, F_RDLCK, MAIL_INDEX_LOCK_SECS, lock_id_r); - if (ret > 0) + if (ret > 0) { + mail_index_flush_read_cache(index); return 0; + } if (ret < 0) return -1; @@ -137,7 +156,11 @@ int mail_index_try_lock_exclusive(struct mail_index *index, unsigned int *lock_id_r) { - return mail_index_lock(index, F_WRLCK, 0, lock_id_r); + int ret; + + if ((ret = mail_index_lock(index, F_WRLCK, 0, lock_id_r)) > 0) + mail_index_flush_read_cache(index); + return ret; } void mail_index_unlock(struct mail_index *index, unsigned int *_lock_id)
--- a/src/lib-index/mail-index-map.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index-map.c Thu Jul 12 23:55:08 2007 +0300 @@ -678,6 +678,9 @@ if (mail_index_lock_shared(index, &lock_id) < 0) return -1; + if (index->nfs_flush) + nfs_flush_attr_cache_fd(index->filepath, index->fd); + if (fstat(index->fd, &st) == 0) file_size = st.st_size; else {
--- a/src/lib-index/mail-index-private.h Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index-private.h Thu Jul 12 23:55:08 2007 +0300 @@ -200,6 +200,7 @@ unsigned int mmap_disable:1; unsigned int fsync_disable:1; unsigned int use_excl_dotlocks:1; + unsigned int nfs_flush:1; unsigned int readonly:1; unsigned int fsck:1; unsigned int mapping:1;
--- a/src/lib-index/mail-index-write.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index-write.c Thu Jul 12 23:55:08 2007 +0300 @@ -138,6 +138,7 @@ const struct mail_index_header *hdr = &map->hdr; struct stat st; unsigned int lock_id; + int ret; if (!mail_index_map_has_changed(map)) return; @@ -192,14 +193,23 @@ } } } else { - if (mail_index_write_map_over(index) < 0) { + ret = mail_index_write_map_over(index); + if (ret < 0) mail_index_set_syscall_error(index, "pwrite_full()"); + else if (index->nfs_flush) { + ret = fdatasync(index->fd); + if (ret < 0) { + mail_index_set_syscall_error(index, + "fdatasync()"); + } + } + mail_index_unlock(index, &lock_id); + + if (ret < 0) { /* hopefully didn't break badly */ - mail_index_unlock(index, &lock_id); mail_index_move_to_memory(index); return; } - mail_index_unlock(index, &lock_id); } index->last_read_log_file_seq = hdr->log_file_seq;
--- a/src/lib-index/mail-index.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index.c Thu Jul 12 23:55:08 2007 +0300 @@ -475,8 +475,21 @@ (flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0; index->fsync_disable = (flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0; + index->nfs_flush = + (flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0; index->lock_method = lock_method; + if (index->nfs_flush && index->fsync_disable) { + i_warning("nfs_flush_cache=yes requires " + "fsync_disable=no, changing it"); + index->fsync_disable = FALSE; + } + if (index->nfs_flush && !index->mmap_disable) { + i_warning("nfs_flush_cache=yes requires " + "mmap_disable=yes, changing it"); + index->mmap_disable = TRUE; + } + i_assert(!index->opened); if (!mail_index_open_files(index, flags)) { /* doesn't exist and create flag not used */ @@ -560,6 +573,9 @@ /* deleted/recreated, reopen */ return mail_index_try_open_only(index); } + + if (index->nfs_flush) + nfs_flush_attr_cache(index->filepath); if (nfs_safe_stat(index->filepath, &st2) < 0) { if (errno == ENOENT) return 0;
--- a/src/lib-index/mail-index.h Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-index.h Thu Jul 12 23:55:08 2007 +0300 @@ -19,7 +19,9 @@ /* 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 + MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE = 0x20, + /* Flush NFS attr/data/write cache when necessary */ + MAIL_INDEX_OPEN_FLAG_NFS_FLUSH = 0x40, }; enum mail_index_header_compat_flags {
--- a/src/lib-index/mail-transaction-log-file.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-transaction-log-file.c Thu Jul 12 23:55:08 2007 +0300 @@ -434,6 +434,9 @@ int fd, ret; bool rename_existing; + if (index->nfs_flush) + nfs_flush_attr_cache(file->filepath); + /* log creation is locked now - see if someone already created it. note that if we're rotating, we need to keep the log locked until the file has been rewritten. and because fcntl() locks are stupid, @@ -498,6 +501,16 @@ return -1; } + if (index->nfs_flush) { + /* the header isn't important, so don't bother calling + fdatasync() unless NFS is used */ + if (fdatasync(new_fd) < 0) { + mail_index_file_set_syscall_error(index, file->filepath, + "fdatasync()"); + return -1; + } + } + file->fd = new_fd; ret = mail_transaction_log_file_stat(file, FALSE); @@ -782,7 +795,12 @@ } return -1; } - // FIXME: here we probably want to flush NFS data cache + + if (file->log->index->nfs_flush) { + /* The size field will be updated soon */ + nfs_flush_read_cache(file->filepath, file->fd, + F_UNLCK, FALSE); + } } if (file->next != NULL && @@ -845,6 +863,11 @@ i_assert(file->mmap_base == NULL); + if (file->log->index->nfs_flush) { + /* Make sure we know the latest file size */ + nfs_flush_attr_cache_fd(file->filepath, file->fd); + } + if (file->buffer != NULL && file->buffer_offset > start_offset) { /* we have to insert missing data to beginning of buffer */ ret = mail_transaction_log_file_insert_read(file, start_offset);
--- a/src/lib-index/mail-transaction-log.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mail-transaction-log.c Thu Jul 12 23:55:08 2007 +0300 @@ -269,6 +269,8 @@ path = t_strconcat(log->index->filepath, MAIL_TRANSACTION_LOG_SUFFIX, NULL); + if (log->index->nfs_flush) + nfs_flush_attr_cache(path); if (nfs_safe_stat(path, &st) < 0) { if (errno != ENOENT) { mail_index_file_set_syscall_error(log->index, path,
--- a/src/lib-index/mailbox-list-index-sync.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mailbox-list-index-sync.c Thu Jul 12 23:55:08 2007 +0300 @@ -336,6 +336,11 @@ 0) < 0) return -1; + if (ctx->index->mail_index->nfs_flush) { + nfs_flush_read_cache(ctx->index->filepath, ctx->index->fd, + F_UNLCK, FALSE); + } + /* we should have only external transactions in here, for which we don't need to do anything but write them to the index */ while (mail_index_sync_next(ctx->mail_sync_ctx, &sync_rec) > 0) @@ -825,6 +830,18 @@ o_stream_send(ctx->output, &ctx->hdr, sizeof(ctx->hdr)); } + if (o_stream_flush(ctx->output) < 0) { + mailbox_list_index_set_syscall_error(ctx->index, + "o_stream_flush()"); + ret = -1; + } + if (ret == 0 && ctx->index->mail_index->nfs_flush && + fdatasync(ctx->index->fd) < 0) { + mailbox_list_index_set_syscall_error(ctx->index, + "fdatasync()"); + ret = -1; + } + o_stream_destroy(&ctx->output); buffer_free(ctx->output_buf); }
--- a/src/lib-index/mailbox-list-index.c Thu Jul 12 23:54:34 2007 +0300 +++ b/src/lib-index/mailbox-list-index.c Thu Jul 12 23:55:08 2007 +0300 @@ -9,6 +9,7 @@ #include "file-dotlock.h" #include "mmap-util.h" #include "write-full.h" +#include "nfs-workarounds.h" #include "mail-index-private.h" #include "mailbox-list-index-private.h" @@ -61,6 +62,11 @@ static void mailbox_list_index_unmap(struct mailbox_list_index *index) { + if (index->mail_index->nfs_flush && index->fd != -1) { + nfs_flush_read_cache(index->filepath, index->fd, + F_UNLCK, FALSE); + } + if (index->file_cache != NULL) file_cache_invalidate(index->file_cache, 0, (uoff_t)-1); @@ -224,7 +230,10 @@ if (index->fd == -1) return 1; - if (stat(index->filepath, &st1) < 0) { + if (index->mail_index->nfs_flush) + nfs_flush_attr_cache(index->filepath); + + if (nfs_safe_stat(index->filepath, &st1) < 0) { if (errno == ENOENT) return 1; @@ -272,6 +281,12 @@ return -1; } + if (index->mail_index->nfs_flush && fdatasync(fd) < 0) { + mailbox_list_index_set_syscall_error(index, "fdatasync()"); + (void)file_dotlock_delete(&dotlock); + return -1; + } + if (file_dotlock_replace(&dotlock, DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) { mailbox_list_index_set_syscall_error(index,