The branch, v3-6-test has been updated
       via  151bea2 s3:smb2_server: keep compound_related on struct 
smbd_smb2_request
       via  bd377e8 Based on metze's fix for Bug 8407 - SMB2 server can return 
requests out-of-order when processing a compound request.
       via  90e4b68 s3:smb2_server: make sure we prefer responses over requests 
on the client socket
      from  7d2006c Fix bug 8433, segfault in iconv.c

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 151bea2cc30f5a3e3cfaafd9e080f0d510f9563e
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Aug 25 23:33:41 2011 +0200

    s3:smb2_server: keep compound_related on struct smbd_smb2_request
    
    metze
    (cherry picked from commit 0d450d166bab952daf37d922e5c2e5cac16f1cc3)
    
    The last 3 patches address bug #8407 (SMB2 server can return requests
    out-of-order when processing a compound request).

commit bd377e89a6bc5fa20485bf9614c06159c9785cdf
Author: Jeremy Allison <j...@samba.org>
Date:   Fri Aug 26 14:23:26 2011 -0700

    Based on metze's fix for Bug 8407 - SMB2 server can return requests 
out-of-order when processing a compound request.
    
    (cherry picked from commit 726b4685aa25b0b3b4470bfec5d514fb2db7a95e)

commit 90e4b68a3b0e46c238753e66ededa16de3104302
Author: Stefan Metzmacher <me...@samba.org>
Date:   Fri Aug 5 20:34:43 2011 +0200

    s3:smb2_server: make sure we prefer responses over requests on the client 
socket
    
    metze
    
    Autobuild-User: Stefan Metzmacher <me...@samba.org>
    Autobuild-Date: Fri Aug 12 16:46:43 CEST 2011 on sn-devel-104
    (cherry picked from commit 42cde0480bd6a5e2dddaa66917e1fa71e6a4edcd)

-----------------------------------------------------------------------

Summary of changes:
 source3/smbd/globals.h     |    2 +
 source3/smbd/smb2_server.c |  107 +++++++++++++++++++++++++++++++++++++-------
 2 files changed, 93 insertions(+), 16 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 58e03a5..abeaed4 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -358,6 +358,7 @@ struct smbd_smb2_request {
        bool do_signing;
        bool async;
        bool cancelled;
+       bool compound_related;
 
        /* fake smb1 request. */
        struct smb_request *smb1req;
@@ -601,6 +602,7 @@ struct smbd_server_connection {
                uint32_t credits_granted;
                uint32_t max_credits;
                struct bitmap *credits_bitmap;
+               bool compound_related_in_progress;
        } smb2;
 };
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 0cc80ed..d7a40ed 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -357,7 +357,6 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
 {
        int count;
        int idx;
-       bool compound_related = false;
 
        count = req->in.vector_count;
 
@@ -405,7 +404,7 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
                         * compounded requests
                         */
                        if (flags & SMB2_HDR_FLAG_CHAINED) {
-                               compound_related = true;
+                               req->compound_related = true;
                        }
                } else if (idx > 4) {
 #if 0
@@ -418,13 +417,13 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
                         * all other requests should match the 2nd one
                         */
                        if (flags & SMB2_HDR_FLAG_CHAINED) {
-                               if (!compound_related) {
+                               if (!req->compound_related) {
                                        req->next_status =
                                                NT_STATUS_INVALID_PARAMETER;
                                        return NT_STATUS_OK;
                                }
                        } else {
-                               if (compound_related) {
+                               if (req->compound_related) {
                                        req->next_status =
                                                NT_STATUS_INVALID_PARAMETER;
                                        return NT_STATUS_OK;
@@ -884,6 +883,20 @@ NTSTATUS smbd_smb2_request_pending_queue(struct 
smbd_smb2_request *req,
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
+
+               /*
+                * We're splitting off the last SMB2
+                * request in a compound set, and the
+                * smb2_send_async_interim_response()
+                * call above just sent all the replies
+                * for the previous SMB2 requests in
+                * this compound set. So we're no longer
+                * in the "compound_related_in_progress"
+                * state, and this is no longer a compound
+                * request.
+                */
+               req->compound_related = false;
+               req->sconn->smb2.compound_related_in_progress = false;
        }
 
        /* Don't return an intermediate packet on a pipe read/write. */
@@ -1175,6 +1188,10 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
                req->compat_chain_fsp = NULL;
        }
 
+       if (req->compound_related) {
+               req->sconn->smb2.compound_related_in_progress = true;
+       }
+
        switch (opcode) {
        case SMB2_OP_NEGPROT:
                /* This call needs to be run as root */
@@ -1621,6 +1638,10 @@ static NTSTATUS smbd_smb2_request_reply(struct 
smbd_smb2_request *req)
                return NT_STATUS_OK;
        }
 
+       if (req->compound_related) {
+               req->sconn->smb2.compound_related_in_progress = false;
+       }
+
        smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
 
        /* Set credit for this operation (zero credits if this
@@ -1671,6 +1692,8 @@ static NTSTATUS smbd_smb2_request_reply(struct 
smbd_smb2_request *req)
        return NT_STATUS_OK;
 }
 
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection 
*sconn);
+
 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
                                        struct tevent_immediate *im,
                                        void *private_data)
@@ -1693,6 +1716,12 @@ void smbd_smb2_request_dispatch_immediate(struct 
tevent_context *ctx,
                smbd_server_connection_terminate(sconn, nt_errstr(status));
                return;
        }
+
+       status = smbd_smb2_request_next_incoming(sconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(sconn, nt_errstr(status));
+               return;
+       }
 }
 
 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
@@ -1702,17 +1731,24 @@ static void smbd_smb2_request_writev_done(struct 
tevent_req *subreq)
        struct smbd_server_connection *sconn = req->sconn;
        int ret;
        int sys_errno;
+       NTSTATUS status;
 
        ret = tstream_writev_queue_recv(subreq, &sys_errno);
        TALLOC_FREE(subreq);
        TALLOC_FREE(req);
        if (ret == -1) {
-               NTSTATUS status = map_nt_error_from_unix(sys_errno);
+               status = map_nt_error_from_unix(sys_errno);
                DEBUG(2,("smbd_smb2_request_writev_done: client write error 
%s\n",
                        nt_errstr(status)));
                smbd_server_connection_terminate(sconn, nt_errstr(status));
                return;
        }
+
+       status = smbd_smb2_request_next_incoming(sconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(sconn, nt_errstr(status));
+               return;
+       }
 }
 
 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
@@ -2317,12 +2353,55 @@ static NTSTATUS smbd_smb2_request_read_recv(struct 
tevent_req *req,
 
 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
 
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection 
*sconn)
+{
+       size_t max_send_queue_len;
+       size_t cur_send_queue_len;
+       struct tevent_req *subreq;
+
+       if (sconn->smb2.compound_related_in_progress) {
+               /*
+                * Can't read another until the related
+                * compound is done.
+                */
+               return NT_STATUS_OK;
+       }
+
+       if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
+               /*
+                * if there is already a smbd_smb2_request_read
+                * pending, we are done.
+                */
+               return NT_STATUS_OK;
+       }
+
+       max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
+       cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
+
+       if (cur_send_queue_len > max_send_queue_len) {
+               /*
+                * if we have a lot of requests to send,
+                * we wait until they are on the wire until we
+                * ask for the next request.
+                */
+               return NT_STATUS_OK;
+       }
+
+       /* ask for the next request */
+       subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, 
sconn);
+       if (subreq == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
+
+       return NT_STATUS_OK;
+}
+
 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
                             const uint8_t *inbuf, size_t size)
 {
        NTSTATUS status;
        struct smbd_smb2_request *req = NULL;
-       struct tevent_req *subreq;
 
        DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
                 (unsigned int)size));
@@ -2351,13 +2430,11 @@ void smbd_smb2_first_negprot(struct 
smbd_server_connection *sconn,
                return;
        }
 
-       /* ask for the next request */
-       subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, 
sconn);
-       if (subreq == NULL) {
-               smbd_server_connection_terminate(sconn, "no memory for 
reading");
+       status = smbd_smb2_request_next_incoming(sconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(sconn, nt_errstr(status));
                return;
        }
-       tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
 
        sconn->num_requests++;
 }
@@ -2409,13 +2486,11 @@ static void smbd_smb2_request_incoming(struct 
tevent_req *subreq)
        }
 
 next:
-       /* ask for the next request (this constructs the main loop) */
-       subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, 
sconn);
-       if (subreq == NULL) {
-               smbd_server_connection_terminate(sconn, "no memory for 
reading");
+       status = smbd_smb2_request_next_incoming(sconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(sconn, nt_errstr(status));
                return;
        }
-       tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
 
        sconn->num_requests++;
 


-- 
Samba Shared Repository

Reply via email to