The branch, master has been updated
via 481b961be99 async_sock: try recvmsg(MSG_DONTWAIT) without fd event
handler first
via d4b5784cb59 async_sock: split out read_packet_do() from
read_packet_handler()
via 5d1ab4b02f1 async_sock: make use of recvmsg() in
read_packet_handler()
via 75ca6f5aa08 async_sock: let writev_do() try sendmsg() first
from cdb9fa71db3 source3/wscript: Remove extra config
WITH_PROMETHEUS_EXPORTER
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 481b961be9971b999f9ef73a26dbad6dfdbc5ae4
Author: Stefan Metzmacher <[email protected]>
Date: Mon Apr 28 17:56:37 2025 +0200
async_sock: try recvmsg(MSG_DONTWAIT) without fd event handler first
Also callers typically read a header to get the length and then
the remaining data, for that we typically don't need an additional
hop via [e]poll.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
Autobuild-User(master): Stefan Metzmacher <[email protected]>
Autobuild-Date(master): Mon May 12 11:28:47 UTC 2025 on atb-devel-224
commit d4b5784cb599b9ee8cb4cf94feccb880ad94f1d3
Author: Stefan Metzmacher <[email protected]>
Date: Mon Apr 28 17:54:31 2025 +0200
async_sock: split out read_packet_do() from read_packet_handler()
We'll call read_packet_do() in other places too in future.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 5d1ab4b02f113b9a0d87013748475d6668caa72a
Author: Stefan Metzmacher <[email protected]>
Date: Mon Apr 28 17:46:44 2025 +0200
async_sock: make use of recvmsg() in read_packet_handler()
This typically has a better call stack in the kernel.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 75ca6f5aa08251885b1ba414ed72afc272f20f93
Author: Stefan Metzmacher <[email protected]>
Date: Mon Apr 28 17:38:15 2025 +0200
async_sock: let writev_do() try sendmsg() first
This is typically more efficient on the kernel call stack.
As far as I can see writev_send/recv is only used with sockets
so far, but in any case we fallback on ENOTSOCK.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
lib/async_req/async_sock.c | 108 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 97 insertions(+), 11 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 795a2c63dba..06ffb942967 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -235,6 +235,7 @@ struct writev_state {
struct tevent_context *ev;
struct tevent_queue_entry *queue_entry;
int fd;
+ bool is_sock;
struct tevent_fd *fde;
struct iovec *iov;
int count;
@@ -264,6 +265,7 @@ struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct
tevent_context *ev,
}
state->ev = ev;
state->fd = fd;
+ state->is_sock = true;
state->total_size = 0;
state->count = count;
state->iov = (struct iovec *)talloc_memdup(
@@ -341,7 +343,20 @@ static void writev_do(struct tevent_req *req, struct
writev_state *state)
ssize_t written;
bool ok;
- written = writev(state->fd, state->iov, state->count);
+ if (state->is_sock) {
+ struct msghdr msg = {
+ .msg_iov = state->iov,
+ .msg_iovlen = state->count,
+ };
+
+ written = sendmsg(state->fd, &msg, 0);
+ if ((written == -1) && (errno == ENOTSOCK)) {
+ state->is_sock = false;
+ }
+ }
+ if (!state->is_sock) {
+ written = writev(state->fd, state->iov, state->count);
+ }
if ((written == -1) &&
((errno == EINTR) ||
(errno == EAGAIN) ||
@@ -434,6 +449,7 @@ ssize_t writev_recv(struct tevent_req *req, int *perrno)
struct read_packet_state {
int fd;
+ bool is_sock;
struct tevent_fd *fde;
uint8_t *buf;
size_t nread;
@@ -443,6 +459,8 @@ struct read_packet_state {
static void read_packet_cleanup(struct tevent_req *req,
enum tevent_req_state req_state);
+static void read_packet_do(struct tevent_req *req,
+ uint16_t ready_flags);
static void read_packet_handler(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags, void *private_data);
@@ -463,6 +481,7 @@ struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
return NULL;
}
state->fd = fd;
+ state->is_sock = true;
state->nread = 0;
state->more = more;
state->private_data = private_data;
@@ -474,6 +493,17 @@ struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
+ /*
+ * Call read_packet_do()
+ * with ready_flags = 0,
+ * so only recvmsg(MSG_DONTWAIT)
+ * will be tried.
+ */
+ read_packet_do(req, 0);
+ if (!tevent_req_is_in_progress(req)) {
+ return tevent_req_post(req, ev);
+ }
+
state->fde = tevent_add_fd(ev, state, fd,
TEVENT_FD_READ, read_packet_handler,
req);
@@ -492,26 +522,54 @@ static void read_packet_cleanup(struct tevent_req *req,
TALLOC_FREE(state->fde);
}
-static void read_packet_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *private_data)
+static void read_packet_do(struct tevent_req *req,
+ uint16_t ready_flags)
{
- struct tevent_req *req = talloc_get_type_abort(
- private_data, struct tevent_req);
struct read_packet_state *state =
tevent_req_data(req, struct read_packet_state);
- size_t total = talloc_get_size(state->buf);
+ size_t total;
ssize_t nread, more;
uint8_t *tmp;
- nread = recv(state->fd, state->buf+state->nread, total-state->nread,
- 0);
- if ((nread == -1) && (errno == ENOTSOCK)) {
+retry:
+ total = talloc_get_size(state->buf);
+ if (state->is_sock) {
+ struct iovec iov = {
+ .iov_base = state->buf+state->nread,
+ .iov_len = total-state->nread,
+ };
+ struct msghdr msg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ nread = recvmsg(state->fd, &msg, MSG_DONTWAIT);
+ if ((nread == -1) && (errno == ENOTSOCK)) {
+ state->is_sock = false;
+ }
+ }
+ if (!state->is_sock) {
+ if (!(ready_flags & TEVENT_FD_READ)) {
+ /*
+ * With out TEVENT_FD_READ read() may block,
+ * so we just return here and retry via
+ * fd event handler
+ */
+ return;
+ }
nread = read(state->fd, state->buf+state->nread,
total-state->nread);
}
if ((nread == -1) && (errno == EINTR)) {
- /* retry */
+ /* retry directly */
+ goto retry;
+ }
+ if ((nread == -1) && (errno == EAGAIN)) {
+ /* retry later via fd event handler */
+ return;
+ }
+ if ((nread == -1) && (errno == EWOULDBLOCK)) {
+ /* retry later via fd event handler */
return;
}
if (nread == -1) {
@@ -523,6 +581,13 @@ static void read_packet_handler(struct tevent_context *ev,
return;
}
+ /*
+ * We have pulled some data out of the fd!
+ * A possible retry can't rely
+ * on TEVENT_FD_READ semantics anymore.
+ */
+ ready_flags &= ~TEVENT_FD_READ;
+
state->nread += nread;
if (state->nread < total) {
/* Come back later */
@@ -560,6 +625,27 @@ static void read_packet_handler(struct tevent_context *ev,
return;
}
state->buf = tmp;
+
+ /*
+ * We already cleared TEVENT_FD_READ,
+ * we do a retry without it.
+ *
+ * We either do recvmsg(MSG_DONTWAIT)
+ * or return without any further read
+ * because TEVENT_FD_READ was already
+ * cleared.
+ */
+ goto retry;
+}
+
+static void read_packet_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
+{
+ struct tevent_req *req = talloc_get_type_abort(
+ private_data, struct tevent_req);
+
+ read_packet_do(req, flags);
}
ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
--
Samba Shared Repository