From: Stephan Bosch Date: Thu, 23 Feb 2023 00:31:31 +0000 (+0100) Subject: lib: ostream-file - Improve write errors: mention the failing syscall. X-Git-Tag: 2.4.0~2883 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01d2a3ad7857785ad1d5a032caff1b0bfcfbd6b1;p=thirdparty%2Fdovecot%2Fcore.git lib: ostream-file - Improve write errors: mention the failing syscall. --- diff --git a/src/lib/ostream-file-private.h b/src/lib/ostream-file-private.h index 2d58933559..fd2ac632f4 100644 --- a/src/lib/ostream-file-private.h +++ b/src/lib/ostream-file-private.h @@ -8,7 +8,7 @@ struct file_ostream { ssize_t (*writev)(struct file_ostream *fstream, const struct const_iovec *iov, - unsigned int iov_count); + unsigned int iov_count, const char **error_r); int fd; struct io *io; @@ -34,8 +34,8 @@ struct ostream * o_stream_create_file_common(struct file_ostream *fstream, int fd, size_t max_buffer_size, bool autoclose_fd); ssize_t o_stream_file_writev(struct file_ostream *fstream, - const struct const_iovec *iov, - unsigned int iov_size); + const struct const_iovec *iov, + unsigned int iov_size, const char **error_r); ssize_t o_stream_file_sendv(struct ostream_private *stream, const struct const_iovec *iov, unsigned int iov_count); diff --git a/src/lib/ostream-file.c b/src/lib/ostream-file.c index 7ad9c0b7fd..241ea6bea5 100644 --- a/src/lib/ostream-file.c +++ b/src/lib/ostream-file.c @@ -153,9 +153,11 @@ static int o_stream_lseek(struct file_ostream *fstream) } ssize_t o_stream_file_writev(struct file_ostream *fstream, - const struct const_iovec *iov, - unsigned int iov_count) + const struct const_iovec *iov, + unsigned int iov_count, + const char **error_r) { + const char *syscall = NULL; ssize_t ret; size_t size, sent; unsigned int i; @@ -165,17 +167,22 @@ ssize_t o_stream_file_writev(struct file_ostream *fstream, if (!fstream->file || fstream->real_offset == fstream->buffer_offset) { + syscall = "write"; ret = write(fstream->fd, iov->iov_base, iov->iov_len); if (ret > 0) fstream->real_offset += ret; } else { + syscall = "pwrite"; ret = pwrite(fstream->fd, iov->iov_base, iov->iov_len, fstream->buffer_offset); } } else { - if (o_stream_lseek(fstream) < 0) + if (o_stream_lseek(fstream) < 0) { + *error_r = t_strdup(o_stream_get_error(&fstream->ostream.ostream)); return -1; + } + syscall = "writev"; sent = 0; while (iov_count > IOV_MAX) { size = 0; @@ -211,6 +218,10 @@ ssize_t o_stream_file_writev(struct file_ostream *fstream, ret = sent; } } + if (ret < 0) { + i_assert(syscall != NULL); + *error_r = t_strdup_printf("%s() failed: %m", syscall); + } return ret; } @@ -219,6 +230,7 @@ o_stream_file_writev_full(struct file_ostream *fstream, const struct const_iovec *iov, unsigned int iov_count) { + const char *error = NULL; ssize_t ret, ret2; size_t size, total_size; bool partial; @@ -228,10 +240,11 @@ o_stream_file_writev_full(struct file_ostream *fstream, total_size += iov[i].iov_len; o_stream_socket_cork(fstream); - ret = fstream->writev(fstream, iov, iov_count); + ret = fstream->writev(fstream, iov, iov_count, &error); partial = ret != (ssize_t)total_size; if (ret < 0) { + i_assert(error != NULL); if (fstream->file) { if (errno == EINTR) { /* automatically retry */ @@ -241,6 +254,7 @@ o_stream_file_writev_full(struct file_ostream *fstream, /* try again later */ return 0; } + io_stream_set_error(&fstream->ostream.iostream, "%s", error); fstream->ostream.ostream.stream_errno = errno; stream_closed(fstream); return -1; diff --git a/src/lib/ostream-unix.c b/src/lib/ostream-unix.c index 279913549a..1d12baacb2 100644 --- a/src/lib/ostream-unix.c +++ b/src/lib/ostream-unix.c @@ -17,8 +17,9 @@ o_stream_unix_close(struct iostream_private *stream, bool close_parent) } static ssize_t o_stream_unix_writev(struct file_ostream *fstream, - const struct const_iovec *iov, - unsigned int iov_count) + const struct const_iovec *iov, + unsigned int iov_count, + const char **error_r) { struct unix_ostream *ustream = container_of(fstream, struct unix_ostream, fstream); @@ -27,7 +28,7 @@ static ssize_t o_stream_unix_writev(struct file_ostream *fstream, if (ustream->write_fd == -1) { /* no fd */ - return o_stream_file_writev(fstream, iov, iov_count); + return o_stream_file_writev(fstream, iov, iov_count, error_r); } /* send first iovec along with fd */ @@ -36,8 +37,10 @@ static ssize_t o_stream_unix_writev(struct file_ostream *fstream, i_assert(iov[0].iov_len > 0); ret = fd_send(fstream->fd, ustream->write_fd, iov[0].iov_base, iov[0].iov_len); - if (ret < 0) + if (ret < 0) { + *error_r = t_strdup_printf("fd_send() failed: %m"); return ret; + } /* update stream */ sent = ret; @@ -51,7 +54,7 @@ static ssize_t o_stream_unix_writev(struct file_ostream *fstream, } /* send remaining iovecs */ - ret = o_stream_file_writev(fstream, &iov[1], iov_count-1); + ret = o_stream_file_writev(fstream, &iov[1], iov_count-1, error_r); if (ret < 0) return (errno == EAGAIN || errno == EINTR ? (ssize_t)sent : ret); sent += ret;