[SCM] Samba Shared Repository - branch v3-6-test updated

Karolin Seeger kseeger at samba.org
Mon May 13 01:28:36 MDT 2013


The branch, v3-6-test has been updated
       via  9094b53 Remove the compound_related_in_progress state from the smb2 global state.
       via  f4900ce The core of the fix to allow opens to go async inside a compound request.
       via  5185365 Ensure we don't try and cancel anything that is in a compound-related request.
       via  171087a Only do the 1 second delay for sharing violations for SMB1, not SMB2.
      from  1303a68 WHATSNEW: Start release notes for Samba 3.6.16.

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


- Log -----------------------------------------------------------------
commit 9094b538c85a550b40827799f56427a926d315cd
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 8 15:10:32 2013 -0700

    Remove the compound_related_in_progress state from the smb2 global state.
    
    And also remove the restriction that we can't read a new
    request whilst we're in this state.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    
    The last 4 patches address bug #9722 - Samba does not properly handle Oplock
    breaks in compound requests.

commit f4900ce9e0c52beb2dcf34eaf4bcd5f398d7900c
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 8 15:08:50 2013 -0700

    The core of the fix to allow opens to go async inside a compound request.
    
    This is only allowed for opens that cause an oplock break, otherwise it
    is not allowed. See [MS-SMB2].pdf note <194> on Section 3.3.5.2.7.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 5185365c6b215905663aca5161924a357268f64d
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 8 11:51:38 2013 -0700

    Ensure we don't try and cancel anything that is in a compound-related request.
    
    Too hard to deal with splitting off the replies.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 171087a499531bf529fe800de73e0e10ecdcc6f7
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 8 11:50:32 2013 -0700

    Only do the 1 second delay for sharing violations for SMB1, not SMB2.
    
    Match Windows behavior.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 source3/smbd/globals.h     |    1 -
 source3/smbd/open.c        |    3 +-
 source3/smbd/smb2_server.c |  145 +++++++++++++++++++------------------------
 3 files changed, 66 insertions(+), 83 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 730bb7e..ce5b18d 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -647,7 +647,6 @@ struct smbd_server_connection {
 		uint32_t max_trans;
 		uint32_t max_read;
 		uint32_t max_write;
-		bool compound_related_in_progress;
 	} smb2;
 };
 
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d10b697..447de80 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2002,10 +2002,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 
 			/*
 			 * If we're returning a share violation, ensure we
-			 * cope with the braindead 1 second delay.
+			 * cope with the braindead 1 second delay (SMB1 only).
 			 */
 
 			if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
+			    !conn->sconn->using_smb2 &&
 			    lp_defer_sharing_violations()) {
 				struct timeval timeout;
 				struct deferred_open_record state;
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index cc884c3..9615907 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -927,7 +927,6 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 	uint32_t flags = 0;
 	uint64_t message_id = 0;
 	uint64_t async_id = 0;
-	struct iovec *outvec = NULL;
 
 	if (!tevent_req_is_in_progress(subreq)) {
 		return NT_STATUS_OK;
@@ -944,16 +943,27 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 	if (req->in.vector_count > i + 3) {
 		/*
 		 * We're trying to go async in a compound
-		 * request chain. This is not allowed.
-		 * Cancel the outstanding request.
+		 * request chain.
+		 * This is only allowed for opens that
+		 * cause an oplock break, otherwise it
+		 * is not allowed. See [MS-SMB2].pdf
+		 * note <194> on Section 3.3.5.2.7.
 		 */
-		bool ok = tevent_req_cancel(req->subreq);
-		if (ok) {
-			return NT_STATUS_OK;
-		}
-		TALLOC_FREE(req->subreq);
-		return smbd_smb2_request_error(req,
-			NT_STATUS_INTERNAL_ERROR);
+		const uint8_t *inhdr =
+			(const uint8_t *)req->in.vector[i].iov_base;
+
+		if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
+			/*
+			 * Cancel the outstanding request.
+			 */
+			bool ok = tevent_req_cancel(req->subreq);
+			if (ok) {
+				return NT_STATUS_OK;
+			}
+			TALLOC_FREE(req->subreq);
+			return smbd_smb2_request_error(req,
+				NT_STATUS_INTERNAL_ERROR);
+                }
 	}
 
 	if (DEBUGLEVEL >= 10) {
@@ -962,35 +972,54 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 		print_req_vectors(req);
 	}
 
-	if (req->out.vector_count > 4) {
-		/* This is a compound reply. We
-		 * must do an interim response
-		 * followed by the async response
-		 * to match W2K8R2.
+	if (i > 1) {
+		/*
+		 * We're going async in a compound
+		 * chain after the first request has
+		 * already been processed. Send an
+		 * interim response containing the
+		 * set of replies already generated.
 		 */
 		status = smb2_send_async_interim_response(req);
 		if (!NT_STATUS_IS_OK(status)) {
 			return status;
 		}
 
+		req->current_idx = 1;
+
 		/*
-		 * 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.
+		 * Re-arrange the in.vectors to remove what
+		 * we just sent.
 		 */
-		req->compound_related = false;
-		req->sconn->smb2.compound_related_in_progress = false;
+		memmove(&req->in.vector[1],
+			&req->in.vector[i],
+			sizeof(req->in.vector[0])*(req->in.vector_count - i));
+		req->in.vector_count = 1 + (req->in.vector_count - i);
+
+		smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
+
+		/* Re-arrange the out.vectors to match. */
+		memmove(&req->out.vector[1],
+			&req->out.vector[i],
+			sizeof(req->out.vector[0])*(req->out.vector_count - i));
+		req->out.vector_count = 1 + (req->out.vector_count - i);
+
+		if (req->in.vector_count == 4) {
+			uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
+			/*
+			 * We only have one remaining request as
+			 * we've processed everything else.
+			 * This is no longer a compound request.
+			 */
+			req->compound_related = false;
+			flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
+			SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
+		}
 	}
 
 	/* Don't return an intermediate packet on a pipe read/write. */
 	if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
-		goto ipc_out;
+		goto out;
 	}
 
 	reqhdr = (uint8_t *)req->out.vector[i].iov_base;
@@ -1081,50 +1110,6 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 	/* Note we're going async with this request. */
 	req->async = true;
 
-  ipc_out:
-
-	/*
-	 * Now manipulate req so that the outstanding async request
-	 * is the only one left in the struct smbd_smb2_request.
-	 */
-
-	if (req->current_idx == 1) {
-		/* There was only one. */
-		goto out;
-	}
-
-	/* Re-arrange the in.vectors. */
-	req->in.vector[1] = req->in.vector[i];
-	req->in.vector[2] = req->in.vector[i+1];
-	req->in.vector[3] = req->in.vector[i+2];
-	req->in.vector_count = 4;
-	/* Reset the new in size. */
-	smb2_setup_nbt_length(req->in.vector, 4);
-
-	/* Now recreate the out.vectors. */
-	outvec = talloc_zero_array(req, struct iovec, 4);
-	if (!outvec) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	/* 0 is always boilerplate and must
-	 * be of size 4 for the length field. */
-
-	outvec[0].iov_base = req->out.nbt_hdr;
-	outvec[0].iov_len = 4;
-	SIVAL(req->out.nbt_hdr, 0, 0);
-
-	if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	TALLOC_FREE(req->out.vector);
-
-	req->out.vector = outvec;
-
-	req->current_idx = 1;
-	req->out.vector_count = 4;
-
   out:
 
 	smb2_setup_nbt_length(req->out.vector,
@@ -1178,6 +1163,14 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
 		uint64_t message_id;
 		uint64_t async_id;
 
+		if (cur->compound_related) {
+			/*
+			 * Never cancel anything in a compound request.
+			 * Way too hard to deal with the result.
+			 */
+			continue;
+		}
+
 		i = cur->current_idx;
 
 		outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
@@ -1360,7 +1353,6 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 
 	if (flags & SMB2_HDR_FLAG_CHAINED) {
 		req->compound_related = true;
-		req->sconn->smb2.compound_related_in_progress = true;
 	}
 
 	switch (opcode) {
@@ -1830,7 +1822,6 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 
 	if (req->compound_related) {
 		req->compound_related = false;
-		req->sconn->smb2.compound_related_in_progress = false;
 	}
 
 	smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
@@ -2547,14 +2538,6 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s
 	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


-- 
Samba Shared Repository


More information about the samba-cvs mailing list