dovecot: Keep better track of when we need to flush NFS attribut...

dovecot at dovecot.org dovecot at dovecot.org
Thu Nov 15 03:15:24 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/ba58eaf06763
changeset: 6802:ba58eaf06763
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Nov 15 03:15:18 2007 +0200
description:
Keep better track of when we need to flush NFS attribute caches.

diffstat:

4 files changed, 50 insertions(+), 14 deletions(-)
src/lib-index/mail-transaction-log-file.c    |   26 +++++++++++++++++++++++++-
src/lib-index/mail-transaction-log-private.h |    2 +-
src/lib-index/mail-transaction-log-view.c    |   12 ++++++++----
src/lib-index/mail-transaction-log.c         |   24 ++++++++++++++++--------

diffs (146 lines):

diff -r 6a5540e5a464 -r ba58eaf06763 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c	Thu Nov 15 02:04:21 2007 +0200
+++ b/src/lib-index/mail-transaction-log-file.c	Thu Nov 15 03:15:18 2007 +0200
@@ -885,6 +885,29 @@ mail_transaction_log_file_read_more(stru
 	return 1;
 }
 
+static bool
+mail_transaction_log_file_need_nfs_flush(struct mail_transaction_log_file *file)
+{
+	const struct mail_index_header *hdr = &file->log->index->map->hdr;
+
+	if (file->locked)
+		return TRUE;
+
+	if (file->next != NULL &&
+	    file->hdr.file_seq == file->next->hdr.prev_file_seq &&
+	    file->next->hdr.prev_file_offset != file->sync_offset) {
+		/* we already have a newer log file which says that we haven't
+		   synced the entire file. */
+		return TRUE;
+	}
+
+	if (file->hdr.file_seq == hdr->log_file_seq &&
+	    file->sync_offset < hdr->log_file_head_offset)
+		return TRUE;
+
+	return FALSE;
+}
+
 static int
 mail_transaction_log_file_read(struct mail_transaction_log_file *file,
 			       uoff_t start_offset)
@@ -893,7 +916,8 @@ mail_transaction_log_file_read(struct ma
 
 	i_assert(file->mmap_base == NULL);
 
-	if (file->log->index->nfs_flush && file->locked) {
+	if (file->log->index->nfs_flush &&
+	    mail_transaction_log_file_need_nfs_flush(file)) {
 		/* Make sure we know the latest file size */
 		nfs_flush_attr_cache_fd(file->filepath, file->fd);
 	}
diff -r 6a5540e5a464 -r ba58eaf06763 src/lib-index/mail-transaction-log-private.h
--- a/src/lib-index/mail-transaction-log-private.h	Thu Nov 15 02:04:21 2007 +0200
+++ b/src/lib-index/mail-transaction-log-private.h	Thu Nov 15 03:15:18 2007 +0200
@@ -93,7 +93,7 @@ int mail_transaction_log_file_lock(struc
 int mail_transaction_log_file_lock(struct mail_transaction_log_file *file);
 
 int mail_transaction_log_find_file(struct mail_transaction_log *log,
-				   uint32_t file_seq,
+				   uint32_t file_seq, bool nfs_flush,
 				   struct mail_transaction_log_file **file_r);
 
 /* Returns 1 if ok, 0 if file is corrupted or offset range is invalid,
diff -r 6a5540e5a464 -r ba58eaf06763 src/lib-index/mail-transaction-log-view.c
--- a/src/lib-index/mail-transaction-log-view.c	Thu Nov 15 02:04:21 2007 +0200
+++ b/src/lib-index/mail-transaction-log-view.c	Thu Nov 15 03:15:18 2007 +0200
@@ -152,9 +152,13 @@ int mail_transaction_log_view_set(struct
 	view->tail = view->head = file = NULL;
 	for (seq = min_file_seq; seq <= max_file_seq; seq++) {
 		if (file == NULL || file->hdr.file_seq != seq) {
-			/* see if we could find the missing file */
-			ret = mail_transaction_log_find_file(view->log,
-							     seq, &file);
+			/* see if we could find the missing file. if we know
+			   the max. file sequence, make sure NFS attribute
+			   cache gets flushed if necessary. */
+			bool nfs_flush = max_file_seq != (uint32_t)-1;
+
+			ret = mail_transaction_log_find_file(view->log, seq,
+							     nfs_flush, &file);
 			if (ret <= 0) {
 				if (ret < 0)
 					return -1;
@@ -284,7 +288,7 @@ void mail_transaction_log_view_clear(str
 	struct mail_transaction_log_file *file;
 
 	mail_transaction_log_view_unref_all(view);
-	if (mail_transaction_log_find_file(view->log, oldest_file_seq,
+	if (mail_transaction_log_find_file(view->log, oldest_file_seq, FALSE,
 					   &file) > 0) {
 		array_append(&view->file_refs, &file, 1);
 		file->refcount++;
diff -r 6a5540e5a464 -r ba58eaf06763 src/lib-index/mail-transaction-log.c
--- a/src/lib-index/mail-transaction-log.c	Thu Nov 15 02:04:21 2007 +0200
+++ b/src/lib-index/mail-transaction-log.c	Thu Nov 15 03:15:18 2007 +0200
@@ -265,7 +265,8 @@ int mail_transaction_log_rotate(struct m
 	return 0;
 }
 
-static int mail_transaction_log_refresh(struct mail_transaction_log *log)
+static int
+mail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush)
 {
         struct mail_transaction_log_file *file;
 	struct stat st;
@@ -278,7 +279,7 @@ static int mail_transaction_log_refresh(
 
 	path = t_strconcat(log->index->filepath,
 			   MAIL_TRANSACTION_LOG_SUFFIX, NULL);
-	if (log->index->nfs_flush && log->head->locked)
+	if (log->index->nfs_flush && nfs_flush)
 		nfs_flush_attr_cache(path, TRUE);
 	if (nfs_safe_stat(path, &st) < 0) {
 		if (errno != ENOENT) {
@@ -345,7 +346,7 @@ void mail_transaction_log_set_mailbox_sy
 }
 
 int mail_transaction_log_find_file(struct mail_transaction_log *log,
-				   uint32_t file_seq,
+				   uint32_t file_seq, bool nfs_flush,
 				   struct mail_transaction_log_file **file_r)
 {
 	struct mail_transaction_log_file *file;
@@ -360,10 +361,17 @@ int mail_transaction_log_find_file(struc
 			return 0;
 		}
 
-		if (mail_transaction_log_refresh(log) < 0)
-			return -1;
-		if (file_seq > log->head->hdr.file_seq)
-			return 0;
+		if (mail_transaction_log_refresh(log, FALSE) < 0)
+			return -1;
+		if (file_seq > log->head->hdr.file_seq) {
+			if (!nfs_flush || !log->index->nfs_flush)
+				return 0;
+			/* try again, this time flush attribute cache */
+			if (mail_transaction_log_refresh(log, TRUE) < 0)
+				return -1;
+			if (file_seq > log->head->hdr.file_seq)
+				return 0;
+		}
 	}
 
 	for (file = log->files; file != NULL; file = file->next) {
@@ -410,7 +418,7 @@ int mail_transaction_log_lock_head(struc
 			return -1;
 
 		file->refcount++;
-		ret = mail_transaction_log_refresh(log);
+		ret = mail_transaction_log_refresh(log, TRUE);
 		if (--file->refcount == 0) {
 			mail_transaction_logs_clean(log);
 			file = NULL;


More information about the dovecot-cvs mailing list