Latest leases patchset - getting there !

Stefan (metze) Metzmacher metze at samba.org
Thu Nov 13 19:02:19 MST 2014


Am 14.11.2014 um 02:56 schrieb Jeremy Allison:
> On Fri, Nov 14, 2014 at 01:42:58AM +0100, Stefan (metze) Metzmacher wrote:
>>> On Thu, Nov 13, 2014 at 09:09:05PM +0100, Stefan (metze) Metzmacher wrote:
>>>> Am 13.11.2014 um 08:12 schrieb Jeremy Allison:
>>>>> On Thu, Nov 13, 2014 at 01:17:43AM +0100, Stefan (metze) Metzmacher wrote:
>>>>>>
>>>>>> I've integrated this with a few more tests we fail (sorry...:-)
>>>>>>
>>>>>> ontop17.diff.txt replaces the older ontop13.diff.txt
>>>>>> and also includes your changes.
>>>>>
>>>>> No problem. Attached are some new patches to fix the new
>>>>> tests we fail :-). They apply on top of ontop17.diff.txt.
>>>>>
>>>>> on-top-of-ontop17.patchset
>>>>>
>>>>> The current state of play with this new code are:
>>>>>
>>>>> request 		PASS
>>>>> break_twice		PASS
>>>>> nobreakself		PASS
>>>>> upgrade			PASS
>>>>> upgrade2		PASS
>>>>> upgrade3		PASS
>>>>> break			PASS
>>>>> oplock			PASS
>>>>> multibreak		PASS
>>>>> breaking1		--- PASS WITH smbtorture MODIFICATION (*)
>>>>
>>>> fixed in ontop17-3.diff.txt
>>>>
>>>>> breaking2		--- TEST CRASHES in smbtorture.(**)
>>>>
>>>> the crash is fixed in ontop17-3.diff.txt
>>>>
>>>>> complex1		PASS
>>>>> v2_epoch1		PASS
>>>>> v2_epoch2			insane test - see below
>>>>> v2_epoch3			insane test - see below
>>>>
>>>> I've fixed those in ontop17-3.diff.txt
>>>
>>> Looks like you added lease_version to struct share_mode_oplock,
>>> but I don't see the patch adding this to the IDL, or the
>>> code that sets this on lease creation.
>>>
>>> Are you missing a posted patch ?
>>
>> Yes, sorry.
>>
>> Here's the full patchset (leases18.diff.txt) on top of master.
>>
>> And the partial patch (todo18.diff.txt) on top of it.
> 
> With just leases18.diff.txt all tests except breaking2
> (commented out) pass.
> 
> Unfortunately, when I add todo18.diff.txt on top:
> 
> nobreakself and multibreak start to fail.
> 
> I will investigate and post more I have better
> info.

This is fixed with todo19.diff.txt :-)

There we just need to check what to do in the timeout handler.

metze
metze
-------------- next part --------------
From 165212ac9a7bdac5c2d3722efa6bf176975eee59 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 13 Nov 2014 11:50:14 +0100
Subject: [PATCH] TODO: breaking_to_state... works...

---
 source3/locking/locking.c  |  60 +++++++++--
 source3/locking/proto.h    |   4 +-
 source3/smbd/globals.h     |   6 +-
 source3/smbd/open.c        |   8 ++
 source3/smbd/oplock.c      | 244 +++++++++++++++++++++++++++++++++------------
 source3/smbd/proto.h       |   5 +-
 source3/smbd/smb2_break.c  |  30 ++++--
 source3/smbd/smb2_create.c |   8 --
 source3/smbd/smb2_server.c |  17 ++--
 9 files changed, 276 insertions(+), 106 deletions(-)

diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 006d6d3..b3ab9ad 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -945,6 +945,7 @@ bool fsp_lease_broken(struct share_mode_lock *lck,
 {
 	struct share_mode_data *d = lck->data;
 	struct share_mode_entry *e;
+	struct share_mode_oplock *o;
 
 	if (!file_id_equal(&fsp->file_id, &lck_id)) {
 		return false;
@@ -960,27 +961,42 @@ bool fsp_lease_broken(struct share_mode_lock *lck,
 		return false;
 	}
 
+	o = &d->leases[e->lease_idx];
+
 	if (!smb2_lease_equal(&fsp->conn->sconn->client->connections->smb2.client.guid,
-			      key,
-			      &d->leases[e->lease_idx].client_guid,
-			      &d->leases[e->lease_idx].lease_key)) {
+			      key, &o->client_guid, &o->lease_key)) {
 		return false;
 	}
-	fsp->sent_oplock_break = NO_BREAK_SENT;
+
 	TALLOC_FREE(fsp->oplock_timeout);
-	fsp->lease->lease.lease_state = new_lease_state;
+
+	DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+	/* Ensure we're in sync with current lease state. */
+	fsp->lease->lease.lease_state = o->current_state;
+	fsp->lease->lease.lease_epoch = o->epoch;
+	if (o->breaking) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+		fsp->lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
+	} else {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+		fsp->lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
+	}
+
 	return true;
 }
 
 NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
 			       struct share_mode_lock *lck,
 			       const struct smb2_lease_key *key,
-			       uint32_t new_lease_state)
+			       uint32_t new_lease_state,
+			       struct share_mode_oplock **_l)
 {
 	struct share_mode_data *d = lck->data;
 	struct share_mode_oplock *l;
 	uint32_t i;
 
+	*_l = NULL;
+
 	for (i=0; i<d->num_leases; i++) {
 		if (smb2_lease_equal(&sconn->client->connections->smb2.client.guid,
 				     key,
@@ -996,18 +1012,44 @@ NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
 
 	l = &d->leases[i];
 
+	if (!l->breaking) {
+		DEBUG(0, ("Attempt to break from %d to %d - but we're not in breaking state\n",
+			   (int)l->current_state, (int)new_lease_state));
+		return NT_STATUS_INVALID_OPLOCK_PROTOCOL;
+	}
+
 	/*
 	 * Can't upgrade anything: l->current_state must be a strict bitwise
 	 * superset of new_lease_state
 	 */
 
 	if ((new_lease_state & l->current_state) != new_lease_state) {
-		DEBUG(10, ("Attempt to upgrade from %d to %d\n",
-			   (int)l->current_state, (int)new_lease_state));
+		DEBUG(0, ("Attempt to upgrade from %d to %d - expected %d\n",
+			   (int)l->current_state, (int)new_lease_state,
+			   (int)l->breaking_to_state));
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
 	}
 
-	l->current_state = new_lease_state;
+	if (l->current_state != new_lease_state) {
+		l->current_state = new_lease_state;
+		d->modified = true;
+	}
+
+	if ((new_lease_state & ~l->breaking_to_state) != 0) {
+		DEBUG(0, ("lease state %d not fully broken from %d to %d\n",
+			   (int)new_lease_state,
+			   (int)l->current_state,
+			   (int)l->breaking_to_state));
+		*_l = l;
+		return NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
+	}
+
+	//TODO: verify new_lease_state == l->breaking_to_state ???
+
+	DEBUG(0, ("breaking from %d to %d - expected %d\n",
+		   (int)l->current_state, (int)new_lease_state,
+		   (int)l->breaking_to_state));
+
 	l->breaking_to_state = 0;
 	l->breaking = 0;
 
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 94e9b8f..c48cd89 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -179,10 +179,12 @@ bool fsp_lease_broken(struct share_mode_lock *lck,
 		      struct file_id lck_id,
 		      const struct smb2_lease_key *key,
 		      files_struct *fsp, uint32_t new_lease_state);
+struct share_mode_oplock;
 NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
 			       struct share_mode_lock *lck,
 			       const struct smb2_lease_key *key,
-			       uint32_t new_lease_state);
+			       uint32_t new_lease_state,
+			       struct share_mode_oplock **_l);
 bool get_delete_on_close_token(struct share_mode_lock *lck,
 				uint32_t name_hash,
 				const struct security_token **pp_nt_tok,
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index f297ff7..0ce1982 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -251,8 +251,6 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
 				     struct smbXsrv_open *op,
 				     uint8_t oplock_level);
 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
-				    struct smbXsrv_session *session,
-				    struct smbXsrv_tcon *tcon,
 				    uint16_t new_epoch,
 				    uint32_t lease_flags,
 				    struct smb2_lease_key *lease_key,
@@ -306,7 +304,9 @@ void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
 struct deferred_open_record;
 
 /* SMB1 -> SMB2 glue. */
-void send_break_message_smb2(files_struct *fsp, uint32_t break_to);
+void send_break_message_smb2(files_struct *fsp,
+			     uint32_t break_from,
+			     uint32_t break_to);
 struct blocking_lock_record *get_pending_smb2req_blr(struct smbd_smb2_request *smb2req);
 bool push_blocking_lock_request_smb2( struct byte_range_lock *br_lck,
 				struct smb_request *req,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 804b6f0..33a2bf9 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1430,6 +1430,14 @@ static bool delay_for_oplock(files_struct *fsp,
 			if (share_mode_stale_pid(d, i)) {
 				continue;
 			}
+
+			//if (e->op_type == LEASE_OPLOCK) {
+			//	struct share_mode_oplock *o = NULL;
+			//	o = &d->leases[e->lease_idx];
+			//	if (o->breaking) {
+			//		continue;
+			//	}
+			//}
 			send_break_message(fsp->conn->sconn->msg_ctx, e,
 					   e_lease_type & ~SMB2_LEASE_HANDLE);
 			have_broken = true;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 4755ca6..240ff59 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -291,6 +291,40 @@ bool downgrade_oplock(files_struct *fsp)
 	return ret;
 }
 
+struct downgrade_lease_additional_state {
+	struct tevent_immediate *im;
+	struct smbXsrv_connection *xconn;
+	uint32_t lease_flags;
+	struct smb2_lease_key lease_key;
+	uint32_t current_lease_state;
+	uint32_t new_lease_state;
+	uint16_t new_epoch;
+};
+
+static void downgrade_lease_additional_trigger(struct tevent_context *ev,
+					       struct tevent_immediate *im,
+					       void *private_data)
+{
+	struct downgrade_lease_additional_state *state =
+		talloc_get_type_abort(private_data,
+		struct downgrade_lease_additional_state);
+	struct smbXsrv_connection *xconn = state->xconn;
+	NTSTATUS status;
+
+	status = smbd_smb2_send_lease_break(xconn,
+					    state->new_epoch,
+					    state->lease_flags,
+					    &state->lease_key,
+					    state->current_lease_state,
+					    state->new_lease_state);
+	TALLOC_FREE(state);
+	if (!NT_STATUS_IS_OK(status)) {
+		smbd_server_connection_terminate(xconn,
+						 nt_errstr(status));
+		return;
+	}
+}
+
 struct downgrade_lease_fsps_state {
 	struct file_id id;
 	struct share_mode_lock *lck;
@@ -312,22 +346,59 @@ static struct files_struct *downgrade_lease_fsps(struct files_struct *fsp,
 	return NULL;
 }
 
-NTSTATUS downgrade_lease(struct smbd_server_connection *sconn,
+NTSTATUS downgrade_lease(struct smbXsrv_connection *xconn,
 			 const struct file_id id,
-			 const struct smb2_lease_key *key,
+			 const struct smb2_lease *lease,
 			 uint32_t lease_state)
 {
+	struct smbd_server_connection *sconn = xconn->client->sconn;
+	const struct smb2_lease_key *key = &lease->lease_key;
 	struct share_mode_lock *lck;
+	struct share_mode_oplock *l = NULL;
 	NTSTATUS status;
 
-	DEBUG(10, ("%s: Downgrading %s to %x\n", __func__,
+	DEBUG(0, ("%s: Downgrading %s to %x\n", __func__,
 		   file_id_string_tos(&id), (unsigned)lease_state));
 
 	lck = get_existing_share_mode_lock(talloc_tos(), id);
 	if (lck == NULL) {
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
-	status = downgrade_share_lease(sconn, lck, key, lease_state);
+	status = downgrade_share_lease(sconn, lck, key, lease_state, &l);
+
+	DEBUG(0, ("%s: Downgrading %s to %x => %s\n", __func__,
+		   file_id_string_tos(&id), (unsigned)lease_state, nt_errstr(status)));
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_BREAK_IN_PROGRESS)) {
+		struct downgrade_lease_additional_state *state;
+
+		state = talloc_zero(xconn,
+				    struct downgrade_lease_additional_state);
+		if (state == NULL) {
+			TALLOC_FREE(lck);
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		state->im = tevent_create_immediate(state);
+		if (state->im == NULL) {
+			TALLOC_FREE(state);
+			TALLOC_FREE(lck);
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		state->xconn = xconn;
+		state->lease_flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
+		state->lease_key = l->lease_key;
+		state->current_lease_state = l->current_state;
+		state->new_lease_state = l->breaking_to_state;
+		if (l->lease_version > 1) {
+			state->new_epoch = lease->lease_epoch;
+		}
+
+		tevent_schedule_immediate(state->im, xconn->ev_ctx,
+					  downgrade_lease_additional_trigger,
+					  state);
+	}
 
 	/*
 	 * This sucks. We have to reset fsp->sent_oplock_break on all fsps
@@ -346,6 +417,8 @@ NTSTATUS downgrade_lease(struct smbd_server_connection *sconn,
 	}
 
 	TALLOC_FREE(lck);
+	DEBUG(0, ("%s: Downgrading %s to %x => %s\n", __func__,
+		   file_id_string_tos(&id), (unsigned)lease_state, nt_errstr(status)));
 	return status;
 }
 
@@ -444,6 +517,11 @@ static void oplock_timeout_handler(struct tevent_context *ctx,
 {
 	files_struct *fsp = (files_struct *)private_data;
 
+	if (fsp->oplock_type == LEASE_OPLOCK) {
+		//TODO
+		SMB_ASSERT(false);
+	}
+
 	SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
 
 	/* Remove the timed event handler. */
@@ -526,7 +604,9 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 		struct smbd_server_connection);
 	struct server_id self = messaging_server_id(sconn->msg_ctx);
 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
+	uint16_t break_from;
 	uint16_t break_to;
+	bool break_needed = true;
 
 	if (data->data == NULL) {
 		DEBUG(0, ("Got NULL buffer\n"));
@@ -542,7 +622,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 	message_to_share_mode_entry(&msg, (char *)data->data);
 	break_to = msg.op_type;
 
-	DEBUG(10, ("Got oplock break to %u message from pid %s: %s/%llu\n",
+	DEBUG(0, ("Got oplock break to %u message from pid %s: %s/%llu\n",
 		   (unsigned)break_to, server_id_str(talloc_tos(), &src),
 		   file_id_string_tos(&msg.id),
 		   (unsigned long long)msg.share_file_id));
@@ -556,13 +636,21 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 		return;
 	}
 
-	if (fsp->sent_oplock_break != NO_BREAK_SENT) {
-		/*
-		 * Nothing to do anymore
-		 */
-		DEBUG(10, ("fsp->sent_oplock_break = %d\n",
-			   fsp->sent_oplock_break));
-		return;
+	if (fsp->oplock_timeout != NULL) {
+//		return;
+	}
+
+	break_from = fsp_lease_type(fsp);
+
+	if (fsp->oplock_type != LEASE_OPLOCK) {
+		if (fsp->sent_oplock_break != NO_BREAK_SENT) {
+			/*
+			 * Nothing to do anymore
+			 */
+			DEBUG(10, ("fsp->sent_oplock_break = %d\n",
+				   fsp->sent_oplock_break));
+			return;
+		}
 	}
 
 	if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
@@ -581,30 +669,15 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 		break_to &= ~SMB2_LEASE_READ;
 	}
 
-	DEBUG(10, ("msg.op_type=%u, break_to=%u\n",
-		   (unsigned)msg.op_type, (unsigned)break_to));
-
-	if (fsp->oplock_type == NO_OPLOCK) {
-		DEBUG(3, ("Already downgraded oplock to none on %s: %s\n",
-			  file_id_string_tos(&fsp->file_id),
-			  fsp_str_dbg(fsp)));
-		return;
-	}
-	if ((break_to & SMB2_LEASE_READ) &&
-	    (fsp->oplock_type == LEVEL_II_OPLOCK)) {
-		DEBUG(3, ("Already downgraded oplock to level2 on %s: %s\n",
-			  file_id_string_tos(&fsp->file_id),
-			  fsp_str_dbg(fsp)));
-		return;
-	}
-
 	if (fsp->oplock_type == LEASE_OPLOCK) {
 		struct share_mode_lock *lck;
 		int idx;
 
+		DEBUG(0,("%s: refresh lease state - begin\n", __func__));
 		lck = get_existing_share_mode_lock(
 			talloc_tos(), fsp->file_id);
 
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
 		idx = find_share_mode_oplock(
 			lck->data,
 			&fsp->conn->sconn->client->connections->
@@ -613,16 +686,78 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 		if (idx != -1) {
 			struct share_mode_oplock *o;
 			o = &lck->data->leases[idx];
+
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+			break_from = o->current_state;
+			break_to &= o->current_state;
+
+			if (o->breaking) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				break_to &= o->breaking_to_state;
+				if (o->breaking_to_state != break_to) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+					o->breaking_to_state = break_to;
+					lck->data->modified = true;
+				}
+				break_needed = false;
+			} else if (o->current_state == break_to) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				break_needed = false;
+			} else if (o->current_state == SMB2_LEASE_READ) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				o->current_state = SMB2_LEASE_NONE;
+				lck->data->modified = true;
+			} else {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				o->breaking = true;
+				o->breaking_to_state = break_to;
+				lck->data->modified = true;
+			}
+
+			/* Need to increment the epoch */
+			if (lck->data->modified) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				o->epoch += 1;
+			}
+
 			/* Ensure we're in sync with current lease state. */
 			fsp->lease->lease.lease_state = o->current_state;
-			/* Need to increment the epoch */
-			o->epoch += 1;
 			fsp->lease->lease.lease_epoch = o->epoch;
-			/* And remember to write it out again.. */
-			lck->data->modified = true;
+			if (o->breaking) {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				fsp->lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
+			} else {
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
+				fsp->lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
+			}
 		}
 
+		DEBUG(0,("%s: refresh lease state - line(%d)\n", __func__, __LINE__));
 		TALLOC_FREE(lck);
+		DEBUG(0,("%s: refresh lease state - end\n", __func__));
+	}
+
+	if (!break_needed) {
+		DEBUG(0,("%s: skip break\n", __func__));
+		return;
+	}
+
+	if ((break_from == SMB2_LEASE_NONE) && !break_needed) {
+		DEBUG(3, ("Already downgraded oplock to none on %s: %s\n",
+			  file_id_string_tos(&fsp->file_id),
+			  fsp_str_dbg(fsp)));
+		return;
+	}
+
+	DEBUG(0, ("msg.op_type=%u, break_to=%u\n",
+		   (unsigned)msg.op_type, (unsigned)break_to));
+
+	if ((break_from == break_to) && !break_needed) {
+		DEBUG(3, ("Already downgraded oplock to %u on %s: %s\n",
+			  (unsigned)break_to,
+			  file_id_string_tos(&fsp->file_id),
+			  fsp_str_dbg(fsp)));
+		return;
 	}
 
 	/* Need to wait before sending a break
@@ -632,33 +767,31 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 	}
 
 	if (sconn->using_smb2) {
-		send_break_message_smb2(fsp, break_to);
+		DEBUG(0,("%s: send_break_message_smb2 \n", __func__));
+		send_break_message_smb2(fsp, break_from, break_to);
 	} else {
 		send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
 					OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
 	}
 
-	if ((fsp_lease_type(fsp) == SMB2_LEASE_READ) &&
+	if ((break_from == SMB2_LEASE_READ) &&
 	    (break_to == SMB2_LEASE_NONE)) {
 		/*
 		 * This is an async break without a reply and thus no timeout
+		 *
+		 * leases are handled above.
 		 */
-		if (fsp->oplock_type == LEASE_OPLOCK) {
-			/*
-			 * We must leave the lease around, it might be
-			 * upgraded later
-			 */
-			downgrade_lease(fsp->conn->sconn, fsp->file_id,
-					&fsp->lease->lease.lease_key,
-					break_to);
-		} else {
+		if (fsp->oplock_type != LEASE_OPLOCK) {
 			remove_oplock(fsp);
 		}
 		return;
 	}
-	fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
-		LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
+	if (fsp->oplock_type != LEASE_OPLOCK) {
+		fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
+			LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
+	}
 
+	DEBUG(0,("%s: add_oplock_timeout_handler \n", __func__));
 	add_oplock_timeout_handler(fsp);
 }
 
@@ -713,7 +846,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
 	}
 
 	if (sconn->using_smb2) {
-		send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);
+		send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
 	} else {
 		send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
 	}
@@ -937,23 +1070,6 @@ done:
 	return;
 }
 
-bool break_in_progress(const files_struct *fsp)
-{
-	files_struct *new_fsp;
-
-	for (new_fsp = file_find_di_first(fsp->conn->sconn, fsp->file_id);
-			new_fsp != NULL;
-			new_fsp = file_find_di_next(new_fsp)) {
-		if (new_fsp == fsp) {
-			continue;
-		}
-		if (new_fsp->sent_oplock_break != NO_BREAK_SENT) {
-			return true;
-		}
-	}
-	return false;
-}
-
 void smbd_contend_level2_oplocks_begin(files_struct *fsp,
 				  enum level2_contention_type type)
 {
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index c8e404e..c4f8920 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -667,11 +667,10 @@ void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp);
 NTSTATUS set_file_oplock(files_struct *fsp);
 bool remove_oplock(files_struct *fsp);
 bool downgrade_oplock(files_struct *fsp);
-NTSTATUS downgrade_lease(struct smbd_server_connection *sconn,
+NTSTATUS downgrade_lease(struct smbXsrv_connection *xconn,
 			 const struct file_id id,
-			 const struct smb2_lease_key *key,
+			 const struct smb2_lease *lease,
 			 uint32_t lease_state);
-bool break_in_progress(const files_struct *fsp);
 void contend_level2_oplocks_begin(files_struct *fsp,
 				  enum level2_contention_type type);
 void contend_level2_oplocks_end(files_struct *fsp,
diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c
index 9ab118d..f9fce5a 100644
--- a/source3/smbd/smb2_break.c
+++ b/source3/smbd/smb2_break.c
@@ -354,8 +354,15 @@ static struct tevent_req *smbd_smb2_lease_break_send(
 		return tevent_req_post(req, ev);
 	}
 
-	status = downgrade_lease(smb2_req->sconn, fsp->file_id, &in_lease_key,
-				 in_lease_state);
+	status = downgrade_lease(smb2_req->xconn, fsp->file_id,
+				 &fsp->lease->lease, in_lease_state);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_BREAK_IN_PROGRESS)) {
+		/*
+		 * here we keep the fsp->oplock_timeout
+		 */
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}
 	if (tevent_req_nterror(req, status)) {
 		DEBUG(10, ("downgrade_lease returned %s\n",
 			   nt_errstr(status)));
@@ -386,7 +393,9 @@ static NTSTATUS smbd_smb2_lease_break_recv(struct tevent_req *req,
  SMB2 OPLOCK_BREAK_NOTIFICATION.
 *********************************************************/
 
-void send_break_message_smb2(files_struct *fsp, uint32_t break_to)
+void send_break_message_smb2(files_struct *fsp,
+			     uint32_t break_from,
+			     uint32_t break_to)
 {
 	NTSTATUS status;
 	struct smbXsrv_connection *xconn = NULL;
@@ -425,11 +434,12 @@ void send_break_message_smb2(files_struct *fsp, uint32_t break_to)
 		(unsigned int)break_to ));
 
 	if (fsp->oplock_type == LEASE_OPLOCK) {
-		bool no_ack;
+		uint32_t break_flags = 0;
 		uint16_t new_epoch;
 
-		no_ack = ((fsp->lease->lease.lease_state == SMB2_LEASE_READ) &&
-			  (break_to == SMB2_LEASE_NONE));
+		if (fsp->lease->lease.lease_state != SMB2_LEASE_NONE) {
+			break_flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
+		}
 
 		if (fsp->lease->lease.lease_version > 1) {
 			new_epoch = fsp->lease->lease.lease_epoch;
@@ -437,11 +447,9 @@ void send_break_message_smb2(files_struct *fsp, uint32_t break_to)
 			new_epoch = 0;
 		}
 
-		status = smbd_smb2_send_lease_break(
-			xconn, session, fsp->conn->tcon, new_epoch,
-			no_ack ? 0 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED,
-			&fsp->lease->lease.lease_key,
-			fsp->lease->lease.lease_state, break_to);
+		status = smbd_smb2_send_lease_break(xconn, new_epoch, break_flags,
+						    &fsp->lease->lease.lease_key,
+						    break_from, break_to);
 	} else {
 		uint8_t smb2_oplock_level;
 		smb2_oplock_level = (break_to & SMB2_LEASE_READ) ?
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 482bb66..91583fa 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1204,14 +1204,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			uint8_t buf[52];
 
 			lease = result->lease->lease;
-			lease.lease_flags &=
-				SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET;
-
-			/* Is there a break in progress ? */
-			if (break_in_progress(result)) {
-				lease.lease_flags |=
-					SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
-			}
 
 			lease_len = sizeof(buf);
 			if (lease.lease_version == 1) {
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 36ac0d7..16eed90 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2760,14 +2760,19 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
 				     size_t body_len)
 {
 	struct smbd_smb2_send_break_state *state;
-	bool do_encryption = session->global->encryption_required;
+	bool do_encryption = false;
+	uint64_t session_wire_id = 0;
 	uint64_t nonce_high = 0;
 	uint64_t nonce_low = 0;
 	NTSTATUS status;
 	size_t statelen;
 
-	if (tcon->global->encryption_required) {
-		do_encryption = true;
+	if (session != NULL) {
+		session_wire_id = session->global->session_wire_id;
+		do_encryption = session->global->encryption_required;
+		if (tcon->global->encryption_required) {
+			do_encryption = true;
+		}
 	}
 
 	statelen = offsetof(struct smbd_smb2_send_break_state, body) +
@@ -2793,7 +2798,7 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
 	SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
 	SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
 	SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
-	SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
+	SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
 
 	SIVAL(state->hdr, 0,				SMB2_MAGIC);
 	SSVAL(state->hdr, SMB2_HDR_LENGTH,		SMB2_HDR_BODY);
@@ -2889,8 +2894,6 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
 }
 
 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
-				    struct smbXsrv_session *session,
-				    struct smbXsrv_tcon *tcon,
 				    uint16_t new_epoch,
 				    uint32_t lease_flags,
 				    struct smb2_lease_key *lease_key,
@@ -2910,7 +2913,7 @@ NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
 	SIVAL(body, 0x24, 0);		/* AccessMaskHint, MUST be 0 */
 	SIVAL(body, 0x28, 0);		/* ShareMaskHint, MUST be 0 */
 
-	return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
+	return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
 }
 
 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20141114/6bd1b3eb/attachment.pgp>


More information about the samba-technical mailing list