[SCM] Samba Shared Repository - branch v3-6-test updated

Jeremy Allison jra at samba.org
Tue Feb 1 17:52:22 MST 2011


The branch, v3-6-test has been updated
       via  a5b7549 Based on a conversation with Volker, refactor some of the oplock code to make it comprehensible.
       via  db1f553 s3: Fix bug 7940 -- fall back for utimes calls
       via  ac8fa07 s3:rpcclient/cmd_samr: remove useless ';'
       via  af692c2 s3:libnet/libnet_samsync_display: fix netr_DELTA_* display
       via  0c668fe s3:rpcclient/cmd_netlogon: fix netr_DELTA_* display
      from  75493e6 s3-net: prefer dcerpc_samr_X functions in rpc_trustdom_list.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit a5b754953412aa6daedbf97f680fadf3c545b95d
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Feb 1 16:01:57 2011 -0800

    Based on a conversation with Volker, refactor some of the oplock code to make it comprehensible.
    
    delay_for_oplocks() did 4 things.
    
    1). Validation of existing oplock types.
    2). Check for compatibility with batch oplocks (pass 1).
    3). Check for compatibility with exclusive oplocks (pass 2).
    4). Set the correct oplock type from the requested value.
    
    Refactor into 4 separate functions:
    
    1). find_oplock_types() - does validation of oplock types and
    	returns pointers to specific values.
    2). delay_for_batch_oplocks() - the pass 1 phase above.
    3). delay_for_exclusive_oplocks() - the pass 2 phase above
    4). grant_fsp_oplock_type() - Set the correct oplock type from the requested value.
    
    Now separated out this code should be much easier to understand
    and modify. This also fixes an erroneous SMB_ASSERT which was
    hidden by the previous complexity of the single delay_for_oplocks()
    code.
    
    Jeremy.
    (cherry picked from commit 8c226c3c9db422ee6cb35cecdc3fe39130c64752)

commit db1f553a446e7b70192202a8a99d06666033b120
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 29 10:59:14 2011 +0100

    s3: Fix bug 7940 -- fall back for utimes calls
    
    There are systems where ./configure has detected advanced utimes calls which
    are then not available on other kernels. We should do a proper fallback.
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Tue Feb  1 22:37:35 CET 2011 on sn-devel-104
    (cherry picked from commit ba4ec70529c0fa9cf4dc797176dbae1a2c949dbc)

commit ac8fa0749e93dff51fea29fa88bbd99c7e4f59cd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 1 17:38:02 2011 +0100

    s3:rpcclient/cmd_samr: remove useless ';'
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Tue Feb  1 19:19:24 CET 2011 on sn-devel-104
    (cherry picked from commit ff0f63329a884d74d088436958b963787426dc7c)

commit af692c25ef111ff751c5bc316333486d11489a1c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 1 17:37:13 2011 +0100

    s3:libnet/libnet_samsync_display: fix netr_DELTA_* display
    
    metze
    (cherry picked from commit a152f20dd10288ce51ac987af8fb87ab30eb5654)

commit 0c668fea6587cd6e68bb57af5700f6effcb5b126
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 1 17:36:33 2011 +0100

    s3:rpcclient/cmd_netlogon: fix netr_DELTA_* display
    
    metze
    (cherry picked from commit 5e4691e70e92e12dd08e88f6abd046637f7b4210)

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

Summary of changes:
 source3/libnet/libnet_samsync_display.c |   21 ++--
 source3/modules/vfs_default.c           |   18 ++-
 source3/rpcclient/cmd_netlogon.c        |   25 ++--
 source3/rpcclient/cmd_samr.c            |    2 +-
 source3/smbd/open.c                     |  231 +++++++++++++++++++++----------
 5 files changed, 201 insertions(+), 96 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libnet/libnet_samsync_display.c b/source3/libnet/libnet_samsync_display.c
index eb891cf..f2cff78 100644
--- a/source3/libnet/libnet_samsync_display.c
+++ b/source3/libnet/libnet_samsync_display.c
@@ -206,29 +206,32 @@ static NTSTATUS display_sam_entry(TALLOC_CTX *mem_ctx,
 		display_alias_mem(id.rid, u.alias_member);
 		break;
 	case NETR_DELTA_POLICY:
-		printf("Policy\n");
+		printf("Policy: %s\n",
+			sid_string_dbg(id.sid));
 		break;
 	case NETR_DELTA_TRUSTED_DOMAIN:
 		printf("Trusted Domain: %s\n",
 			u.trusted_domain->domain_name.string);
 		break;
 	case NETR_DELTA_DELETE_TRUST:
-		printf("Delete Trust: %d\n",
-			u.delete_trust.unknown);
+		printf("Delete Trust: %s\n",
+			sid_string_dbg(id.sid));
 		break;
 	case NETR_DELTA_ACCOUNT:
-		printf("Account\n");
+		printf("Account: %s\n",
+			sid_string_dbg(id.sid));
 		break;
 	case NETR_DELTA_DELETE_ACCOUNT:
-		printf("Delete Account: %d\n",
-			u.delete_account.unknown);
+		printf("Delete Account: %s\n",
+			sid_string_dbg(id.sid));
 		break;
 	case NETR_DELTA_SECRET:
-		printf("Secret\n");
+		printf("Secret: %s\n",
+			id.name);
 		break;
 	case NETR_DELTA_DELETE_SECRET:
-		printf("Delete Secret: %d\n",
-			u.delete_secret.unknown);
+		printf("Delete Secret: %s\n",
+			id.name);
 		break;
 	case NETR_DELTA_DELETE_GROUP2:
 		printf("Delete Group2: %s\n",
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 9cca349..698e745 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -786,7 +786,11 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
 	} else {
 		result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
 	}
-#elif defined(HAVE_UTIMES)
+	if (!((result == -1) && (errno == ENOSYS))) {
+		goto out;
+	}
+#endif
+#if defined(HAVE_UTIMES)
 	if (ft != NULL) {
 		struct timeval tv[2];
 		tv[0] = convert_timespec_to_timeval(ft->atime);
@@ -795,7 +799,11 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
 	} else {
 		result = utimes(smb_fname->base_name, NULL);
 	}
-#elif defined(HAVE_UTIME)
+	if (!((result == -1) && (errno == ENOSYS))) {
+		goto out;
+	}
+#endif
+#if defined(HAVE_UTIME)
 	if (ft != NULL) {
 		struct utimbuf times;
 		times.actime = convert_timespec_to_time_t(ft->atime);
@@ -804,10 +812,12 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
 	} else {
 		result = utime(smb_fname->base_name, NULL);
 	}
-#else
+	if (!((result == -1) && (errno == ENOSYS))) {
+		goto out;
+	}
+#endif
 	errno = ENOSYS;
 	result = -1;
-#endif
 
  out:
 	END_PROFILE(syscall_ntimes);
diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c
index c909efe..63057ac 100644
--- a/source3/rpcclient/cmd_netlogon.c
+++ b/source3/rpcclient/cmd_netlogon.c
@@ -478,7 +478,7 @@ static void display_sam_sync(struct netr_DELTA_ENUM_ARRAY *r)
 			break;
 		case NETR_DELTA_DELETE_GROUP:
 			printf("Delete Group: %d\n",
-				u.delete_account.unknown);
+				id.rid);
 			break;
 		case NETR_DELTA_RENAME_GROUP:
 			printf("Rename Group: %s -> %s\n",
@@ -511,7 +511,7 @@ static void display_sam_sync(struct netr_DELTA_ENUM_ARRAY *r)
 			break;
 		case NETR_DELTA_DELETE_ALIAS:
 			printf("Delete Alias: %d\n",
-				r->delta_enum[i].delta_id_union.rid);
+				id.rid);
 			break;
 		case NETR_DELTA_RENAME_ALIAS:
 			printf("Rename alias: %s -> %s\n",
@@ -527,29 +527,32 @@ static void display_sam_sync(struct netr_DELTA_ENUM_ARRAY *r)
 			}
 			break;
 		case NETR_DELTA_POLICY:
-			printf("Policy\n");
+			printf("Policy: %s\n",
+				sid_string_dbg(id.sid));
 			break;
 		case NETR_DELTA_TRUSTED_DOMAIN:
 			printf("Trusted Domain: %s\n",
 				u.trusted_domain->domain_name.string);
 			break;
 		case NETR_DELTA_DELETE_TRUST:
-			printf("Delete Trust: %d\n",
-				u.delete_trust.unknown);
+			printf("Delete Trust: %s\n",
+				sid_string_dbg(id.sid));
 			break;
 		case NETR_DELTA_ACCOUNT:
-			printf("Account\n");
+			printf("Account: %s\n",
+				sid_string_dbg(id.sid));
 			break;
 		case NETR_DELTA_DELETE_ACCOUNT:
-			printf("Delete Account: %d\n",
-				u.delete_account.unknown);
+			printf("Delete Account: %s\n",
+				sid_string_dbg(id.sid));
 			break;
 		case NETR_DELTA_SECRET:
-			printf("Secret\n");
+			printf("Secret: %s\n",
+				id.name);
 			break;
 		case NETR_DELTA_DELETE_SECRET:
-			printf("Delete Secret: %d\n",
-				u.delete_secret.unknown);
+			printf("Delete Secret: %s\n",
+				id.name);
 			break;
 		case NETR_DELTA_DELETE_GROUP2:
 			printf("Delete Group2: %s\n",
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index 4c1dc90..727c9d1 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -2055,7 +2055,7 @@ static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
 	uint32 num_names;
 	struct samr_Ids rids, name_types;
 	int i;
-	struct lsa_String *names = NULL;;
+	struct lsa_String *names = NULL;
 	struct dcerpc_binding_handle *b = cli->binding_handle;
 
 	if (argc < 3) {
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 5a725c6..f236243 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -915,93 +915,137 @@ static NTSTATUS send_break_message(files_struct *fsp,
 }
 
 /*
- * 1) No files open at all or internal open: Grant whatever the client wants.
- *
- * 2) Exclusive (or batch) oplock around: If the requested access is a delete
- *    request, break if the oplock around is a batch oplock. If it's another
- *    requested access type, break.
- *
- * 3) Only level2 around: Grant level2 and do nothing else.
+ * Return share_mode_entry pointers for :
+ * 1). Batch oplock entry.
+ * 2). Batch or exclusive oplock entry (may be identical to #1).
+ * bool have_level2_oplock
+ * bool have_no_oplock.
+ * Do internal consistency checks on the share mode for a file.
  */
 
-static bool delay_for_oplocks(struct share_mode_lock *lck,
-			      files_struct *fsp,
-			      uint64_t mid,
-			      int pass_number,
-			      int oplock_request)
+static void find_oplock_types(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)
 {
 	int i;
-	struct share_mode_entry *exclusive = NULL;
-	bool valid_entry = false;
-	bool have_level2 = false;
-	bool have_a_none_oplock = false;
-	bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
-		            lp_level2_oplocks(SNUM(fsp->conn));
-
-	if (oplock_request & INTERNAL_OPEN_ONLY) {
-		fsp->oplock_type = NO_OPLOCK;
-	}
 
-	if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
-		return false;
-	}
+	*pp_batch = NULL;
+	*pp_ex_or_batch = NULL;
+	*got_level2 = false;
+	*got_no_oplock = false;
 
 	for (i=0; i<lck->num_share_modes; i++) {
-
 		if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
 			continue;
 		}
 
-		/* At least one entry is not an invalid or deferred entry. */
-		valid_entry = true;
-
-		if (pass_number == 1) {
-			if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
-				SMB_ASSERT(exclusive == NULL);
-				exclusive = &lck->share_modes[i];
+		if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
+			/* batch - can only be one. */
+			if (*pp_batch || *got_level2 || *got_no_oplock) {
+				smb_panic("Bad batch oplock entry.");
 			}
-		} else {
-			if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
-				SMB_ASSERT(exclusive == NULL);
-				exclusive = &lck->share_modes[i];
+			*pp_batch = &lck->share_modes[i];
+		}
+
+		if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
+			/* 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.");
 			}
+			*pp_ex_or_batch = &lck->share_modes[i];
 		}
 
 		if (LEVEL_II_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
-			SMB_ASSERT(exclusive == NULL);
-			have_level2 = true;
+			if (*pp_batch || *pp_ex_or_batch) {
+				smb_panic("Bad levelII oplock entry.");
+			}
+			*got_level2 = true;
 		}
 
 		if (lck->share_modes[i].op_type == NO_OPLOCK) {
-			have_a_none_oplock = true;
+			if (*pp_batch || *pp_ex_or_batch) {
+				smb_panic("Bad no oplock entry.");
+			}
+			*got_no_oplock = true;
 		}
 	}
+}
+
+static bool delay_for_batch_oplocks(files_struct *fsp,
+					uint64_t mid,
+					int oplock_request,
+					struct share_mode_entry *batch_entry)
+{
+	if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
+		return false;
+	}
+
+	if (batch_entry != NULL) {
+		/* Found a batch oplock */
+		send_break_message(fsp, batch_entry, mid, oplock_request);
+		return true;
+	}
+	return false;
+}
+
+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 (exclusive != NULL) { /* Found an exclusive oplock */
+	if (ex_entry != NULL) {
+		/* Found an exclusive or batch oplock */
 		bool delay_it = is_delete_request(fsp) ?
-				BATCH_OPLOCK_TYPE(exclusive->op_type) :	true;
-		SMB_ASSERT(!have_level2);
+				BATCH_OPLOCK_TYPE(ex_entry->op_type) : true;
 		if (delay_it) {
-			send_break_message(fsp, exclusive, mid, oplock_request);
+			send_break_message(fsp, ex_entry, mid, oplock_request);
 			return true;
 		}
 	}
+	return false;
+}
+
+static void grant_fsp_oplock_type(files_struct *fsp,
+				int oplock_request,
+				bool got_level2_oplock,
+				bool got_a_none_oplock)
+{
+	bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
+		            lp_level2_oplocks(SNUM(fsp->conn));
+
+	/* Start by granting what the client asked for,
+	   but ensure no SAMBA_PRIVATE bits can be set. */
+	fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
+
+	if (oplock_request & INTERNAL_OPEN_ONLY) {
+		/* No oplocks on internal open. */
+		fsp->oplock_type = NO_OPLOCK;
+		DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
+			fsp->oplock_type, fsp_str_dbg(fsp)));
+		return;
+	}
+
+	if (is_stat_open(fsp->access_mask)) {
+		/* Leave the value already set. */
+		DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
+			fsp->oplock_type, fsp_str_dbg(fsp)));
+		return;
+	}
 
 	/*
 	 * Match what was requested (fsp->oplock_type) with
  	 * what was found in the existing share modes.
  	 */
 
-	if (!valid_entry) {
-		/* All entries are placeholders or deferred.
-		 * Directly grant whatever the client wants. */
-		if (fsp->oplock_type == NO_OPLOCK) {
-			/* Store a level2 oplock, but don't tell the client */
-			fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
-		}
-	} else if (have_a_none_oplock) {
+	if (got_a_none_oplock) {
 		fsp->oplock_type = NO_OPLOCK;
-	} else if (have_level2) {
+	} else if (got_level2_oplock) {
 		if (fsp->oplock_type == NO_OPLOCK ||
 				fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
 			/* Store a level2 oplock, but don't tell the client */
@@ -1010,8 +1054,13 @@ static bool delay_for_oplocks(struct share_mode_lock *lck,
 			fsp->oplock_type = LEVEL_II_OPLOCK;
 		}
 	} else {
-		/* This case can never happen. */
-		SMB_ASSERT(1);
+		/* All share_mode_entries are placeholders or deferred.
+		 * Silently upgrade to fake levelII if the client didn't
+		 * ask for an oplock. */
+		if (fsp->oplock_type == NO_OPLOCK) {
+			/* Store a level2 oplock, but don't tell the client */
+			fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+		}
 	}
 
 	/*
@@ -1022,11 +1071,8 @@ static bool delay_for_oplocks(struct share_mode_lock *lck,
 		fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
 	}
 
-	DEBUG(10,("delay_for_oplocks: oplock type 0x%x on file %s\n",
+	DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
 		  fsp->oplock_type, fsp_str_dbg(fsp)));
-
-	/* No delay. */
-	return false;
 }
 
 bool request_timed_out(struct timeval request_time,
@@ -1801,6 +1847,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	}
 
 	if (file_existed) {
+		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 = smb_fname->st.st_ex_mtime;
 		id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
 
@@ -1813,10 +1864,19 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			return NT_STATUS_SHARING_VIOLATION;
 		}
 
+		/* Get the types we need to examine. */
+		find_oplock_types(lck,
+				&batch_entry,
+				&exclusive_entry,
+				&got_level2_oplock,
+				&got_a_none_oplock);
+
 		/* First pass - send break only on batch oplocks. */
-		if ((req != NULL)
-		    && delay_for_oplocks(lck, fsp, req->mid, 1,
-					 oplock_request)) {
+		if ((req != NULL) &&
+				delay_for_batch_oplocks(fsp,
+					req->mid,
+					oplock_request,
+					batch_entry)) {
 			schedule_defer_open(lck, request_time, req);
 			TALLOC_FREE(lck);
 			return NT_STATUS_SHARING_VIOLATION;
@@ -1833,9 +1893,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			 * status again. */
 			/* Second pass - send break for both batch or
 			 * exclusive oplocks. */
-			if ((req != NULL)
-			     && delay_for_oplocks(lck, fsp, req->mid, 2,
-						  oplock_request)) {
+			if ((req != NULL) &&
+					delay_for_exclusive_oplocks(
+						fsp,
+						req->mid,
+						oplock_request,
+						exclusive_entry)) {
 				schedule_defer_open(lck, request_time, req);
 				TALLOC_FREE(lck);
 				return NT_STATUS_SHARING_VIOLATION;
@@ -1848,6 +1911,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			return status;
 		}
 
+		grant_fsp_oplock_type(fsp,
+                                oplock_request,
+                                got_level2_oplock,
+                                got_a_none_oplock);
+
 		if (!NT_STATUS_IS_OK(status)) {
 			uint32 can_access_mask;
 			bool can_access = True;
@@ -2007,6 +2075,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	}
 
 	if (!file_existed) {
+		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 = smb_fname->st.st_ex_mtime;
 		/*
 		 * Deal with the race condition where two smbd's detect the
@@ -2037,10 +2109,19 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			return NT_STATUS_SHARING_VIOLATION;
 		}
 
+		/* Get the types we need to examine. */
+		find_oplock_types(lck,
+				&batch_entry,
+				&exclusive_entry,
+				&got_level2_oplock,
+				&got_a_none_oplock);
+
 		/* First pass - send break only on batch oplocks. */
-		if ((req != NULL)
-		    && delay_for_oplocks(lck, fsp, req->mid, 1,
-					 oplock_request)) {
+		if ((req != NULL) &&
+				delay_for_batch_oplocks(fsp,
+					req->mid,
+					oplock_request,
+					batch_entry)) {
 			schedule_defer_open(lck, request_time, req);
 			TALLOC_FREE(lck);
 			fd_close(fsp);
@@ -2056,9 +2137,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			 * status again. */
 			/* Second pass - send break for both batch or
 			 * exclusive oplocks. */
-			if ((req != NULL)
-			    && delay_for_oplocks(lck, fsp, req->mid, 2,
-						 oplock_request)) {
+			if ((req != NULL) &&
+					delay_for_exclusive_oplocks(
+						fsp,
+						req->mid,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list