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 <me...@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 <me...@samba.org>
    Autobuild-Date: Tue Nov 15 18:47:55 CET 2011 on sn-devel-104

commit 21eb1450cc2541e23dedf1a0dec24e3313ab8739
Author: Stefan Metzmacher <me...@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 <me...@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 <me...@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 <me...@samba.org>
Date:   Mon Nov 14 09:52:47 2011 +0100

    s3:smbd/aio: add cancel_smb2_aio()
    
    metze

commit 0cd67698ca69d82936da29658103ce449d797c25
Author: Stefan Metzmacher <me...@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 <me...@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 <me...@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 <me...@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

Reply via email to