dovecot: mmap_disable=yes: Find the latest cache field header by...

dovecot at dovecot.org dovecot at dovecot.org
Tue Nov 6 20:49:49 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/b0e8403b4bb1
changeset: 6704:b0e8403b4bb1
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Nov 06 20:49:45 2007 +0200
description:
mmap_disable=yes: Find the latest cache field header by pread()ing the file
instead of invalidating+reading full pages.

diffstat:

1 file changed, 42 insertions(+), 41 deletions(-)
src/lib-index/mail-cache-fields.c |   83 ++++++++++++++++++-------------------

diffs (150 lines):

diff -r 75c48f171ad3 -r b0e8403b4bb1 src/lib-index/mail-cache-fields.c
--- a/src/lib-index/mail-cache-fields.c	Tue Nov 06 20:28:01 2007 +0200
+++ b/src/lib-index/mail-cache-fields.c	Tue Nov 06 20:49:45 2007 +0200
@@ -4,13 +4,12 @@
 #include "buffer.h"
 #include "hash.h"
 #include "file-cache.h"
+#include "read-full.h"
 #include "write-full.h"
 #include "mmap-util.h"
 #include "mail-cache-private.h"
 
 #include <stddef.h>
-
-#define CACHE_HDR_PREFETCH 1024
 
 #define CACHE_FIELD_IS_NEWLY_WANTED(cache, field_idx) \
 	((cache)->field_file_map[field_idx] == (uint32_t)-1 && \
@@ -166,14 +165,13 @@ mail_cache_register_get_list(struct mail
 }
 
 static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
-					       uint32_t *offset_r)
-{
-	const size_t page_size = mmap_get_page_size();
+					       uint32_t *offset_r, bool map)
+{
 	const struct mail_cache_header_fields *field_hdr;
-	const unsigned int size = sizeof(*field_hdr) + CACHE_HDR_PREFETCH;
+	struct mail_cache_header_fields tmp_field_hdr;
 	uint32_t offset, next_offset;
-	uoff_t invalid_start = 0, invalid_end = 0;
 	unsigned int next_count = 0;
+	int ret;
 
 	if (MAIL_CACHE_IS_UNUSABLE(cache)) {
 		*offset_r = 0;
@@ -192,27 +190,30 @@ static int mail_cache_header_fields_get_
 		}
 		offset = next_offset;
 
-		if (offset < invalid_start && cache->file_cache != NULL) {
-			uoff_t new_start = offset;
-
-			new_start &= ~(page_size-1);
-			file_cache_invalidate(cache->file_cache,
-					      new_start, invalid_start);
-			invalid_start = new_start;
-		}
-		if (offset + size > invalid_end && cache->file_cache != NULL) {
-			uoff_t new_size = invalid_end - invalid_start + size;
-
-			new_size = (new_size + page_size-1) & ~(page_size - 1);
-			file_cache_invalidate(cache->file_cache,
-					      invalid_end, new_size);
-			invalid_end = offset + new_size;
-		}
-
-		if (mail_cache_map(cache, offset, size) < 0)
-			return -1;
-
-		field_hdr = CONST_PTR_OFFSET(cache->data, offset);
+		if (cache->mmap_base != NULL) {
+			if (mail_cache_map(cache, offset,
+					   sizeof(*field_hdr)) < 0)
+				return -1;
+
+			field_hdr = CONST_PTR_OFFSET(cache->data, offset);
+		} else {
+			/* if we need to follow multiple offsets to get to
+			   the last one, it's faster to just pread() the file
+			   instead of going through cache */
+			ret = pread_full(cache->fd, &tmp_field_hdr,
+					 sizeof(tmp_field_hdr), offset);
+			if (ret < 0) {
+				mail_cache_set_syscall_error(cache, "pread()");
+				return -1;
+			}
+			if (ret == 0) {
+				mail_cache_set_corrupted(cache,
+					"next_offset points outside file");
+				return -1;
+			}
+			field_hdr = &tmp_field_hdr;
+		}
+
 		next_offset =
 			mail_index_offset_to_uint32(field_hdr->next_offset);
 		next_count++;
@@ -220,6 +221,16 @@ static int mail_cache_header_fields_get_
 
 	if (next_count > MAIL_CACHE_HEADER_FIELD_CONTINUE_COUNT)
 		cache->need_compress_file_seq = cache->hdr->file_seq;
+
+	if (map) {
+		if (cache->file_cache != NULL) {
+			/* we can't trust that the cached data is valid */
+			file_cache_invalidate(cache->file_cache, offset,
+					      field_hdr->size);
+		}
+		if (mail_cache_map(cache, offset, field_hdr->size) < 0)
+			return -1;
+	}
 
 	*offset_r = offset;
 	return 0;
@@ -237,7 +248,7 @@ int mail_cache_header_fields_read(struct
 	time_t max_drop_time;
 	uint32_t offset, i;
 
-	if (mail_cache_header_fields_get_offset(cache, &offset) < 0)
+	if (mail_cache_header_fields_get_offset(cache, &offset, TRUE) < 0)
 		return -1;
 
 	if (offset == 0) {
@@ -260,16 +271,6 @@ int mail_cache_header_fields_read(struct
 		return -1;
 	}
 
-	if (field_hdr->size > sizeof(*field_hdr) + CACHE_HDR_PREFETCH) {
-		if (cache->file_cache != NULL) {
-			/* we can't trust that the cached data is valid */
-			file_cache_invalidate(cache->file_cache, offset,
-					      sizeof(*field_hdr) +
-					      CACHE_HDR_PREFETCH);
-		}
-		if (mail_cache_map(cache, offset, field_hdr->size) < 0)
-			return -1;
-	}
 	field_hdr = CONST_PTR_OFFSET(cache->data, offset);
 	new_fields_count = field_hdr->fields_count;
 
@@ -421,7 +422,7 @@ static int mail_cache_header_fields_upda
 	int ret = 0;
 
 	if (mail_cache_header_fields_read(cache) < 0 ||
-	    mail_cache_header_fields_get_offset(cache, &offset) < 0)
+	    mail_cache_header_fields_get_offset(cache, &offset, FALSE) < 0)
 		return -1;
 
 	t_push();
@@ -524,7 +525,7 @@ int mail_cache_header_fields_get_next_of
 int mail_cache_header_fields_get_next_offset(struct mail_cache *cache,
 					     uint32_t *offset_r)
 {
-	if (mail_cache_header_fields_get_offset(cache, offset_r) < 0)
+	if (mail_cache_header_fields_get_offset(cache, offset_r, FALSE) < 0)
 		return -1;
 
 	if (*offset_r == 0) {


More information about the dovecot-cvs mailing list