dovecot: Flush NFS caches when needed if MAIL_INDEX_OPEN_FLAG_NF...

dovecot at dovecot.org dovecot at dovecot.org
Fri Jul 13 00:18:32 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/9fb9dc4d8df8
changeset: 5972:9fb9dc4d8df8
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jul 12 23:55:08 2007 +0300
description:
Flush NFS caches when needed if MAIL_INDEX_OPEN_FLAG_NFS_FLUSH is enabled.

diffstat:

15 files changed, 181 insertions(+), 19 deletions(-)
src/lib-index/mail-cache-compress.c       |    4 ++
src/lib-index/mail-cache-private.h        |    1 
src/lib-index/mail-cache-sync-update.c    |    2 +
src/lib-index/mail-cache.c                |   53 +++++++++++++++++++++++------
src/lib-index/mail-hash.c                 |   12 ++++++
src/lib-index/mail-index-lock.c           |   27 +++++++++++++-
src/lib-index/mail-index-map.c            |    3 +
src/lib-index/mail-index-private.h        |    1 
src/lib-index/mail-index-write.c          |   16 +++++++-
src/lib-index/mail-index.c                |   16 ++++++++
src/lib-index/mail-index.h                |    4 +-
src/lib-index/mail-transaction-log-file.c |   25 +++++++++++++
src/lib-index/mail-transaction-log.c      |    2 +
src/lib-index/mailbox-list-index-sync.c   |   17 +++++++++
src/lib-index/mailbox-list-index.c        |   17 ++++++++-

diffs (truncated from 498 to 300 lines):

diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-cache-compress.c
--- 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 @@ static int mail_cache_compress_has_file_
 			return -1;
 		}
 
+		mail_cache_flush_read_cache(cache, FALSE);
 		ret = read_full(fd, &hdr, sizeof(hdr));
 		close_keep_errno(fd);
 
@@ -286,6 +287,9 @@ static int mail_cache_compress_locked(st
 	const uint32_t *offsets;
 	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)
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-cache-private.h
--- 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 @@ int mail_cache_lock(struct mail_cache *c
 /* 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);
 
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-cache-sync-update.c
--- 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 @@ int mail_cache_sync_handler(struct mail_
 		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 @@ int mail_cache_sync_handler(struct mail_
 
 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);
 }
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-cache.c
--- 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
@@ -76,6 +76,9 @@ static void mail_cache_init_file_cache(s
 
 	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);
 
@@ -397,19 +400,44 @@ void mail_cache_free(struct mail_cache *
 	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 @@ int mail_cache_lock(struct mail_cache *c
 	}
 
 	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;
@@ -536,6 +564,11 @@ int mail_cache_unlock(struct mail_cache 
 				     sizeof(cache->hdr_copy), 0) < 0)
 			ret = -1;
 		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);
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-hash.c
--- 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 @@ static int mail_hash_file_read(struct ma
 		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()");
@@ -356,6 +360,9 @@ static int mail_hash_file_map(struct mai
 {
 	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()");
@@ -644,7 +651,10 @@ static int mail_hash_reopen_if_needed(st
 	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);
 
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-index-lock.c
--- 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 @@ static int mail_index_lock(struct mail_i
 	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
 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)
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-index-map.c
--- 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 @@ static int mail_index_map_latest_file(st
 	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 {
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-index-private.h
--- 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 @@ struct mail_index {
 	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;
diff -r 2bc25f61431f -r 9fb9dc4d8df8 src/lib-index/mail-index-write.c
--- 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 @@ void mail_index_write(struct mail_index 
 	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 @@ void mail_index_write(struct mail_index 
 			}
 		}
 	} 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;


More information about the dovecot-cvs mailing list