pespin has submitted this change. ( 
https://gerrit.osmocom.org/c/libosmocore/+/41832?usp=email )

Change subject: omo_io: poll: Support multiple iov on all read/write variants
......................................................................

omo_io: poll: Support multiple iov on all read/write variants

The logic was already in place for io_uring, but was missing for poll
backend. So this patch mainly takes the existing logic from there and
adapts it to poll.
This way we can get some easy optimizations even when using poll(),
for programs doing multiple msgb sends on the same event loop iteration.

Related: OS#6705
Change-Id: I64a2a6725f91b5e5f575c6fc104bd58b50063873
---
M src/core/osmo_io.c
M src/core/osmo_io_poll.c
2 files changed, 87 insertions(+), 35 deletions(-)

Approvals:
  daniel: Looks good to me, but someone else must approve
  Jenkins Builder: Verified
  pespin: Looks good to me, approved
  laforge: Looks good to me, but someone else must approve
  osmith: Looks good to me, but someone else must approve




diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c
index 10e6e3f..b28f170 100644
--- a/src/core/osmo_io.c
+++ b/src/core/osmo_io.c
@@ -857,9 +857,6 @@
        if (iofd->mode != OSMO_IO_FD_MODE_READ_WRITE)
                return -EINVAL;

-       if (g_io_backend != OSMO_IO_BACKEND_IO_URING)
-               return -EINVAL;
-
        if (buffers < 1 || buffers > IOFD_MSGHDR_IO_BUFFERS)
                return -EINVAL;

diff --git a/src/core/osmo_io_poll.c b/src/core/osmo_io_poll.c
index d27a5d6..c37d436 100644
--- a/src/core/osmo_io_poll.c
+++ b/src/core/osmo_io_poll.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <stdbool.h>
 #include <sys/socket.h>
+#include <sys/uio.h>

 #include <osmocom/core/osmo_io.h>
 #include <osmocom/core/linuxlist.h>
@@ -41,62 +42,116 @@

 #include "osmo_io_internal.h"

+/*! completion call-back for READ */
+static void iofd_poll_handle_recv(struct iofd_msghdr *msghdr, int rc)
+{
+       struct osmo_io_fd *iofd = msghdr->iofd;
+       uint8_t idx;
+
+       for (idx = 0; idx < msghdr->io_len; idx++) {
+               struct msgb *msg = msghdr->msg[idx];
+               int chunk;
+
+               msghdr->msg[idx] = NULL;
+               if (rc > 0) {
+                       if (rc > msghdr->iov[idx].iov_len)
+                               chunk = msghdr->iov[idx].iov_len;
+                       else
+                               chunk = rc;
+                       rc -= chunk;
+                       msgb_put(msg, chunk);
+               } else {
+                       chunk = rc;
+               }
+
+               /* Check for every iteration, because iofd might get 
unregistered/closed during receive function. */
+               if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_FD_REGISTERED) && 
(iofd->u.poll.ofd.when & OSMO_FD_READ))
+                       iofd_handle_recv(iofd, msg, chunk, msghdr);
+               else
+                       msgb_free(msg);
+
+               if (rc <= 0)
+                       break;
+       }
+       while (++idx < msghdr->io_len) {
+               msgb_free(msghdr->msg[idx]);
+               msghdr->msg[idx] = NULL;
+       }
+
+       iofd_msghdr_free(msghdr);
+}
+
 static void iofd_poll_ofd_cb_recvmsg_sendmsg(struct osmo_fd *ofd, unsigned int 
what)
 {
        struct osmo_io_fd *iofd = ofd->data;
-       struct msgb *msg;
-       int rc, flags = 0;
+       enum iofd_msg_action action;
+       struct iofd_msghdr *msghdr;
+       int rc;
+       uint8_t idx;

        if (what & OSMO_FD_READ) {
-               struct iofd_msghdr hdr;
-
-               msg = iofd_msgb_alloc(iofd);
-               if (!msg) {
-                       LOGPIO(iofd, LOGL_ERROR, "Could not allocate msgb for 
reading\n");
-                       OSMO_ASSERT(0);
-               }

                switch (iofd->mode) {
                case OSMO_IO_FD_MODE_READ_WRITE:
-                       rc = read(ofd->fd, msg->tail, msgb_tailroom(msg));
-                       if (rc > 0)
-                               msgb_put(msg, rc);
-                       iofd_handle_recv(iofd, msg, (rc < 0 && errno > 0) ? 
-errno : rc, NULL);
+                       action = IOFD_ACT_READ;
                        break;
                case OSMO_IO_FD_MODE_RECVFROM_SENDTO:
+                       action = IOFD_ACT_RECVFROM;
+                       break;
                case OSMO_IO_FD_MODE_RECVMSG_SENDMSG:
-                       hdr.msg[0] = msg;
-                       hdr.iov[0].iov_base = msg->tail;
-                       hdr.iov[0].iov_len = msgb_tailroom(msg);
-                       hdr.hdr = (struct msghdr) {
-                               .msg_iov = &hdr.iov[0],
-                               .msg_iovlen = 1,
-                               .msg_name = &hdr.osa.u.sa,
-                               .msg_namelen = sizeof(struct osmo_sockaddr),
-                       };
-                       if (iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG) {
-                               hdr.hdr.msg_control = alloca(iofd->cmsg_size);
-                               hdr.hdr.msg_controllen = iofd->cmsg_size;
-                       }
-                       rc = recvmsg(ofd->fd, &hdr.hdr, flags);
-                       if (rc > 0)
-                               msgb_put(msg, rc);
-                       iofd_handle_recv(iofd, msg, (rc < 0 && errno > 0) ? 
-errno : rc, &hdr);
+                       action = IOFD_ACT_RECVMSG;
                        break;
                default:
                        OSMO_ASSERT(0);
                }
+
+               msghdr = iofd_msghdr_alloc(iofd, action, NULL, iofd->cmsg_size);
+               for (idx = 0; idx < msghdr->io_len; idx++) {
+                       msghdr->iov[idx].iov_base = msghdr->msg[idx]->tail;
+                       msghdr->iov[idx].iov_len = 
msgb_tailroom(msghdr->msg[idx]);
+               }
+
+               switch (action) {
+               case IOFD_ACT_RECVMSG:
+                       msghdr->hdr.msg_control = msghdr->cmsg;
+                       msghdr->hdr.msg_controllen = iofd->cmsg_size;
+                       /* fall-through */
+               case IOFD_ACT_RECVFROM:
+                       msghdr->hdr.msg_name = &msghdr->osa.u.sa;
+                       msghdr->hdr.msg_namelen = 
osmo_sockaddr_size(&msghdr->osa);
+                       /* fall-through */
+               case IOFD_ACT_READ:
+                       msghdr->hdr.msg_iov = &msghdr->iov[0];
+                       msghdr->hdr.msg_iovlen = msghdr->io_len;
+                       break;
+               default:
+                       OSMO_ASSERT(0);
+               }
+
+               switch (action) {
+               case IOFD_ACT_READ:
+                       rc = readv(ofd->fd, msghdr->hdr.msg_iov, 
msghdr->hdr.msg_iovlen);
+                       break;
+               case IOFD_ACT_RECVFROM:
+               case IOFD_ACT_RECVMSG:
+                       rc = recvmsg(ofd->fd, &msghdr->hdr, msghdr->flags);
+                       break;
+               default:
+                       OSMO_ASSERT(0);
+               }
+
+               iofd_poll_handle_recv(msghdr, (rc < 0 && errno > 0) ? -errno : 
rc);
        }

        if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))
                return;

        if (what & OSMO_FD_WRITE) {
-               struct iofd_msghdr *msghdr = iofd_txqueue_dequeue(iofd);
+               msghdr = iofd_txqueue_dequeue(iofd);
                if (msghdr) {
                        switch (iofd->mode) {
                        case OSMO_IO_FD_MODE_READ_WRITE:
-                               rc = write(ofd->fd, msghdr->iov[0].iov_base, 
msghdr->iov[0].iov_len);
+                               rc = writev(ofd->fd, msghdr->iov, 
msghdr->io_len);
                                break;
                        case OSMO_IO_FD_MODE_RECVFROM_SENDTO:
                        case OSMO_IO_FD_MODE_RECVMSG_SENDMSG:

--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/41832?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I64a2a6725f91b5e5f575c6fc104bd58b50063873
Gerrit-Change-Number: 41832
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <[email protected]>
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: jolly <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to