[PATCH] io: Limit readv/writev to IOV_MAX

Andrew Deason posted 1 patch 2 years, 1 month ago
Test checkpatch passed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20220320215733.5523-1-adeason@sinenomine.net
Maintainers: "Daniel P. Berrangé" <berrange@redhat.com>
io/channel.c | 4 ++++
1 file changed, 4 insertions(+)
[PATCH] io: Limit readv/writev to IOV_MAX
Posted by Andrew Deason 2 years, 1 month ago
The unit tests 'test-io-channel-file' and 'test-io-channel-socket'
currently fail on Solaris, because we try to perform vectored I/O with
a batch of 250 (CHUNK_COUNT) iovs. This exceeds MAX_IOV on Solaris
(only 16, much lower than Linux's 1024), and so results in an EINVAL
for file operations, and EMSGSIZE for sockets.

To fix this, make qio_channel_readv_full and qio_channel_writev_full
only use the first IOV_MAX iovs passed in, and we'll return the number
of bytes actually processed like always.

Signed-off-by: Andrew Deason <adeason@sinenomine.net>
---
These aren't the only tests that fail on Solaris right now, but this
seemed easy to fix (assuming this is correct), so I'm just submitting
something while I'm looking at it.

 io/channel.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/io/channel.c b/io/channel.c
index e8b019dc36..cb9d85a30d 100644
--- a/io/channel.c
+++ b/io/channel.c
@@ -56,40 +56,44 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
 {
     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
 
     if ((fds || nfds) &&
         !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
         error_setg_errno(errp, EINVAL,
                          "Channel does not support file descriptor passing");
         return -1;
     }
 
+    niov = MIN(niov, IOV_MAX);
+
     return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
 }
 
 
 ssize_t qio_channel_writev_full(QIOChannel *ioc,
                                 const struct iovec *iov,
                                 size_t niov,
                                 int *fds,
                                 size_t nfds,
                                 Error **errp)
 {
     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
 
     if ((fds || nfds) &&
         !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
         error_setg_errno(errp, EINVAL,
                          "Channel does not support file descriptor passing");
         return -1;
     }
 
+    niov = MIN(niov, IOV_MAX);
+
     return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
 }
 
 
 int qio_channel_readv_all_eof(QIOChannel *ioc,
                               const struct iovec *iov,
                               size_t niov,
                               Error **errp)
 {
     return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp);
-- 
2.11.0