svn commit: samba r15139 - in trunk/source/smbd: .
jra at samba.org
jra at samba.org
Wed Apr 19 18:48:18 GMT 2006
Author: jra
Date: 2006-04-19 18:48:17 +0000 (Wed, 19 Apr 2006)
New Revision: 15139
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15139
Log:
Teach Samba the difference between exclusive and batch oplocks.
Pass Samba4 oplock test (with kernel oplocks off).
Jeremy.
Modified:
trunk/source/smbd/open.c
Changeset:
Modified: trunk/source/smbd/open.c
===================================================================
--- trunk/source/smbd/open.c 2006-04-19 18:48:14 UTC (rev 15138)
+++ trunk/source/smbd/open.c 2006-04-19 18:48:17 UTC (rev 15139)
@@ -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