s3: smbd: Restart reading the incoming SMB2 fd when the send queue is drained.
authorJeremy Allison <jra@samba.org>
Thu, 2 Mar 2017 17:13:23 +0000 (09:13 -0800)
committerRalph Boehme <slow@samba.org>
Fri, 3 Mar 2017 01:23:20 +0000 (02:23 +0100)
When the send queue grows greater than xconn->smb2.credits.max/16,
smbd_smb2_request_next_incoming() doesn't allocate a new request in state->req.

After smbd_smb2_io_handler() is called, it marks the fd not readable as
state->req == NULL, and never marks it readable again.

Fix by calling smbd_smb2_request_next_incoming() to restart
reads inside smbd_smb2_flush_send_queue() which drains the
send queue.

Reported by <chen.yehua@h3c.com>

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12608

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Fri Mar  3 02:23:20 CET 2017 on sn-devel-144

source3/smbd/smb2_server.c

index b0a4afc867504eb1afbb1e43130a4019ee81ac66..acaa0126dd8ad118ddc85f024fb93cf223df1b41 100644 (file)
@@ -3566,6 +3566,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
        int ret;
        int err;
        bool retry;
+       NTSTATUS status;
 
        if (xconn->smb2.send_queue == NULL) {
                TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
@@ -3577,11 +3578,12 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
                bool ok;
 
                if (e->sendfile_header != NULL) {
-                       NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
                        size_t size = 0;
                        size_t i = 0;
                        uint8_t *buf;
 
+                       status = NT_STATUS_INTERNAL_ERROR;
+
                        for (i=0; i < e->count; i++) {
                                size += e->vector[i].iov_len;
                        }
@@ -3653,6 +3655,16 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
                talloc_free(e->mem_ctx);
        }
 
+       /*
+        * Restart reads if we were blocked on
+        * draining the send queue.
+        */
+
+       status = smbd_smb2_request_next_incoming(xconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        return NT_STATUS_OK;
 }