Blame SOURCES/kvm-io-Add-support-for-MSG_PEEK-for-socket-channel.patch

97168e
From 88b5e059462a72ca758d84c0d4d0895a03baac50 Mon Sep 17 00:00:00 2001
97168e
From: "manish.mishra" <manish.mishra@nutanix.com>
97168e
Date: Tue, 20 Dec 2022 18:44:17 +0000
97168e
Subject: [PATCH 1/3] io: Add support for MSG_PEEK for socket channel
97168e
MIME-Version: 1.0
97168e
Content-Type: text/plain; charset=UTF-8
97168e
Content-Transfer-Encoding: 8bit
97168e
97168e
RH-Author: Peter Xu <peterx@redhat.com>
97168e
RH-MergeRequest: 258: migration: Fix multifd crash due to channel disorder
97168e
RH-Bugzilla: 2137740
97168e
RH-Acked-by: quintela1 <quintela@redhat.com>
97168e
RH-Acked-by: Leonardo BrĂ¡s <leobras@redhat.com>
97168e
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
97168e
RH-Commit: [1/2] 04fc6fae358599b8509f5355469d2e8720f01903
97168e
97168e
Conflicts:
97168e
	io/channel-null.c
97168e
	migration/channel-block.c
97168e
97168e
        Because these two files do not exist in rhel8.8 tree, dropping the
97168e
        changes.
97168e
97168e
MSG_PEEK peeks at the channel, The data is treated as unread and
97168e
the next read shall still return this data. This support is
97168e
currently added only for socket class. Extra parameter 'flags'
97168e
is added to io_readv calls to pass extra read flags like MSG_PEEK.
97168e
97168e
Reviewed-by: Peter Xu <peterx@redhat.com>
97168e
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
97168e
Reviewed-by: Juan Quintela <quintela@redhat.com>
97168e
Suggested-by: Daniel P. Berrange <berrange@redhat.com>
97168e
Signed-off-by: manish.mishra <manish.mishra@nutanix.com>
97168e
Signed-off-by: Juan Quintela <quintela@redhat.com>
97168e
(cherry picked from commit 84615a19ddf2bfb38d7b3a0d487d2397ee55e4f3)
97168e
Signed-off-by: Peter Xu <peterx@redhat.com>
97168e
---
97168e
 chardev/char-socket.c               |  4 ++--
97168e
 include/io/channel.h                |  6 ++++++
97168e
 io/channel-buffer.c                 |  1 +
97168e
 io/channel-command.c                |  1 +
97168e
 io/channel-file.c                   |  1 +
97168e
 io/channel-socket.c                 | 19 ++++++++++++++++++-
97168e
 io/channel-tls.c                    |  1 +
97168e
 io/channel-websock.c                |  1 +
97168e
 io/channel.c                        | 16 ++++++++++++----
97168e
 migration/rdma.c                    |  1 +
97168e
 scsi/qemu-pr-helper.c               |  2 +-
97168e
 tests/qtest/tpm-emu.c               |  2 +-
97168e
 tests/unit/test-io-channel-socket.c |  1 +
97168e
 util/vhost-user-server.c            |  2 +-
97168e
 14 files changed, 48 insertions(+), 10 deletions(-)
97168e
97168e
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
97168e
index 836cfa0bc2..4cdf79e0c2 100644
97168e
--- a/chardev/char-socket.c
97168e
+++ b/chardev/char-socket.c
97168e
@@ -339,11 +339,11 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
97168e
     if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
97168e
         ret = qio_channel_readv_full(s->ioc, &iov, 1,
97168e
                                      &msgfds, &msgfds_num,
97168e
-                                     NULL);
97168e
+                                     0, NULL);
97168e
     } else {
97168e
         ret = qio_channel_readv_full(s->ioc, &iov, 1,
97168e
                                      NULL, NULL,
97168e
-                                     NULL);
97168e
+                                     0, NULL);
97168e
     }
97168e
 
97168e
     if (ret == QIO_CHANNEL_ERR_BLOCK) {
97168e
diff --git a/include/io/channel.h b/include/io/channel.h
97168e
index c680ee7480..716235d496 100644
97168e
--- a/include/io/channel.h
97168e
+++ b/include/io/channel.h
97168e
@@ -34,6 +34,8 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
97168e
 
97168e
 #define QIO_CHANNEL_WRITE_FLAG_ZERO_COPY 0x1
97168e
 
97168e
+#define QIO_CHANNEL_READ_FLAG_MSG_PEEK 0x1
97168e
+
97168e
 typedef enum QIOChannelFeature QIOChannelFeature;
97168e
 
97168e
 enum QIOChannelFeature {
97168e
@@ -41,6 +43,7 @@ enum QIOChannelFeature {
97168e
     QIO_CHANNEL_FEATURE_SHUTDOWN,
97168e
     QIO_CHANNEL_FEATURE_LISTEN,
97168e
     QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY,
97168e
+    QIO_CHANNEL_FEATURE_READ_MSG_PEEK,
97168e
 };
97168e
 
97168e
 
97168e
@@ -114,6 +117,7 @@ struct QIOChannelClass {
97168e
                         size_t niov,
97168e
                         int **fds,
97168e
                         size_t *nfds,
97168e
+                        int flags,
97168e
                         Error **errp);
97168e
     int (*io_close)(QIOChannel *ioc,
97168e
                     Error **errp);
97168e
@@ -188,6 +192,7 @@ void qio_channel_set_name(QIOChannel *ioc,
97168e
  * @niov: the length of the @iov array
97168e
  * @fds: pointer to an array that will received file handles
97168e
  * @nfds: pointer filled with number of elements in @fds on return
97168e
+ * @flags: read flags (QIO_CHANNEL_READ_FLAG_*)
97168e
  * @errp: pointer to a NULL-initialized error object
97168e
  *
97168e
  * Read data from the IO channel, storing it in the
97168e
@@ -224,6 +229,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
97168e
                                size_t niov,
97168e
                                int **fds,
97168e
                                size_t *nfds,
97168e
+                               int flags,
97168e
                                Error **errp);
97168e
 
97168e
 
97168e
diff --git a/io/channel-buffer.c b/io/channel-buffer.c
97168e
index bf52011be2..8096180f85 100644
97168e
--- a/io/channel-buffer.c
97168e
+++ b/io/channel-buffer.c
97168e
@@ -54,6 +54,7 @@ static ssize_t qio_channel_buffer_readv(QIOChannel *ioc,
97168e
                                         size_t niov,
97168e
                                         int **fds,
97168e
                                         size_t *nfds,
97168e
+                                        int flags,
97168e
                                         Error **errp)
97168e
 {
97168e
     QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
97168e
diff --git a/io/channel-command.c b/io/channel-command.c
97168e
index 5ff1691bad..2834413b3a 100644
97168e
--- a/io/channel-command.c
97168e
+++ b/io/channel-command.c
97168e
@@ -230,6 +230,7 @@ static ssize_t qio_channel_command_readv(QIOChannel *ioc,
97168e
                                          size_t niov,
97168e
                                          int **fds,
97168e
                                          size_t *nfds,
97168e
+                                         int flags,
97168e
                                          Error **errp)
97168e
 {
97168e
     QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
97168e
diff --git a/io/channel-file.c b/io/channel-file.c
97168e
index 348a48545e..490f0e5d84 100644
97168e
--- a/io/channel-file.c
97168e
+++ b/io/channel-file.c
97168e
@@ -86,6 +86,7 @@ static ssize_t qio_channel_file_readv(QIOChannel *ioc,
97168e
                                       size_t niov,
97168e
                                       int **fds,
97168e
                                       size_t *nfds,
97168e
+                                      int flags,
97168e
                                       Error **errp)
97168e
 {
97168e
     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
97168e
diff --git a/io/channel-socket.c b/io/channel-socket.c
97168e
index 6010ad7017..ca8b180b69 100644
97168e
--- a/io/channel-socket.c
97168e
+++ b/io/channel-socket.c
97168e
@@ -174,6 +174,9 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
97168e
     }
97168e
 #endif
97168e
 
97168e
+    qio_channel_set_feature(QIO_CHANNEL(ioc),
97168e
+                            QIO_CHANNEL_FEATURE_READ_MSG_PEEK);
97168e
+
97168e
     return 0;
97168e
 }
97168e
 
97168e
@@ -407,6 +410,9 @@ qio_channel_socket_accept(QIOChannelSocket *ioc,
97168e
     }
97168e
 #endif /* WIN32 */
97168e
 
97168e
+    qio_channel_set_feature(QIO_CHANNEL(cioc),
97168e
+                            QIO_CHANNEL_FEATURE_READ_MSG_PEEK);
97168e
+
97168e
     trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
97168e
     return cioc;
97168e
 
97168e
@@ -497,6 +503,7 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
97168e
                                         size_t niov,
97168e
                                         int **fds,
97168e
                                         size_t *nfds,
97168e
+                                        int flags,
97168e
                                         Error **errp)
97168e
 {
97168e
     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
97168e
@@ -518,6 +525,10 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
97168e
 
97168e
     }
97168e
 
97168e
+    if (flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) {
97168e
+        sflags |= MSG_PEEK;
97168e
+    }
97168e
+
97168e
  retry:
97168e
     ret = recvmsg(sioc->fd, &msg, sflags);
97168e
     if (ret < 0) {
97168e
@@ -625,11 +636,17 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
97168e
                                         size_t niov,
97168e
                                         int **fds,
97168e
                                         size_t *nfds,
97168e
+                                        int flags,
97168e
                                         Error **errp)
97168e
 {
97168e
     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
97168e
     ssize_t done = 0;
97168e
     ssize_t i;
97168e
+    int sflags = 0;
97168e
+
97168e
+    if (flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) {
97168e
+        sflags |= MSG_PEEK;
97168e
+    }
97168e
 
97168e
     for (i = 0; i < niov; i++) {
97168e
         ssize_t ret;
97168e
@@ -637,7 +654,7 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
97168e
         ret = recv(sioc->fd,
97168e
                    iov[i].iov_base,
97168e
                    iov[i].iov_len,
97168e
-                   0);
97168e
+                   sflags);
97168e
         if (ret < 0) {
97168e
             if (errno == EAGAIN) {
97168e
                 if (done) {
97168e
diff --git a/io/channel-tls.c b/io/channel-tls.c
97168e
index 4ce890a538..c730cb8ec5 100644
97168e
--- a/io/channel-tls.c
97168e
+++ b/io/channel-tls.c
97168e
@@ -260,6 +260,7 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
97168e
                                      size_t niov,
97168e
                                      int **fds,
97168e
                                      size_t *nfds,
97168e
+                                     int flags,
97168e
                                      Error **errp)
97168e
 {
97168e
     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
97168e
diff --git a/io/channel-websock.c b/io/channel-websock.c
97168e
index 035dd6075b..13c94f2afe 100644
97168e
--- a/io/channel-websock.c
97168e
+++ b/io/channel-websock.c
97168e
@@ -1081,6 +1081,7 @@ static ssize_t qio_channel_websock_readv(QIOChannel *ioc,
97168e
                                          size_t niov,
97168e
                                          int **fds,
97168e
                                          size_t *nfds,
97168e
+                                         int flags,
97168e
                                          Error **errp)
97168e
 {
97168e
     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
97168e
diff --git a/io/channel.c b/io/channel.c
97168e
index 0640941ac5..a8c7f11649 100644
97168e
--- a/io/channel.c
97168e
+++ b/io/channel.c
97168e
@@ -52,6 +52,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
97168e
                                size_t niov,
97168e
                                int **fds,
97168e
                                size_t *nfds,
97168e
+                               int flags,
97168e
                                Error **errp)
97168e
 {
97168e
     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
97168e
@@ -63,7 +64,14 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
97168e
         return -1;
97168e
     }
97168e
 
97168e
-    return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
97168e
+    if ((flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) &&
97168e
+        !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
97168e
+        error_setg_errno(errp, EINVAL,
97168e
+                         "Channel does not support peek read");
97168e
+        return -1;
97168e
+    }
97168e
+
97168e
+    return klass->io_readv(ioc, iov, niov, fds, nfds, flags, errp);
97168e
 }
97168e
 
97168e
 
97168e
@@ -146,7 +154,7 @@ int qio_channel_readv_full_all_eof(QIOChannel *ioc,
97168e
     while ((nlocal_iov > 0) || local_fds) {
97168e
         ssize_t len;
97168e
         len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
97168e
-                                     local_nfds, errp);
97168e
+                                     local_nfds, 0, errp);
97168e
         if (len == QIO_CHANNEL_ERR_BLOCK) {
97168e
             if (qemu_in_coroutine()) {
97168e
                 qio_channel_yield(ioc, G_IO_IN);
97168e
@@ -284,7 +292,7 @@ ssize_t qio_channel_readv(QIOChannel *ioc,
97168e
                           size_t niov,
97168e
                           Error **errp)
97168e
 {
97168e
-    return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
97168e
+    return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, 0, errp);
97168e
 }
97168e
 
97168e
 
97168e
@@ -303,7 +311,7 @@ ssize_t qio_channel_read(QIOChannel *ioc,
97168e
                          Error **errp)
97168e
 {
97168e
     struct iovec iov = { .iov_base = buf, .iov_len = buflen };
97168e
-    return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
97168e
+    return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, 0, errp);
97168e
 }
97168e
 
97168e
 
97168e
diff --git a/migration/rdma.c b/migration/rdma.c
97168e
index 54acd2000e..dcf98bd7f8 100644
97168e
--- a/migration/rdma.c
97168e
+++ b/migration/rdma.c
97168e
@@ -2917,6 +2917,7 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
97168e
                                       size_t niov,
97168e
                                       int **fds,
97168e
                                       size_t *nfds,
97168e
+                                      int flags,
97168e
                                       Error **errp)
97168e
 {
97168e
     QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc);
97168e
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
97168e
index f281daeced..12ec8e9368 100644
97168e
--- a/scsi/qemu-pr-helper.c
97168e
+++ b/scsi/qemu-pr-helper.c
97168e
@@ -612,7 +612,7 @@ static int coroutine_fn prh_read(PRHelperClient *client, void *buf, int sz,
97168e
         iov.iov_base = buf;
97168e
         iov.iov_len = sz;
97168e
         n_read = qio_channel_readv_full(QIO_CHANNEL(client->ioc), &iov, 1,
97168e
-                                        &fds, &nfds, errp);
97168e
+                                        &fds, &nfds, 0, errp);
97168e
 
97168e
         if (n_read == QIO_CHANNEL_ERR_BLOCK) {
97168e
             qio_channel_yield(QIO_CHANNEL(client->ioc), G_IO_IN);
97168e
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
97168e
index 2994d1cf42..3cf1acaf7d 100644
97168e
--- a/tests/qtest/tpm-emu.c
97168e
+++ b/tests/qtest/tpm-emu.c
97168e
@@ -106,7 +106,7 @@ void *tpm_emu_ctrl_thread(void *data)
97168e
         int *pfd = NULL;
97168e
         size_t nfd = 0;
97168e
 
97168e
-        qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort);
97168e
+        qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, 0, &error_abort);
97168e
         cmd = be32_to_cpu(cmd);
97168e
         g_assert_cmpint(cmd, ==, CMD_SET_DATAFD);
97168e
         g_assert_cmpint(nfd, ==, 1);
97168e
diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c
97168e
index 6713886d02..de2930f203 100644
97168e
--- a/tests/unit/test-io-channel-socket.c
97168e
+++ b/tests/unit/test-io-channel-socket.c
97168e
@@ -452,6 +452,7 @@ static void test_io_channel_unix_fd_pass(void)
97168e
                            G_N_ELEMENTS(iorecv),
97168e
                            &fdrecv,
97168e
                            &nfdrecv,
97168e
+                           0,
97168e
                            &error_abort);
97168e
 
97168e
     g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
97168e
diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
97168e
index 783d847a6d..e6a9ef72b7 100644
97168e
--- a/util/vhost-user-server.c
97168e
+++ b/util/vhost-user-server.c
97168e
@@ -102,7 +102,7 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
97168e
          * qio_channel_readv_full may have short reads, keeping calling it
97168e
          * until getting VHOST_USER_HDR_SIZE or 0 bytes in total
97168e
          */
97168e
-        rc = qio_channel_readv_full(ioc, &iov, 1, &fds, &nfds, &local_err);
97168e
+        rc = qio_channel_readv_full(ioc, &iov, 1, &fds, &nfds, 0, &local_err);
97168e
         if (rc < 0) {
97168e
             if (rc == QIO_CHANNEL_ERR_BLOCK) {
97168e
                 assert(local_err == NULL);
97168e
-- 
97168e
2.37.3
97168e