[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue Nov 15 10:48:04 MST 2011


The branch, master has been updated
       via  31cd1fb s3:smbd/aio: handle_aio_completed() should do nothing if aio_ex->fsp is NULL
       via  21eb145 s3:smbd/aio: pass ECANCELED to the smb2 aio handlers
       via  483b79c s3:smb2_read: make it possible to cancel aio reads
       via  3fbf322 s3:smb2_write: make it possible to cancel aio writes
       via  2802be7 s3:smbd/aio: add cancel_smb2_aio()
       via  0cd6769 s3:smb2_ioctl: STATUS_PENDING is defered by 1 millisecond for SMB2_IOCTL
       via  05246ae s3:smb2_create: defer STATUS_PENDING for 2 seconds as before
       via  88dd90d s3:smb2_server: pass explicit defer_times to smbd_smb2_request_pending_queue()
       via  693cb77 s3:smb2_server: always send STATUS_PENDING responses, but delayed by 0.5 milliseconds
      from  10b285c s3-winbind: Don't fail on users without a uid.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 31cd1fbd2b1c2d1635662688e979bb5baa992855
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 09:54:05 2011 +0100

    s3:smbd/aio: handle_aio_completed() should do nothing if aio_ex->fsp is NULL
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Tue Nov 15 18:47:55 CET 2011 on sn-devel-104

commit 21eb1450cc2541e23dedf1a0dec24e3313ab8739
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 09:53:25 2011 +0100

    s3:smbd/aio: pass ECANCELED to the smb2 aio handlers
    
    metze

commit 483b79cfc4af4dd48089b12b279d174f54132e9d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 09:33:22 2011 +0100

    s3:smb2_read: make it possible to cancel aio reads
    
    metze

commit 3fbf32213a9523ecab4bc201018d94f38b561b0b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 09:33:22 2011 +0100

    s3:smb2_write: make it possible to cancel aio writes
    
    metze

commit 2802be75e38d5ae64ad5ec36e46d0799c77eec30
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 09:52:47 2011 +0100

    s3:smbd/aio: add cancel_smb2_aio()
    
    metze

commit 0cd67698ca69d82936da29658103ce449d797c25
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 15:29:37 2011 +0100

    s3:smb2_ioctl: STATUS_PENDING is defered by 1 millisecond for SMB2_IOCTL
    
    metze

commit 05246ae6238483eff759897d8a6aa9be7f49529f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 15:50:47 2011 +0100

    s3:smb2_create: defer STATUS_PENDING for 2 seconds as before
    
    metze

commit 88dd90d9288e49c33f4e8d528bf109a40fc997d8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 14 15:42:55 2011 +0100

    s3:smb2_server: pass explicit defer_times to smbd_smb2_request_pending_queue()
    
    metze

commit 693cb77b2fdb96205ab83bb2c22b67fe91de61b0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Nov 9 11:47:33 2011 +0100

    s3:smb2_server: always send STATUS_PENDING responses, but delayed by 0.5 milliseconds
    
    In future we'll pass the delay from the caller.
    
    metze

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

Summary of changes:
 source3/smbd/aio.c          |   48 +++++++++-
 source3/smbd/globals.h      |    5 +-
 source3/smbd/proto.h        |    1 +
 source3/smbd/smb2_break.c   |    2 +-
 source3/smbd/smb2_create.c  |   42 ++------
 source3/smbd/smb2_find.c    |    2 +-
 source3/smbd/smb2_flush.c   |    2 +-
 source3/smbd/smb2_getinfo.c |    2 +-
 source3/smbd/smb2_ioctl.c   |    2 +-
 source3/smbd/smb2_lock.c    |    2 +-
 source3/smbd/smb2_notify.c  |    2 +-
 source3/smbd/smb2_read.c    |   25 +++--
 source3/smbd/smb2_server.c  |  227 +++++++++++++++++++++++--------------------
 source3/smbd/smb2_setinfo.c |    2 +-
 source3/smbd/smb2_write.c   |   25 +++--
 15 files changed, 223 insertions(+), 166 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 98a35ed..d367826 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -49,6 +49,7 @@ struct aio_extra {
 	DATA_BLOB outbuf;
 	struct lock_struct lock;
 	bool write_through;
+	bool pass_cancel;
 	int (*handle_completion)(struct aio_extra *ex, int errcode);
 };
 
@@ -380,6 +381,37 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
 	return NT_STATUS_OK;
 }
 
+bool cancel_smb2_aio(struct smb_request *smbreq)
+{
+	struct smbd_smb2_request *smb2req = smbreq->smb2req;
+	struct aio_extra *aio_ex = NULL;
+	int ret;
+
+	if (smbreq) {
+		smb2req = smbreq->smb2req;
+	}
+
+	if (smb2req) {
+		aio_ex = talloc_get_type(smbreq->async_priv,
+					 struct aio_extra);
+	}
+
+	if (aio_ex == NULL) {
+		return false;
+	}
+
+	if (aio_ex->fsp == NULL) {
+		return false;
+	}
+
+	ret = SMB_VFS_AIO_CANCEL(aio_ex->fsp, &aio_ex->acb);
+	if (ret != AIO_CANCELED) {
+		return false;
+	}
+
+	return true;
+}
+
 /****************************************************************************
  Set up an aio request from a SMB2 read call.
 *****************************************************************************/
@@ -440,6 +472,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
 		return NT_STATUS_NO_MEMORY;
 	}
 	aio_ex->handle_completion = handle_aio_smb2_read_complete;
+	aio_ex->pass_cancel = true;
 
 	init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
 		(uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
@@ -476,6 +509,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
 	/* We don't need talloc_move here as both aio_ex and
 	 * smbreq are children of smbreq->smb2req. */
 	aio_ex->smbreq = smbreq;
+	smbreq->async_priv = aio_ex;
 
 	DEBUG(10,("smb2: scheduled aio_read for file %s, "
 		"offset %.0f, len = %u (mid = %u)\n",
@@ -540,6 +574,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 
 	aio_ex->handle_completion = handle_aio_smb2_write_complete;
 	aio_ex->write_through = write_through;
+	aio_ex->pass_cancel = true;
 
 	init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
 		in_offset, (uint64_t)in_data.length, WRITE_LOCK,
@@ -576,6 +611,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 	/* We don't need talloc_move here as both aio_ex and
 	* smbreq are children of smbreq->smb2req. */
 	aio_ex->smbreq = smbreq;
+	smbreq->async_priv = aio_ex;
 
 	/* This should actually be improved to span the write. */
 	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
@@ -835,6 +871,11 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
 		return false;
 	}
 
+	if (!aio_ex->fsp) {
+	        DEBUG(3, ("handle_aio_completed: aio_ex->fsp == NULL\n"));
+		return false;
+	}
+
 	fsp = aio_ex->fsp;
 
 	/* Ensure the operation has really completed. */
@@ -850,7 +891,7 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
 	/* Unlock now we're done. */
 	SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
 
-	if (err == ECANCELED) {
+	if (!aio_ex->pass_cancel && err == ECANCELED) {
 		/* If error is ECANCELED then don't return anything to the
 		 * client. */
 	        DEBUG(10,( "handle_aio_completed: operation mid %llu"
@@ -1039,6 +1080,11 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
 	return NT_STATUS_RETRY;
 }
 
+bool cancel_smb2_aio(struct smb_request *smbreq)
+{
+	return false;
+}
+
 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
                                 struct smb_request *smbreq,
                                 files_struct *fsp,
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 2e94b55..a02988a 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -259,7 +259,8 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
 				     uint8_t oplock_level);
 
 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
-					 struct tevent_req *subreq);
+					 struct tevent_req *subreq,
+					 uint32_t defer_time);
 
 struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req);
 void remove_smb2_chained_fsp(files_struct *fsp);
@@ -347,7 +348,7 @@ struct smbd_smb2_request {
 
 	int current_idx;
 	bool do_signing;
-	bool async;
+	struct tevent_timer *async_te;
 	bool cancelled;
 	bool compound_related;
 
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 0a68a6c..fe90766 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -86,6 +86,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 				uint64_t in_offset,
 				DATA_BLOB in_data,
 				bool write_through);
+bool cancel_smb2_aio(struct smb_request *smbreq);
 int wait_for_aio_completion(files_struct *fsp);
 void cancel_aio_by_fsp(files_struct *fsp);
 void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex);
diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c
index ce583ac..9899d92 100644
--- a/source3/smbd/smb2_break.c
+++ b/source3/smbd/smb2_break.c
@@ -78,7 +78,7 @@ NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_oplock_break_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_oplock_break_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 29696dc..6d7d4ac 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -244,7 +244,13 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
 	}
 	tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
 
-	return smbd_smb2_request_pending_queue(smb2req, tsubreq);
+	/*
+	 * For now we keep the logic that we do not send STATUS_PENDING
+	 * for sharing violations, so we just wait 2 seconds.
+	 *
+	 * TODO: we need more tests for this.
+	 */
+	return smbd_smb2_request_pending_queue(smb2req, tsubreq, 2000000);
 }
 
 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
@@ -437,7 +443,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 	}
 
 
-	if (!smb2req->async) {
+	if (smb2req->subreq == NULL) {
 		/* New create call. */
 		req = tevent_req_create(mem_ctx, &state,
 				struct smbd_smb2_create_state);
@@ -445,7 +451,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			return NULL;
 		}
 		state->smb2req = smb2req;
-		smb2req->subreq = req; /* So we can find this when going async. */
 
 		smb1req = smbd_smb2_fake_smb_request(smb2req);
 		if (tevent_req_nomem(smb1req, req)) {
@@ -892,7 +897,7 @@ bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
 	if (!smb2req) {
 		return false;
 	}
-	if (!smb2req->async) {
+	if (smb2req->subreq == NULL) {
 		return false;
 	}
 	req = smb2req->subreq;
@@ -1201,35 +1206,6 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
 		return false;
 	}
 
-#if 1
-	/* Boo - turns out this isn't what W2K8R2
-	   does. It actually sends the STATUS_PENDING
-	   message followed by the STATUS_SHARING_VIOLATION
-	   message. Surely this means that all open
-	   calls (even on directories) will potentially
-	   fail in a chain.... ? And I've seen directory
-	   opens as the start of a chain. JRA.
-
-	   Update: 19th May 2010. Talking with Microsoft
-	   engineers at the plugfest this is a bug in
-	   Windows. Re-enable this code.
-	*/
-	/*
-	 * More subtlety. To match W2K8R2 don't
-	 * send a "gone async" message if it's simply
-	 * a STATUS_SHARING_VIOLATION (short) wait, not
-	 * an oplock break wait. We do this by prematurely
-	 * setting smb2req->async flag.
-	 */
-	if (timeout.tv_sec < 2) {
-		DEBUG(10,("push_deferred_open_message_smb2: "
-			"short timer wait (usec = %u). "
-			"Don't send async message.\n",
-			(unsigned int)timeout.tv_usec ));
-		smb2req->async = true;
-	}
-#endif
-
 	/* Re-schedule us to retry on timer expiry. */
 	end_time = timeval_sum(&request_time, &timeout);
 
diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index 6369e7f..9b1179f 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -135,7 +135,7 @@ NTSTATUS smbd_smb2_request_process_find(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_find_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_find_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
index 5f3c42a..3464c58 100644
--- a/source3/smbd/smb2_flush.c
+++ b/source3/smbd/smb2_flush.c
@@ -64,7 +64,7 @@ NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_flush_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_flush_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index c5d2d62..81d781a 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -118,7 +118,7 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_getinfo_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
index 5a766e1..b7b4592 100644
--- a/source3/smbd/smb2_ioctl.c
+++ b/source3/smbd/smb2_ioctl.c
@@ -110,7 +110,7 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_ioctl_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 1000);
 }
 
 static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
index ed1d688..4f88bb8 100644
--- a/source3/smbd/smb2_lock.c
+++ b/source3/smbd/smb2_lock.c
@@ -133,7 +133,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_lock_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_lock_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
index 49c6a54..5375e21 100644
--- a/source3/smbd/smb2_notify.c
+++ b/source3/smbd/smb2_notify.c
@@ -95,7 +95,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_notify_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_notify_done(struct tevent_req *subreq)
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 405e82d..0862209 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -100,7 +100,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 	}
 	tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
 
-	return smbd_smb2_request_pending_queue(req, subreq);
+	return smbd_smb2_request_pending_queue(req, subreq, 500);
 }
 
 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
@@ -169,6 +169,7 @@ static void smbd_smb2_request_read_done(struct tevent_req *subreq)
 
 struct smbd_smb2_read_state {
 	struct smbd_smb2_request *smb2req;
+	struct smb_request *smbreq;
 	files_struct *fsp;
 	uint64_t in_file_id_volatile;
 	uint32_t in_length;
@@ -364,6 +365,17 @@ NTSTATUS smb2_read_complete(struct tevent_req *req, ssize_t nread, int err)
 	return NT_STATUS_OK;
 }
 
+static bool smbd_smb2_read_cancel(struct tevent_req *req)
+{
+	struct smbd_smb2_read_state *state =
+		tevent_req_data(req,
+		struct smbd_smb2_read_state);
+
+	state->smb2req->cancelled = true;
+
+	return cancel_smb2_aio(state->smbreq);
+}
+
 static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 					      struct tevent_context *ev,
 					      struct smbd_smb2_request *smb2req,
@@ -403,6 +415,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 	if (tevent_req_nomem(smbreq, req)) {
 		return tevent_req_post(req, ev);
 	}
+	state->smbreq = smbreq;
 
 	fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
 	if (fsp == NULL) {
@@ -466,14 +479,10 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 
 	if (NT_STATUS_IS_OK(status)) {
 		/*
-		 * Doing an async read. Don't
-		 * send a "gone async" message
-		 * as we expect this to be less
-		 * than the client timeout period.
-		 * JRA. FIXME for offline files..
-		 * FIXME. Add cancel code..
+		 * Doing an async read, allow this
+		 * request to be canceled
 		 */
-		smb2req->async = true;
+		tevent_req_set_cancel_fn(req, smbd_smb2_read_cancel);
 		return req;
 	}
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 33e95ad..dbb0089 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -711,15 +711,6 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
 	newreq->session = req->session;
 	newreq->do_signing = req->do_signing;
 	newreq->current_idx = req->current_idx;
-	newreq->async = false;
-	newreq->cancelled = false;
-	/* Note we are leaving:
-		->tcon
-		->smb1req
-		->compat_chain_fsp
-	   uninitialized as NULL here as
-	   they're not used in the interim
-	   response code. JRA. */
 
 	outvec = talloc_zero_array(newreq, struct iovec, count);
 	if (!outvec) {
@@ -844,19 +835,20 @@ static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
 	TALLOC_FREE(state);
 }
 
+static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
+					    struct tevent_timer *te,
+					    struct timeval current_time,
+					    void *private_data);
+
 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
-					 struct tevent_req *subreq)
+					 struct tevent_req *subreq,
+					 uint32_t defer_time)
 {
 	NTSTATUS status;
-	struct smbd_smb2_request_pending_state *state = NULL;
 	int i = req->current_idx;
-	uint8_t *reqhdr = NULL;
-	uint8_t *hdr = NULL;
-	uint8_t *body = NULL;
-	uint32_t flags = 0;
-	uint64_t message_id = 0;
-	uint64_t async_id = 0;
-	struct iovec *outvec = NULL;
+	struct timeval defer_endtime;
+	uint8_t *outhdr = NULL;
+	uint32_t flags;
 
 	if (!tevent_req_is_in_progress(subreq)) {
 		return NT_STATUS_OK;
@@ -865,7 +857,14 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 	req->subreq = subreq;
 	subreq = NULL;
 
-	if (req->async) {
+	if (req->async_te) {
+		/* We're already async. */
+		return NT_STATUS_OK;
+	}
+
+	outhdr = (uint8_t *)req->out.vector[i].iov_base;
+	flags = IVAL(outhdr, SMB2_HDR_FLAGS);
+	if (flags & SMB2_HDR_FLAG_ASYNC) {
 		/* We're already async. */
 		return NT_STATUS_OK;
 	}
@@ -888,6 +887,8 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 	}
 
 	if (req->out.vector_count > 4) {
+		struct iovec *outvec = NULL;
+
 		/* This is a compound reply. We
 		 * must do an interim response
 		 * followed by the async response
@@ -911,18 +912,94 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 		 */
 		req->compound_related = false;
 		req->sconn->smb2.compound_related_in_progress = false;
+
+		/* 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;
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list