diff options
author | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
commit | 7f10bf980edef3ace1522d0c9c082b35e225c950 (patch) | |
tree | d4e9af21de194cca812e754b28f9358a3651f4ce /source3/smbd | |
parent | f8f68703da58cf7f61b655b48bbbc45cda647748 (diff) | |
parent | f930f504e1d5e78d2f6f36cab9ce36dbeb34e955 (diff) | |
download | samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.gz samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.bz2 samba-7f10bf980edef3ace1522d0c9c082b35e225c950.zip |
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/ipc.c | 4 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 131 | ||||
-rw-r--r-- | source3/smbd/oplock_onefs.c | 79 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 8 |
4 files changed, 74 insertions, 148 deletions
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d39aab4f47..2d5713590d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -754,6 +754,8 @@ void reply_trans(struct smb_request *req) return; } + talloc_steal(talloc_tos(), state); + handle_trans(conn, req, state); SAFE_FREE(state->data); @@ -852,6 +854,8 @@ void reply_transs(struct smb_request *req) return; } + talloc_steal(talloc_tos(), state); + handle_trans(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ce00397bbd..b937e8e07d 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,8 +422,9 @@ 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 %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); + 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)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -388,52 +436,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_to_pid(&src) == sys_getpid()) { - 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); } /******************************************************************* @@ -464,8 +467,9 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); + DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), + msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -518,7 +522,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, } /* Need to wait before sending a break message if we sent ourselves this message. */ - if (procid_to_pid(&src) == sys_getpid()) { + if (procid_is_me(&src)) { wait_before_sending_break(); } @@ -571,8 +575,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, pull_file_id_24((char *)data->data, &id); file_id = (unsigned long)IVAL(data->data, 24); - DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", - (int)procid_to_pid(&src), file_id_string_tos(&id), + DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&id), (unsigned int)file_id)); fsp = initial_break_processing(id, file_id); @@ -667,9 +671,9 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id, - (unsigned int)msg.op_mid)); + DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), + msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ schedule_deferred_open_smb_message(msg.op_mid); @@ -696,8 +700,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n", - (int)procid_to_pid(&src), file_id_string_tos(&msg.id), + DEBUG(10, ("Got open retry msg from pid %s: %s mid %u\n", + procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id), (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); @@ -788,13 +792,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, diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index d4f181fc47..b69d937915 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -550,87 +550,18 @@ static void onefs_semlock_write(int fd, enum level2_contention_type type, * the cluster except the fsp's own level 2 oplock. This lack of * self-contention is a limitation of the current OneFS kernel oplocks * implementation. Luckily it is easy to contend our own level 2 oplock by - * iterating the share mode entries and only breaking the oplock if the pid - * matches our's. + * checking the the fsp's oplock_type. If it's a level2, send a break message + * to the client and remove the oplock. */ static void onefs_contend_level2_oplocks_begin(files_struct *fsp, enum level2_contention_type type) { - int i; - struct share_mode_lock *lck; - /* Take care of level 2 kernel contention. */ onefs_semlock_write(fsp->fh->fd, type, SEMLOCK_LOCK); - /* - * If this file is level II oplocked then we need - * to grab the shared memory lock and inform all - * other files with a level II lock that they need - * to flush their read caches. We keep the lock over - * the shared memory area whilst doing this. - */ - - if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - return; - - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, - NULL); - if (lck == NULL) { - DEBUG(0,("onefs_contend_level2_oplocks_begin: failed to lock " - "share mode entry for file %s.\n", fsp->fsp_name )); - return; - } - - DEBUG(10,("onefs_contend_level2_oplocks_begin: num_share_modes = %d\n", - lck->num_share_modes )); - - for(i = 0; i < lck->num_share_modes; i++) { - struct share_mode_entry *share_entry = &lck->share_modes[i]; - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; - - if (!is_valid_share_mode_entry(share_entry)) { - continue; - } - - DEBUG(10,("onefs_contend_level2_oplocks_begin: " - "share_entry[%i]->op_type == %d\n", - i, share_entry->op_type )); - - if (share_entry->op_type == NO_OPLOCK) { - continue; - } - - /* Paranoia .... */ - if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(0,("onefs_contend_level2_oplocks_begin: PANIC. " - "share mode entry %d is an exlusive " - "oplock !\n", i )); - TALLOC_FREE(lck); - abort(); - } - - share_mode_entry_to_message(msg, share_entry); - - /* - * Only contend our own level 2 oplock. The other processes - * will be get break events from the kernel. - */ - 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); - } - } - - /* We let the message receivers handle removing the oplock state - in the share mode lock db. */ - - TALLOC_FREE(lck); + /* Take care of level 2 self contention. */ + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + break_level2_to_none_async(fsp); } /** diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e8878a29ab..d524f21817 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -333,7 +333,6 @@ static void reply_spnego_kerberos(struct smb_request *req, DEBUG(3,("Doesn't look like a valid principal\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); - SAFE_FREE(client); talloc_destroy(mem_ctx); reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE)); return; @@ -355,7 +354,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); data_blob_free(&session_key); - SAFE_FREE(client); talloc_destroy(mem_ctx); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); @@ -445,7 +443,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !pw ) { DEBUG(1,("Username %s is invalid on this system\n", user)); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -471,7 +468,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -485,7 +481,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_pw failed: %s!\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -513,7 +508,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(10,("failed to create local token: %s\n", nt_errstr(ret))); - SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE( mem_ctx ); @@ -541,8 +535,6 @@ static void reply_spnego_kerberos(struct smb_request *req, nullblob, client); - SAFE_FREE(client); - reply_outbuf(req, 4, 0); SSVAL(req->outbuf,smb_uid,sess_vuid); |