P5.X: xconn->smb2.recv_uring smbd_smb2_request_next_uring_recvmsg
authorStefan Metzmacher <metze@samba.org>
Wed, 14 Apr 2021 23:54:06 +0000 (23:54 +0000)
committerStefan Metzmacher <metze@samba.org>
Mon, 16 Oct 2023 11:03:50 +0000 (13:03 +0200)
source3/smbd/globals.h
source3/smbd/smb2_server.c

index 8529283dd9e4dd59e49921983a2d3edd0e51f5fc..29b92f4fe68e8f2ec3b7a68717954a73265df326 100644 (file)
@@ -460,6 +460,10 @@ struct smbXsrv_connection {
                struct smbd_smb2_request_read_state {
                        struct smbXsrv_connection *xconn;
                        struct smbd_smb2_request *req;
+                       struct {
+                               struct samba_io_uring_completion completion;
+                               struct samba_io_uring_submission submission;
+                       } io_uring;
                        struct {
                                uint8_t nbt[NBT_HDR_SIZE];
                        } hdr;
@@ -479,6 +483,10 @@ struct smbXsrv_connection {
                        struct samba_io_uring *uring;
                        size_t async_threshhold;
                } send_io_uring;
+               struct {
+                       struct samba_io_uring *uring;
+                       size_t async_threshhold;
+               } recv_io_uring;
 
                struct {
                        /*
index 8d84d0af8000b1922bfb7b5d46a5a83135900a3b..1967ae65a2ffeb766a958e6242063d968c946ab5 100644 (file)
@@ -359,6 +359,24 @@ static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
                        xconn->smb2.send_io_uring.uring = xconn->client->sconn->uring;
                }
        }
+       xconn->smb2.recv_io_uring.async_threshhold = ~0;
+       if (lp_parm_bool(-1, "smb2srv", "recv_uring", false)) {
+               const struct samba_io_uring_features *features =
+                       samba_io_uring_get_features(xconn->client->sconn->uring);
+               int tmp;
+
+               tmp = lp_parm_bytes(-1,
+                                   "smb2srv",
+                                   "recvmsg_uring_async_threshhold",
+                                   -1);
+               if (features->flag_async && tmp >= 0) {
+                       xconn->smb2.recv_io_uring.async_threshhold = tmp;
+               }
+
+               if (features->op_recvmsg) {
+                       xconn->smb2.recv_io_uring.uring = xconn->client->sconn->uring;
+               }
+       }
 
        /*
         * Ensure child is set to non-blocking mode,
@@ -4644,6 +4662,107 @@ static void smbd_smb2_noop_submission_io_uring(struct samba_io_uring *ring,
 {
 }
 
+static void smbd_smb2_recv_completion_io_uring(struct samba_io_uring_completion *completion,
+                                              void *completion_private,
+                                              const struct io_uring_cqe *cqe);
+
+static NTSTATUS smbd_smb2_request_next_uring_recvmsg(struct smbXsrv_connection *xconn)
+{
+       struct smbd_smb2_request_read_state *state = xconn->smb2.request_read_state;
+       struct samba_io_uring_submission *submission = NULL;
+
+       ZERO_STRUCT(state->io_uring);
+
+       if (state->count > 0) {
+               unsigned recvmsg_flags = MSG_WAITALL;
+               struct io_uring_sqe *sqe = NULL;
+               ssize_t blen;
+
+               blen = iov_buflen(state->vector, state->count);
+               SMB_ASSERT(blen >= 0);
+
+               state->msg = (struct msghdr) {
+                       .msg_iov = state->vector,
+                       .msg_iovlen = state->count,
+               };
+
+               samba_io_uring_completion_prepare(&state->io_uring.completion,
+                                                 smbd_smb2_recv_completion_io_uring,
+                                                 xconn);
+               samba_io_uring_submission_prepare(&state->io_uring.submission,
+                                                 smbd_smb2_noop_submission_io_uring,
+                                                 NULL,
+                                                 &state->io_uring.completion);
+               sqe = samba_io_uring_submission_sqe(&state->io_uring.submission);
+               io_uring_prep_recvmsg(sqe,
+                                     xconn->transport.sock,
+                                     &state->msg,
+                                     recvmsg_flags);
+               if (blen >= xconn->smb2.recv_io_uring.async_threshhold) {
+                       sqe->flags |= IOSQE_ASYNC;
+               }
+
+               submission = &state->io_uring.submission;
+       } else {
+               smb_panic(__location__);
+       }
+
+       samba_io_uring_queue_submissions(xconn->smb2.recv_io_uring.uring,
+                                        submission);
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS smbd_smb2_advance_incoming(struct smbXsrv_connection *xconn, size_t n);
+
+static void smbd_smb2_recv_completion_io_uring(struct samba_io_uring_completion *completion,
+                                              void *completion_private,
+                                              const struct io_uring_cqe *cqe)
+{
+       struct smbXsrv_connection *xconn =
+               talloc_get_type_abort(completion_private,
+               struct smbXsrv_connection);
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       ret = cqe->res;
+       if (ret > 0) {
+               status = NT_STATUS_OK;
+       } else if (ret == 0) {
+               /* propagate end of file */
+               status = NT_STATUS_END_OF_FILE;
+       } else if (ret < 0) {
+               status = map_nt_error_from_unix_common(-ret);
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(xconn, nt_errstr(status));
+               return;
+       }
+
+       status = smbd_smb2_advance_incoming(xconn, ret);
+       if (NT_STATUS_IS_OK(status)) {
+               return;
+       }
+       if (NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
+               status = NT_STATUS_RETRY;
+       }
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
+               smbd_server_connection_terminate(xconn, nt_errstr(status));
+               return;
+       }
+
+       /*
+        * we need to receive more data.
+        */
+       status = smbd_smb2_request_next_uring_recvmsg(xconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(xconn, nt_errstr(status));
+               return;
+       }
+
+       return;
+}
+
 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
 {
        struct smbd_smb2_request_read_state *state = xconn->smb2.request_read_state;
@@ -4696,6 +4815,10 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn
                .count = 1,
        };
 
+       if (xconn->smb2.recv_io_uring.uring != NULL) {
+               return smbd_smb2_request_next_uring_recvmsg(xconn);
+       }
+
        TEVENT_FD_READABLE(xconn->transport.fde);
 
        return NT_STATUS_OK;
@@ -5394,8 +5517,15 @@ static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
                return NT_STATUS_OK;
        }
 
+       if (xconn->smb2.recv_io_uring.uring != NULL) {
+               TEVENT_FD_NOT_READABLE(xconn->transport.fde);
+               return NT_STATUS_OK;
+       }
+
 again:
 
+       SMB_ASSERT(state->count != 0);
+
        state->msg = (struct msghdr) {
                .msg_iov = state->vector,
                .msg_iovlen = state->count,