laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/40760?usp=email )
Change subject: osmo-io: Put together message buffers when dequeued from tx queue
......................................................................
osmo-io: Put together message buffers when dequeued from tx queue
Write operations may be incomplete. osmo-io processs will remove
complete message buffers after a write operation from msghdr and put
the msghdr with the remaining buffers back into tx_queue.
If the user requests multiple messages buffers per write operation, the
msghdr of an incomplete write may have less message buffers than the
user requested. The remaining buffers are buffers are taken from next
msghdr in the queue, if exists.
Change-Id: I97c366211dd266fd58ec252890ec017d6d334534
---
M src/core/osmo_io.c
1 file changed, 36 insertions(+), 5 deletions(-)
Approvals:
pespin: Looks good to me, approved
laforge: Looks good to me, but someone else must approve
Jenkins Builder: Verified
diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c
index bfc75c6..62d2362 100644
--- a/src/core/osmo_io.c
+++ b/src/core/osmo_io.c
@@ -247,21 +247,52 @@
*/
struct iofd_msghdr *iofd_txqueue_dequeue(struct osmo_io_fd *iofd)
{
- struct llist_head *lh;
+ struct iofd_msghdr *msghdr;
if (iofd->tx_queue.current_length == 0)
return NULL;
- lh = iofd->tx_queue.msg_queue.next;
+ msghdr = llist_first_entry_or_null(&iofd->tx_queue.msg_queue, struct iofd_msghdr, list);
- OSMO_ASSERT(lh);
+ OSMO_ASSERT(msghdr);
iofd->tx_queue.current_length--;
- llist_del(lh);
+ llist_del(&msghdr->list);
+
+ /* Fill up empty buffers in dequeued msghdr with buffers from the next msghdr.
+ * There can be empty buffers, when a msghdr is queued to the front with incomplete write. */
+ while (OSMO_UNLIKELY(msghdr->io_len < iofd->io_write_buffers)) {
+ struct iofd_msghdr *next;
+ int i;
+
+ if (iofd->tx_queue.current_length == 0)
+ break;
+ next = llist_first_entry_or_null(&iofd->tx_queue.msg_queue, struct iofd_msghdr, list);
+ OSMO_ASSERT(next->io_len > 0);
+ /* Get first message buffer from next msghdr and store them in the dequeued one. */
+ msghdr->iov[msghdr->io_len] = next->iov[0];
+ msghdr->msg[msghdr->io_len] = next->msg[0];
+ msghdr->hdr.msg_iovlen = ++msghdr->io_len;
+ /* Remove the message buffer from the next msghdr and free, if empty. */
+ next->io_len--;
+ for (i = 0; i < next->io_len; i++) {
+ next->iov[i] = next->iov[i + 1];
+ next->msg[i] = next->msg[i + 1];
+ }
+ if (next->io_len == 0) {
+ iofd->tx_queue.current_length--;
+ llist_del(&next->list);
+ iofd_msghdr_free(next);
+ } else {
+ memset(&next->iov[next->io_len], 0, sizeof(struct iovec));
+ next->msg[next->io_len] = NULL;
+ next->hdr.msg_iovlen = --next->io_len;
+ }
+ }
if (iofd->tx_queue.current_length == 0)
osmo_iofd_ops.write_disable(iofd);
- return llist_entry(lh, struct iofd_msghdr, list);
+ return msghdr;
}
/*! Handle segmentation of the msg. If this function returns *_HANDLE_ONE or MORE then the data in msg will contain
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/40760?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: I97c366211dd266fd58ec252890ec017d6d334534
Gerrit-Change-Number: 40760
Gerrit-PatchSet: 7
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>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/40491?usp=email )
Change subject: Add multiple messages buffers to struct iofd_msghdr
......................................................................
Add multiple messages buffers to struct iofd_msghdr
This is a prerequisite for transfering multiple buffers with a single
SQE or CQE when using osmo_io with io_uring.
The message buffers at struct iofd_msghr, as well as the io vectors are
arrays. A maximum number is stored, as well as the current number.
As this patch does not implement multiple buffers yet, only index 0 of a
message buffer is used. (msg[0])
Having more than one buffer is optional and the number can be controlled
via environment variable.
Related: OS#6705
Change-Id: I4fb1067de4615cc22cc6caf99b481491e7f2ef92
---
M include/osmocom/core/osmo_io.h
M src/core/libosmocore.map
M src/core/osmo_io.c
M src/core/osmo_io_internal.h
M src/core/osmo_io_poll.c
M src/core/osmo_io_uring.c
6 files changed, 74 insertions(+), 16 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, approved
diff --git a/include/osmocom/core/osmo_io.h b/include/osmocom/core/osmo_io.h
index c8b8517..0b3dc83 100644
--- a/include/osmocom/core/osmo_io.h
+++ b/include/osmocom/core/osmo_io.h
@@ -70,6 +70,14 @@
OSMO_IO_FD_MODE_RECVMSG_SENDMSG,
};
+/*! The _operation_ of an osmo_io_fd determines if read or write operation are to be configured used. */
+enum osmo_io_op {
+ /*! change parameters for read() */
+ OSMO_IO_OP_READ,
+ /*! change parameters for write() */
+ OSMO_IO_OP_WRITE,
+};
+
/*! The back-end used by osmo_io. There can be multiple different back-ends available on a given system;
* only one of it is used for all I/O performed via osmo_io in one given process. */
enum osmo_io_backend {
@@ -204,6 +212,7 @@
struct osmo_io_fd *osmo_iofd_setup(const void *ctx, int fd, const char *name,
enum osmo_io_fd_mode mode, const struct osmo_io_ops *ioops, void *data);
int osmo_iofd_set_cmsg_size(struct osmo_io_fd *iofd, size_t cmsg_size);
+int osmo_iofd_set_io_buffers(struct osmo_io_fd *iofd, enum osmo_io_op op, uint8_t buffers);
int osmo_iofd_register(struct osmo_io_fd *iofd, int fd);
int osmo_iofd_unregister(struct osmo_io_fd *iofd);
unsigned int osmo_iofd_txqueue_len(struct osmo_io_fd *iofd);
diff --git a/src/core/libosmocore.map b/src/core/libosmocore.map
index b48c4e6..239597c 100644
--- a/src/core/libosmocore.map
+++ b/src/core/libosmocore.map
@@ -275,6 +275,7 @@
osmo_iofd_sendmsg_msgb;
osmo_iofd_set_alloc_info;
osmo_iofd_set_cmsg_size;
+osmo_iofd_set_io_buffers;
osmo_iofd_set_data;
osmo_iofd_set_ioops;
osmo_iofd_set_priv_nr;
diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c
index 6b4b919..72e30c1 100644
--- a/src/core/osmo_io.c
+++ b/src/core/osmo_io.c
@@ -159,7 +159,8 @@
hdr->action = action;
hdr->iofd = iofd;
- hdr->msg = msg;
+ hdr->msg[0] = msg;
+ hdr->io_len = 1;
return hdr;
}
@@ -407,7 +408,7 @@
*/
void iofd_handle_send_completion(struct osmo_io_fd *iofd, int rc, struct iofd_msghdr *msghdr)
{
- struct msgb *msg = msghdr->msg;
+ struct msgb *msg = msghdr->msg[0];
/* Incomplete write */
if (rc > 0 && rc < msgb_length(msg)) {
@@ -442,7 +443,7 @@
OSMO_ASSERT(0);
}
- msgb_free(msghdr->msg);
+ msgb_free(msghdr->msg[0]);
iofd_msghdr_free(msghdr);
}
@@ -478,8 +479,8 @@
return -ENOMEM;
msghdr->flags = MSG_NOSIGNAL;
- msghdr->iov[0].iov_base = msgb_data(msghdr->msg);
- msghdr->iov[0].iov_len = msgb_length(msghdr->msg);
+ msghdr->iov[0].iov_base = msgb_data(msghdr->msg[0]);
+ msghdr->iov[0].iov_len = msgb_length(msghdr->msg[0]);
msghdr->hdr.msg_iov = &msghdr->iov[0];
msghdr->hdr.msg_iovlen = 1;
@@ -530,8 +531,8 @@
msghdr->hdr.msg_namelen = osmo_sockaddr_size(&msghdr->osa);
}
msghdr->flags = sendto_flags;
- msghdr->iov[0].iov_base = msgb_data(msghdr->msg);
- msghdr->iov[0].iov_len = msgb_length(msghdr->msg);
+ msghdr->iov[0].iov_base = msgb_data(msghdr->msg[0]);
+ msghdr->iov[0].iov_len = msgb_length(msghdr->msg[0]);
msghdr->hdr.msg_iov = &msghdr->iov[0];
msghdr->hdr.msg_iovlen = 1;
@@ -595,8 +596,8 @@
}
/* build iov from msgb */
- msghdr->iov[0].iov_base = msgb_data(msghdr->msg);
- msghdr->iov[0].iov_len = msgb_length(msghdr->msg);
+ msghdr->iov[0].iov_base = msgb_data(msghdr->msg[0]);
+ msghdr->iov[0].iov_len = msgb_length(msghdr->msg[0]);
msghdr->hdr.msg_iov = &msghdr->iov[0];
msghdr->hdr.msg_iovlen = 1;
@@ -724,6 +725,9 @@
iofd->tx_queue.max_length = 1024;
INIT_LLIST_HEAD(&iofd->tx_queue.msg_queue);
+ iofd->io_read_buffers = 1;
+ iofd->io_write_buffers = 1;
+
return iofd;
}
@@ -741,6 +745,41 @@
return 0;
}
+/*! Set the number of buffers that can be used in a single read or write operation.
+ *
+ * If the osmo_io_fd is in OSMO_IO_FD_MODE_READ_WRITE mode, this API function can be used to tell the
+ * osmo_io proecess how many buffers should be read or written with a single read or write operation.
+ * This feature is supported with io_uring backend only.
+ *
+ * \param[in] iofd the iofd file descriptor
+ * \param[in] op the osmo_io_op (read or write) to set the number of IO buffers for
+ * \param[in] buffers the number of IO buffer for each specified operation
+ * \returns zero on success, a negative value on error
+ */
+int osmo_iofd_set_io_buffers(struct osmo_io_fd *iofd, enum osmo_io_op op, uint8_t buffers)
+{
+ 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;
+
+ switch (op) {
+ case OSMO_IO_OP_READ:
+ iofd->io_read_buffers = buffers;
+ break;
+ case OSMO_IO_OP_WRITE:
+ iofd->io_write_buffers = buffers;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
/*! Register the osmo_io_fd for active I/O.
*
* Calling this function will register a previously initialized osmo_io_fd for performing I/O.
@@ -836,7 +875,7 @@
{
struct iofd_msghdr *hdr;
while ((hdr = iofd_txqueue_dequeue(iofd))) {
- msgb_free(hdr->msg);
+ msgb_free(hdr->msg[0]);
iofd_msghdr_free(hdr);
}
}
diff --git a/src/core/osmo_io_internal.h b/src/core/osmo_io_internal.h
index 79b3fa9..d28e3d7 100644
--- a/src/core/osmo_io_internal.h
+++ b/src/core/osmo_io_internal.h
@@ -76,6 +76,12 @@
/*! size of iofd_msghdr.cmsg[] when allocated in recvmsg path */
size_t cmsg_size;
+ /*! maximum number of message-buffers per read operation */
+ uint8_t io_read_buffers;
+
+ /*! maximum number of message-buffers per write operation */
+ uint8_t io_write_buffers;
+
struct {
/*! talloc context from which to allocate msgb when reading */
const void *ctx;
@@ -119,6 +125,7 @@
IOFD_ACT_SENDMSG,
};
+#define IOFD_MSGHDR_IO_BUFFERS 8
/*! serialized version of 'struct msghdr' employed by sendmsg/recvmsg */
struct iofd_msghdr {
@@ -131,12 +138,14 @@
struct osmo_sockaddr osa;
/*! io-vector we need to pass as argument to sendmsg/recvmsg; is set up
* to point into msg below */
- struct iovec iov[1];
+ struct iovec iov[IOFD_MSGHDR_IO_BUFFERS];
/*! flags we pass as argument to sendmsg / recvmsg */
int flags;
+ /*! current number of message-buffers that are stored */
+ uint8_t io_len;
/*! message-buffer containing data for this I/O operation */
- struct msgb *msg;
+ struct msgb *msg[IOFD_MSGHDR_IO_BUFFERS];
/*! I/O file descriptor on which we perform this I/O operation */
struct osmo_io_fd *iofd;
diff --git a/src/core/osmo_io_poll.c b/src/core/osmo_io_poll.c
index 466973d..d27a5d6 100644
--- a/src/core/osmo_io_poll.c
+++ b/src/core/osmo_io_poll.c
@@ -65,7 +65,7 @@
break;
case OSMO_IO_FD_MODE_RECVFROM_SENDTO:
case OSMO_IO_FD_MODE_RECVMSG_SENDMSG:
- hdr.msg = msg;
+ hdr.msg[0] = msg;
hdr.iov[0].iov_base = msg->tail;
hdr.iov[0].iov_len = msgb_tailroom(msg);
hdr.hdr = (struct msghdr) {
diff --git a/src/core/osmo_io_uring.c b/src/core/osmo_io_uring.c
index 17853b6..fff632c 100644
--- a/src/core/osmo_io_uring.c
+++ b/src/core/osmo_io_uring.c
@@ -201,7 +201,7 @@
static void iofd_uring_handle_recv(struct iofd_msghdr *msghdr, int rc)
{
struct osmo_io_fd *iofd = msghdr->iofd;
- struct msgb *msg = msghdr->msg;
+ struct msgb *msg = msghdr->msg[0];
if (rc > 0)
msgb_put(msg, rc);
@@ -235,7 +235,7 @@
iofd->u.uring.write_msghdr = NULL;
if (OSMO_UNLIKELY(IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))) {
- msgb_free(msghdr->msg);
+ msgb_free(msghdr->msg[0]);
iofd_msghdr_free(msghdr);
} else {
iofd_handle_send_completion(iofd, rc, msghdr);
@@ -431,7 +431,7 @@
LOGPIO(iofd, LOGL_DEBUG, "Cancelling write\n");
iofd->u.uring.write_msghdr = NULL;
talloc_steal(OTC_GLOBAL, msghdr);
- msgb_free(msghdr->msg);
+ msgb_free(msghdr->msg[0]);
msghdr->iofd = NULL;
io_uring_prep_cancel(sqe, msghdr, 0);
}
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/40491?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: I4fb1067de4615cc22cc6caf99b481491e7f2ef92
Gerrit-Change-Number: 40491
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>
Attention is currently required from: jolly.
laforge has posted comments on this change by jolly. ( https://gerrit.osmocom.org/c/libosmocore/+/40856?usp=email )
Change subject: Put all io_uring related read and write states into sub structures
......................................................................
Patch Set 5: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/40856?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I3cf4ab6d9aebf5532ad174c90c7b0e9633491c88
Gerrit-Change-Number: 40856
Gerrit-PatchSet: 5
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>
Gerrit-Attention: jolly <andreas(a)eversberg.eu>
Gerrit-Comment-Date: Thu, 18 Sep 2025 09:41:53 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Attention is currently required from: jolly, pespin.
laforge has posted comments on this change by jolly. ( https://gerrit.osmocom.org/c/libosmocore/+/40725?usp=email )
Change subject: Automatically increase io_uring, if too small.
......................................................................
Patch Set 14: Code-Review+2
(1 comment)
Patchset:
PS2:
> I think having two rings and gradually migrating over is clean, and we can test the scenario by runn […]
Done
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/40725?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Id9230146acc8d54bfd44834e783c31b37bd64bca
Gerrit-Change-Number: 40725
Gerrit-PatchSet: 14
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>
Gerrit-Attention: jolly <andreas(a)eversberg.eu>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Thu, 18 Sep 2025 09:41:05 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: laforge <laforge(a)osmocom.org>
Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>