[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Mon Oct 14 19:43:01 MDT 2013
The branch, master has been updated
via 9646dfc smbd: Inline break_level2_to_none_async
via 1d2c6f4 smbd: Remove a special case for level2 break
via cc9cd51 smbd: Remove some FAKE_LEVEL_II comments
via 47f65d5 smbd: Add debugs to brlock.c
via c92ac4c torture: Extend raw.oplock.batch10
via fcafaf6 smbd: Remove FAKE_LEVEL_II_OPLOCK
via eb50c18 smbd: Put "have_read_oplocks" into brlock.tdb
from 54019ca docs: Explain why this option should not be used
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 9646dfcdf2ffe0fbd56284a87007b63a9ab34a30
Author: Volker Lendecke <vl at samba.org>
Date: Fri Oct 4 10:11:38 2013 +0000
smbd: Inline break_level2_to_none_async
With the special case for bug 5980 in do_break_to_none we only have
one caller: process_oplock_async_level2_break_message. The further
goal is to merge process_oplock_async_level2_break_message with
process_oplock_break_message.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Tue Oct 15 03:42:53 CEST 2013 on sn-devel-104
commit 1d2c6f477b5bc17ac8b940de56432c69d7039304
Author: Volker Lendecke <vl at samba.org>
Date: Fri Oct 4 09:24:29 2013 +0000
smbd: Remove a special case for level2 break
With the level2 indicator in brlock.tdb this race condition does not
exist anymore
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit cc9cd5142a861360861407fd6018385524bf150d
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 13 15:18:15 2013 +0200
smbd: Remove some FAKE_LEVEL_II comments
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 47f65d5829167f061756621e50b480a8c16e4fbc
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 13 14:13:51 2013 +0200
smbd: Add debugs to brlock.c
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit c92ac4c8eebf4ddaaab4e8b640650406b259b05d
Author: Volker Lendecke <vl at samba.org>
Date: Mon Sep 9 18:53:15 2013 +0000
torture: Extend raw.oplock.batch10
With FAKE_LEVEL_II_OPLOCKS around we did not grant LEVEL2 after
a NO_OPLOCK file got written to. Windows does grant LEVEL2 in this
case. With the have_level2_oplocks in brlocks.tdb we can now grant LEVEL2
in this case as well.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit fcafaf6022832835fc8fa76a4c33056605dc53e4
Author: Volker Lendecke <vl at samba.org>
Date: Wed Sep 11 16:07:33 2013 +0000
smbd: Remove FAKE_LEVEL_II_OPLOCK
FAKE_LEVEL_II_OPLOCK was an indicator to break level2 oplock holders
on write. This information is now being held in brlock.tdb, which makes
the FAKE_LEVEL_II_OPLOCK type unnecessary.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit eb50c18c4a2d0caa3b8d21b2e1b536adc8dc0276
Author: Volker Lendecke <vl at samba.org>
Date: Wed Sep 11 12:48:14 2013 +0000
smbd: Put "have_read_oplocks" into brlock.tdb
This implements an idea by metze: Right now Samba does not grant level2
oplocks where it should: After an initial no-oplock open that has been
written to, we don't have the FAKE_LEVEL2_OPLOCK entry in locking.tdb
around anymore, this downgraded to NO_OPLOCK. Windows in this case will
grant level2 if being asked, we don't. Part of the reason for this
is that we don't have a proper mechanism to communicate the fact that
level2 needs to be broken to other smbds. Metze's insight was that we
have to look into brlock.tdb for every write anyway, so this might be
the right place to store this information.
My first reaction was that this is really hackish, but on further thought
this is not. oplocks depend on brlocks anyway, and we have the proper
mechanisms in place for brlocks.
The format for this change is to add one byte to the end of the brlock.tdb
record with value 1 if we have level2 oplocks around. Thus this patch
effectively reverts 8f41142 which I discovered while writing this
change. We now legally have unaligned records.
We can certainly talk about the format, but I'm not yet convinced we
need an idl for this yet. This is a potentially very hot code path,
and ndr marshalling has a cost.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
-----------------------------------------------------------------------
Summary of changes:
source3/include/smb.h | 5 +-
source3/locking/brlock.c | 70 ++++++++++++++--
source3/locking/locking.c | 14 +---
source3/locking/proto.h | 3 +
source3/smbd/files.c | 3 +-
source3/smbd/open.c | 41 ++++------
source3/smbd/oplock.c | 186 +++++++++++++++++++++++------------------
source3/smbd/smb2_create.c | 5 -
source4/torture/raw/oplock.c | 12 +++
9 files changed, 200 insertions(+), 139 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 0d07f71..5c0dfdc 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -686,7 +686,8 @@ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
/* The following are Samba-private. */
#define INTERNAL_OPEN_ONLY 0x8
-#define FAKE_LEVEL_II_OPLOCK 0x10 /* Client requested no_oplock, but we have to
+/* #define FAKE_LEVEL_II_OPLOCK 0x10 */ /* Not used anymore */
+ /* Client requested no_oplock, but we have to
* inform potential level2 holders on
* write. */
/* #define DEFERRED_OPEN_ENTRY 0x20 */ /* Not used anymore */
@@ -698,7 +699,7 @@ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
#define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK))
#define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK)
-#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)LEVEL_II_OPLOCK|(unsigned int)FAKE_LEVEL_II_OPLOCK))
+#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & (unsigned int)LEVEL_II_OPLOCK)
/* kernel_oplock_message definition.
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 0d45501..b5eebc8 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -47,6 +47,7 @@ struct byte_range_lock {
struct files_struct *fsp;
unsigned int num_locks;
bool modified;
+ bool have_read_oplocks;
struct lock_struct *lock_data;
struct db_record *record;
};
@@ -81,6 +82,21 @@ struct files_struct *brl_fsp(struct byte_range_lock *brl)
return brl->fsp;
}
+bool brl_have_read_oplocks(const struct byte_range_lock *brl)
+{
+ return brl->have_read_oplocks;
+}
+
+void brl_set_have_read_oplocks(struct byte_range_lock *brl,
+ bool have_read_oplocks)
+{
+ DEBUG(10, ("Setting have_read_oplocks to %s\n",
+ have_read_oplocks ? "true" : "false"));
+ SMB_ASSERT(brl->record != NULL); /* otherwise we're readonly */
+ brl->have_read_oplocks = have_read_oplocks;
+ brl->modified = true;
+}
+
/****************************************************************************
See if two locking contexts are equal.
****************************************************************************/
@@ -1878,11 +1894,21 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
static void byte_range_lock_flush(struct byte_range_lock *br_lck)
{
+ size_t data_len;
if (!br_lck->modified) {
+ DEBUG(10, ("br_lck not modified\n"));
goto done;
}
- if (br_lck->num_locks == 0) {
+ data_len = br_lck->num_locks * sizeof(struct lock_struct);
+
+ if (br_lck->have_read_oplocks) {
+ data_len += 1;
+ }
+
+ DEBUG(10, ("data_len=%d\n", (int)data_len));
+
+ if (data_len == 0) {
/* No locks - delete this entry. */
NTSTATUS status = dbwrap_record_delete(br_lck->record);
if (!NT_STATUS_IS_OK(status)) {
@@ -1894,16 +1920,27 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck)
TDB_DATA data;
NTSTATUS status;
- data.dptr = (uint8 *)br_lck->lock_data;
- data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
+ data.dsize = data_len;
+ data.dptr = talloc_array(talloc_tos(), uint8_t, data_len);
+ SMB_ASSERT(data.dptr != NULL);
+
+ memcpy(data.dptr, br_lck->lock_data,
+ br_lck->num_locks * sizeof(struct lock_struct));
+
+ if (br_lck->have_read_oplocks) {
+ data.dptr[data_len-1] = 1;
+ }
status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
+ TALLOC_FREE(data.dptr);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("store returned %s\n", nt_errstr(status)));
smb_panic("Could not store byte range mode entry");
}
}
+ DEBUG(10, ("seqnum=%d\n", dbwrap_get_seqnum(brlock_db)));
+
done:
br_lck->modified = false;
TALLOC_FREE(br_lck->record);
@@ -1932,6 +1969,7 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
br_lck->fsp = fsp;
br_lck->num_locks = 0;
+ br_lck->have_read_oplocks = false;
br_lck->modified = False;
key.dptr = (uint8 *)&fsp->file_id;
@@ -1947,12 +1985,6 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
data = dbwrap_record_get_value(br_lck->record);
- if ((data.dsize % sizeof(struct lock_struct)) != 0) {
- DEBUG(3, ("Got invalid brlock data\n"));
- TALLOC_FREE(br_lck);
- return NULL;
- }
-
br_lck->lock_data = NULL;
talloc_set_destructor(br_lck, byte_range_lock_destructor);
@@ -1968,7 +2000,14 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
return NULL;
}
- memcpy(br_lck->lock_data, data.dptr, data.dsize);
+ memcpy(br_lck->lock_data, data.dptr,
+ talloc_get_size(br_lck->lock_data));
+ }
+
+ DEBUG(10, ("data.dsize=%d\n", (int)data.dsize));
+
+ if ((data.dsize % sizeof(struct lock_struct)) == 1) {
+ br_lck->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
}
if (!fsp->lockdb_clean) {
@@ -2038,6 +2077,13 @@ static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data,
br_lock, data.dptr, data.dsize);
br_lock->num_locks = data.dsize / sizeof(struct lock_struct);
+ if ((data.dsize % sizeof(struct lock_struct)) == 1) {
+ br_lock->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
+ }
+
+ DEBUG(10, ("Got %d bytes, have_read_oplocks: %s\n", (int)data.dsize,
+ br_lock->have_read_oplocks ? "true" : "false"));
+
*state->br_lock = br_lock;
}
@@ -2046,6 +2092,9 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
struct byte_range_lock *br_lock = NULL;
struct byte_range_lock *rw = NULL;
+ DEBUG(10, ("seqnum=%d, fsp->brlock_seqnum=%d\n",
+ dbwrap_get_seqnum(brlock_db), fsp->brlock_seqnum));
+
if ((fsp->brlock_rec != NULL)
&& (dbwrap_get_seqnum(brlock_db) == fsp->brlock_seqnum)) {
/*
@@ -2079,6 +2128,7 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
if (br_lock == NULL) {
goto fail;
}
+ br_lock->have_read_oplocks = rw->have_read_oplocks;
br_lock->num_locks = rw->num_locks;
br_lock->lock_data = (struct lock_struct *)talloc_memdup(
br_lock, rw->lock_data, lock_data_size);
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index b9db27c..7ac04a4 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -823,19 +823,7 @@ bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
return False;
}
- if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
- /*
- * Going from exclusive or batch,
- * we always go through FAKE_LEVEL_II
- * first.
- */
- if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- smb_panic("remove_share_oplock: logic error");
- }
- e->op_type = FAKE_LEVEL_II_OPLOCK;
- } else {
- e->op_type = NO_OPLOCK;
- }
+ e->op_type = NO_OPLOCK;
lck->data->modified = True;
return True;
}
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 02e2bf5..f6ae462 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -30,6 +30,9 @@ void brl_shutdown(void);
unsigned int brl_num_locks(const struct byte_range_lock *brl);
struct files_struct *brl_fsp(struct byte_range_lock *brl);
+bool brl_have_read_oplocks(const struct byte_range_lock *brl);
+void brl_set_have_read_oplocks(struct byte_range_lock *brl,
+ bool have_read_oplocks);
NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
struct lock_struct *plock,
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index d94ee11..c64c841 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -318,8 +318,7 @@ files_struct *file_find_dif(struct smbd_server_connection *sconn,
}
/* Paranoia check. */
if ((fsp->fh->fd == -1) &&
- (fsp->oplock_type != NO_OPLOCK) &&
- (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
+ (fsp->oplock_type != NO_OPLOCK)) {
DEBUG(0,("file_find_dif: file %s file_id = "
"%s, gen = %u oplock_type = %u is a "
"stat open with oplock type !\n",
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index f6df035..93b69d5 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1052,14 +1052,6 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn,
"share entry with an open file\n");
}
- if ((share_entry->op_type == NO_OPLOCK) &&
- (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK))
- {
- /* Someone has already written to it, but I haven't yet
- * noticed */
- return;
- }
-
if (((uint16)fsp->oplock_type) != share_entry->op_type) {
goto panic;
}
@@ -1408,24 +1400,10 @@ static void grant_fsp_oplock_type(files_struct *fsp,
* what was found in the existing share modes.
*/
- if (got_a_none_oplock) {
- fsp->oplock_type = NO_OPLOCK;
- } 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 */
- fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
- } else {
+ if (got_level2_oplock || got_a_none_oplock) {
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
fsp->oplock_type = LEVEL_II_OPLOCK;
}
- } else {
- /* 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;
- }
}
/*
@@ -1433,7 +1411,20 @@ static void grant_fsp_oplock_type(files_struct *fsp,
* or if we've turned them off.
*/
if (fsp->oplock_type == LEVEL_II_OPLOCK && !allow_level2) {
- fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+ fsp->oplock_type = NO_OPLOCK;
+ }
+
+ if (fsp->oplock_type == LEVEL_II_OPLOCK && !got_level2_oplock) {
+ /*
+ * We're the first level2 oplock. Indicate that in brlock.tdb.
+ */
+ struct byte_range_lock *brl;
+
+ brl = brl_get_locks(talloc_tos(), fsp);
+ if (brl != NULL) {
+ brl_set_have_read_oplocks(brl, true);
+ TALLOC_FREE(brl);
+ }
}
DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 70f168e..e2880c5 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -66,7 +66,6 @@ NTSTATUS set_file_oplock(files_struct *fsp, int oplock_type)
}
if ((fsp->oplock_type != NO_OPLOCK) &&
- (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) &&
use_kernel &&
!koplocks->ops->set_oplock(koplocks, fsp, oplock_type))
{
@@ -100,7 +99,6 @@ void release_file_oplock(files_struct *fsp)
struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
if ((fsp->oplock_type != NO_OPLOCK) &&
- (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) &&
koplocks) {
koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
}
@@ -114,12 +112,7 @@ void release_file_oplock(files_struct *fsp)
SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
SMB_ASSERT(sconn->oplocks.level_II_open>=0);
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- /* This doesn't matter for close. */
- fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
- } else {
- fsp->oplock_type = NO_OPLOCK;
- }
+ fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH);
@@ -164,6 +157,9 @@ bool remove_oplock(files_struct *fsp)
bool ret;
struct share_mode_lock *lck;
+ DEBUG(10, ("remove_oplock called for %s\n",
+ fsp_str_dbg(fsp)));
+
/* Remove the oplock flag from the sharemode. */
lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
@@ -171,6 +167,45 @@ bool remove_oplock(files_struct *fsp)
"file %s\n", fsp_str_dbg(fsp)));
return False;
}
+
+ if (fsp->oplock_type == LEVEL_II_OPLOCK) {
+
+ /*
+ * If we're the only LEVEL_II holder, we have to remove the
+ * have_read_oplocks from the brlock entry
+ */
+
+ struct share_mode_data *data = lck->data;
+ uint32_t i, num_level2;
+
+ num_level2 = 0;
+ for (i=0; i<data->num_share_modes; i++) {
+ if (data->share_modes[i].op_type == LEVEL_II_OPLOCK) {
+ num_level2 += 1;
+ }
+ if (num_level2 > 1) {
+ /*
+ * No need to count them all...
+ */
+ break;
+ }
+ }
+
+ if (num_level2 == 1) {
+ /*
+ * That's only us. We are dropping that level2 oplock,
+ * so remove the brlock flag.
+ */
+ struct byte_range_lock *brl;
+
+ brl = brl_get_locks(talloc_tos(), fsp);
+ if (brl) {
+ brl_set_have_read_oplocks(brl, false);
+ TALLOC_FREE(brl);
+ }
+ }
+ }
+
ret = remove_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("remove_oplock: failed to remove share oplock for "
@@ -190,6 +225,10 @@ bool downgrade_oplock(files_struct *fsp)
{
bool ret;
struct share_mode_lock *lck;
+ struct byte_range_lock *brl;
+
+ DEBUG(10, ("downgrade_oplock called for %s\n",
+ fsp_str_dbg(fsp)));
lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
@@ -206,6 +245,13 @@ bool downgrade_oplock(files_struct *fsp)
}
downgrade_file_oplock(fsp);
+
+ brl = brl_get_locks(talloc_tos(), fsp);
+ if (brl != NULL) {
+ brl_set_have_read_oplocks(brl, true);
+ TALLOC_FREE(brl);
+ }
+
TALLOC_FREE(lck);
return ret;
}
@@ -363,49 +409,11 @@ static void send_break_message_smb1(files_struct *fsp, int level)
}
}
-static void break_level2_to_none_async(files_struct *fsp)
-{
- struct smbd_server_connection *sconn = fsp->conn->sconn;
-
- if (fsp->oplock_type == NO_OPLOCK) {
- /* We already got a "break to none" message and we've handled
- * it. just ignore. */
- DEBUG(3, ("process_oplock_async_level2_break_message: already "
- "broken to none, ignoring.\n"));
- return;
- }
-
- if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
- /* Don't tell the client, just downgrade. */
- DEBUG(3, ("process_oplock_async_level2_break_message: "
- "downgrading fake level 2 oplock.\n"));
- remove_oplock(fsp);
- return;
- }
-
- /* Ensure we're really at level2 state. */
- SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
-
- DEBUG(10,("process_oplock_async_level2_break_message: sending break "
- "to none message for %s, file %s\n", fsp_fnum_dbg(fsp),
- fsp_str_dbg(fsp)));
-
- /* Now send a break to none message to our client. */
- if (sconn->using_smb2) {
- send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);
- } else {
- send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
- }
-
- /* Async level2 request, don't send a reply, just remove the oplock. */
- remove_oplock(fsp);
-}
-
/*******************************************************************
This handles the case of a write triggering a break to none
message on a level2 oplock.
- When we get this message we may be in any of three states :
- NO_OPLOCK, LEVEL_II, FAKE_LEVEL2. We only send a message to
+ When we get this message we may be in any of two states :
+ NO_OPLOCK, LEVEL_II. We only send a message to
the client for LEVEL2.
*******************************************************************/
@@ -420,6 +428,7 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
struct smbd_server_connection *sconn =
talloc_get_type_abort(private_data,
struct smbd_server_connection);
+ struct server_id self = messaging_server_id(sconn->msg_ctx);
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -449,7 +458,37 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
return;
}
- break_level2_to_none_async(fsp);
+
+ if (fsp->oplock_type == NO_OPLOCK) {
+ /* We already got a "break to none" message and we've handled
+ * it. just ignore. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: already "
+ "broken to none, ignoring.\n"));
+ return;
+ }
+
+ /* Ensure we're really at level2 state. */
+ SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
+
+ DEBUG(10,("process_oplock_async_level2_break_message: sending break "
+ "to none message for %s, file %s\n", fsp_fnum_dbg(fsp),
+ fsp_str_dbg(fsp)));
+
+ /* Need to wait before sending a break
+ message if we sent ourselves this message. */
+ if (serverid_equal(&self, &src)) {
+ wait_before_sending_break();
--
Samba Shared Repository
More information about the samba-cvs
mailing list