dovecot: o_stream_send_istream(): Don't fstat() the stream unles...

dovecot at dovecot.org dovecot at dovecot.org
Thu Nov 8 01:58:09 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/ba048bb01842
changeset: 6723:ba048bb01842
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Nov 08 01:58:04 2007 +0200
description:
o_stream_send_istream(): Don't fstat() the stream unless we have to.

diffstat:

1 file changed, 33 insertions(+), 37 deletions(-)
src/lib/ostream-file.c |   70 ++++++++++++++++++++++--------------------------

diffs (134 lines):

diff -r a9739ce5a7e4 -r ba048bb01842 src/lib/ostream-file.c
--- a/src/lib/ostream-file.c	Thu Nov 08 01:56:57 2007 +0200
+++ b/src/lib/ostream-file.c	Thu Nov 08 01:58:04 2007 +0200
@@ -530,13 +530,20 @@ static ssize_t o_stream_file_sendv(struc
 }
 
 static off_t io_stream_sendfile(struct ostream_private *outstream,
-				struct istream *instream,
-				int in_fd, uoff_t in_size)
+				struct istream *instream, int in_fd)
 {
 	struct file_ostream *foutstream = (struct file_ostream *)outstream;
+	const struct stat *st;
 	uoff_t start_offset;
-	uoff_t offset, send_size, v_offset;
+	uoff_t in_size, offset, send_size, v_offset;
 	ssize_t ret;
+
+	st = i_stream_stat(instream, TRUE);
+	if (st == NULL) {
+		outstream->ostream.stream_errno = instream->stream_errno;
+		return -1;
+	}
+	in_size = st->st_size;
 
 	o_stream_socket_cork(foutstream);
 
@@ -580,14 +587,14 @@ static off_t io_stream_sendfile(struct o
 }
 
 static off_t io_stream_copy(struct ostream_private *outstream,
-			    struct istream *instream, uoff_t in_size)
+			    struct istream *instream)
 {
 	struct file_ostream *foutstream = (struct file_ostream *)outstream;
 	uoff_t start_offset;
 	struct const_iovec iov[3];
 	int iov_len;
 	const unsigned char *data;
-	size_t size, skip_size, block_size;
+	size_t size, skip_size;
 	ssize_t ret;
 	int pos;
 
@@ -598,12 +605,9 @@ static off_t io_stream_copy(struct ostre
 		skip_size += iov[pos].iov_len;
 
 	start_offset = instream->v_offset;
-	in_size -= instream->v_offset;
-	while (in_size > 0) {
-		block_size = I_MIN(foutstream->optimal_block_size, in_size);
-		(void)i_stream_read_data(instream, &data, &size, block_size-1);
-		in_size -= size;
-
+	for (;;) {
+		(void)i_stream_read_data(instream, &data, &size,
+					 foutstream->optimal_block_size-1);
 		if (size == 0) {
 			/* all sent */
 			break;
@@ -721,30 +725,21 @@ static off_t o_stream_file_send_istream(
 {
 	struct file_ostream *foutstream = (struct file_ostream *)outstream;
 	const struct stat *st;
-	uoff_t in_size;
 	off_t ret;
-	int in_fd, overlapping;
-
-	st = i_stream_stat(instream, TRUE);
-	if (st == NULL) {
-		outstream->ostream.stream_errno = instream->stream_errno;
-		return -1;
-	}
+	int in_fd;
 
 	in_fd = i_stream_get_fd(instream);
-	in_size = st->st_size;
-	i_assert(instream->v_offset <= in_size);
 
 	outstream->ostream.stream_errno = 0;
-	if (in_fd != foutstream->fd)
-		overlapping = 0;
-	else {
+	if (in_fd == foutstream->fd) {
 		/* copying data within same fd. we'll have to be careful with
 		   seeks and overlapping writes. */
-		if (in_size == (uoff_t)-1) {
-			outstream->ostream.stream_errno = EINVAL;
+		st = i_stream_stat(instream, TRUE);
+		if (st == NULL) {
+			outstream->ostream.stream_errno = instream->stream_errno;
 			return -1;
 		}
+		i_assert(instream->v_offset <= (uoff_t)st->st_size);
 
 		ret = (off_t)outstream->ostream.offset -
 			(off_t)(instream->real_stream->abs_start_offset +
@@ -752,13 +747,17 @@ static off_t o_stream_file_send_istream(
 		if (ret == 0) {
 			/* copying data over itself. we don't really
 			   need to do that, just fake it. */
-			return in_size - instream->v_offset;
-		}
-		overlapping = ret < 0 ? -1 : 1;
-	}
-
-	if (!foutstream->no_sendfile && in_fd != -1 && overlapping <= 0) {
-		ret = io_stream_sendfile(outstream, instream, in_fd, in_size);
+			return st->st_size - instream->v_offset;
+		}
+		if (ret > 0) {
+			/* overlapping */
+			return io_stream_copy_backwards(outstream, instream,
+							st->st_size);
+		}
+	}
+
+	if (!foutstream->no_sendfile && in_fd != -1 && instream->seekable) {
+		ret = io_stream_sendfile(outstream, instream, in_fd);
 		if (ret >= 0 || outstream->ostream.stream_errno != EINVAL)
 			return ret;
 
@@ -768,10 +767,7 @@ static off_t o_stream_file_send_istream(
 		foutstream->no_sendfile = TRUE;
 	}
 
-	if (overlapping <= 0)
-		return io_stream_copy(outstream, instream, in_size);
-	else
-		return io_stream_copy_backwards(outstream, instream, in_size);
+	return io_stream_copy(outstream, instream);
 }
 
 static struct file_ostream *


More information about the dovecot-cvs mailing list