laforge has submitted this change. (
https://gerrit.osmocom.org/c/libosmocore/+/40492?usp=email )
Change subject: Add multiple messages buffers to io_uring read operations
......................................................................
Add multiple messages buffers to io_uring read operations
Multiple message buffers can be read by receiving a single CQE when
using io_uring. If there is less data available than available buffers,
not all buffers will be filled.
Having more than one buffer is optional and the number can be controlled
via environment variable.
Related: OS#6705
Change-Id: Ic4544b8fcbad5a266db748d6864d3ae93ee06bce
---
M src/core/osmo_io.c
M src/core/osmo_io_uring.c
2 files changed, 60 insertions(+), 24 deletions(-)
Approvals:
pespin: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c
index 72e30c1..46885aa 100644
--- a/src/core/osmo_io.c
+++ b/src/core/osmo_io.c
@@ -138,29 +138,38 @@
struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action
action, struct msgb *msg,
size_t cmsg_size)
{
- bool free_msg = false;
struct iofd_msghdr *hdr;
+ uint8_t idx, io_len;
- if (!msg) {
- msg = iofd_msgb_alloc(iofd);
- if (!msg)
- return NULL;
- free_msg = true;
- } else {
- talloc_steal(iofd, msg);
- }
hdr = talloc_zero_size(iofd, sizeof(struct iofd_msghdr) + cmsg_size);
- if (!hdr) {
- if (free_msg)
- talloc_free(msg);
+ if (!hdr)
return NULL;
- }
hdr->action = action;
hdr->iofd = iofd;
- hdr->msg[0] = msg;
- hdr->io_len = 1;
+
+ /* Allocate the number of read buffers, configured by the user. Use msg as first buffer,
if not NULL.
+ * Only READ may have multiple buffers, because packets will only be written to the
first buffer. */
+ io_len = (action == IOFD_ACT_READ) ? iofd->io_read_buffers : 1;
+ for (idx = 0; idx < io_len; idx++) {
+ if (msg) {
+ talloc_steal(iofd, msg);
+ hdr->msg[idx] = msg;
+ msg = NULL;
+ } else {
+ hdr->msg[idx] = iofd_msgb_alloc(iofd);
+ if (!hdr->msg[idx])
+ break;
+ }
+ }
+ /* If at least one msgb is allocated, we can continue with only one msgb, instead of
completely failing. */
+ if (idx == 0) {
+ talloc_free(hdr);
+ return NULL;
+ }
+
+ hdr->io_len = idx;
return hdr;
}
diff --git a/src/core/osmo_io_uring.c b/src/core/osmo_io_uring.c
index fff632c..754a39a 100644
--- a/src/core/osmo_io_uring.c
+++ b/src/core/osmo_io_uring.c
@@ -139,6 +139,7 @@
struct msgb *msg;
struct iofd_msghdr *msghdr;
struct io_uring_sqe *sqe;
+ uint8_t idx;
msg = iofd_msgb_alloc(iofd);
if (!msg) {
@@ -152,8 +153,10 @@
OSMO_ASSERT(0);
}
- msghdr->iov[0].iov_base = msg->tail;
- msghdr->iov[0].iov_len = msgb_tailroom(msg);
+ 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:
@@ -166,7 +169,7 @@
/* fall-through */
case IOFD_ACT_READ:
msghdr->hdr.msg_iov = &msghdr->iov[0];
- msghdr->hdr.msg_iovlen = 1;
+ msghdr->hdr.msg_iovlen = msghdr->io_len;
break;
default:
OSMO_ASSERT(0);
@@ -180,7 +183,7 @@
switch (action) {
case IOFD_ACT_READ:
- io_uring_prep_readv(sqe, iofd->fd, msghdr->iov, 1, -1);
+ io_uring_prep_readv(sqe, iofd->fd, msghdr->iov, msghdr->hdr.msg_iovlen, -1);
break;
case IOFD_ACT_RECVMSG:
case IOFD_ACT_RECVFROM:
@@ -201,13 +204,37 @@
static void iofd_uring_handle_recv(struct iofd_msghdr *msghdr, int rc)
{
struct osmo_io_fd *iofd = msghdr->iofd;
- struct msgb *msg = msghdr->msg[0];
+ uint8_t idx;
- if (rc > 0)
- msgb_put(msg, rc);
+ for (idx = 0; idx < msghdr->io_len; idx++) {
+ struct msgb *msg = msghdr->msg[idx];
+ int chunk;
- if (!IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))
- iofd_handle_recv(iofd, msg, rc, msghdr);
+ 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->u.uring.read_enabled && !IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))
+ 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;
+ }
if (iofd->u.uring.read_enabled && !IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))
iofd_uring_submit_recv(iofd, msghdr->action);
--
To view, visit
https://gerrit.osmocom.org/c/libosmocore/+/40492?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: Ic4544b8fcbad5a266db748d6864d3ae93ee06bce
Gerrit-Change-Number: 40492
Gerrit-PatchSet: 13
Gerrit-Owner: jolly <andreas(a)eversberg.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>