laforge submitted this change.
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(-)
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 change 40491. To unsubscribe, or for help writing mail filters, visit settings.