dovecot: Handle partial reads with mmap_disable=no correctly.

dovecot at dovecot.org dovecot at dovecot.org
Wed Jun 20 20:49:58 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/2a05cff7eca4
changeset: 5791:2a05cff7eca4
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jun 20 20:49:51 2007 +0300
description:
Handle partial reads with mmap_disable=no correctly.

diffstat:

1 file changed, 26 insertions(+), 23 deletions(-)
src/lib-index/mail-transaction-log-file.c |   49 +++++++++++++++--------------

diffs (72 lines):

diff -r e1347a122140 -r 2a05cff7eca4 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c	Wed Jun 20 16:22:48 2007 +0300
+++ b/src/lib-index/mail-transaction-log-file.c	Wed Jun 20 20:49:51 2007 +0300
@@ -723,16 +723,20 @@ mail_transaction_log_file_sync(struct ma
 				return -1;
 		}
 		file->sync_offset += trans_size;
+		trans_size = 0;
 	}
 
 	avail = file->sync_offset - file->buffer_offset;
-	if (avail != size && avail >= sizeof(*hdr)) {
-		/* Record goes outside the file we've seen. Unless we're
-		   locked, we can't know if this is expected or not. Even when
-		   we're read()ing the file, the kernel (at least Linux 2.6)
-		   can show the last read memory page updated, but without the
-		   expected next page. */
-		if (file->locked) {
+	if (avail != size) {
+		/* There's more data than we could sync at the moment. If the
+		   last record's size wasn't valid, we can't know if it will
+		   be updated unless we've locked the log.
+
+		   Without locking we can be sure only if we're not using
+		   mmaping, because with mmaping the data and the file size
+		   can get updated at any time. */
+		if (file->locked ||
+		    (trans_size != 0 && file->mmap_base == NULL)) {
 			if (trans_size != 0) {
 				mail_transaction_log_file_set_corrupted(file,
 					"hdr.size too large (%u)", trans_size);
@@ -822,25 +826,24 @@ mail_transaction_log_file_read(struct ma
 
 	file->last_size = read_offset;
 
+	if (ret < 0) {
+		if (errno == ESTALE) {
+			/* log file was deleted in NFS server, fail silently */
+			return 0;
+		}
+
+		mail_index_file_set_syscall_error(file->log->index,
+						  file->filepath, "pread()");
+		return -1;
+	}
+
 	if (mail_transaction_log_file_sync(file) < 0)
 		return 0;
 
-	if (ret == 0) {
-		/* EOF */
-		i_assert(file->sync_offset >= file->buffer_offset);
-		buffer_set_used_size(file->buffer,
-				     file->sync_offset - file->buffer_offset);
-		return 1;
-	}
-
-	if (errno == ESTALE) {
-		/* log file was deleted in NFS server, fail silently */
-		return 0;
-	}
-
-	mail_index_file_set_syscall_error(file->log->index, file->filepath,
-					  "pread()");
-	return -1;
+	i_assert(file->sync_offset >= file->buffer_offset);
+	buffer_set_used_size(file->buffer,
+			     file->sync_offset - file->buffer_offset);
+	return 1;
 }
 
 static int


More information about the dovecot-cvs mailing list