From f6c883b4b00f4cd751cd312a27bddffb3be9c059 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 2008 14:18:35 -0700 Subject: Simply our main loop processing. A lot :-). Correctly use events for all the previous "special" cases. A step on the way to adding signals to the events and being able to merge the S3 event system with the S4 one. Jeremy. --- source3/smbd/process.c | 193 +++---------------------------------------------- source3/smbd/reply.c | 3 - source3/smbd/server.c | 31 ++++++++ 3 files changed, 40 insertions(+), 187 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b2d19e11e3..32629fd392 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -706,7 +706,7 @@ The timeout is in milliseconds ****************************************************************************/ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, - size_t *buffer_len, int timeout, + size_t *buffer_len, size_t *p_unread, bool *p_encrypted) { fd_set r_fds, w_fds; @@ -720,13 +720,8 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, again: - if (timeout >= 0) { - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - } else { - to.tv_sec = SMBD_SELECT_TIMEOUT; - to.tv_usec = 0; - } + to.tv_sec = SMBD_SELECT_TIMEOUT; + to.tv_usec = 0; /* * Note that this call must be before processing any SMB @@ -869,7 +864,7 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, /* Did we timeout ? */ if (selrtn == 0) { - return NT_STATUS_IO_TIMEOUT; + goto again; } /* @@ -1836,23 +1831,6 @@ void chain_reply(struct smb_request *req) return; } -/**************************************************************************** - Setup the needed select timeout in milliseconds. -****************************************************************************/ - -static int setup_select_timeout(void) -{ - int select_timeout; - - select_timeout = SMBD_SELECT_TIMEOUT*1000; - - if (print_notify_messages_pending()) { - select_timeout = MIN(select_timeout, 1000); - } - - return select_timeout; -} - /**************************************************************************** Check if services need reloading. ****************************************************************************/ @@ -1906,114 +1884,19 @@ void check_reload(time_t t) } } -/**************************************************************************** - Process any timeout housekeeping. Return False if the caller should exit. -****************************************************************************/ - -static void timeout_processing(int *select_timeout, - time_t *last_timeout_processing_time) -{ - time_t t; - - *last_timeout_processing_time = t = time(NULL); - - /* become root again if waiting */ - change_to_root_user(); - - /* check if we need to reload services */ - check_reload(t); - - if(global_machine_password_needs_changing && - /* for ADS we need to do a regular ADS password change, not a domain - password change */ - lp_security() == SEC_DOMAIN) { - - unsigned char trust_passwd_hash[16]; - time_t lct; - void *lock; - - /* - * We're in domain level security, and the code that - * read the machine password flagged that the machine - * password needs changing. - */ - - /* - * First, open the machine password file with an exclusive lock. - */ - - lock = secrets_get_trust_account_lock(NULL, lp_workgroup()); - - if (lock == NULL) { - DEBUG(0,("process: unable to lock the machine account password for \ -machine %s in domain %s.\n", global_myname(), lp_workgroup() )); - return; - } - - if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { - DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname(), lp_workgroup())); - TALLOC_FREE(lock); - return; - } - - /* - * Make sure someone else hasn't already done this. - */ - - if(t < lct + lp_machine_password_timeout()) { - global_machine_password_needs_changing = False; - TALLOC_FREE(lock); - return; - } - - /* always just contact the PDC here */ - - change_trust_account_password( lp_workgroup(), NULL); - global_machine_password_needs_changing = False; - TALLOC_FREE(lock); - } - - /* update printer queue caches if necessary */ - - update_monitored_printq_cache(); - - /* - * Now we are root, check if the log files need pruning. - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); - - /* Send any queued printer notify message to interested smbd's. */ - - print_notify_send_messages(smbd_messaging_context(), 0); - - /* - * Modify the select timeout depending upon - * what we have remaining in our queues. - */ - - *select_timeout = setup_select_timeout(); - - return; -} - /**************************************************************************** Process commands from the client ****************************************************************************/ void smbd_process(void) { - time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; size_t unread_bytes = 0; max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { - int select_timeout = setup_select_timeout(); - int num_echos; + NTSTATUS status; char *inbuf = NULL; size_t inbuf_len = 0; bool encrypted = false; @@ -2021,82 +1904,24 @@ void smbd_process(void) errno = 0; - /* Did someone ask for immediate checks on things like blocking locks ? */ - if (select_timeout == 0) { - timeout_processing(&select_timeout, - &last_timeout_processing_time); - num_smbs = 0; /* Reset smb counter. */ - } - run_events(smbd_event_context(), 0, NULL, NULL); - while (True) { - NTSTATUS status; - - status = receive_message_or_smb( - talloc_tos(), &inbuf, &inbuf_len, - select_timeout, &unread_bytes, &encrypted); - - if (NT_STATUS_IS_OK(status)) { - break; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - timeout_processing( - &select_timeout, - &last_timeout_processing_time); - continue; - } + status = receive_message_or_smb( + talloc_tos(), &inbuf, &inbuf_len, + &unread_bytes, &encrypted); + if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("receive_message_or_smb failed: %s, " "exiting\n", nt_errstr(status))); return; - - num_smbs = 0; /* Reset smb counter. */ } - - /* - * Ensure we do timeout processing if the SMB we just got was - * only an echo request. This allows us to set the select - * timeout in 'receive_message_or_smb()' to any value we like - * without worrying that the client will send echo requests - * faster than the select timeout, thus starving out the - * essential processing (change notify, blocking locks) that - * the timeout code does. JRA. - */ - num_echos = smb_echo_count; - process_smb(inbuf, inbuf_len, unread_bytes, encrypted); TALLOC_FREE(inbuf); - if (smb_echo_count != num_echos) { - timeout_processing(&select_timeout, - &last_timeout_processing_time); - num_smbs = 0; /* Reset smb counter. */ - } - num_smbs++; - /* - * If we are getting smb requests in a constant stream - * with no echos, make sure we attempt timeout processing - * every select_timeout milliseconds - but only check for this - * every 200 smb requests. - */ - - if ((num_smbs % 200) == 0) { - time_t new_check_time = time(NULL); - if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) { - timeout_processing( - &select_timeout, - &last_timeout_processing_time); - num_smbs = 0; /* Reset smb counter. */ - last_timeout_processing_time = new_check_time; /* Reset time. */ - } - } - /* The timeout_processing function isn't run nearly often enough to implement 'max log size' without overrunning the size of the file by many megabytes. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8bfa28faea..0226d314f7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -29,7 +29,6 @@ /* look in server.c for some explanation of these variables */ extern enum protocol_types Protocol; extern int max_recv; -unsigned int smb_echo_count = 0; extern uint32 global_client_caps; extern bool global_encrypted_passwords_negotiated; @@ -4611,8 +4610,6 @@ void reply_echo(struct smb_request *req) TALLOC_FREE(req->outbuf); - smb_echo_count++; - END_PROFILE(SMBecho); return; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 53116f3d98..69a483e4fc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1067,6 +1067,30 @@ static bool deadtime_fn(const struct timeval *now, void *private_data) return True; } +/* + * Do the recurring log file and smb.conf reload checks. + */ + +static bool housekeeping_fn(const struct timeval *now, void *private_data) +{ + change_to_root_user(); + + /* update printer queue caches if necessary */ + update_monitored_printq_cache(); + + /* check if we need to reload services */ + check_reload(time(NULL)); + + /* Change machine password if neccessary. */ + attempt_machine_password_change(); + + /* + * Force a log file check. + */ + force_check_log_size(); + check_log_size(); + return true; +} /**************************************************************************** main program. @@ -1426,6 +1450,13 @@ extern void build_options(bool screen); exit(1); } + if (!(event_add_idle(smbd_event_context(), NULL, + timeval_set(SMBD_SELECT_TIMEOUT, 0), + "housekeeping", housekeeping_fn, NULL))) { + DEBUG(0, ("Could not add housekeeping event\n")); + exit(1); + } + #ifdef CLUSTER_SUPPORT if (lp_clustering()) { -- cgit