[SCM] Samba Shared Repository - branch master updated

Michael Adam obnox at samba.org
Tue Oct 15 18:52:02 MDT 2013


The branch, master has been updated
       via  a1fcd71 smbd: Simplify open_file_ntcreate
       via  4c0cf9f smbd: Remove "file_existed" handling from open_mode_check
       via  4263d16 smbd: Decouple grant_fsp_oplock_type from oplock validation
       via  00d84ad smbd: Reduce the complexity of open_file_ntcreate
       via  c938a10 smbd: Factor out remove_stale_share_mode_entries
       via  4d85f91 smbd: Make find_oplock_types return bool
       via  0f71730 smbd: Make loop index type match loop limit
       via  388bf36 smbd: Unify delay_for_*_oplocks
       via  c33015c smbd: Simplify find_oplock_types a bit
      from  f50b6da s4:torture: add smb2.session.reauth6 : test failing reauth

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


- Log -----------------------------------------------------------------
commit a1fcd71f9aad98428e33bc2e31cf6d077b0c02fc
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Sep 26 15:20:36 2013 -0700

    smbd: Simplify open_file_ntcreate
    
    Only one call to delay_for_oplocks left. Metze showed me the new logic:
    BATCH is broken if we have a sharing violation. Exclusive is broken
    otherwise. That's it.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>
    
    Autobuild-User(master): Michael Adam <obnox at samba.org>
    Autobuild-Date(master): Wed Oct 16 02:51:53 CEST 2013 on sn-devel-104

commit 4c0cf9fade8e9118c8da31cf3db3a4497321294b
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Sep 26 14:32:09 2013 -0700

    smbd: Remove "file_existed" handling from open_mode_check
    
    No clue what this does. In open_directory, "dir_existed" is not used after
    open_mode_check. In open_file_ntcreate it's used, but I can't think of a case
    right now where we would find a formerly nonexisting file to exist suddenly.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 4263d16f134bd93813a880ccb81503bc998a98f3
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Sep 3 09:02:12 2013 +0000

    smbd: Decouple grant_fsp_oplock_type from oplock validation
    
    This makes grant_fsp_oplock_type independent from the values computed
    in validate_oplock_types. It *might* make oplock calculation a bit
    slower for heavily shared files, as we are walking the share mode array
    twice. But we are doing so much stuff in open that I doubt the difference
    is measurable. It clears up the code for me however, and I think that's
    worth it.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 00d84ad1928a07bc892e8a37d53e7c35b8628b7f
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 2 12:25:07 2013 +0000

    smbd: Reduce the complexity of open_file_ntcreate
    
    This removes two variables in open_file_ntcreate based on the observation
    that for exclusive and batch oplocks there can only be one entry. So
    in these cases we don't need to keep pointers from find_oplock_types to
    delay_for_oplocks. We can just reference the only share mode entry around.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit c938a1065fed2a001da69b6a6d826ef31be75003
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 2 11:37:57 2013 +0000

    smbd: Factor out remove_stale_share_mode_entries
    
    Will be used in the next commit
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 4d85f91a5b309fac76ed8b0ed2a18132c18b2659
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 15 10:01:54 2013 +0000

    smbd: Make find_oplock_types return bool
    
    smb_panic() does not take a printf style argument. This improves debug
    output by easily printing the index that we fell over. Also, doing
    smb_panic deep down is bad style IMHO.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 0f71730d1bd1e60b439a45e56d5e68423706c897
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 15 09:56:21 2013 +0000

    smbd: Make loop index type match loop limit
    
    share_mode_data.num_share_modes is a uint32.
    
    48 bytes less in .o text size for -O3 :-)
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 388bf3643d4c0254dbc6e9f77b15a8911405c4e6
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 20 11:58:15 2013 +0000

    smbd: Unify delay_for_*_oplocks
    
    This is the same code in both routines
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit c33015c069de285cf6e14bacb1e3a7937e466ef3
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 2 12:33:40 2013 +0000

    smbd: Simplify find_oplock_types a bit
    
    Define a variable to dereference lck->data just once. Believe it or not,
    this saves a few bytes .o with -O3 :-)
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

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

Summary of changes:
 source3/locking/locking.c         |   16 +++
 source3/locking/proto.h           |    1 +
 source3/locking/share_mode_lock.c |   15 +--
 source3/smbd/open.c               |  241 +++++++++++++++++++------------------
 4 files changed, 142 insertions(+), 131 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7ac04a4..b5d4f24 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -693,6 +693,22 @@ bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
 	return true;
 }
 
+void remove_stale_share_mode_entries(struct share_mode_data *d)
+{
+	uint32_t i;
+
+	i = 0;
+	while (i < d->num_share_modes) {
+		if (d->share_modes[i].stale) {
+			struct share_mode_entry *m = d->share_modes;
+			m[i] = m[d->num_share_modes-1];
+			d->num_share_modes -= 1;
+		} else {
+			i += 1;
+		}
+	}
+}
+
 bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
 		    uid_t uid, uint64_t mid, uint16 op_type)
 {
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index f6ae462..2c9654c 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -176,6 +176,7 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e);
 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx);
 bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
 		    uid_t uid, uint64_t mid, uint16 op_type);
+void remove_stale_share_mode_entries(struct share_mode_data *d);
 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
 				  struct files_struct *fsp);
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 342f910..5d7a08c 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -171,26 +171,13 @@ static TDB_DATA unparse_share_modes(struct share_mode_data *d)
 {
 	DATA_BLOB blob;
 	enum ndr_err_code ndr_err;
-	uint32_t i;
 
 	if (DEBUGLEVEL >= 10) {
 		DEBUG(10, ("unparse_share_modes:\n"));
 		NDR_PRINT_DEBUG(share_mode_data, d);
 	}
 
-	i = 0;
-	while (i < d->num_share_modes) {
-		if (d->share_modes[i].stale) {
-			/*
-			 * Remove the stale entries before storing
-			 */
-			struct share_mode_entry *m = d->share_modes;
-			m[i] = m[d->num_share_modes-1];
-			d->num_share_modes -= 1;
-		} else {
-			i += 1;
-		}
-	}
+	remove_stale_share_mode_entries(d);
 
 	if (d->num_share_modes == 0) {
 		DEBUG(10, ("No used share mode found\n"));
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 93b69d5..fa52fcc 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1114,8 +1114,7 @@ static bool has_delete_on_close(struct share_mode_lock *lck,
 static NTSTATUS open_mode_check(connection_struct *conn,
 				struct share_mode_lock *lck,
 				uint32 access_mask,
-				uint32 share_access,
-				bool *file_existed)
+				uint32 share_access)
 {
 	int i;
 
@@ -1156,16 +1155,10 @@ static NTSTATUS open_mode_check(connection_struct *conn,
 				continue;
 			}
 
-			*file_existed = true;
-
 			return NT_STATUS_SHARING_VIOLATION;
 		}
 	}
 
-	if (lck->data->num_share_modes != 0) {
-		*file_existed = true;
-	}
-
 	return NT_STATUS_OK;
 }
 
@@ -1209,31 +1202,27 @@ static NTSTATUS send_break_message(files_struct *fsp,
  * Do internal consistency checks on the share mode for a file.
  */
 
-static void find_oplock_types(files_struct *fsp,
-				int oplock_request,
-				const struct share_mode_lock *lck,
-				struct share_mode_entry **pp_batch,
-				struct share_mode_entry **pp_ex_or_batch,
-				bool *got_level2,
-				bool *got_no_oplock)
+static bool validate_oplock_types(files_struct *fsp,
+				  int oplock_request,
+				  struct share_mode_lock *lck)
 {
-	int i;
-
-	*pp_batch = NULL;
-	*pp_ex_or_batch = NULL;
-	*got_level2 = false;
-	*got_no_oplock = false;
+	struct share_mode_data *d = lck->data;
+	bool batch = false;
+	bool ex_or_batch = false;
+	bool level2 = false;
+	bool no_oplock = false;
+	uint32_t i;
 
 	/* Ignore stat or internal opens, as is done in
 		delay_for_batch_oplocks() and
 		delay_for_exclusive_oplocks().
 	 */
 	if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
-		return;
+		return true;
 	}
 
-	for (i=0; i<lck->data->num_share_modes; i++) {
-		struct share_mode_entry *e = &lck->data->share_modes[i];
+	for (i=0; i<d->num_share_modes; i++) {
+		struct share_mode_entry *e = &d->share_modes[i];
 
 		if (!is_valid_share_mode_entry(e)) {
 			continue;
@@ -1248,67 +1237,94 @@ static void find_oplock_types(files_struct *fsp,
 
 		if (BATCH_OPLOCK_TYPE(e->op_type)) {
 			/* batch - can only be one. */
-			if (share_mode_stale_pid(lck->data, i)) {
+			if (share_mode_stale_pid(d, i)) {
 				DEBUG(10, ("Found stale batch oplock\n"));
 				continue;
 			}
-			if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
-				smb_panic("Bad batch oplock entry.");
+			if (ex_or_batch || batch || level2 || no_oplock) {
+				DEBUG(0, ("Bad batch oplock entry %u.",
+					  (unsigned)i));
+				return false;
 			}
-			*pp_batch = e;
+			batch = true;
 		}
 
 		if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
-			if (share_mode_stale_pid(lck->data, i)) {
+			if (share_mode_stale_pid(d, i)) {
 				DEBUG(10, ("Found stale duplicate oplock\n"));
 				continue;
 			}
 			/* Exclusive or batch - can only be one. */
-			if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) {
-				smb_panic("Bad exclusive or batch oplock entry.");
+			if (ex_or_batch || level2 || no_oplock) {
+				DEBUG(0, ("Bad exclusive or batch oplock "
+					  "entry %u.", (unsigned)i));
+				return false;
 			}
-			*pp_ex_or_batch = e;
+			ex_or_batch = true;
 		}
 
 		if (LEVEL_II_OPLOCK_TYPE(e->op_type)) {
-			if (*pp_batch || *pp_ex_or_batch) {
-				if (share_mode_stale_pid(lck->data, i)) {
+			if (batch || ex_or_batch) {
+				if (share_mode_stale_pid(d, i)) {
 					DEBUG(10, ("Found stale LevelII "
 						   "oplock\n"));
 					continue;
 				}
-				smb_panic("Bad levelII oplock entry.");
+				DEBUG(0, ("Bad levelII oplock entry %u.",
+					  (unsigned)i));
+				return false;
 			}
-			*got_level2 = true;
+			level2 = true;
 		}
 
 		if (e->op_type == NO_OPLOCK) {
-			if (*pp_batch || *pp_ex_or_batch) {
-				if (share_mode_stale_pid(lck->data, i)) {
+			if (batch || ex_or_batch) {
+				if (share_mode_stale_pid(d, i)) {
 					DEBUG(10, ("Found stale NO_OPLOCK "
 						   "entry\n"));
 					continue;
 				}
-				smb_panic("Bad no oplock entry.");
+				DEBUG(0, ("Bad no oplock entry %u.",
+					  (unsigned)i));
+				return false;
 			}
-			*got_no_oplock = true;
+			no_oplock = true;
 		}
 	}
+
+	remove_stale_share_mode_entries(d);
+
+	if ((batch || ex_or_batch) && (d->num_share_modes != 1)) {
+		DEBUG(1, ("got batch (%d) or ex (%d) non-exclusively (%d)\n",
+			  (int)batch, (int)ex_or_batch,
+			  (int)d->num_share_modes));
+		return false;
+	}
+
+	return true;
 }
 
-static bool delay_for_batch_oplocks(files_struct *fsp,
-					uint64_t mid,
-					int oplock_request,
-					struct share_mode_entry *batch_entry)
+static bool delay_for_oplock(files_struct *fsp,
+			     uint64_t mid,
+			     int oplock_request,
+			     struct share_mode_lock *lck,
+			     bool have_sharing_violation)
 {
+	struct share_mode_data *d = lck->data;
+	struct share_mode_entry *entry;
+
 	if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
 		return false;
 	}
-	if (batch_entry == NULL) {
+	if (lck->data->num_share_modes != 1) {
+		/*
+		 * More than one. There can't be any exclusive or batch left.
+		 */
 		return false;
 	}
+	entry = &d->share_modes[0];
 
-	if (server_id_is_disconnected(&batch_entry->pid)) {
+	if (server_id_is_disconnected(&entry->pid)) {
 		/*
 		 * TODO: clean up.
 		 * This could be achieved by sending a break message
@@ -1321,33 +1337,31 @@ static bool delay_for_batch_oplocks(files_struct *fsp,
 		return false;
 	}
 
-	/* Found a batch oplock */
-	send_break_message(fsp, batch_entry, mid, oplock_request);
-	return true;
-}
-
-static bool delay_for_exclusive_oplocks(files_struct *fsp,
-					uint64_t mid,
-					int oplock_request,
-					struct share_mode_entry *ex_entry)
-{
-	if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
-		return false;
+	if (have_sharing_violation && (entry->op_type & BATCH_OPLOCK)) {
+		if (share_mode_stale_pid(d, 0)) {
+			return false;
+		}
+		send_break_message(fsp, entry, mid, oplock_request);
+		return true;
 	}
-	if (ex_entry == NULL) {
+	if (have_sharing_violation) {
+		/*
+		 * Non-batch exclusive is not broken if we have a sharing
+		 * violation
+		 */
 		return false;
 	}
-
-	if (server_id_is_disconnected(&ex_entry->pid)) {
+	if (!EXCLUSIVE_OPLOCK_TYPE(entry->op_type)) {
 		/*
-		 * since only durable handles can get disconnected,
-		 * and we can only get durable handles with batch oplocks,
-		 * this should actually never be reached...
+		 * No break for NO_OPLOCK or LEVEL2_OPLOCK oplocks
 		 */
 		return false;
 	}
+	if (share_mode_stale_pid(d, 0)) {
+		return false;
+	}
 
-	send_break_message(fsp, ex_entry, mid, oplock_request);
+	send_break_message(fsp, entry, mid, oplock_request);
 	return true;
 }
 
@@ -1363,12 +1377,13 @@ static bool file_has_brlocks(files_struct *fsp)
 }
 
 static void grant_fsp_oplock_type(files_struct *fsp,
-				int oplock_request,
-				bool got_level2_oplock,
-				bool got_a_none_oplock)
+				  struct share_mode_lock *lck,
+				  int oplock_request)
 {
 	bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
 		            lp_level2_oplocks(SNUM(fsp->conn));
+	bool got_level2_oplock, got_a_none_oplock;
+	uint32_t i;
 
 	/* Start by granting what the client asked for,
 	   but ensure no SAMBA_PRIVATE bits can be set. */
@@ -1395,6 +1410,20 @@ static void grant_fsp_oplock_type(files_struct *fsp,
 		return;
 	}
 
+	got_level2_oplock = false;
+	got_a_none_oplock = false;
+
+	for (i=0; i<lck->data->num_share_modes; i++) {
+		int op_type = lck->data->share_modes[i].op_type;
+
+		if (LEVEL_II_OPLOCK_TYPE(op_type)) {
+			got_level2_oplock = true;
+		}
+		if (op_type == NO_OPLOCK) {
+			got_a_none_oplock = true;
+		}
+	}
+
 	/*
 	 * Match what was requested (fsp->oplock_type) with
  	 * what was found in the existing share modes.
@@ -1965,10 +1994,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	NTSTATUS status;
 	char *parent_dir;
 	SMB_STRUCT_STAT saved_stat = smb_fname->st;
-	struct share_mode_entry *batch_entry = NULL;
-	struct share_mode_entry *exclusive_entry = NULL;
-	bool got_level2_oplock = false;
-	bool got_a_none_oplock = false;
 	struct timespec old_write_time;
 	struct file_id id;
 
@@ -2309,12 +2334,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			return NT_STATUS_SHARING_VIOLATION;
 		}
 
-		find_oplock_types(fsp, 0, lck, &batch_entry, &exclusive_entry,
-				  &got_level2_oplock, &got_a_none_oplock);
+		if (!validate_oplock_types(fsp, 0, lck)) {
+			smb_panic("validate_oplock_types failed");
+		}
 
-		if (delay_for_batch_oplocks(fsp, req->mid, 0, batch_entry) ||
-		    delay_for_exclusive_oplocks(fsp, req->mid, 0,
-						exclusive_entry)) {
+		if (delay_for_oplock(fsp, req->mid, 0, lck, false)) {
 			schedule_defer_open(lck, request_time, req);
 			TALLOC_FREE(lck);
 			DEBUG(10, ("Sent oplock break request to kernel "
@@ -2398,13 +2422,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	}
 
 	/* Get the types we need to examine. */
-	find_oplock_types(fsp,
-			  oplock_request,
-			  lck,
-			  &batch_entry,
-			  &exclusive_entry,
-			  &got_level2_oplock,
-			  &got_a_none_oplock);
+	if (!validate_oplock_types(fsp, oplock_request, lck)) {
+		smb_panic("validate_oplock_types failed");
+	}
 
 	if (has_delete_on_close(lck, fsp->name_hash)) {
 		TALLOC_FREE(lck);
@@ -2412,40 +2432,31 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 		return NT_STATUS_DELETE_PENDING;
 	}
 
-	/* First pass - send break only on batch oplocks. */
+	status = open_mode_check(conn, lck,
+				 access_mask, share_access);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+	    (lck->data->num_share_modes > 0)) {
+		/*
+		 * This comes from ancient times out of open_mode_check. I
+		 * have no clue whether this is still necessary. I can't think
+		 * of a case where this would actually matter further down in
+		 * this function. I leave it here for further investigation
+		 * :-)
+		 */
+		file_existed = true;
+	}
+
 	if ((req != NULL) &&
-	    delay_for_batch_oplocks(fsp,
-				    req->mid,
-				    oplock_request,
-				    batch_entry)) {
+	    delay_for_oplock(
+		    fsp, req->mid, oplock_request, lck,
+		    NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))) {
 		schedule_defer_open(lck, request_time, req);
 		TALLOC_FREE(lck);
 		fd_close(fsp);
 		return NT_STATUS_SHARING_VIOLATION;
 	}
 
-	status = open_mode_check(conn, lck,
-				 access_mask, share_access,
-				 &file_existed);
-
-	if (NT_STATUS_IS_OK(status)) {
-		/* We might be going to allow this open. Check oplock
-		 * status again. */
-		/* Second pass - send break for both batch or
-		 * exclusive oplocks. */
-		if ((req != NULL) &&
-		    delay_for_exclusive_oplocks(
-			    fsp,
-			    req->mid,
-			    oplock_request,
-			    exclusive_entry)) {
-			schedule_defer_open(lck, request_time, req);
-			TALLOC_FREE(lck);
-			fd_close(fsp);
-			return NT_STATUS_SHARING_VIOLATION;
-		}
-	}
-
 	if (!NT_STATUS_IS_OK(status)) {
 		uint32 can_access_mask;
 		bool can_access = True;
@@ -2573,10 +2584,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 		return status;
 	}
 
-	grant_fsp_oplock_type(fsp,
-			      oplock_request,
-			      got_level2_oplock,
-			      got_a_none_oplock);
+	grant_fsp_oplock_type(fsp, lck, oplock_request);
 
 	/*
 	 * We have the share entry *locked*.....
@@ -3163,8 +3171,7 @@ static NTSTATUS open_directory(connection_struct *conn,
 	}
 
 	status = open_mode_check(conn, lck,
-				access_mask, share_access,
-				 &dir_existed);
+				 access_mask, share_access);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(lck);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list