summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/oplock.c45
1 files changed, 12 insertions, 33 deletions
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index ffea57bd1d..b0ab1b58cb 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -409,9 +409,10 @@ static void send_break_message_smb1(files_struct *fsp, int level)
}
}
-static void break_level2_to_none_async(files_struct *fsp)
+static void break_level2_to_none_async(struct server_id src, files_struct *fsp)
{
struct smbd_server_connection *sconn = fsp->conn->sconn;
+ struct server_id self = messaging_server_id(sconn->msg_ctx);
if (fsp->oplock_type == NO_OPLOCK) {
/* We already got a "break to none" message and we've handled
@@ -428,6 +429,12 @@ static void break_level2_to_none_async(files_struct *fsp)
"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();
+ }
+
/* Now send a break to none message to our client. */
if (sconn->using_smb2) {
send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);
@@ -487,7 +494,7 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
return;
}
- break_level2_to_none_async(fsp);
+ break_level2_to_none_async(src, fsp);
}
/*******************************************************************
@@ -713,7 +720,6 @@ static void do_break_to_none(struct tevent_context *ctx,
{
struct break_to_none_state *state = talloc_get_type_abort(
private_data, struct break_to_none_state);
- struct server_id self = messaging_server_id(state->sconn->msg_ctx);
int i;
struct share_mode_lock *lck;
@@ -766,36 +772,9 @@ static void do_break_to_none(struct tevent_context *ctx,
share_mode_entry_to_message(msg, share_entry);
- /*
- * Deal with a race condition when breaking level2
- * oplocks. Don't send all the messages and release
- * the lock, this allows someone else to come in and
- * get a level2 lock before any of the messages are
- * processed, and thus miss getting a break message.
- * Ensure at least one entry (the one we're breaking)
- * is processed immediately under the lock and becomes
- * set as NO_OPLOCK to stop any waiter getting a level2.
- * Bugid #5980.
- */
-
- if (serverid_equal(&self, &share_entry->pid)) {
- struct files_struct *cur_fsp =
- initial_break_processing(state->sconn,
- share_entry->id,
- share_entry->share_file_id);
- if (cur_fsp != NULL) {
- wait_before_sending_break();
- break_level2_to_none_async(cur_fsp);
- } else {
- DEBUG(3, ("release_level_2_oplocks_on_change: "
- "Did not find fsp, ignoring\n"));
- }
- } else {
- messaging_send_buf(state->sconn->msg_ctx,
- share_entry->pid,
- MSG_SMB_ASYNC_LEVEL2_BREAK,
- (uint8 *)msg, sizeof(msg));
- }
+ messaging_send_buf(state->sconn->msg_ctx, share_entry->pid,
+ MSG_SMB_ASYNC_LEVEL2_BREAK,
+ (uint8 *)msg, sizeof(msg));
}
/* We let the message receivers handle removing the oplock state