The Samba-Bugzilla – Attachment 5602 Details for
Bug 7331
Compound async SMB 2 requests don't work right.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
smb2_compound.patch
smb2_compound.patch (text/plain), 10.45 KB, created by
Ira Cooper
on 2010-04-06 13:20:49 UTC
(
hide
)
Description:
smb2_compound.patch
Filename:
MIME Type:
Creator:
Ira Cooper
Created:
2010-04-06 13:20:49 UTC
Size:
10.45 KB
patch
obsolete
>Author: Ira Cooper <samba@ira.wakeful.net> >Date: Tue Feb 23 10:16:32 2010 -0500 > > Updates needed for basic SMB2 support. > > It also needs basic code clean up. But it is good enough to check in. > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index 3cc967f..15ac1e8 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -334,6 +334,10 @@ struct smbd_smb2_request { > struct smbd_smb2_tcon *tcon; > > int current_idx; >+ int async_idx; >+ int cancelled; >+ struct iovec *async_out; >+ > bool do_signing; > > struct files_struct *compat_chain_fsp; >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index 9e5be40..a1175a7 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -23,6 +23,8 @@ > #include "../libcli/smb/smb_common.h" > #include "../lib/tsocket/tsocket.h" > >+static void smbd_smb2_requeue_main_eventloop(struct smbd_server_connection *); >+ > bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size) > { > if (size < (4 + SMB2_HDR_BODY)) { >@@ -418,20 +420,25 @@ struct smbd_smb2_request_pending_state { > struct iovec vector; > }; > >+static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *); > static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq); > >+/* This was orginally (4 + SMB2_HDR_BODY + 0x08) */ >+#define PENDING_REPLY_SIZE (SMB2_HDR_BODY + 0x08 ) > NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > struct tevent_req *subreq) > { > struct smbd_smb2_request_pending_state *state; > uint8_t *outhdr; > int i = req->current_idx; >+ int j; > uint32_t flags; > uint64_t message_id; > uint64_t async_id; > uint8_t *hdr; > uint8_t *body; > >+ DEBUG(10,("smbd_smb2_request_pending_queue: idx[%d of %d] \n",i, req->out.vector_count)); > if (!tevent_req_is_in_progress(subreq)) { > return NT_STATUS_OK; > } >@@ -439,6 +446,10 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > req->subreq = subreq; > subreq = NULL; > >+ /* No request in a compound chain can succeed after we go async. */ >+ req->async_idx = req->current_idx; >+ req->next_status = NT_STATUS_INSUFFICIENT_RESOURCES; >+ > outhdr = (uint8_t *)req->out.vector[i].iov_base; > > flags = IVAL(outhdr, SMB2_HDR_FLAGS); >@@ -448,19 +459,26 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC); > SBVAL(outhdr, SMB2_HDR_PID, async_id); > >- /* TODO: add a paramter to delay this */ >- state = talloc(req->sconn, struct smbd_smb2_request_pending_state); >- if (state == NULL) { >+ /* The hdr/body now go into the main reply, the impact is pretty large. */ >+ >+ req->out.vector[i].iov_base = talloc_size(req, PENDING_REPLY_SIZE); >+ req->async_out = talloc_array(req, struct iovec, 3); >+ if(req->out.vector[i].iov_base == NULL || req->async_out == NULL) { > return NT_STATUS_NO_MEMORY; > } >- state->sconn = req->sconn; > >- state->vector.iov_base = (void *)state->buf; >- state->vector.iov_len = sizeof(state->buf); >+ for(j=0;j<3;j++) { >+ req->async_out[j].iov_len = req->out.vector[i+j].iov_len; >+ req->async_out[j].iov_base = req->out.vector[i+j].iov_base; >+ } > >- _smb2_setlen(state->buf, sizeof(state->buf) - 4); >- hdr = state->buf + 4; >- body = hdr + SMB2_HDR_BODY; >+ req->out.vector[i].iov_len = PENDING_REPLY_SIZE; >+ _smb2_setlen(req->out.vector[i].iov_base, PENDING_REPLY_SIZE); >+ req->out.vector[i+1].iov_len = 0; >+ req->out.vector[i+2].iov_len = 0; >+ >+ hdr = req->out.vector[i].iov_base; >+ body = hdr + SMB2_HDR_BODY; > > SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC); > SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); >@@ -485,7 +503,7 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > SCVAL(body, 0x02, 0); > SCVAL(body, 0x03, 0); > SIVAL(body, 0x04, 0); >- >+#if 0 > subreq = tstream_writev_queue_send(state, > req->sconn->smb2.event_ctx, > req->sconn->smb2.stream, >@@ -497,8 +515,8 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > tevent_req_set_callback(subreq, > smbd_smb2_request_pending_writev_done, > state); >- >- return NT_STATUS_OK; >+#endif >+ return smbd_smb2_request_reply(req); > } > > static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq) >@@ -511,6 +529,7 @@ static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq) > int sys_errno; > > ret = tstream_writev_queue_recv(subreq, &sys_errno); >+ DEBUG(10,(" smbd_smb2_request_pending_writev_done - %d\n",ret)); > TALLOC_FREE(subreq); > if (ret == -1) { > NTSTATUS status = map_nt_error_from_unix(sys_errno); >@@ -537,11 +556,9 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req) > search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID); > search_async_id = BVAL(inhdr, SMB2_HDR_PID); > >- /* >- * we don't need the request anymore >- * cancel requests never have a response >- */ >- TALLOC_FREE(req); >+ DEBUG(10,("smbd_smb2_request_process_cancel: mid - %d aid - %d\n", >+ search_message_id, >+ search_async_id)); > > for (cur = sconn->smb2.requests; cur; cur = cur->next) { > const uint8_t *outhdr; >@@ -567,9 +584,21 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req) > } > > if (cur && cur->subreq) { >+ DEBUG(10,("cancelled: mid - %d aid - %d\n", >+ search_message_id, >+ search_async_id)); >+ cur->cancelled=1; > tevent_req_cancel(cur->subreq); >- } >+ } else { >+ DEBUG(10,("did non cancel: mid - %d aid - %d\n", >+ search_message_id, >+ search_async_id)); >+ } >+ >+ TALLOC_FREE(req); > >+ /* Respool the event loop. */ >+ smbd_smb2_requeue_main_eventloop(sconn); > return NT_STATUS_OK; > } > >@@ -803,8 +832,13 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq); > static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > { > struct tevent_req *subreq; >+ struct iovec *async_in; >+ struct iovec *async_out; >+ int j; > >- req->subreq = NULL; >+/* req->subreq = NULL; */ >+ >+ DEBUG(10,("smbd_smb2_request_reply: idx[%d of %d] \n",req->current_idx, req->out.vector_count)); > > smb2_setup_nbt_length(req->out.vector, req->out.vector_count); > >@@ -835,6 +869,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > return NT_STATUS_OK; > } > >+ DEBUG(10,("smbd_smb2_request_reply sent: idx[%d of %d] \n",req->current_idx, req->out.vector_count)); > subreq = tstream_writev_queue_send(req, > req->sconn->smb2.event_ctx, > req->sconn->smb2.stream, >@@ -842,9 +877,43 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > req->out.vector, > req->out.vector_count); > if (subreq == NULL) { >+ DEBUG(10,("smbd_smb2_request_reply - bailed early! \n")); >+ req->async_idx = 0; > return NT_STATUS_NO_MEMORY; > } >+ >+ /* Now to setup the async if there is one. */ >+ >+ if (req->async_idx > 0) { >+ DEBUG(10,("smbd_smb2_request_reply - async processing\n")); >+ async_in = talloc_array(req, struct iovec, 4); >+ async_out = talloc_array(req, struct iovec, 4); >+ req->out.vector_count = 4; >+ req->in.vector_count = 4; >+ async_in[0].iov_base = req->in.vector[0].iov_base; >+ async_in[0].iov_len = req->in.vector[0].iov_len; >+ >+ async_out[0].iov_base = talloc_size(req, req->out.vector[0].iov_len); >+ memcpy(async_out[0].iov_base, >+ req->out.vector[0].iov_base, >+ req->out.vector[0].iov_len); >+ async_out[0].iov_len = req->out.vector[0].iov_len; >+ >+ for (j=0;j<3;j++) { >+ async_in[j+1].iov_base = req->in.vector[req->async_idx+j].iov_base; >+ async_in[j+1].iov_len = req->in.vector[req->async_idx+j].iov_len; >+ async_out[j+1].iov_base = req->async_out[j].iov_base; >+ async_out[j+1].iov_len = req->async_out[j].iov_len; >+ } >+ req->in.vector = async_in; >+ req->out.vector = async_out; >+ req->async_idx = -1; >+ req->current_idx = 1; >+ } >+ >+ DEBUG(10,("smbd_smb2_request_reply - async processing done\n")); > tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req); >+ DEBUG(10,("smbd_smb2_request_reply - callback installed\n")); > > return NT_STATUS_OK; > } >@@ -877,9 +946,21 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq) > int ret; > int sys_errno; > >+ DEBUG(10,("smbd_smb2_request_writev_done - async: %d\n", req->async_idx)); >+ > ret = tstream_writev_queue_recv(subreq, &sys_errno); > TALLOC_FREE(subreq); >- TALLOC_FREE(req); >+ if ((req->async_idx==0 ^ req->async_out!=NULL) && !req->cancelled) { >+ DEBUG(10,("requeued main event loop\n")); >+ smbd_smb2_requeue_main_eventloop(sconn); >+ } >+ >+ if (req->async_idx==0) { >+ TALLOC_FREE(req); >+ } else { >+ req->async_idx = 0; >+ } >+ > if (ret == -1) { > NTSTATUS status = map_nt_error_from_unix(sys_errno); > smbd_server_connection_terminate(sconn, nt_errstr(status)); >@@ -921,8 +1002,14 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, > /* > * if a request fails, all other remaining > * compounded requests should fail too >+ * >+ * But the exact status matters, if we got NT_STATUS_INSUFFICIENT_RESOURCES, we >+ * need to pass it on, so the compounded request fails correctly. >+ * > */ >- req->next_status = NT_STATUS_INVALID_PARAMETER; >+ if(NT_STATUS_V(req->next_status) != NT_STATUS_V(NT_STATUS_INSUFFICIENT_RESOURCES)) { >+ req->next_status = NT_STATUS_INVALID_PARAMETER; >+ } > > return smbd_smb2_request_reply(req); > } >@@ -1538,7 +1625,11 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq) > NTSTATUS status; > struct smbd_smb2_request *req = NULL; > >+ /* This should not be needed, but... safety first. */ >+ tevent_req_set_callback(subreq,NULL,NULL); >+ > status = smbd_smb2_request_read_recv(subreq, sconn, &req); >+ tevent_queue_stop(sconn->smb2.recv_queue); > TALLOC_FREE(subreq); > if (!NT_STATUS_IS_OK(status)) { > smbd_server_connection_terminate(sconn, nt_errstr(status)); >@@ -1574,13 +1665,22 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq) > smbd_server_connection_terminate(sconn, nt_errstr(status)); > return; > } >+ return; >+ > > next: > /* ask for the next request (this constructs the main loop) */ >+ smbd_smb2_requeue_main_eventloop(sconn); >+} >+ >+static void smbd_smb2_requeue_main_eventloop(struct smbd_server_connection *sconn) { >+ struct tevent_req *subreq; >+ tevent_queue_start(sconn->smb2.recv_queue); > subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn); > if (subreq == NULL) { > smbd_server_connection_terminate(sconn, "no memory for reading"); > return; > } > tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn); >+ return; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 7331
:
5602
|
5603
|
5604
|
5605
|
5636
|
5637
|
5638
|
5639