]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
async_sock: let writev_do() try sendmsg() first
authorStefan Metzmacher <metze@samba.org>
Mon, 28 Apr 2025 15:38:15 +0000 (17:38 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 12 May 2025 10:31:30 +0000 (10:31 +0000)
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 <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
lib/async_req/async_sock.c

index 795a2c63dbaceaedc5fbf7089b6726796bcd5e42..2185961ea3ccbb6e2a1a7547d2eae0eb20551ee0 100644 (file)
@@ -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) ||