diff options
author | Tim Prouty <tprouty@samba.org> | 2009-04-02 18:33:30 -0700 |
---|---|---|
committer | Tim Prouty <tprouty@samba.org> | 2009-04-06 13:53:45 -0700 |
commit | 651fa0964a6c49a071c28cdb1e4891b1d95d5b09 (patch) | |
tree | 487c797c304f3154ec092d5397609fba9a95d82e /source3 | |
parent | 12d9765177fc16f7b13e460e1d79c50c256d6fa8 (diff) | |
download | samba-651fa0964a6c49a071c28cdb1e4891b1d95d5b09.tar.gz samba-651fa0964a6c49a071c28cdb1e4891b1d95d5b09.tar.bz2 samba-651fa0964a6c49a071c28cdb1e4891b1d95d5b09.zip |
s3 oplocks: Refactor level II oplock contention
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 110 |
2 files changed, 54 insertions, 57 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index d76ee08fd2..b677c3d922 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6677,6 +6677,7 @@ void release_file_oplock(files_struct *fsp); bool remove_oplock(files_struct *fsp); bool downgrade_oplock(files_struct *fsp); bool should_notify_deferred_opens(void); +void break_level2_to_none_async(files_struct *fsp); void reply_to_oplock_break_requests(files_struct *fsp); void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx, void *private_data, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6add9f5fc1..98f89ac40c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -344,6 +344,54 @@ static void add_oplock_timeout_handler(files_struct *fsp) } } +void break_level2_to_none_async(files_struct *fsp) +{ + char *break_msg; + + 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 fid %d, file %s\n", fsp->fnum, + fsp->fsp_name)); + + /* Now send a break to none message to our client. */ + break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); + } + + show_msg(break_msg); + if (!srv_send_smb(smbd_server_fd(), + break_msg, false, 0, + IS_CONN_ENCRYPTED(fsp->conn), + NULL)) { + exit_server_cleanly("oplock_break: srv_send_smb failed."); + } + + TALLOC_FREE(break_msg); + + /* 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. @@ -360,7 +408,6 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx { struct share_mode_entry msg; files_struct *fsp; - char *break_msg; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -375,9 +422,8 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %s: " - "%s/%lu\n", procid_str(debug_ctx(), &src), - file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -389,52 +435,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx return; } - 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 fid %d, file %s\n", - fsp->fnum, - fsp->fsp_name)); - - /* Now send a break to none message to our client. */ - - break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); - if (break_msg == NULL) { - exit_server("Could not talloc break_msg\n"); - } - - /* Need to wait before sending a break message if we sent ourselves this message. */ - if (procid_is_me(&src)) { - wait_before_sending_break(); - } - - show_msg(break_msg); - if (!srv_send_smb(smbd_server_fd(), - break_msg, false, 0, - IS_CONN_ENCRYPTED(fsp->conn), - NULL)) { - exit_server_cleanly("oplock_break: srv_send_smb failed."); - } - - TALLOC_FREE(break_msg); - - /* Async level2 request, don't send a reply, just remove the oplock. */ - remove_oplock(fsp); + break_level2_to_none_async(fsp); } /******************************************************************* @@ -790,13 +791,8 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, */ if (procid_is_me(&share_entry->pid)) { - DATA_BLOB blob = data_blob_const(msg, - MSG_SMB_SHARE_MODE_ENTRY_SIZE); - process_oplock_async_level2_break_message(smbd_messaging_context(), - NULL, - MSG_SMB_ASYNC_LEVEL2_BREAK, - share_entry->pid, - &blob); + wait_before_sending_break(); + break_level2_to_none_async(fsp); } else { messaging_send_buf(smbd_messaging_context(), share_entry->pid, |