Simply our main loop processing. A lot :-). Correctly use events for all the previous... v3-3-test
authorJeremy Allison <jra@samba.org>
Fri, 3 Oct 2008 21:19:44 +0000 (14:19 -0700)
committerJeremy Allison <jra@samba.org>
Fri, 3 Oct 2008 21:19:44 +0000 (14:19 -0700)
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.

source/auth/auth_domain.c
source/include/proto.h
source/lib/dummysmbd.c
source/printing/notify.c
source/smbd/process.c
source/smbd/reply.c
source/smbd/server.c

index c25e62ab809310a213789954014e674620c62ba4..f11dbe60ee13a41493c8f12f1599ea5163a6ecee 100644 (file)
 extern bool global_machine_password_needs_changing;
 static struct named_mutex *mutex;
 
+/*
+ * Change machine password (called from main loop
+ * idle timeout. Must be done as root.
+ */
+
+void attempt_machine_password_change(void)
+{
+       unsigned char trust_passwd_hash[16];
+       time_t lct;
+       void *lock;
+
+       if (!global_machine_password_needs_changing) {
+               return;
+       }
+
+       if (lp_security() != SEC_DOMAIN) {
+               return;
+       }
+
+       /*
+        * 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,("attempt_machine_password_change: 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,("attempt_machine_password_change: unable to read the "
+                       "machine account password for %s in domain %s.\n",
+                       global_myname(), lp_workgroup()));
+               TALLOC_FREE(lock);
+               return;
+       }
+
+       /*
+        * Make sure someone else hasn't already done this.
+        */
+
+       if(time(NULL) < 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);
+}
+
 /**
  * Connect to a remote server for (inter)domain security authenticaion.
  *
index 950d2b553b57a3023e0cdfe31bbb3d8c813c177f..6066ce2617b535ae77a33357c98041e12f1a290d 100644 (file)
@@ -43,7 +43,8 @@ bool password_ok(const char *smb_name, DATA_BLOB password_blob);
 
 /* The following definitions come from auth/auth_domain.c  */
 
-NTSTATUS auth_domain_init(void) ;
+void attempt_machine_password_change(void);
+NTSTATUS auth_domain_init(void);
 
 /* The following definitions come from auth/auth_ntlmssp.c  */
 
index dbe886e3d130c776753a41fbd93405621d0a4e52..5c624bdebfb9e86cbe67506e8c8b47ee7ede58d5 100644 (file)
@@ -51,3 +51,18 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
 {
        return NT_STATUS_OK;
 }
+
+bool change_to_root_user(void)
+{
+       return false;
+}
+
+struct event_context *smbd_event_context(void)
+{
+       return NULL;
+}
+
+struct messaging_context *smbd_messaging_context(void)
+{
+       return NULL;
+}
index 23df17c3896ab97a017700c07ef19b5707229fa0..f6599c413d042bb159f76bed503c0abe9f61a26b 100644 (file)
@@ -34,6 +34,7 @@ static struct notify_queue {
        size_t buflen;
 } *notify_queue_head = NULL;
 
+static struct timed_event *notify_event;
 
 static bool create_send_ctx(void)
 {
@@ -214,6 +215,22 @@ void print_notify_send_messages(struct messaging_context *msg_ctx,
        num_messages = 0;
 }
 
+/*******************************************************************
+ Event handler to send the messages.
+*******************************************************************/
+
+static void print_notify_event_send_messages(struct event_context *event_ctx,
+                                       struct timed_event *te,
+                                       const struct timeval *now,
+                                       void *private_data)
+{
+       /* Remove this timed event handler. */
+       TALLOC_FREE(notify_event);
+
+       change_to_root_user();
+       print_notify_send_messages(smbd_messaging_context(), 0);
+}
+
 /**********************************************************************
  deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX
  *********************************************************************/
@@ -304,6 +321,15 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer));
 
        DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *);
        num_messages++;
+
+       if (smbd_event_context()) {
+               /* Add an event for 1 second's time to send this queue. */
+               notify_event = event_add_timed(smbd_event_context(), NULL,
+                                       timeval_current_ofs(1,0),
+                                       "print_notify",
+                                       print_notify_event_send_messages, NULL);
+       }
+
 }
 
 static void send_notify_field_values(const char *sharename, uint32 type,
index c7e5c4cde37b651570ee0edf9cdf57f8f83837f4..0b8ff4f34bc6a44d84975551be83911b85b257c7 100644 (file)
@@ -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.
index fbda57db5181d7ac1d540553507304b8c9efcdc9..ae8e7699f8402b57553921c57bf6220cdee859ce 100644 (file)
@@ -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;
@@ -4614,8 +4613,6 @@ void reply_echo(struct smb_request *req)
 
        TALLOC_FREE(req->outbuf);
 
-       smb_echo_count++;
-
        END_PROFILE(SMBecho);
        return;
 }
index 53116f3d98ea016173d0b28c8e49d2fef3df5e33..69a483e4fca894e97cf056d3b13093212a3e1bbf 100644 (file)
@@ -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()) {