diff -r b7d13ee51aa4 src/lib-index/mail-transaction-log-append.c
--- a/src/lib-index/mail-transaction-log-append.c	Fri Dec 03 04:25:06 2010 +0000
+++ b/src/lib-index/mail-transaction-log-append.c	Fri Dec 03 04:39:43 2010 +0000
@@ -32,6 +32,7 @@
 	buffer_append(ctx->output, data, size);
 
 	mail_transaction_update_modseq(&hdr, data, &ctx->new_highest_modseq);
+	ctx->transaction_count++;
 }
 
 static int
@@ -60,8 +61,6 @@
 static int log_buffer_write(struct mail_transaction_log_append_ctx *ctx)
 {
 	struct mail_transaction_log_file *file = ctx->log->head;
-	struct mail_transaction_header *hdr;
-	uint32_t first_size;
 
 	if (ctx->output->used == 0)
 		return 0;
@@ -77,15 +76,8 @@
 	}
 
 	/* size will be written later once everything is in disk */
-	hdr = buffer_get_space_unsafe(ctx->output, 0, sizeof(*hdr));
-	first_size = hdr->size;
-	i_assert(first_size != 0);
-	hdr->size = 0;
-
-	if (pwrite_full(file->fd, ctx->output->data, ctx->output->used,
-			file->sync_offset) < 0) {
+	if (write_full(file->fd, ctx->output->data, ctx->output->used) < 0) {
 		/* write failure, fallback to in-memory indexes. */
-		hdr->size = first_size;
 		mail_index_file_set_syscall_error(ctx->log->index,
 						  file->filepath,
 						  "pwrite_full()");
@@ -96,18 +88,6 @@
 		 file->sync_offset + ctx->output->used ==
 		 file->max_tail_offset);
 
-	/* now that the whole transaction has been written, rewrite the first
-	   record's size so the transaction becomes visible */
-	hdr->size = first_size;
-	if (pwrite_full(file->fd, &first_size, sizeof(uint32_t),
-			file->sync_offset +
-			offsetof(struct mail_transaction_header, size)) < 0) {
-		mail_index_file_set_syscall_error(ctx->log->index,
-						  file->filepath,
-						  "pwrite_full()");
-		return log_buffer_move_to_memory(ctx);
-	}
-
 	if ((ctx->want_fsync &&
 	     file->log->index->fsync_mode != FSYNC_MODE_NEVER) ||
 	    file->log->index->fsync_mode == FSYNC_MODE_ALWAYS) {
@@ -177,6 +157,7 @@
 mail_transaction_log_append_locked(struct mail_transaction_log_append_ctx *ctx)
 {
 	struct mail_transaction_log_file *file = ctx->log->head;
+	struct mail_transaction_boundary *boundary;
 
 	if (file->sync_offset < file->last_size) {
 		/* there is some garbage at the end of the transaction log
@@ -192,6 +173,21 @@
 		}
 	}
 
+	/* don't include log_file_tail_offset update in the transaction */
+	boundary = buffer_get_space_unsafe(ctx->output,
+				sizeof(struct mail_transaction_header),
+				sizeof(*boundary));
+	boundary->size = ctx->output->used;
+
+	if (ctx->transaction_count <= 2) {
+		/* 0-1 changes. don't bother with the boundary */
+		unsigned int boundary_size =
+			sizeof(struct mail_transaction_header) +
+			sizeof(*boundary);
+
+		buffer_delete(ctx->output, 0, boundary_size);
+	}
+
 	if (ctx->append_sync_offset)
 		log_append_sync_offset_if_needed(ctx);
 
@@ -205,6 +201,7 @@
 				      struct mail_transaction_log_append_ctx **ctx_r)
 {
 	struct mail_transaction_log_append_ctx *ctx;
+	struct mail_transaction_boundary boundary;
 
 	if (!index->log_sync_locked) {
 		if (mail_transaction_log_lock_head(index->log) < 0)
@@ -215,6 +212,10 @@
 	ctx->output = buffer_create_dynamic(default_pool, 1024);
 	ctx->external = external;
 
+	memset(&boundary, 0, sizeof(boundary));
+	mail_transaction_log_append_add(ctx, MAIL_TRANSACTION_BOUNDARY,
+					&boundary, sizeof(boundary));
+
 	*ctx_r = ctx;
 	return 0;
 }
diff -r b7d13ee51aa4 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c	Fri Dec 03 04:25:06 2010 +0000
+++ b/src/lib-index/mail-transaction-log-file.c	Fri Dec 03 04:39:43 2010 +0000
@@ -596,6 +596,9 @@
 	int fd, ret;
 	bool rename_existing;
 
+	if (fcntl(new_fd, F_SETFL, O_APPEND) < 0)
+		return log_file_set_syscall_error(file, "fcntl(O_APPEND)");
+
 	if (file->log->nfs_flush) {
 		/* although we check also mtime and file size below, it's done
 		   only to fix broken log files. we don't bother flushing
@@ -625,7 +628,7 @@
 		rename_existing = TRUE;
 	} else {
 		/* recreated. use the file if its header is ok */
-		fd = nfs_safe_open(file->filepath, O_RDWR);
+		fd = nfs_safe_open(file->filepath, O_RDWR | O_APPEND);
 		if (fd == -1) {
 			if (errno != ENOENT) {
 				log_file_set_syscall_error(file, "open()");
@@ -765,7 +768,7 @@
 	int ret;
 
         for (i = 0;; i++) {
-                file->fd = nfs_safe_open(file->filepath, O_RDWR);
+                file->fd = nfs_safe_open(file->filepath, O_RDWR | O_APPEND);
                 if (file->fd == -1) {
 			if (errno == ENOENT)
 				return 0;
@@ -1280,18 +1283,11 @@
 		/* 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. */
-		if (trans_size != 0) {
-			/* pread()s or the above fstat() check for mmaps should
-			   have guaranteed that this doesn't happen */
-			mail_transaction_log_file_set_corrupted(file,
-				"hdr.size too large (%u)", trans_size);
-			return -1;
-		} else if (file->locked) {
+		if (file->locked) {
 			mail_transaction_log_file_set_corrupted(file,
 				"Unexpected garbage at EOF");
 			return -1;
 		}
-
 		/* The size field will be updated soon */
 		mail_index_flush_read_cache(file->log->index, file->filepath,
 					    file->fd, file->locked);
diff -r b7d13ee51aa4 src/lib-index/mail-transaction-log.h
--- a/src/lib-index/mail-transaction-log.h	Fri Dec 03 04:25:06 2010 +0000
+++ b/src/lib-index/mail-transaction-log.h	Fri Dec 03 04:39:43 2010 +0000
@@ -167,6 +167,8 @@
 	buffer_t *output;
 
 	uint64_t new_highest_modseq;
+	unsigned int transaction_count;
+
 	unsigned int external:1;
 	unsigned int append_sync_offset:1;
 	unsigned int sync_includes_this:1;
