svn commit: samba r15138 - in branches/SAMBA_3_0/source/smbd: .

jra at samba.org jra at samba.org
Wed Apr 19 18:48:14 GMT 2006


Author: jra
Date: 2006-04-19 18:48:14 +0000 (Wed, 19 Apr 2006)
New Revision: 15138

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15138

Log:
Teach Samba the difference between exclusive and batch oplocks.
Pass Samba4 oplock test (with kernel oplocks off).
Jeremy.

Modified:
   branches/SAMBA_3_0/source/smbd/open.c


Changeset:
Modified: branches/SAMBA_3_0/source/smbd/open.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/open.c	2006-04-19 15:43:48 UTC (rev 15137)
+++ branches/SAMBA_3_0/source/smbd/open.c	2006-04-19 18:48:14 UTC (rev 15138)
@@ -608,7 +608,7 @@
  * 3) Only level2 around: Grant level2 and do nothing else.
  */
 
-static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
+static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number)
 {
 	int i;
 	struct share_mode_entry *exclusive = NULL;
@@ -630,9 +630,16 @@
 		/* At least one entry is not an invalid or deferred entry. */
 		valid_entry = True;
 
-		if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
-			SMB_ASSERT(exclusive == NULL);			
-			exclusive = &lck->share_modes[i];
+		if (pass_number == 1) {
+			if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
+				SMB_ASSERT(exclusive == NULL);			
+				exclusive = &lck->share_modes[i];
+			}
+		} else {
+			if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
+				SMB_ASSERT(exclusive == NULL);			
+				exclusive = &lck->share_modes[i];
+			}
 		}
 
 		if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) {
@@ -1024,6 +1031,42 @@
 
 }
 
+static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time)
+{
+	struct deferred_open_record state;
+
+	/* This is a relative time, added to the absolute
+	   request_time value to get the absolute timeout time.
+	   Note that if this is the second or greater time we enter
+	   this codepath for this particular request mid then
+	   request_time is left as the absolute time of the *first*
+	   time this request mid was processed. This is what allows
+	   the request to eventually time out. */
+
+	struct timeval timeout;
+
+	/* Normally the smbd we asked should respond within
+	 * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
+	 * the client did, give twice the timeout as a safety
+	 * measure here in case the other smbd is stuck
+	 * somewhere else. */
+
+	timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+
+	/* Nothing actually uses state.delayed_for_oplocks
+	   but it's handy to differentiate in debug messages
+	   between a 30 second delay due to oplock break, and
+	   a 1 second delay for share mode conflicts. */
+
+	state.delayed_for_oplocks = True;
+	state.dev = lck->dev;
+	state.inode = lck->ino;
+
+	if (!request_timed_out(request_time, timeout)) {
+		defer_open(lck, request_time, timeout, &state);
+	}
+}
+
 /****************************************************************************
  Open a file with a share mode.
 ****************************************************************************/
@@ -1310,7 +1353,6 @@
 	}
 
 	if (file_existed) {
-
 		dev = psbuf->st_dev;
 		inode = psbuf->st_ino;
 
@@ -1324,41 +1366,9 @@
 			return NULL;
 		}
 
-		if (delay_for_oplocks(lck, fsp)) {
-			struct deferred_open_record state;
-
-			/* This is a relative time, added to the absolute
-			   request_time value to get the absolute timeout time.
-			   Note that if this is the second or greater time we enter
-			   this codepath for this particular request mid then
-			   request_time is left as the absolute time of the *first*
-			   time this request mid was processed. This is what allows
-			   the request to eventually time out. */
-
-			struct timeval timeout;
-
-			/* Normally the smbd we asked should respond within
-			 * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
-			 * the client did, give twice the timeout as a safety
-			 * measure here in case the other smbd is stuck
-			 * somewhere else. */
-
-			timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
-
-			/* Nothing actually uses state.delayed_for_oplocks
-			   but it's handy to differentiate in debug messages
-			   between a 30 second delay due to oplock break, and
-			   a 1 second delay for share mode conflicts. */
-
-			state.delayed_for_oplocks = True;
-			state.dev = dev;
-			state.inode = inode;
-
-			if (!request_timed_out(request_time, timeout)) {
-				defer_open(lck, request_time, timeout,
-					   &state);
-			}
-
+		/* First pass - send break only on batch oplocks. */
+		if (delay_for_oplocks(lck, fsp, 1)) {
+			schedule_defer_open(lck, request_time);
 			TALLOC_FREE(lck);
 			return NULL;
 		}
@@ -1367,6 +1377,16 @@
 					 access_mask, share_access,
 					 create_options, &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 (delay_for_oplocks(lck, fsp, 2)) {
+				schedule_defer_open(lck, request_time);
+				TALLOC_FREE(lck);
+				return NULL;
+			}
+		}
+
 		if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
 			/* DELETE_PENDING is not deferred for a second */
 			set_saved_ntstatus(status);



More information about the samba-cvs mailing list