sq smbd_smb2_flush_with_io_uring
authorStefan Metzmacher <metze@samba.org>
Wed, 30 Sep 2020 22:26:21 +0000 (00:26 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 30 Sep 2020 22:26:21 +0000 (00:26 +0200)
source3/smbd/smb2_server.c

index 095285fb1a8ffc751fb8f509dbd019cdc4699922..542f99af7578ea56372d0ed1a1495d594d975071 100644 (file)
@@ -4739,6 +4739,9 @@ static NTSTATUS smbd_smb2_flush_with_sendmsg(struct smbXsrv_connection *xconn)
        return NT_STATUS_OK;
 }
 
+static void smbd_smb2_flush_completion_io_uring(struct samba_io_uring_qe *qe,
+                                               const char *location);
+
 static NTSTATUS smbd_smb2_flush_with_io_uring(struct smbXsrv_connection *xconn)
 {
        int ret;
@@ -4748,6 +4751,11 @@ static NTSTATUS smbd_smb2_flush_with_io_uring(struct smbXsrv_connection *xconn)
 
        while (xconn->smb2.send_queue != NULL) {
                struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
+               struct samba_io_uring_qe *qe = NULL;
+
+               if (e->io_uring.num_qes != 0) {
+                       continue;
+               }
 
                SMB_ASSERT(e->sendfile_header == NULL);
 
@@ -4756,40 +4764,66 @@ static NTSTATUS smbd_smb2_flush_with_io_uring(struct smbXsrv_connection *xconn)
                        .msg_iovlen = e->count,
                };
 
-               ret = sendmsg(xconn->transport.sock, &e->msg, MSG_DONTWAIT);
-               if (ret == 0) {
-                       /* propagate end of file */
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-               err = socket_error_from_errno(ret, errno, &retry);
-               if (retry) {
-                       /* retry later */
-                       TEVENT_FD_WRITEABLE(xconn->transport.fde);
-                       return NT_STATUS_OK;
-               }
-               if (err != 0) {
-                       status = map_nt_error_from_unix_common(err);
-                       smbXsrv_connection_disconnect_transport(xconn,
-                                                               status);
-                       return status;
-               }
+               qe = &e->io_uring.qes[e->io_uring.num_qes++];
+               io_uring_prep_sendmsg(&qe->sqe,
+                                     xconn->transport.sock,
+                                     &e->msg,
+                                     0);
+               qe->drain = true;
+               qe->private_data = e;
+               qe->completion_fn = smbd_smb2_flush_completion_io_uring;
 
-               status = smbd_smb2_advance_send_queue(xconn, e, ret);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
-                       /* retry later */
-                       TEVENT_FD_WRITEABLE(xconn->transport.fde);
-                       return NT_STATUS_OK;
-               }
-               if (!NT_STATUS_IS_OK(status)) {
-                       smbXsrv_connection_disconnect_transport(xconn,
-                                                               status);
-                       return status;
-               }
+               samba_io_uring_request_submit(xconn->smb2.send_uring,
+                                             &e->io_uring);
        }
 
        return NT_STATUS_OK;
 }
 
+static void smbd_smb2_flush_completion_io_uring(struct samba_io_uring_qe *qe,
+                                               const char *location)
+{
+       struct smbd_smb2_send_queue *e =
+               (struct smbd_smb2_send_queue *)qe->private_data;
+       struct smbXsrv_connection *xconn = e->xconn;
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       ret = qe->cqe.res;
+       if (ret > 0) {
+               status = NT_STATUS_OK;
+       } else if (ret == 0) {
+               /* propagate end of file */
+               status = NT_STATUS_INTERNAL_ERROR;
+       } else if (ret < 0) {
+               status = map_nt_error_from_unix_common(-ret);
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               smbXsrv_connection_disconnect_transport(xconn,
+                                                       status);
+               smbd_server_connection_terminate_ex(xconn,
+                                                   nt_errstr(status),
+                                                   location);
+               return;
+       }
+
+       status = smbd_smb2_advance_send_queue(xconn, e, ret);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
+               /* retry later */
+               ZERO_STRUCT(e->io_uring);
+               smbd_smb2_flush_send_queue(xconn);
+               return;
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               smbXsrv_connection_disconnect_transport(xconn,
+                                                       status);
+               smbd_server_connection_terminate_ex(xconn,
+                                                   nt_errstr(status),
+                                                   __location__);
+               return;
+       }
+}
+
 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
 {
        NTSTATUS status;