summaryrefslogtreecommitdiff
path: root/source3/smbd/oplock.c
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2012-01-13 13:26:41 +0100
committerVolker Lendecke <vlendec@samba.org>2012-01-18 14:48:04 +0100
commitcf77a21c633807b178fb716dba7a6284cca58511 (patch)
tree9a697989fc9089b38ba0f08fcdba9b70bc75bf8a /source3/smbd/oplock.c
parent333c92384b0680b8f8e5198dd68d49b249b34ec7 (diff)
downloadsamba-cf77a21c633807b178fb716dba7a6284cca58511.tar.gz
samba-cf77a21c633807b178fb716dba7a6284cca58511.tar.bz2
samba-cf77a21c633807b178fb716dba7a6284cca58511.zip
s3: Change locking order between brlock and locking
But 8175 was fixed in a way that brlock.tdb was always locked before locking.tdb. This patch fixes the bug in a different way. locking.tdb is the central tdb for files and should always be locked first. This patch solves the problem by postponing the level2 break messages, which are async anyway.
Diffstat (limited to 'source3/smbd/oplock.c')
-rw-r--r--source3/smbd/oplock.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 2197c7947f..0c4155d9d6 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -735,6 +735,12 @@ static void process_open_retry_message(struct messaging_context *msg_ctx,
schedule_deferred_open_message_smb(sconn, msg.op_mid);
}
+struct break_to_none_state {
+ struct smbd_server_connection *sconn;
+ struct file_id id;
+};
+static void do_break_to_none(struct tevent_req *req);
+
/****************************************************************************
This function is called on any file modification or lock request. If a file
is level 2 oplocked then it must tell all other level 2 holders to break to
@@ -744,8 +750,9 @@ static void process_open_retry_message(struct messaging_context *msg_ctx,
static void contend_level2_oplocks_begin_default(files_struct *fsp,
enum level2_contention_type type)
{
- int i;
- struct share_mode_lock *lck;
+ struct smbd_server_connection *sconn = fsp->conn->sconn;
+ struct tevent_req *req;
+ struct break_to_none_state *state;
/*
* If this file is level II oplocked then we need
@@ -758,12 +765,52 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
return;
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id);
- if (lck == NULL) {
- DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
- "share mode entry for file %s.\n", fsp_str_dbg(fsp)));
+ /*
+ * When we get here we might have a brlock entry locked. Also
+ * locking the share mode entry would violate the locking
+ * order. Breaking level2 oplocks to none is asynchronous
+ * anyway, so we postpone this into an immediate timed event.
+ */
+
+ state = talloc(sconn, struct break_to_none_state);
+ if (state == NULL) {
+ DEBUG(1, ("talloc failed\n"));
+ return;
+ }
+ state->sconn = sconn;
+ state->id = fsp->file_id;
+
+ req = tevent_wakeup_send(state, sconn->ev_ctx, timeval_set(0, 0));
+ if (req == NULL) {
+ DEBUG(1, ("tevent_wakeup_send failed\n"));
+ TALLOC_FREE(state);
return;
}
+ tevent_req_set_callback(req, do_break_to_none, state);
+ return;
+}
+
+static void do_break_to_none(struct tevent_req *req)
+{
+ struct break_to_none_state *state = tevent_req_callback_data(
+ req, struct break_to_none_state);
+ bool ret;
+ int i;
+ struct share_mode_lock *lck;
+
+ ret = tevent_wakeup_recv(req);
+ TALLOC_FREE(req);
+ if (!ret) {
+ DEBUG(1, ("tevent_wakeup_recv failed\n"));
+ goto done;
+ }
+ lck = get_share_mode_lock(talloc_tos(), state->id);
+ if (lck == NULL) {
+ DEBUG(1, ("release_level_2_oplocks_on_change: failed to lock "
+ "share mode entry for file %s.\n",
+ file_id_string_tos(&state->id)));
+ goto done;
+ }
DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
lck->data->num_share_modes ));
@@ -820,7 +867,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
if (procid_is_me(&share_entry->pid)) {
struct files_struct *cur_fsp =
- initial_break_processing(fsp->conn->sconn,
+ initial_break_processing(state->sconn,
share_entry->id,
share_entry->share_file_id);
wait_before_sending_break();
@@ -831,7 +878,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
"Did not find fsp, ignoring\n"));
}
} else {
- messaging_send_buf(fsp->conn->sconn->msg_ctx,
+ messaging_send_buf(state->sconn->msg_ctx,
share_entry->pid,
MSG_SMB_ASYNC_LEVEL2_BREAK,
(uint8 *)msg,
@@ -843,6 +890,9 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
in the share mode lock db. */
TALLOC_FREE(lck);
+done:
+ TALLOC_FREE(state);
+ return;
}
void smbd_contend_level2_oplocks_begin(files_struct *fsp,