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); }