thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone

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

7f1c5b
From 3a29b50036b972caae5bca0e5dfc34d910b1d5e9 Mon Sep 17 00:00:00 2001
7f1c5b
From: "manish.mishra" <manish.mishra@nutanix.com>
7f1c5b
Date: Tue, 20 Dec 2022 18:44:17 +0000
7f1c5b
Subject: [PATCH 6/8] io: Add support for MSG_PEEK for socket channel
7f1c5b
MIME-Version: 1.0
7f1c5b
Content-Type: text/plain; charset=UTF-8
7f1c5b
Content-Transfer-Encoding: 8bit
7f1c5b
7f1c5b
RH-Author: Peter Xu <peterx@redhat.com>
7f1c5b
RH-MergeRequest: 150: migration: Fix multifd crash on channel disorders
7f1c5b
RH-Bugzilla: 2169732
7f1c5b
RH-Acked-by: quintela1 <quintela@redhat.com>
7f1c5b
RH-Acked-by: Leonardo BrĂ¡s <leobras@redhat.com>
7f1c5b
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
7f1c5b
RH-Commit: [1/2] 266563f3e387e97ec710d9bc179e5de26dfd09f1 (peterx/qemu-kvm)
7f1c5b
7f1c5b
MSG_PEEK peeks at the channel, The data is treated as unread and
7f1c5b
the next read shall still return this data. This support is
7f1c5b
currently added only for socket class. Extra parameter 'flags'
7f1c5b
is added to io_readv calls to pass extra read flags like MSG_PEEK.
7f1c5b
7f1c5b
Reviewed-by: Peter Xu <peterx@redhat.com>
7f1c5b
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7f1c5b
Reviewed-by: Juan Quintela <quintela@redhat.com>
7f1c5b
Suggested-by: Daniel P. Berrange <berrange@redhat.com>
7f1c5b
Signed-off-by: manish.mishra <manish.mishra@nutanix.com>
7f1c5b
Signed-off-by: Juan Quintela <quintela@redhat.com>
7f1c5b
(cherry picked from commit 84615a19ddf2bfb38d7b3a0d487d2397ee55e4f3)
7f1c5b
Signed-off-by: Peter Xu <peterx@redhat.com>
7f1c5b
---
7f1c5b
 chardev/char-socket.c               |  4 ++--
7f1c5b
 include/io/channel.h                |  6 ++++++
7f1c5b
 io/channel-buffer.c                 |  1 +
7f1c5b
 io/channel-command.c                |  1 +
7f1c5b
 io/channel-file.c                   |  1 +
7f1c5b
 io/channel-null.c                   |  1 +
7f1c5b
 io/channel-socket.c                 | 19 ++++++++++++++++++-
7f1c5b
 io/channel-tls.c                    |  1 +
7f1c5b
 io/channel-websock.c                |  1 +
7f1c5b
 io/channel.c                        | 16 ++++++++++++----
7f1c5b
 migration/channel-block.c           |  1 +
7f1c5b
 migration/rdma.c                    |  1 +
7f1c5b
 scsi/qemu-pr-helper.c               |  2 +-
7f1c5b
 tests/qtest/tpm-emu.c               |  2 +-
7f1c5b
 tests/unit/test-io-channel-socket.c |  1 +
7f1c5b
 util/vhost-user-server.c            |  2 +-
7f1c5b
 16 files changed, 50 insertions(+), 10 deletions(-)
7f1c5b
7f1c5b
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
7f1c5b
index 879564aa8a..5afce9a464 100644
7f1c5b
--- a/chardev/char-socket.c
7f1c5b
+++ b/chardev/char-socket.c
7f1c5b
@@ -283,11 +283,11 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
7f1c5b
     if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
7f1c5b
         ret = qio_channel_readv_full(s->ioc, &iov, 1,
7f1c5b
                                      &msgfds, &msgfds_num,
7f1c5b
-                                     NULL);
7f1c5b
+                                     0, NULL);
7f1c5b
     } else {
7f1c5b
         ret = qio_channel_readv_full(s->ioc, &iov, 1,
7f1c5b
                                      NULL, NULL,
7f1c5b
-                                     NULL);
7f1c5b
+                                     0, NULL);
7f1c5b
     }
7f1c5b
 
7f1c5b
     if (msgfds_num) {
7f1c5b
diff --git a/include/io/channel.h b/include/io/channel.h
7f1c5b
index c680ee7480..716235d496 100644
7f1c5b
--- a/include/io/channel.h
7f1c5b
+++ b/include/io/channel.h
7f1c5b
@@ -34,6 +34,8 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
7f1c5b
 
7f1c5b
 #define QIO_CHANNEL_WRITE_FLAG_ZERO_COPY 0x1
7f1c5b
 
7f1c5b
+#define QIO_CHANNEL_READ_FLAG_MSG_PEEK 0x1
7f1c5b
+
7f1c5b
 typedef enum QIOChannelFeature QIOChannelFeature;
7f1c5b
 
7f1c5b
 enum QIOChannelFeature {
7f1c5b
@@ -41,6 +43,7 @@ enum QIOChannelFeature {
7f1c5b
     QIO_CHANNEL_FEATURE_SHUTDOWN,
7f1c5b
     QIO_CHANNEL_FEATURE_LISTEN,
7f1c5b
     QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY,
7f1c5b
+    QIO_CHANNEL_FEATURE_READ_MSG_PEEK,
7f1c5b
 };
7f1c5b
 
7f1c5b
 
7f1c5b
@@ -114,6 +117,7 @@ struct QIOChannelClass {
7f1c5b
                         size_t niov,
7f1c5b
                         int **fds,
7f1c5b
                         size_t *nfds,
7f1c5b
+                        int flags,
7f1c5b
                         Error **errp);
7f1c5b
     int (*io_close)(QIOChannel *ioc,
7f1c5b
                     Error **errp);
7f1c5b
@@ -188,6 +192,7 @@ void qio_channel_set_name(QIOChannel *ioc,
7f1c5b
  * @niov: the length of the @iov array
7f1c5b
  * @fds: pointer to an array that will received file handles
7f1c5b
  * @nfds: pointer filled with number of elements in @fds on return
7f1c5b
+ * @flags: read flags (QIO_CHANNEL_READ_FLAG_*)
7f1c5b
  * @errp: pointer to a NULL-initialized error object
7f1c5b
  *
7f1c5b
  * Read data from the IO channel, storing it in the
7f1c5b
@@ -224,6 +229,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
7f1c5b
                                size_t niov,
7f1c5b
                                int **fds,
7f1c5b
                                size_t *nfds,
7f1c5b
+                               int flags,
7f1c5b
                                Error **errp);
7f1c5b
 
7f1c5b
 
7f1c5b
diff --git a/io/channel-buffer.c b/io/channel-buffer.c
7f1c5b
index bf52011be2..8096180f85 100644
7f1c5b
--- a/io/channel-buffer.c
7f1c5b
+++ b/io/channel-buffer.c
7f1c5b
@@ -54,6 +54,7 @@ static ssize_t qio_channel_buffer_readv(QIOChannel *ioc,
7f1c5b
                                         size_t niov,
7f1c5b
                                         int **fds,
7f1c5b
                                         size_t *nfds,
7f1c5b
+                                        int flags,
7f1c5b
                                         Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
7f1c5b
diff --git a/io/channel-command.c b/io/channel-command.c
7f1c5b
index 74516252ba..e7edd091af 100644
7f1c5b
--- a/io/channel-command.c
7f1c5b
+++ b/io/channel-command.c
7f1c5b
@@ -203,6 +203,7 @@ static ssize_t qio_channel_command_readv(QIOChannel *ioc,
7f1c5b
                                          size_t niov,
7f1c5b
                                          int **fds,
7f1c5b
                                          size_t *nfds,
7f1c5b
+                                         int flags,
7f1c5b
                                          Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
7f1c5b
diff --git a/io/channel-file.c b/io/channel-file.c
7f1c5b
index b67687c2aa..d76663e6ae 100644
7f1c5b
--- a/io/channel-file.c
7f1c5b
+++ b/io/channel-file.c
7f1c5b
@@ -86,6 +86,7 @@ static ssize_t qio_channel_file_readv(QIOChannel *ioc,
7f1c5b
                                       size_t niov,
7f1c5b
                                       int **fds,
7f1c5b
                                       size_t *nfds,
7f1c5b
+                                      int flags,
7f1c5b
                                       Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
7f1c5b
diff --git a/io/channel-null.c b/io/channel-null.c
7f1c5b
index 75e3781507..4fafdb770d 100644
7f1c5b
--- a/io/channel-null.c
7f1c5b
+++ b/io/channel-null.c
7f1c5b
@@ -60,6 +60,7 @@ qio_channel_null_readv(QIOChannel *ioc,
7f1c5b
                        size_t niov,
7f1c5b
                        int **fds G_GNUC_UNUSED,
7f1c5b
                        size_t *nfds G_GNUC_UNUSED,
7f1c5b
+                       int flags,
7f1c5b
                        Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc);
7f1c5b
diff --git a/io/channel-socket.c b/io/channel-socket.c
7f1c5b
index b76dca9cc1..7aca84f61a 100644
7f1c5b
--- a/io/channel-socket.c
7f1c5b
+++ b/io/channel-socket.c
7f1c5b
@@ -173,6 +173,9 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
7f1c5b
     }
7f1c5b
 #endif
7f1c5b
 
7f1c5b
+    qio_channel_set_feature(QIO_CHANNEL(ioc),
7f1c5b
+                            QIO_CHANNEL_FEATURE_READ_MSG_PEEK);
7f1c5b
+
7f1c5b
     return 0;
7f1c5b
 }
7f1c5b
 
7f1c5b
@@ -406,6 +409,9 @@ qio_channel_socket_accept(QIOChannelSocket *ioc,
7f1c5b
     }
7f1c5b
 #endif /* WIN32 */
7f1c5b
 
7f1c5b
+    qio_channel_set_feature(QIO_CHANNEL(cioc),
7f1c5b
+                            QIO_CHANNEL_FEATURE_READ_MSG_PEEK);
7f1c5b
+
7f1c5b
     trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
7f1c5b
     return cioc;
7f1c5b
 
7f1c5b
@@ -496,6 +502,7 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
7f1c5b
                                         size_t niov,
7f1c5b
                                         int **fds,
7f1c5b
                                         size_t *nfds,
7f1c5b
+                                        int flags,
7f1c5b
                                         Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
7f1c5b
@@ -517,6 +524,10 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
7f1c5b
 
7f1c5b
     }
7f1c5b
 
7f1c5b
+    if (flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) {
7f1c5b
+        sflags |= MSG_PEEK;
7f1c5b
+    }
7f1c5b
+
7f1c5b
  retry:
7f1c5b
     ret = recvmsg(sioc->fd, &msg, sflags);
7f1c5b
     if (ret < 0) {
7f1c5b
@@ -624,11 +635,17 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
7f1c5b
                                         size_t niov,
7f1c5b
                                         int **fds,
7f1c5b
                                         size_t *nfds,
7f1c5b
+                                        int flags,
7f1c5b
                                         Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
7f1c5b
     ssize_t done = 0;
7f1c5b
     ssize_t i;
7f1c5b
+    int sflags = 0;
7f1c5b
+
7f1c5b
+    if (flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) {
7f1c5b
+        sflags |= MSG_PEEK;
7f1c5b
+    }
7f1c5b
 
7f1c5b
     for (i = 0; i < niov; i++) {
7f1c5b
         ssize_t ret;
7f1c5b
@@ -636,7 +653,7 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
7f1c5b
         ret = recv(sioc->fd,
7f1c5b
                    iov[i].iov_base,
7f1c5b
                    iov[i].iov_len,
7f1c5b
-                   0);
7f1c5b
+                   sflags);
7f1c5b
         if (ret < 0) {
7f1c5b
             if (errno == EAGAIN) {
7f1c5b
                 if (done) {
7f1c5b
diff --git a/io/channel-tls.c b/io/channel-tls.c
7f1c5b
index 4ce890a538..c730cb8ec5 100644
7f1c5b
--- a/io/channel-tls.c
7f1c5b
+++ b/io/channel-tls.c
7f1c5b
@@ -260,6 +260,7 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
7f1c5b
                                      size_t niov,
7f1c5b
                                      int **fds,
7f1c5b
                                      size_t *nfds,
7f1c5b
+                                     int flags,
7f1c5b
                                      Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
7f1c5b
diff --git a/io/channel-websock.c b/io/channel-websock.c
7f1c5b
index fb4932ade7..a12acc27cf 100644
7f1c5b
--- a/io/channel-websock.c
7f1c5b
+++ b/io/channel-websock.c
7f1c5b
@@ -1081,6 +1081,7 @@ static ssize_t qio_channel_websock_readv(QIOChannel *ioc,
7f1c5b
                                          size_t niov,
7f1c5b
                                          int **fds,
7f1c5b
                                          size_t *nfds,
7f1c5b
+                                         int flags,
7f1c5b
                                          Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
7f1c5b
diff --git a/io/channel.c b/io/channel.c
7f1c5b
index 0640941ac5..a8c7f11649 100644
7f1c5b
--- a/io/channel.c
7f1c5b
+++ b/io/channel.c
7f1c5b
@@ -52,6 +52,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
7f1c5b
                                size_t niov,
7f1c5b
                                int **fds,
7f1c5b
                                size_t *nfds,
7f1c5b
+                               int flags,
7f1c5b
                                Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
7f1c5b
@@ -63,7 +64,14 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
7f1c5b
         return -1;
7f1c5b
     }
7f1c5b
 
7f1c5b
-    return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
7f1c5b
+    if ((flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) &&
7f1c5b
+        !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
7f1c5b
+        error_setg_errno(errp, EINVAL,
7f1c5b
+                         "Channel does not support peek read");
7f1c5b
+        return -1;
7f1c5b
+    }
7f1c5b
+
7f1c5b
+    return klass->io_readv(ioc, iov, niov, fds, nfds, flags, errp);
7f1c5b
 }
7f1c5b
 
7f1c5b
 
7f1c5b
@@ -146,7 +154,7 @@ int qio_channel_readv_full_all_eof(QIOChannel *ioc,
7f1c5b
     while ((nlocal_iov > 0) || local_fds) {
7f1c5b
         ssize_t len;
7f1c5b
         len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
7f1c5b
-                                     local_nfds, errp);
7f1c5b
+                                     local_nfds, 0, errp);
7f1c5b
         if (len == QIO_CHANNEL_ERR_BLOCK) {
7f1c5b
             if (qemu_in_coroutine()) {
7f1c5b
                 qio_channel_yield(ioc, G_IO_IN);
7f1c5b
@@ -284,7 +292,7 @@ ssize_t qio_channel_readv(QIOChannel *ioc,
7f1c5b
                           size_t niov,
7f1c5b
                           Error **errp)
7f1c5b
 {
7f1c5b
-    return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
7f1c5b
+    return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, 0, errp);
7f1c5b
 }
7f1c5b
 
7f1c5b
 
7f1c5b
@@ -303,7 +311,7 @@ ssize_t qio_channel_read(QIOChannel *ioc,
7f1c5b
                          Error **errp)
7f1c5b
 {
7f1c5b
     struct iovec iov = { .iov_base = buf, .iov_len = buflen };
7f1c5b
-    return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
7f1c5b
+    return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, 0, errp);
7f1c5b
 }
7f1c5b
 
7f1c5b
 
7f1c5b
diff --git a/migration/channel-block.c b/migration/channel-block.c
7f1c5b
index f4ab53acdb..b7374363c3 100644
7f1c5b
--- a/migration/channel-block.c
7f1c5b
+++ b/migration/channel-block.c
7f1c5b
@@ -53,6 +53,7 @@ qio_channel_block_readv(QIOChannel *ioc,
7f1c5b
                         size_t niov,
7f1c5b
                         int **fds,
7f1c5b
                         size_t *nfds,
7f1c5b
+                        int flags,
7f1c5b
                         Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc);
7f1c5b
diff --git a/migration/rdma.c b/migration/rdma.c
7f1c5b
index 94a55dd95b..d8b4632094 100644
7f1c5b
--- a/migration/rdma.c
7f1c5b
+++ b/migration/rdma.c
7f1c5b
@@ -2854,6 +2854,7 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
7f1c5b
                                       size_t niov,
7f1c5b
                                       int **fds,
7f1c5b
                                       size_t *nfds,
7f1c5b
+                                      int flags,
7f1c5b
                                       Error **errp)
7f1c5b
 {
7f1c5b
     QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc);
7f1c5b
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
7f1c5b
index 196b78c00d..199227a556 100644
7f1c5b
--- a/scsi/qemu-pr-helper.c
7f1c5b
+++ b/scsi/qemu-pr-helper.c
7f1c5b
@@ -614,7 +614,7 @@ static int coroutine_fn prh_read(PRHelperClient *client, void *buf, int sz,
7f1c5b
         iov.iov_base = buf;
7f1c5b
         iov.iov_len = sz;
7f1c5b
         n_read = qio_channel_readv_full(QIO_CHANNEL(client->ioc), &iov, 1,
7f1c5b
-                                        &fds, &nfds, errp);
7f1c5b
+                                        &fds, &nfds, 0, errp);
7f1c5b
 
7f1c5b
         if (n_read == QIO_CHANNEL_ERR_BLOCK) {
7f1c5b
             qio_channel_yield(QIO_CHANNEL(client->ioc), G_IO_IN);
7f1c5b
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
7f1c5b
index 2994d1cf42..3cf1acaf7d 100644
7f1c5b
--- a/tests/qtest/tpm-emu.c
7f1c5b
+++ b/tests/qtest/tpm-emu.c
7f1c5b
@@ -106,7 +106,7 @@ void *tpm_emu_ctrl_thread(void *data)
7f1c5b
         int *pfd = NULL;
7f1c5b
         size_t nfd = 0;
7f1c5b
 
7f1c5b
-        qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort);
7f1c5b
+        qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, 0, &error_abort);
7f1c5b
         cmd = be32_to_cpu(cmd);
7f1c5b
         g_assert_cmpint(cmd, ==, CMD_SET_DATAFD);
7f1c5b
         g_assert_cmpint(nfd, ==, 1);
7f1c5b
diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c
7f1c5b
index b36a5d972a..b964bb202d 100644
7f1c5b
--- a/tests/unit/test-io-channel-socket.c
7f1c5b
+++ b/tests/unit/test-io-channel-socket.c
7f1c5b
@@ -460,6 +460,7 @@ static void test_io_channel_unix_fd_pass(void)
7f1c5b
                            G_N_ELEMENTS(iorecv),
7f1c5b
                            &fdrecv,
7f1c5b
                            &nfdrecv,
7f1c5b
+                           0,
7f1c5b
                            &error_abort);
7f1c5b
 
7f1c5b
     g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
7f1c5b
diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
7f1c5b
index 232984ace6..145eb17c08 100644
7f1c5b
--- a/util/vhost-user-server.c
7f1c5b
+++ b/util/vhost-user-server.c
7f1c5b
@@ -116,7 +116,7 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
7f1c5b
          * qio_channel_readv_full may have short reads, keeping calling it
7f1c5b
          * until getting VHOST_USER_HDR_SIZE or 0 bytes in total
7f1c5b
          */
7f1c5b
-        rc = qio_channel_readv_full(ioc, &iov, 1, &fds, &nfds, &local_err);
7f1c5b
+        rc = qio_channel_readv_full(ioc, &iov, 1, &fds, &nfds, 0, &local_err);
7f1c5b
         if (rc < 0) {
7f1c5b
             if (rc == QIO_CHANNEL_ERR_BLOCK) {
7f1c5b
                 assert(local_err == NULL);
7f1c5b
-- 
7f1c5b
2.31.1
7f1c5b