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,
{
}
+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;
.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;
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,