Patches for https://bugzilla.samba.org/show_bug.cgi?id=11182

Michael Adam obnox at samba.org
Wed May 6 12:53:38 MDT 2015


On 2015-05-06 at 11:20 -0700, Jeremy Allison wrote:
> On Wed, May 06, 2015 at 02:27:41PM +0200, Stefan (metze) Metzmacher wrote:
> > Hi,
> > 
> > here's an updated patchset renaming smbXsrv_session_shutdown_send/recv
> > to smb2srv_session_shutdown_send/recv as it only handles smb2/3.
> 
> That's really nice work Metze - thanks ! I like the way
> adding the smbd_smb2_session_setup_wrap_send()/_recv()
> gets rid of the horror that was tag_state_session_ptr() :-).
> Makes the whole sessetup SMB2 code path much cleaner.

Indeed.

> Also moving the code out of smbd_smb2_logoff_send()
> into a common function smb2srv_session_shutdown_send()
> to be called on logoff and session setup error is a
> genius move !

:) Indeed again. The main point here is also that
there is now the queue for the outstanding requests
and we put the cleaning of the session at the end of
this queue.

> LGTM.
> 
> Reviewed-by: Jeremy Allison <jra at samba.org>

Now I feel kind of stupid having spent my afternoon
reviewing the patches... ;) When I thought I was done,
Ira brought up one potential issue, the discussion of
which kept me busy until dinner time, which is why I
can only follow up now:

In the session_shutdown helpers mentioned above,
compounded requests are excluded from sending
cancels. Ira points out that when there is a
compounded request in progress, the last of which
is a notify, and we are just at one of the earlier
requests when the shutdown_send is called, isn't
there a chance that we block indefinitely waiting
for the notify to vanish from the queue since it
in the compound and we don't send a cancel?

Attached find my reviewed version of the patchset:
- The session_shutdown helper is flagged with a Q(...)
- I have added some refactoring of an obvious code
  duplication added by the patches.
  (the removal of the code duplication is still there
   as separate patches for squashing with metze's original patches)
- I have done minor changes to some commit messages:
  - few typo fixes
  - added explanation of the session_shutdown helpers
  - added bug references where missing

Cheers - Michael

> > Am 06.05.2015 um 10:19 schrieb Stefan (metze) Metzmacher:
> > > Hi Jeremy,
> > > 
> > > here're the proposed patches for master regarding
> > > https://bugzilla.samba.org/show_bug.cgi?id=11182
> > > 
> > > The main happens when a session setup with a previous session id
> > > removes the previous session while there's a pending change notify
> > > request.
> > > 
> > > Please review and push, then I'll prepare backports.
> > > 
> > > Thanks!
> > > metze
> > > 
> 
> > From d95e3048e480b222348b10d03b3e31dca4443c8a Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:04:55 +0200
> > Subject: [PATCH 01/17] s3:smbd: add a smbd_notify_cancel_by_map() helper
> >  function
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/notify.c | 19 +++++++++++++------
> >  1 file changed, 13 insertions(+), 6 deletions(-)
> > 
> > diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
> > index 3f2d07c..4f4ca2f 100644
> > --- a/source3/smbd/notify.c
> > +++ b/source3/smbd/notify.c
> > @@ -375,6 +375,17 @@ static void change_notify_remove_request(struct smbd_server_connection *sconn,
> >  	TALLOC_FREE(req);
> >  }
> >  
> > +static void smbd_notify_cancel_by_map(struct notify_mid_map *map)
> > +{
> > +	struct smb_request *smbreq = map->req->req;
> > +	struct smbd_server_connection *sconn = smbreq->sconn;
> > +	NTSTATUS notify_status = NT_STATUS_CANCELLED;
> > +
> > +	change_notify_reply(smbreq, notify_status,
> > +			    0, NULL, map->req->reply_fn);
> > +	change_notify_remove_request(sconn, map->req);
> > +}
> > +
> >  /****************************************************************************
> >   Delete entries by mid from the change notify pending queue. Always send reply.
> >  *****************************************************************************/
> > @@ -394,9 +405,7 @@ void remove_pending_change_notify_requests_by_mid(
> >  		return;
> >  	}
> >  
> > -	change_notify_reply(map->req->req,
> > -			    NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
> > -	change_notify_remove_request(sconn, map->req);
> > +	smbd_notify_cancel_by_map(map);
> >  }
> >  
> >  void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq)
> > @@ -414,9 +423,7 @@ void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq)
> >  		return;
> >  	}
> >  
> > -	change_notify_reply(map->req->req,
> > -			    NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
> > -	change_notify_remove_request(sconn, map->req);
> > +	smbd_notify_cancel_by_map(map);
> >  }
> >  
> >  static struct files_struct *smbd_notify_cancel_deleted_fn(
> > -- 
> > 1.9.1
> > 
> > 
> > From 227ed247a33728327dc8bd81124c7a0352deef03 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:02:38 +0200
> > Subject: [PATCH 02/17] s3:smbd: use STATUS_NOTIFY_CLEANUP when closing a smb2
> >  directory handle
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  selftest/knownfail   |  1 -
> >  source3/smbd/close.c | 15 +++++++++++----
> >  2 files changed, 11 insertions(+), 5 deletions(-)
> > 
> > diff --git a/selftest/knownfail b/selftest/knownfail
> > index 3262c9c..26aed77 100644
> > --- a/selftest/knownfail
> > +++ b/selftest/knownfail
> > @@ -189,7 +189,6 @@
> >  ^samba3.smb2.create.blob
> >  ^samba3.smb2.create.open
> >  ^samba3.smb2.notify.valid-req
> > -^samba3.smb2.notify.dir
> >  ^samba3.smb2.notify.rec
> >  ^samba3.smb2.durable-open.delete_on_close2
> >  ^samba3.smb2.durable-v2-open.app-instance
> > diff --git a/source3/smbd/close.c b/source3/smbd/close.c
> > index 09be2e7..0e75bf0 100644
> > --- a/source3/smbd/close.c
> > +++ b/source3/smbd/close.c
> > @@ -1050,6 +1050,13 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
> >  	NTSTATUS status1 = NT_STATUS_OK;
> >  	const struct security_token *del_nt_token = NULL;
> >  	const struct security_unix_token *del_token = NULL;
> > +	NTSTATUS notify_status;
> > +
> > +	if (fsp->conn->sconn->using_smb2) {
> > +		notify_status = STATUS_NOTIFY_CLEANUP;
> > +	} else {
> > +		notify_status = NT_STATUS_OK;
> > +	}
> >  
> >  	/*
> >  	 * NT can set delete_on_close of the last open
> > @@ -1159,8 +1166,8 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
> >  		 * now fail as the directory has been deleted.
> >  		 */
> >  
> > -		if(NT_STATUS_IS_OK(status)) {
> > -			remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
> > +		if (NT_STATUS_IS_OK(status)) {
> > +			notify_status = NT_STATUS_DELETE_PENDING;
> >  		}
> >  	} else {
> >  		if (!del_share_mode(lck, fsp)) {
> > @@ -1169,10 +1176,10 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
> >  		}
> >  
> >  		TALLOC_FREE(lck);
> > -		remove_pending_change_notify_requests_by_fid(
> > -			fsp, NT_STATUS_OK);
> >  	}
> >  
> > +	remove_pending_change_notify_requests_by_fid(fsp, notify_status);
> > +
> >  	status1 = fd_close(fsp);
> >  
> >  	if (!NT_STATUS_IS_OK(status1)) {
> > -- 
> > 1.9.1
> > 
> > 
> > From 8aef6501d53dd38002f1f9531ffd3bacbd5de245 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:02:38 +0200
> > Subject: [PATCH 03/17] s3:smbd: use STATUS_NOTIFY_CLEANUP on smb2 logoff
> >  (explicit and implicit) and tdis
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/notify.c | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> > 
> > diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
> > index 4f4ca2f..b3079d2 100644
> > --- a/source3/smbd/notify.c
> > +++ b/source3/smbd/notify.c
> > @@ -379,8 +379,22 @@ static void smbd_notify_cancel_by_map(struct notify_mid_map *map)
> >  {
> >  	struct smb_request *smbreq = map->req->req;
> >  	struct smbd_server_connection *sconn = smbreq->sconn;
> > +	struct smbd_smb2_request *smb2req = smbreq->smb2req;
> >  	NTSTATUS notify_status = NT_STATUS_CANCELLED;
> >  
> > +	if (smb2req != NULL) {
> > +		if (smb2req->session == NULL) {
> > +			notify_status = STATUS_NOTIFY_CLEANUP;
> > +		} else if (!NT_STATUS_IS_OK(smb2req->session->status)) {
> > +			notify_status = STATUS_NOTIFY_CLEANUP;
> > +		}
> > +		if (smb2req->tcon == NULL) {
> > +			notify_status = STATUS_NOTIFY_CLEANUP;
> > +		} else if (!NT_STATUS_IS_OK(smb2req->tcon->status)) {
> > +			notify_status = STATUS_NOTIFY_CLEANUP;
> > +		}
> > +	}
> > +
> >  	change_notify_reply(smbreq, notify_status,
> >  			    0, NULL, map->req->reply_fn);
> >  	change_notify_remove_request(sconn, map->req);
> > -- 
> > 1.9.1
> > 
> > 
> > From 3d9590a8ab4b8fee4e35228020ee6a52b2ce6f16 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:19:42 +0200
> > Subject: [PATCH 04/17] s4:torture/smb2: verify STATUS_NOTIFY_CLEANUP return
> >  value
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source4/torture/smb2/notify.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
> > index 0f572b6..6c1bf3a 100644
> > --- a/source4/torture/smb2/notify.c
> > +++ b/source4/torture/smb2/notify.c
> > @@ -1309,6 +1309,7 @@ static bool torture_smb2_notify_tree_disconnect_1(
> >  	CHECK_STATUS(status, NT_STATUS_OK);
> >  
> >  	status = smb2_notify_recv(req, torture, &(notify.smb2));
> > +	CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
> >  	CHECK_VAL(notify.smb2.out.num_changes, 0);
> >  
> >  done:
> > @@ -1377,6 +1378,7 @@ static bool torture_smb2_notify_ulogoff(struct torture_context *torture,
> >  	CHECK_STATUS(status, NT_STATUS_OK);
> >  
> >  	status = smb2_notify_recv(req, torture, &(notify.smb2));
> > +	CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
> >  	CHECK_VAL(notify.smb2.out.num_changes, 0);
> >  
> >  done:
> > -- 
> > 1.9.1
> > 
> > 
> > From a19aca28e87629d519b9a0d9d6cca3c0736d0e23 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:20:50 +0200
> > Subject: [PATCH 05/17] s4:torture/smb2: add smb2.notify.close test
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source4/torture/smb2/notify.c | 70 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 70 insertions(+)
> > 
> > diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
> > index 6c1bf3a..d2b3594 100644
> > --- a/source4/torture/smb2/notify.c
> > +++ b/source4/torture/smb2/notify.c
> > @@ -1318,6 +1318,75 @@ done:
> >  }
> >  
> >  /*
> > +  basic testing of change notifies followed by a close
> > +*/
> > +
> > +static bool torture_smb2_notify_close(struct torture_context *torture,
> > +				struct smb2_tree *tree1)
> > +{
> > +	bool ret = true;
> > +	NTSTATUS status;
> > +	union smb_notify notify;
> > +	union smb_open io;
> > +	struct smb2_handle h1;
> > +	struct smb2_request *req;
> > +
> > +	smb2_deltree(tree1, BASEDIR);
> > +	smb2_util_rmdir(tree1, BASEDIR);
> > +
> > +	torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
> > +
> > +	/*
> > +	  get a handle on the directory
> > +	*/
> > +	ZERO_STRUCT(io.smb2);
> > +	io.generic.level = RAW_OPEN_SMB2;
> > +	io.smb2.in.create_flags = 0;
> > +	io.smb2.in.desired_access = SEC_FILE_ALL;
> > +	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
> > +	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
> > +	io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
> > +				NTCREATEX_SHARE_ACCESS_WRITE;
> > +	io.smb2.in.alloc_size = 0;
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
> > +	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
> > +	io.smb2.in.security_flags = 0;
> > +	io.smb2.in.fname = BASEDIR;
> > +
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +	h1 = io.smb2.out.file.handle;
> > +
> > +	/* ask for a change notify,
> > +	   on file or directory name changes */
> > +	ZERO_STRUCT(notify.smb2);
> > +	notify.smb2.level = RAW_NOTIFY_SMB2;
> > +	notify.smb2.in.buffer_size = 1000;
> > +	notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
> > +	notify.smb2.in.file.handle = h1;
> > +	notify.smb2.in.recursive = true;
> > +
> > +	req = smb2_notify_send(tree1, &(notify.smb2));
> > +
> > +	WAIT_FOR_ASYNC_RESPONSE(req);
> > +
> > +	status = smb2_util_close(tree1, h1);
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +
> > +	status = smb2_notify_recv(req, torture, &(notify.smb2));
> > +	CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
> > +	CHECK_VAL(notify.smb2.out.num_changes, 0);
> > +
> > +done:
> > +	smb2_deltree(tree1, BASEDIR);
> > +	return ret;
> > +}
> > +
> > +/*
> >    basic testing of change notifies followed by a ulogoff
> >  */
> >  
> > @@ -2133,6 +2202,7 @@ struct torture_suite *torture_smb2_notify_init(void)
> >  	torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect);
> >  	torture_suite_add_1smb2_test(suite, "tdis1", torture_smb2_notify_tree_disconnect_1);
> >  	torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
> > +	torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
> >  	torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
> >  	torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
> >  	torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
> > -- 
> > 1.9.1
> > 
> > 
> > From 20dc433dda00cf9576e8ce553c5ee0a3cc725a47 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:20:50 +0200
> > Subject: [PATCH 06/17] s4:torture/smb2: add smb2.notify.invalid-reauth test
> > 
> > An invalid reauth closes the session.
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source4/torture/smb2/notify.c | 82 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 82 insertions(+)
> > 
> > diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
> > index d2b3594..33df249 100644
> > --- a/source4/torture/smb2/notify.c
> > +++ b/source4/torture/smb2/notify.c
> > @@ -1455,6 +1455,87 @@ done:
> >  	return ret;
> >  }
> >  
> > +/*
> > +  basic testing of change notifies followed by an invalid reauth
> > +*/
> > +
> > +static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
> > +					       struct smb2_tree *tree1,
> > +					       struct smb2_tree *tree2)
> > +{
> > +	bool ret = true;
> > +	NTSTATUS status;
> > +	union smb_notify notify;
> > +	union smb_open io;
> > +	struct smb2_handle h1;
> > +	struct smb2_request *req;
> > +	struct cli_credentials *invalid_creds;
> > +
> > +	smb2_deltree(tree2, BASEDIR);
> > +	smb2_util_rmdir(tree2, BASEDIR);
> > +
> > +	torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY invalid REAUTH\n");
> > +
> > +	/*
> > +	  get a handle on the directory
> > +	*/
> > +	ZERO_STRUCT(io.smb2);
> > +	io.generic.level = RAW_OPEN_SMB2;
> > +	io.smb2.in.create_flags = 0;
> > +	io.smb2.in.desired_access = SEC_FILE_ALL;
> > +	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
> > +	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
> > +	io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
> > +				NTCREATEX_SHARE_ACCESS_WRITE;
> > +	io.smb2.in.alloc_size = 0;
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
> > +	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
> > +	io.smb2.in.security_flags = 0;
> > +	io.smb2.in.fname = BASEDIR;
> > +
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +	h1 = io.smb2.out.file.handle;
> > +
> > +	/* ask for a change notify,
> > +	   on file or directory name changes */
> > +	ZERO_STRUCT(notify.smb2);
> > +	notify.smb2.level = RAW_NOTIFY_SMB2;
> > +	notify.smb2.in.buffer_size = 1000;
> > +	notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
> > +	notify.smb2.in.file.handle = h1;
> > +	notify.smb2.in.recursive = true;
> > +
> > +	req = smb2_notify_send(tree1, &(notify.smb2));
> > +
> > +	WAIT_FOR_ASYNC_RESPONSE(req);
> > +
> > +	invalid_creds = cli_credentials_init(torture);
> > +	torture_assert(torture, (invalid_creds != NULL), "talloc error");
> > +	cli_credentials_set_username(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
> > +	cli_credentials_set_domain(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
> > +	cli_credentials_set_password(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
> > +	cli_credentials_set_realm(invalid_creds, NULL, CRED_SPECIFIED);
> > +	cli_credentials_set_workstation(invalid_creds, "", CRED_UNINITIALISED);
> > +
> > +	status = smb2_session_setup_spnego(tree1->session,
> > +					   invalid_creds,
> > +					   0 /* previous_session_id */);
> > +	CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
> > +
> > +	status = smb2_notify_recv(req, torture, &(notify.smb2));
> > +	CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
> > +	CHECK_VAL(notify.smb2.out.num_changes, 0);
> > +
> > +done:
> > +	smb2_deltree(tree2, BASEDIR);
> > +	return ret;
> > +}
> > +
> >  static void tcp_dis_handler(struct smb2_transport *t, void *p)
> >  {
> >  	struct smb2_tree *tree = (struct smb2_tree *)p;
> > @@ -2204,6 +2285,7 @@ struct torture_suite *torture_smb2_notify_init(void)
> >  	torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
> >  	torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
> >  	torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
> > +	torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
> >  	torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
> >  	torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
> >  	torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double);
> > -- 
> > 1.9.1
> > 
> > 
> > From 4e6d97ee5efbbbd093fd0a966811585a8c305e05 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 09:57:03 +0200
> > Subject: [PATCH 07/17] s4:torture/smb2: add smb2.notify.session-reconnect test
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source4/torture/smb2/notify.c | 81 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 81 insertions(+)
> > 
> > diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
> > index 33df249..b804ebc 100644
> > --- a/source4/torture/smb2/notify.c
> > +++ b/source4/torture/smb2/notify.c
> > @@ -1456,6 +1456,86 @@ done:
> >  }
> >  
> >  /*
> > +  basic testing of change notifies followed by a session reconnect
> > +*/
> > +
> > +static bool torture_smb2_notify_session_reconnect(struct torture_context *torture,
> > +				struct smb2_tree *tree1)
> > +{
> > +	bool ret = true;
> > +	NTSTATUS status;
> > +	union smb_notify notify;
> > +	union smb_open io;
> > +	struct smb2_handle h1;
> > +	struct smb2_request *req;
> > +	uint64_t previous_session_id = 0;
> > +	struct smb2_session *session2 = NULL;
> > +
> > +	smb2_deltree(tree1, BASEDIR);
> > +	smb2_util_rmdir(tree1, BASEDIR);
> > +
> > +	torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY SESSION RECONNECT\n");
> > +
> > +	/*
> > +	  get a handle on the directory
> > +	*/
> > +	ZERO_STRUCT(io.smb2);
> > +	io.generic.level = RAW_OPEN_SMB2;
> > +	io.smb2.in.create_flags = 0;
> > +	io.smb2.in.desired_access = SEC_FILE_ALL;
> > +	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
> > +	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
> > +	io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
> > +				NTCREATEX_SHARE_ACCESS_WRITE;
> > +	io.smb2.in.alloc_size = 0;
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
> > +	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
> > +	io.smb2.in.security_flags = 0;
> > +	io.smb2.in.fname = BASEDIR;
> > +
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +
> > +	io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
> > +	status = smb2_create(tree1, torture, &(io.smb2));
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +	h1 = io.smb2.out.file.handle;
> > +
> > +	/* ask for a change notify,
> > +	   on file or directory name changes */
> > +	ZERO_STRUCT(notify.smb2);
> > +	notify.smb2.level = RAW_NOTIFY_SMB2;
> > +	notify.smb2.in.buffer_size = 1000;
> > +	notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
> > +	notify.smb2.in.file.handle = h1;
> > +	notify.smb2.in.recursive = true;
> > +
> > +	req = smb2_notify_send(tree1, &(notify.smb2));
> > +
> > +	WAIT_FOR_ASYNC_RESPONSE(req);
> > +
> > +	previous_session_id = smb2cli_session_current_id(tree1->session->smbXcli);
> > +	torture_assert(torture, torture_smb2_session_setup(torture,
> > +		       tree1->session->transport,
> > +		       previous_session_id,
> > +		       torture, &session2),
> > +		       "session setup with previous_session_id failed");
> > +
> > +	status = smb2_notify_recv(req, torture, &(notify.smb2));
> > +	CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
> > +	CHECK_VAL(notify.smb2.out.num_changes, 0);
> > +
> > +	status = smb2_logoff(tree1->session);
> > +	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
> > +
> > +	status = smb2_logoff(session2);
> > +	CHECK_STATUS(status, NT_STATUS_OK);
> > +done:
> > +	smb2_deltree(tree1, BASEDIR);
> > +	return ret;
> > +}
> > +
> > +/*
> >    basic testing of change notifies followed by an invalid reauth
> >  */
> >  
> > @@ -2285,6 +2365,7 @@ struct torture_suite *torture_smb2_notify_init(void)
> >  	torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
> >  	torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
> >  	torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
> > +	torture_suite_add_1smb2_test(suite, "session-reconnect", torture_smb2_notify_session_reconnect);
> >  	torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
> >  	torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
> >  	torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
> > -- 
> > 1.9.1
> > 
> > 
> > From 10c41f4a6635cbfed0df3457604256f0592fe423 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:09:40 +0200
> > Subject: [PATCH 08/17] s3:smbXsrv_session: clear smb2req->session of pending
> >  requests in smbXsrv_session_destructor()
> > 
> > This won't be needed typically needed as the caller is supposted to cancel
> > the requests already, but this makes sure we don't keep dangling pointers.
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smbXsrv_session.c | 23 +++++++++++++++++++++++
> >  1 file changed, 23 insertions(+)
> > 
> > diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
> > index a49e246..41625fc 100644
> > --- a/source3/smbd/smbXsrv_session.c
> > +++ b/source3/smbd/smbXsrv_session.c
> > @@ -1066,6 +1066,29 @@ NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
> >  static int smbXsrv_session_destructor(struct smbXsrv_session *session)
> >  {
> >  	NTSTATUS status;
> > +	struct smbXsrv_connection *xconn = NULL;
> > +
> > +	if (session->client != NULL) {
> > +		xconn = session->client->connections;
> > +	}
> > +
> > +	for (; xconn != NULL; xconn = xconn->next) {
> > +		struct smbd_smb2_request *preq;
> > +
> > +		for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > +			if (preq->session != session) {
> > +				continue;
> > +			}
> > +
> > +			preq->session = NULL;
> > +			/*
> > +			 * If we no longer have a session we can't
> > +			 * sign or encrypt replies.
> > +			 */
> > +			preq->do_signing = false;
> > +			preq->do_encryption = false;
> > +		}
> > +	}
> >  
> >  	status = smbXsrv_session_logoff(session);
> >  	if (!NT_STATUS_IS_OK(status)) {
> > -- 
> > 1.9.1
> > 
> > 
> > From 2793e29e742f45db2c05c8e571a9cdfe0d96468e Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:17:34 +0200
> > Subject: [PATCH 09/17] s3:smbXsrv_session: clear smb2req->session of pending
> >  requests in smbXsrv_session_logoff_all_callback()
> > 
> > smbXsrv_session_logoff_all_callback() is called when the last transport
> > connection is gone, which means we won't need to sign any response...
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smbXsrv_session.c | 23 +++++++++++++++++++++++
> >  1 file changed, 23 insertions(+)
> > 
> > diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
> > index 41625fc..5ee4bbe 100644
> > --- a/source3/smbd/smbXsrv_session.c
> > +++ b/source3/smbd/smbXsrv_session.c
> > @@ -1503,6 +1503,7 @@ static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
> >  	TDB_DATA val;
> >  	void *ptr = NULL;
> >  	struct smbXsrv_session *session = NULL;
> > +	struct smbXsrv_connection *xconn = NULL;
> >  	NTSTATUS status;
> >  
> >  	val = dbwrap_record_get_value(local_rec);
> > @@ -1519,6 +1520,28 @@ static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
> >  	session = talloc_get_type_abort(ptr, struct smbXsrv_session);
> >  
> >  	session->db_rec = local_rec;
> > +
> > +	if (session->client != NULL) {
> > +		xconn = session->client->connections;
> > +	}
> > +	for (; xconn != NULL; xconn = xconn->next) {
> > +		struct smbd_smb2_request *preq;
> > +
> > +		for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > +			if (preq->session != session) {
> > +				continue;
> > +			}
> > +
> > +			preq->session = NULL;
> > +			/*
> > +			 * If we no longer have a session we can't
> > +			 * sign or encrypt replies.
> > +			 */
> > +			preq->do_signing = false;
> > +			preq->do_encryption = false;
> > +		}
> > +	}
> > +
> >  	status = smbXsrv_session_logoff(session);
> >  	if (!NT_STATUS_IS_OK(status)) {
> >  		if (NT_STATUS_IS_OK(state->first_status)) {
> > -- 
> > 1.9.1
> > 
> > 
> > From 9ef38da3bd9e69e01da1a69fad30d824d355bcdf Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 09:57:03 +0200
> > Subject: [PATCH 10/17] s3:smbXsrv_session: add
> >  smb2srv_session_shutdown_send/recv helper functions
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/globals.h         |   5 ++
> >  source3/smbd/smbXsrv_session.c | 121 +++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 126 insertions(+)
> > 
> > diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
> > index c7e2608..22cf5d6 100644
> > --- a/source3/smbd/globals.h
> > +++ b/source3/smbd/globals.h
> > @@ -537,6 +537,11 @@ struct smbXsrv_channel_global0;
> >  NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
> >  				      const struct smbXsrv_connection *conn,
> >  				      struct smbXsrv_channel_global0 **_c);
> > +struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
> > +					struct tevent_context *ev,
> > +					struct smbXsrv_session *session,
> > +					struct smbd_smb2_request *current_req);
> > +NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req);
> >  NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session);
> >  NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_connection *conn);
> >  NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn);
> > diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
> > index 5ee4bbe..f4617f7 100644
> > --- a/source3/smbd/smbXsrv_session.c
> > +++ b/source3/smbd/smbXsrv_session.c
> > @@ -1327,6 +1327,127 @@ NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
> >  	return NT_STATUS_USER_SESSION_DELETED;
> >  }
> >  
> > +struct smb2srv_session_shutdown_state {
> > +	struct tevent_queue *wait_queue;
> > +};
> > +
> > +static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
> > +
> > +struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
> > +					struct tevent_context *ev,
> > +					struct smbXsrv_session *session,
> > +					struct smbd_smb2_request *current_req)
> > +{
> > +	struct tevent_req *req;
> > +	struct smb2srv_session_shutdown_state *state;
> > +	struct tevent_req *subreq;
> > +	struct smbXsrv_connection *xconn = NULL;
> > +	size_t len = 0;
> > +
> > +	/*
> > +	 * Make sure that no new request will be able to use this session.
> > +	 */
> > +	session->status = NT_STATUS_USER_SESSION_DELETED;
> > +
> > +	req = tevent_req_create(mem_ctx, &state,
> > +				struct smb2srv_session_shutdown_state);
> > +	if (req == NULL) {
> > +		return NULL;
> > +	}
> > +
> > +	state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
> > +	if (tevent_req_nomem(state->wait_queue, req)) {
> > +		return tevent_req_post(req, ev);
> > +	}
> > +
> > +	for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
> > +		struct smbd_smb2_request *preq;
> > +
> > +		for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > +			if (preq == current_req) {
> > +				/* Can't cancel current request. */
> > +				continue;
> > +			}
> > +			if (preq->session != session) {
> > +				/* Request on different session. */
> > +				continue;
> > +			}
> > +
> > +			if (!NT_STATUS_IS_OK(xconn->transport.status)) {
> > +				preq->session = NULL;
> > +				/*
> > +				 * If we no longer have a session we can't
> > +				 * sign or encrypt replies.
> > +				 */
> > +				preq->do_signing = false;
> > +				preq->do_encryption = false;
> > +
> > +				if (preq->subreq != NULL) {
> > +					tevent_req_cancel(preq->subreq);
> > +				}
> > +				continue;
> > +			}
> > +
> > +			/*
> > +			 * Never cancel anything in a compound
> > +			 * request. Way too hard to deal with
> > +			 * the result.
> > +			 */
> > +			if (!preq->compound_related && preq->subreq != NULL) {
> > +				tevent_req_cancel(preq->subreq);
> > +			}
> > +
> > +			/*
> > +			 * Now wait until the request is finished.
> > +			 *
> > +			 * We don't set a callback, as we just want to block the
> > +			 * wait queue and the talloc_free() of the request will
> > +			 * remove the item from the wait queue.
> > +			 */
> > +			subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
> > +			if (tevent_req_nomem(subreq, req)) {
> > +				return tevent_req_post(req, ev);
> > +			}
> > +		}
> > +	}
> > +
> > +	len = tevent_queue_length(state->wait_queue);
> > +	if (len == 0) {
> > +		tevent_req_done(req);
> > +		return tevent_req_post(req, ev);
> > +	}
> > +
> > +	/*
> > +	 * Now we add our own waiter to the end of the queue,
> > +	 * this way we get notified when all pending requests are finished
> > +	 * and send to the socket.
> > +	 */
> > +	subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
> > +	if (tevent_req_nomem(subreq, req)) {
> > +		return tevent_req_post(req, ev);
> > +	}
> > +	tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
> > +
> > +	return req;
> > +}
> > +
> > +static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
> > +{
> > +	struct tevent_req *req =
> > +		tevent_req_callback_data(subreq,
> > +		struct tevent_req);
> > +
> > +	tevent_queue_wait_recv(subreq);
> > +	TALLOC_FREE(subreq);
> > +
> > +	tevent_req_done(req);
> > +}
> > +
> > +NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
> > +{
> > +	return tevent_req_simple_recv_ntstatus(req);
> > +}
> > +
> >  NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
> >  {
> >  	struct smbXsrv_session_table *table;
> > -- 
> > 1.9.1
> > 
> > 
> > From db39da8d22db275c913a3b172915510595477397 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:13:27 +0200
> > Subject: [PATCH 11/17] s3:smbXsrv_session: cancel pending requests when we
> >  logoff a previous session
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smbXsrv_session.c | 45 +++++++++++++++++++++++++++++++++++-------
> >  1 file changed, 38 insertions(+), 7 deletions(-)
> > 
> > diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
> > index f4617f7..2ccae0e 100644
> > --- a/source3/smbd/smbXsrv_session.c
> > +++ b/source3/smbd/smbXsrv_session.c
> > @@ -226,6 +226,8 @@ static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
> >  	return NT_STATUS_OK;
> >  }
> >  
> > +static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
> > +
> >  static void smbXsrv_session_close_loop(struct tevent_req *subreq)
> >  {
> >  	struct smbXsrv_client *client =
> > @@ -330,20 +332,22 @@ static void smbXsrv_session_close_loop(struct tevent_req *subreq)
> >  		goto next;
> >  	}
> >  
> > -	/*
> > -	 * TODO: cancel all outstanding requests on the session
> > -	 */
> > -	status = smbXsrv_session_logoff(session);
> > -	if (!NT_STATUS_IS_OK(status)) {
> > +	subreq = smb2srv_session_shutdown_send(session, client->ev_ctx,
> > +					       session, NULL);
> > +	if (subreq == NULL) {
> > +		status = NT_STATUS_NO_MEMORY;
> >  		DEBUG(0, ("smbXsrv_session_close_loop: "
> > -			  "smbXsrv_session_logoff(%llu) failed: %s\n",
> > +			  "smb2srv_session_shutdown_send(%llu) failed: %s\n",
> >  			  (unsigned long long)session->global->session_wire_id,
> >  			  nt_errstr(status)));
> >  		if (DEBUGLVL(1)) {
> >  			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
> >  		}
> > +		goto next;
> >  	}
> > -	TALLOC_FREE(session);
> > +	tevent_req_set_callback(subreq,
> > +				smbXsrv_session_close_shutdown_done,
> > +				session);
> >  
> >  next:
> >  	TALLOC_FREE(rec);
> > @@ -359,6 +363,33 @@ next:
> >  	tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
> >  }
> >  
> > +static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
> > +{
> > +	struct smbXsrv_session *session =
> > +		tevent_req_callback_data(subreq,
> > +		struct smbXsrv_session);
> > +	NTSTATUS status;
> > +
> > +	status = smb2srv_session_shutdown_recv(subreq);
> > +	TALLOC_FREE(subreq);
> > +	if (!NT_STATUS_IS_OK(status)) {
> > +		DEBUG(0, ("smbXsrv_session_close_loop: "
> > +			  "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
> > +			  (unsigned long long)session->global->session_wire_id,
> > +			  nt_errstr(status)));
> > +	}
> > +
> > +	status = smbXsrv_session_logoff(session);
> > +	if (!NT_STATUS_IS_OK(status)) {
> > +		DEBUG(0, ("smbXsrv_session_close_loop: "
> > +			  "smbXsrv_session_logoff(%llu) failed: %s\n",
> > +			  (unsigned long long)session->global->session_wire_id,
> > +			  nt_errstr(status)));
> > +	}
> > +
> > +	TALLOC_FREE(session);
> > +}
> > +
> >  struct smb1srv_session_local_allocate_state {
> >  	const uint32_t lowest_id;
> >  	const uint32_t highest_id;
> > -- 
> > 1.9.1
> > 
> > 
> > From 5a25052bca611617fd5bbab4fec493a247186cc5 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:20:06 +0200
> > Subject: [PATCH 12/17] s3:smb2_sesssetup: let smbd_smb2_logoff_* use
> >  smbXsrv_session_shutdown_*
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smb2_sesssetup.c | 75 +++++++++----------------------------------
> >  1 file changed, 15 insertions(+), 60 deletions(-)
> > 
> > diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
> > index fb7edce..5cd3446 100644
> > --- a/source3/smbd/smb2_sesssetup.c
> > +++ b/source3/smbd/smb2_sesssetup.c
> > @@ -860,95 +860,50 @@ static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
> >  	}
> >  }
> >  
> > -struct smbd_smb2_logout_state {
> > +struct smbd_smb2_logoff_state {
> >  	struct smbd_smb2_request *smb2req;
> > -	struct tevent_queue *wait_queue;
> >  };
> >  
> > -static void smbd_smb2_logoff_wait_done(struct tevent_req *subreq);
> > +static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
> >  
> >  static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
> >  					struct tevent_context *ev,
> >  					struct smbd_smb2_request *smb2req)
> >  {
> >  	struct tevent_req *req;
> > -	struct smbd_smb2_logout_state *state;
> > +	struct smbd_smb2_logoff_state *state;
> >  	struct tevent_req *subreq;
> > -	struct smbd_smb2_request *preq;
> > -	struct smbXsrv_connection *xconn = smb2req->xconn;
> >  
> >  	req = tevent_req_create(mem_ctx, &state,
> > -			struct smbd_smb2_logout_state);
> > +			struct smbd_smb2_logoff_state);
> >  	if (req == NULL) {
> >  		return NULL;
> >  	}
> >  	state->smb2req = smb2req;
> >  
> > -	state->wait_queue = tevent_queue_create(state, "logoff_wait_queue");
> > -	if (tevent_req_nomem(state->wait_queue, req)) {
> > -		return tevent_req_post(req, ev);
> > -	}
> > -
> > -	/*
> > -	 * Make sure that no new request will be able to use this session.
> > -	 */
> > -	smb2req->session->status = NT_STATUS_USER_SESSION_DELETED;
> > -
> > -	for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > -		if (preq == smb2req) {
> > -			/* Can't cancel current request. */
> > -			continue;
> > -		}
> > -		if (preq->session != smb2req->session) {
> > -			/* Request on different session. */
> > -			continue;
> > -		}
> > -
> > -		/*
> > -		 * Never cancel anything in a compound
> > -		 * request. Way too hard to deal with
> > -		 * the result.
> > -		 */
> > -		if (!preq->compound_related && preq->subreq != NULL) {
> > -			tevent_req_cancel(preq->subreq);
> > -		}
> > -
> > -		/*
> > -		 * Now wait until the request is finished.
> > -		 *
> > -		 * We don't set a callback, as we just want to block the
> > -		 * wait queue and the talloc_free() of the request will
> > -		 * remove the item from the wait queue.
> > -		 */
> > -		subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
> > -		if (tevent_req_nomem(subreq, req)) {
> > -			return tevent_req_post(req, ev);
> > -		}
> > -	}
> > -
> > -	/*
> > -	 * Now we add our own waiter to the end of the queue,
> > -	 * this way we get notified when all pending requests are finished
> > -	 * and send to the socket.
> > -	 */
> > -	subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
> > +	subreq = smb2srv_session_shutdown_send(state, ev,
> > +					       smb2req->session,
> > +					       smb2req);
> >  	if (tevent_req_nomem(subreq, req)) {
> >  		return tevent_req_post(req, ev);
> >  	}
> > -	tevent_req_set_callback(subreq, smbd_smb2_logoff_wait_done, req);
> > +	tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
> >  
> >  	return req;
> >  }
> >  
> > -static void smbd_smb2_logoff_wait_done(struct tevent_req *subreq)
> > +static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
> >  {
> >  	struct tevent_req *req = tevent_req_callback_data(
> >  		subreq, struct tevent_req);
> > -	struct smbd_smb2_logout_state *state = tevent_req_data(
> > -		req, struct smbd_smb2_logout_state);
> > +	struct smbd_smb2_logoff_state *state = tevent_req_data(
> > +		req, struct smbd_smb2_logoff_state);
> >  	NTSTATUS status;
> >  
> > -	tevent_queue_wait_recv(subreq);
> > +	status = smb2srv_session_shutdown_recv(subreq);
> > +	if (tevent_req_nterror(req, status)) {
> > +		return;
> > +	}
> >  	TALLOC_FREE(subreq);
> >  
> >  	/*
> > -- 
> > 1.9.1
> > 
> > 
> > From f5b8aa1a1b6ca7db1d67af3feecc0ae07fbad32e Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:27:26 +0200
> > Subject: [PATCH 13/17] s3:smb2_sesssetup: always assign smb2req->session when
> >  a session was created.
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smb2_sesssetup.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
> > index 5cd3446..e7eb414 100644
> > --- a/source3/smbd/smb2_sesssetup.c
> > +++ b/source3/smbd/smb2_sesssetup.c
> > @@ -368,7 +368,6 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
> >  	 * we attach the session to the request
> >  	 * so that the response can be signed
> >  	 */
> > -	smb2req->session = session;
> >  	if (!guest) {
> >  		smb2req->do_signing = true;
> >  	}
> > @@ -587,6 +586,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> >  		if (tevent_req_nterror(req, status)) {
> >  			return tevent_req_post(req, ev);
> >  		}
> > +		smb2req->session = state->session;
> >  	} else {
> >  		if (smb2req->session == NULL) {
> >  			tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
> > -- 
> > 1.9.1
> > 
> > 
> > From 53604c3b1cc52d8ad00133e1c069917a841b47ae Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:21:25 +0200
> > Subject: [PATCH 14/17] s3:smb2_sesssetup: add
> >  smbd_smb2_session_setup_wrap_send/recv()
> > 
> > The wrapper calls smbXsrv_session_shutdown_send/recv() in case of an error,
> > this makes sure a failing reauth shuts down the session like an explicit logoff.
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smb2_sesssetup.c | 186 ++++++++++++++++++++++++++++++++++++++----
> >  1 file changed, 171 insertions(+), 15 deletions(-)
> > 
> > diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
> > index e7eb414..5ddaa48 100644
> > --- a/source3/smbd/smb2_sesssetup.c
> > +++ b/source3/smbd/smb2_sesssetup.c
> > @@ -29,7 +29,7 @@
> >  #include "../libcli/security/security.h"
> >  #include "../lib/util/tevent_ntstatus.h"
> >  
> > -static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> > +static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
> >  					struct tevent_context *ev,
> >  					struct smbd_smb2_request *smb2req,
> >  					uint64_t in_session_id,
> > @@ -37,7 +37,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> >  					uint8_t in_security_mode,
> >  					uint64_t in_previous_session_id,
> >  					DATA_BLOB in_security_buffer);
> > -static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
> > +static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
> >  					uint16_t *out_session_flags,
> >  					TALLOC_CTX *mem_ctx,
> >  					DATA_BLOB *out_security_buffer,
> > @@ -87,14 +87,14 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
> >  	in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
> >  	in_security_buffer.length = in_security_length;
> >  
> > -	subreq = smbd_smb2_session_setup_send(smb2req,
> > -					      smb2req->sconn->ev_ctx,
> > -					      smb2req,
> > -					      in_session_id,
> > -					      in_flags,
> > -					      in_security_mode,
> > -					      in_previous_session_id,
> > -					      in_security_buffer);
> > +	subreq = smbd_smb2_session_setup_wrap_send(smb2req,
> > +						   smb2req->sconn->ev_ctx,
> > +						   smb2req,
> > +						   in_session_id,
> > +						   in_flags,
> > +						   in_security_mode,
> > +						   in_previous_session_id,
> > +						   in_security_buffer);
> >  	if (subreq == NULL) {
> >  		return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
> >  	}
> > @@ -118,11 +118,11 @@ static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
> >  	NTSTATUS status;
> >  	NTSTATUS error; /* transport error */
> >  
> > -	status = smbd_smb2_session_setup_recv(subreq,
> > -					      &out_session_flags,
> > -					      smb2req,
> > -					      &out_security_buffer,
> > -					      &out_session_id);
> > +	status = smbd_smb2_session_setup_wrap_recv(subreq,
> > +						   &out_session_flags,
> > +						   smb2req,
> > +						   &out_security_buffer,
> > +						   &out_session_id);
> >  	TALLOC_FREE(subreq);
> >  	if (!NT_STATUS_IS_OK(status) &&
> >  	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
> > @@ -788,6 +788,162 @@ static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
> >  	return status;
> >  }
> >  
> > +struct smbd_smb2_session_setup_wrap_state {
> > +	struct tevent_context *ev;
> > +	struct smbd_smb2_request *smb2req;
> > +	uint64_t in_session_id;
> > +	uint8_t in_flags;
> > +	uint8_t in_security_mode;
> > +	uint64_t in_previous_session_id;
> > +	DATA_BLOB in_security_buffer;
> > +	uint16_t out_session_flags;
> > +	DATA_BLOB out_security_buffer;
> > +	uint64_t out_session_id;
> > +	NTSTATUS error;
> > +};
> > +
> > +static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
> > +static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
> > +
> > +static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
> > +					struct tevent_context *ev,
> > +					struct smbd_smb2_request *smb2req,
> > +					uint64_t in_session_id,
> > +					uint8_t in_flags,
> > +					uint8_t in_security_mode,
> > +					uint64_t in_previous_session_id,
> > +					DATA_BLOB in_security_buffer)
> > +{
> > +	struct tevent_req *req;
> > +	struct smbd_smb2_session_setup_wrap_state *state;
> > +	struct tevent_req *subreq;
> > +
> > +	req = tevent_req_create(mem_ctx, &state,
> > +				struct smbd_smb2_session_setup_wrap_state);
> > +	if (req == NULL) {
> > +		return NULL;
> > +	}
> > +	state->ev = ev;
> > +	state->smb2req = smb2req;
> > +	state->in_session_id = in_session_id;
> > +	state->in_flags = in_flags;
> > +	state->in_security_mode = in_security_mode;
> > +	state->in_previous_session_id = in_previous_session_id;
> > +	state->in_security_buffer = in_security_buffer;
> > +
> > +	subreq = smbd_smb2_session_setup_send(state, state->ev,
> > +					      state->smb2req,
> > +					      state->in_session_id,
> > +					      state->in_flags,
> > +					      state->in_security_mode,
> > +					      state->in_previous_session_id,
> > +					      state->in_security_buffer);
> > +	if (tevent_req_nomem(subreq, req)) {
> > +		return tevent_req_post(req, ev);
> > +	}
> > +	tevent_req_set_callback(subreq,
> > +				smbd_smb2_session_setup_wrap_setup_done, req);
> > +
> > +	return req;
> > +}
> > +
> > +static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
> > +{
> > +	struct tevent_req *req =
> > +		tevent_req_callback_data(subreq,
> > +		struct tevent_req);
> > +	struct smbd_smb2_session_setup_wrap_state *state =
> > +		tevent_req_data(req,
> > +		struct smbd_smb2_session_setup_wrap_state);
> > +	NTSTATUS status;
> > +
> > +	status = smbd_smb2_session_setup_recv(subreq,
> > +					      &state->out_session_flags,
> > +					      state,
> > +					      &state->out_security_buffer,
> > +					      &state->out_session_id);
> > +	TALLOC_FREE(subreq);
> > +	if (NT_STATUS_IS_OK(status)) {
> > +		tevent_req_done(req);
> > +		return;
> > +	}
> > +	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
> > +		tevent_req_nterror(req, status);
> > +		return;
> > +	}
> > +
> > +	if (state->smb2req->session == NULL) {
> > +		tevent_req_nterror(req, status);
> > +		return;
> > +	}
> > +
> > +	state->error = status;
> > +
> > +	subreq = smb2srv_session_shutdown_send(state, state->ev,
> > +					       state->smb2req->session,
> > +					       state->smb2req);
> > +	if (tevent_req_nomem(subreq, req)) {
> > +		return;
> > +	}
> > +	tevent_req_set_callback(subreq,
> > +				smbd_smb2_session_setup_wrap_shutdown_done,
> > +				req);
> > +}
> > +
> > +static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
> > +{
> > +	struct tevent_req *req =
> > +		tevent_req_callback_data(subreq,
> > +		struct tevent_req);
> > +	struct smbd_smb2_session_setup_wrap_state *state =
> > +		tevent_req_data(req,
> > +		struct smbd_smb2_session_setup_wrap_state);
> > +	NTSTATUS status;
> > +
> > +	status = smb2srv_session_shutdown_recv(subreq);
> > +	TALLOC_FREE(subreq);
> > +	if (tevent_req_nterror(req, status)) {
> > +		return;
> > +	}
> > +
> > +	/*
> > +	 * we may need to sign the response, so we need to keep
> > +	 * the session until the response is sent to the wire.
> > +	 */
> > +	talloc_steal(state->smb2req, state->smb2req->session);
> > +
> > +	tevent_req_nterror(req, state->error);
> > +}
> > +
> > +static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
> > +					uint16_t *out_session_flags,
> > +					TALLOC_CTX *mem_ctx,
> > +					DATA_BLOB *out_security_buffer,
> > +					uint64_t *out_session_id)
> > +{
> > +	struct smbd_smb2_session_setup_wrap_state *state =
> > +		tevent_req_data(req,
> > +		struct smbd_smb2_session_setup_wrap_state);
> > +	NTSTATUS status;
> > +
> > +	if (tevent_req_is_nterror(req, &status)) {
> > +		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
> > +			tevent_req_received(req);
> > +			return nt_status_squash(status);
> > +		}
> > +	} else {
> > +		status = NT_STATUS_OK;
> > +	}
> > +
> > +	*out_session_flags = state->out_session_flags;
> > +	*out_security_buffer = state->out_security_buffer;
> > +	*out_session_id = state->out_session_id;
> > +
> > +	talloc_steal(mem_ctx, out_security_buffer->data);
> > +	tevent_req_received(req);
> > +	return status;
> > +}
> > +
> >  static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
> >  					struct tevent_context *ev,
> >  					struct smbd_smb2_request *smb2req);
> > -- 
> > 1.9.1
> > 
> > 
> > From 5943d75702246d791138092a2b609b95ba674777 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Sat, 2 May 2015 16:29:03 +0200
> > Subject: [PATCH 15/17] s3:smb2_sesssetup: remove unused
> >  smbd_smb2_session_setup_* destructors
> > 
> > The cleanup of a failing session setup is now handled in
> > smbd_smb2_session_setup_wrap_*().
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smb2_sesssetup.c | 98 -------------------------------------------
> >  1 file changed, 98 deletions(-)
> > 
> > diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
> > index 5ddaa48..c56e480 100644
> > --- a/source3/smbd/smb2_sesssetup.c
> > +++ b/source3/smbd/smb2_sesssetup.c
> > @@ -448,94 +448,12 @@ struct smbd_smb2_session_setup_state {
> >  	uint16_t out_session_flags;
> >  	DATA_BLOB out_security_buffer;
> >  	uint64_t out_session_id;
> > -	/* The following pointer is owned by state->session. */
> > -	struct smbd_smb2_session_setup_state **pp_self_ref;
> >  };
> >  
> > -static int pp_self_ref_destructor(struct smbd_smb2_session_setup_state **pp_state)
> > -{
> > -	(*pp_state)->session = NULL;
> > -	/*
> > -	 * To make things clearer, ensure the pp_self_ref
> > -	 * pointer is nulled out. We're never going to
> > -	 * access this again.
> > -	 */
> > -	(*pp_state)->pp_self_ref = NULL;
> > -	return 0;
> > -}
> > -
> > -static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_setup_state *state)
> > -{
> > -	struct smbXsrv_connection *xconn;
> > -	struct smbd_smb2_request *preq;
> > -
> > -	/*
> > -	 * If state->session is not NULL,
> > -	 * we move the session from the session table to the request on failure
> > -	 * so that the error response can be correctly signed, but the session
> > -	 * is then really deleted when the request is done.
> > -	 */
> > -
> > -	if (state->session == NULL) {
> > -		return 0;
> > -	}
> > -
> > -	state->session->status = NT_STATUS_USER_SESSION_DELETED;
> > -	state->smb2req->session = talloc_move(state->smb2req, &state->session);
> > -
> > -	/*
> > -	 * We own the session now - we don't need the
> > -	 * tag talloced on session that keeps track of session independently.
> > -	 */
> > -	TALLOC_FREE(state->pp_self_ref);
> > -
> > -	/*
> > -	 * We've made this session owned by the current request.
> > -	 * Ensure that any outstanding requests don't also refer
> > -	 * to it.
> > -	 */
> > -	xconn = state->smb2req->xconn;
> > -
> > -	for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > -		if (preq == state->smb2req) {
> > -			continue;
> > -		}
> > -		if (preq->session == state->smb2req->session) {
> > -			preq->session = NULL;
> > -			/*
> > -			 * If we no longer have a session we can't
> > -			 * sign or encrypt replies.
> > -			 */
> > -			preq->do_signing = false;
> > -			preq->do_encryption = false;
> > -		}
> > -	}
> > -
> > -	return 0;
> > -}
> > -
> >  static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
> >  static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
> >  static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
> >  
> > -/************************************************************************
> > - We have to tag the state->session pointer with memory talloc'ed
> > - on it to ensure it gets NULL'ed out if the underlying struct smbXsrv_session
> > - is deleted by shutdown whilst this request is in flight.
> > -************************************************************************/
> > -
> > -static NTSTATUS tag_state_session_ptr(struct smbd_smb2_session_setup_state *state)
> > -{
> > -	state->pp_self_ref = talloc_zero(state->session,
> > -			struct smbd_smb2_session_setup_state *);
> > -	if (state->pp_self_ref == NULL) {
> > -		return NT_STATUS_NO_MEMORY;
> > -	}
> > -	*state->pp_self_ref = state;
> > -	talloc_set_destructor(state->pp_self_ref, pp_self_ref_destructor);
> > -	return NT_STATUS_OK;
> > -}
> > -
> >  static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> >  					struct tevent_context *ev,
> >  					struct smbd_smb2_request *smb2req,
> > @@ -577,8 +495,6 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> >  		return tevent_req_post(req, ev);
> >  	}
> >  
> > -	talloc_set_destructor(state, smbd_smb2_session_setup_state_destructor);
> > -
> >  	if (state->in_session_id == 0) {
> >  		/* create a new session */
> >  		status = smbXsrv_session_create(state->smb2req->xconn,
> > @@ -609,11 +525,6 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
> >  		}
> >  	}
> >  
> > -	status = tag_state_session_ptr(state);
> > -	if (tevent_req_nterror(req, status)) {
> > -		return tevent_req_post(req, ev);
> > -	}
> > -
> >  	if (state->session->gensec == NULL) {
> >  		status = auth_generic_prepare(state->session,
> >  					      state->smb2req->xconn->remote_address,
> > @@ -668,9 +579,6 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
> >  
> >  	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
> >  		state->out_session_id = state->session->global->session_wire_id;
> > -		/* we want to keep the session */
> > -		state->session = NULL;
> > -		TALLOC_FREE(state->pp_self_ref);
> >  		tevent_req_nterror(req, status);
> >  		return;
> >  	}
> > @@ -735,9 +643,6 @@ static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
> >  		if (tevent_req_nterror(req, status)) {
> >  			return;
> >  		}
> > -		/* we want to keep the session */
> > -		state->session = NULL;
> > -		TALLOC_FREE(state->pp_self_ref);
> >  		tevent_req_done(req);
> >  		return;
> >  	}
> > @@ -752,9 +657,6 @@ static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
> >  		return;
> >  	}
> >  
> > -	/* we want to keep the session */
> > -	state->session = NULL;
> > -	TALLOC_FREE(state->pp_self_ref);
> >  	tevent_req_done(req);
> >  	return;
> >  }
> > -- 
> > 1.9.1
> > 
> > 
> > From b414e5fc8339fbf893aedd5d3f457c17d3e59265 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 16:50:55 +0200
> > Subject: [PATCH 16/17] s3:smb2_tcon: cancel pending requests on all
> >  connections on tdis
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/smbd/smb2_tcon.c | 66 +++++++++++++++++++++++++-----------------------
> >  1 file changed, 35 insertions(+), 31 deletions(-)
> > 
> > diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
> > index cf085a5..3750bc1 100644
> > --- a/source3/smbd/smb2_tcon.c
> > +++ b/source3/smbd/smb2_tcon.c
> > @@ -502,8 +502,7 @@ static struct tevent_req *smbd_smb2_tdis_send(TALLOC_CTX *mem_ctx,
> >  	struct tevent_req *req;
> >  	struct smbd_smb2_tdis_state *state;
> >  	struct tevent_req *subreq;
> > -	struct smbd_smb2_request *preq;
> > -	struct smbXsrv_connection *xconn = smb2req->xconn;
> > +	struct smbXsrv_connection *xconn = NULL;
> >  
> >  	req = tevent_req_create(mem_ctx, &state,
> >  			struct smbd_smb2_tdis_state);
> > @@ -522,35 +521,40 @@ static struct tevent_req *smbd_smb2_tdis_send(TALLOC_CTX *mem_ctx,
> >  	 */
> >  	smb2req->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
> >  
> > -	for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > -		if (preq == smb2req) {
> > -			/* Can't cancel current request. */
> > -			continue;
> > -		}
> > -		if (preq->tcon != smb2req->tcon) {
> > -			/* Request on different tcon. */
> > -			continue;
> > -		}
> > -
> > -		/*
> > -		 * Never cancel anything in a compound
> > -		 * request. Way too hard to deal with
> > -		 * the result.
> > -		 */
> > -		if (!preq->compound_related && preq->subreq != NULL) {
> > -			tevent_req_cancel(preq->subreq);
> > -		}
> > -
> > -		/*
> > -		 * Now wait until the request is finished.
> > -		 *
> > -		 * We don't set a callback, as we just want to block the
> > -		 * wait queue and the talloc_free() of the request will
> > -		 * remove the item from the wait queue.
> > -		 */
> > -		subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
> > -		if (tevent_req_nomem(subreq, req)) {
> > -			return tevent_req_post(req, ev);
> > +	xconn = smb2req->xconn->client->connections;
> > +	for (; xconn != NULL; xconn = xconn->next) {
> > +		struct smbd_smb2_request *preq;
> > +
> > +		for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
> > +			if (preq == smb2req) {
> > +				/* Can't cancel current request. */
> > +				continue;
> > +			}
> > +			if (preq->tcon != smb2req->tcon) {
> > +				/* Request on different tcon. */
> > +				continue;
> > +			}
> > +
> > +			/*
> > +			 * Never cancel anything in a compound
> > +			 * request. Way too hard to deal with
> > +			 * the result.
> > +			 */
> > +			if (!preq->compound_related && preq->subreq != NULL) {
> > +				tevent_req_cancel(preq->subreq);
> > +			}
> > +
> > +			/*
> > +			 * Now wait until the request is finished.
> > +			 *
> > +			 * We don't set a callback, as we just want to block the
> > +			 * wait queue and the talloc_free() of the request will
> > +			 * remove the item from the wait queue.
> > +			 */
> > +			subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
> > +			if (tevent_req_nomem(subreq, req)) {
> > +				return tevent_req_post(req, ev);
> > +			}
> >  		}
> >  	}
> >  
> > -- 
> > 1.9.1
> > 
> > 
> > From 67c3692a5404f888b637328fdb32c6d4d2f748e3 Mon Sep 17 00:00:00 2001
> > From: Stefan Metzmacher <metze at samba.org>
> > Date: Fri, 1 May 2015 20:26:41 +0200
> > Subject: [PATCH 17/17] s3:selftest: run smb2.notify with --signing=required
> > 
> > This reproduces a bug withe implicit canceled requests.
> > 
> > Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
> > 
> > Signed-off-by: Stefan Metzmacher <metze at samba.org>
> > ---
> >  source3/selftest/tests.py | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
> > index 7436d26..dd06e07 100755
> > --- a/source3/selftest/tests.py
> > +++ b/source3/selftest/tests.py
> > @@ -383,6 +383,9 @@ for t in tests:
> >      elif t == "local.nss":
> >          for env in ["nt4_dc:local", "ad_member:local", "nt4_member:local", "ad_dc:local", "ad_dc_ntvfs:local"]:
> >              plansmbtorture4testsuite(t, env, '//$SERVER/tmp -U$USERNAME%$PASSWORD')
> > +    elif t == "smb2.notify":
> > +        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --signing=required')
> > +        plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD --signing=required')
> >      else:
> >          plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
> >          plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
> > -- 
> > 1.9.1
> > 
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150506/08b251aa/attachment.pgp>


More information about the samba-technical mailing list