dovecot: Delay lseek()s and use pwrite() whenever possible.

dovecot at dovecot.org dovecot at dovecot.org
Thu Aug 2 19:06:40 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/48dbfdba4e24
changeset: 6163:48dbfdba4e24
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Aug 02 18:37:31 2007 +0300
description:
Delay lseek()s and use pwrite() whenever possible.

diffstat:

1 file changed, 49 insertions(+), 22 deletions(-)
src/lib/ostream-file.c |   71 +++++++++++++++++++++++++++++++++---------------

diffs (152 lines):

diff -r 896cc473c1f0 -r 48dbfdba4e24 src/lib/ostream-file.c
--- a/src/lib/ostream-file.c	Thu Aug 02 18:27:46 2007 +0300
+++ b/src/lib/ostream-file.c	Thu Aug 02 18:37:31 2007 +0300
@@ -33,6 +33,7 @@ struct file_ostream {
 
 	int fd;
 	struct io *io;
+	uoff_t real_offset;
 
 	unsigned char *buffer; /* ring-buffer */
 	size_t buffer_size, max_buffer_size, optimal_block_size;
@@ -133,17 +134,50 @@ static void o_stream_socket_cork(struct 
 	}
 }
 
+static int o_stream_lseek(struct file_ostream *fstream)
+{
+	uoff_t offset = fstream->ostream.ostream.offset;
+	off_t ret;
+
+	if (fstream->real_offset == offset)
+		return 0;
+
+	ret = lseek(fstream->fd, (off_t)offset, SEEK_SET);
+	if (ret < 0) {
+		fstream->ostream.ostream.stream_errno = errno;
+		return -1;
+	}
+
+	if (ret != (off_t)offset) {
+		fstream->ostream.ostream.stream_errno = EINVAL;
+		return -1;
+	}
+	fstream->real_offset = offset;
+	return 0;
+}
+
 static ssize_t o_stream_writev(struct file_ostream *fstream,
 			       const struct const_iovec *iov, int iov_size)
 {
+	uoff_t offset = fstream->ostream.ostream.offset;
 	ssize_t ret;
 	size_t size, sent;
 	int i;
 
 	o_stream_socket_cork(fstream);
-	if (iov_size == 1)
-		ret = write(fstream->fd, iov->iov_base, iov->iov_len);
-	else {
+	if (iov_size == 1) {
+		if (!fstream->file || fstream->real_offset == offset) {
+			ret = write(fstream->fd, iov->iov_base, iov->iov_len);
+			if (ret > 0)
+				fstream->real_offset += ret;
+		} else {
+			ret = pwrite(fstream->fd, iov->iov_base, iov->iov_len,
+				     offset);
+		}
+	} else {
+		if (o_stream_lseek(fstream) < 0)
+			return -1;
+
 		sent = 0;
 		while (iov_size > IOV_MAX) {
 			size = 0;
@@ -155,6 +189,7 @@ static ssize_t o_stream_writev(struct fi
 			if (ret != (ssize_t)size)
 				break;
 
+			fstream->real_offset += ret;
 			sent += ret;
 			iov += IOV_MAX;
 			iov_size -= IOV_MAX;
@@ -164,8 +199,10 @@ static ssize_t o_stream_writev(struct fi
 			ret = writev(fstream->fd, (const struct iovec *)iov,
 				     iov_size);
 		}
-		if (ret > 0)
+		if (ret > 0) {
+			fstream->real_offset += ret;
 			ret += sent;
+		}
 	}
 
 	if (ret < 0) {
@@ -292,26 +329,14 @@ static int _seek(struct _ostream *stream
 static int _seek(struct _ostream *stream, uoff_t offset)
 {
 	struct file_ostream *fstream = (struct file_ostream *)stream;
-	off_t ret;
-
-	if (offset > OFF_T_MAX) {
+
+	if (offset > OFF_T_MAX || !fstream->file) {
 		stream->ostream.stream_errno = EINVAL;
 		return -1;
 	}
 
 	if (buffer_flush(fstream) < 0)
 		return -1;
-
-	ret = lseek(fstream->fd, (off_t)offset, SEEK_SET);
-	if (ret < 0) {
-		stream->ostream.stream_errno = errno;
-		return -1;
-	}
-
-	if (ret != (off_t)offset) {
-		stream->ostream.stream_errno = EINVAL;
-		return -1;
-	}
 
 	stream->ostream.stream_errno = 0;
 	stream->ostream.offset = offset;
@@ -505,6 +530,9 @@ static off_t io_stream_sendfile(struct _
 	/* flush out any data in buffer */
 	if ((ret = buffer_flush(foutstream)) <= 0)
 		return ret;
+
+	if (o_stream_lseek(foutstream) < 0)
+		return -1;
 
         start_offset = v_offset = instream->v_offset;
 	do {
@@ -662,10 +690,7 @@ static off_t io_stream_copy_backwards(st
 		}
 		in_limit -= size;
 
-		if (o_stream_seek(&outstream->ostream, out_offset) < 0)
-			return -1;
-
-		ret = write_full(foutstream->fd, data, size);
+		ret = pwrite_full(foutstream->fd, data, size, out_offset);
 		if (ret < 0) {
 			/* error */
 			outstream->ostream.stream_errno = errno;
@@ -792,6 +817,7 @@ o_stream_create_fd(int fd, size_t max_bu
 	offset = lseek(fd, 0, SEEK_CUR);
 	if (offset >= 0) {
 		ostream->offset = offset;
+		fstream->real_offset = offset;
 		fstream_init_file(fstream);
 	} else {
 		if (net_getsockname(fd, NULL, NULL) < 0) {
@@ -818,6 +844,7 @@ o_stream_create_fd_file(int fd, uoff_t o
 	fstream = o_stream_create_fd_common(fd, autoclose_fd);
 	fstream_init_file(fstream);
 	fstream->max_buffer_size = fstream->optimal_block_size;
+	fstream->real_offset = offset;
 
 	ostream = _o_stream_create(&fstream->ostream);
 	ostream->offset = offset;


More information about the dovecot-cvs mailing list