s3: printing: Fix problem with server taking too long to respond to a MSG_PRINTER_DRV...
authorJeremy Allison <jra@samba.org>
Wed, 12 Feb 2014 18:13:19 +0000 (10:13 -0800)
committerKarolin Seeger <kseeger@samba.org>
Sun, 23 Feb 2014 03:57:30 +0000 (04:57 +0100)
Receiving a MSG_PRINTER_DRVUPGRADE causes
smbd to iterate over all printers looking
for ones that uses the driver. This is a very
expensive operation requiring a read of all
registry printer parameters.

On a system with a large number of printers,
this causes the clients to timeout (smbd
can take longer than 60 seconds to respond).

This patch fixes the problem by forwarding
the MSG_PRINTER_DRVUPGRADE to the background
lpq queue updater process and allowing it to
take care of the updating of the changeid
in the registry, allowing the smbd connected
to the client to return to processing requests
immediately.

https://bugzilla.samba.org/show_bug.cgi?id=9942

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Tue Feb 18 17:48:30 CET 2014 on sn-devel-104

(cherry picked from commit cd655715b8ee0a4e681d67b3996f71017b941401)

Autobuild-User(v4-0-test): Karolin Seeger <kseeger@samba.org>
Autobuild-Date(v4-0-test): Sun Feb 23 04:57:30 CET 2014 on sn-devel-104

source3/printing/nt_printing.c
source3/printing/queue_process.c
source3/rpc_server/spoolss/srv_spoolss_nt.c

index 766e4c658aa01af4ace13aee9b8d432910673d1b..c472d410ad42b10adcf5a8b2ffa97b25e01b5d81 100644 (file)
@@ -74,6 +74,31 @@ static const struct print_architecture_table_node archi_table[]= {
        {NULL,                   "",            -1 }
 };
 
+/****************************************************************************
+ Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
+ background lpq updater.
+****************************************************************************/
+
+static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
+                               void *private_data,
+                               uint32_t msg_type,
+                               struct server_id server_id,
+                               DATA_BLOB *data)
+{
+       extern pid_t background_lpq_updater_pid;
+
+       if (background_lpq_updater_pid == -1) {
+               DEBUG(3,("no background lpq queue updater\n"));
+               return;
+       }
+
+       messaging_send_buf(msg,
+                       pid_to_procid(background_lpq_updater_pid),
+                       MSG_PRINTER_DRVUPGRADE,
+                       data->data,
+                       data->length);
+}
+
 /****************************************************************************
  Open the NT printing tdbs. Done once before fork().
 ****************************************************************************/
@@ -88,10 +113,10 @@ bool nt_printing_init(struct messaging_context *msg_ctx)
 
        /*
         * register callback to handle updating printers as new
-        * drivers are installed
+        * drivers are installed. Forwards to background lpq updater.
         */
        messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
-                          do_drv_upgrade_printer);
+                       forward_drv_upgrade_printer_msg);
 
        /* of course, none of the message callbacks matter if you don't
           tell messages.c that you interested in receiving PRINT_GENERAL
index 3d142dd7693d93c38e54822735834e2cf7c7befa..0969c7bfb4f5c1d674a3d37ba5ce08c4f3295edc 100644 (file)
@@ -31,6 +31,7 @@
 #include "smbd/smbd.h"
 #include "rpc_server/rpc_config.h"
 #include "printing/load.h"
+#include "rpc_server/spoolss/srv_spoolss_nt.h"
 
 extern pid_t start_spoolssd(struct event_context *ev_ctx,
                            struct messaging_context *msg_ctx);
@@ -311,6 +312,11 @@ pid_t start_background_queue(struct tevent_context *ev,
                                   bq_smb_conf_updated);
                messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
                                   print_queue_receive);
+               /* Remove previous forwarder message set in parent. */
+               messaging_deregister(msg_ctx, MSG_PRINTER_DRVUPGRADE, NULL);
+
+               messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
+                                  do_drv_upgrade_printer);
 
                fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
                                    printing_pause_fd_handler,
index 3703349f2073f8a04573f0c125fea003a7ed07c1..c878679c2d388d5198da966ef897cf46051f4e1d 100644 (file)
@@ -1513,6 +1513,7 @@ void srv_spoolss_cleanup(void)
 /**********************************************************************
  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
  over all printers, upgrading ones as necessary
+ This is now *ONLY* called inside the background lpq updater. JRA.
  **********************************************************************/
 
 void do_drv_upgrade_printer(struct messaging_context *msg,