[SCM] Samba Shared Repository - branch v3-6-test updated
Karolin Seeger
kseeger at samba.org
Thu Sep 15 12:27:34 MDT 2011
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 <metze at 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 <jra at 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 <metze at 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 <metze at 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
More information about the samba-cvs
mailing list