]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: ostream-file - Improve write errors: mention the failing syscall.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Thu, 23 Feb 2023 00:31:31 +0000 (01:31 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 24 Mar 2023 07:14:54 +0000 (07:14 +0000)
src/lib/ostream-file-private.h
src/lib/ostream-file.c
src/lib/ostream-unix.c

index 2d58933559efc05afa29588ec2cf6eefe027fd21..fd2ac632f4dbfd56fd8db5d781ea4707dbf91c9a 100644 (file)
@@ -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);
index 7ad9c0b7fd60302b5ee050fd9d7c08cd321447d4..241ea6bea5f19bffe9a6c159cfeff5b25e094077 100644 (file)
@@ -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;
index 279913549a2dc128d1357e67c82b2e51177bcb20..1d12baacb2bbfa731b1fb690ad72895bc698a0f1 100644 (file)
@@ -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;