[PATCH 2/7] printing: only reload printer shares on client enum

David Disseldorp ddiss at samba.org
Mon Aug 4 07:58:02 MDT 2014


Currently, automatic printer share updates are handled in the following
way:
- Background printer process (BPP) forked on startup
- Parent smbd and per-client children await MSG_PRINTER_PCAP messages
- BPP periodically polls the printing backend for printcap data
	- printcap data written to printer_list.tdb
	- MSG_PRINTER_PCAP sent to all smbd processes following update
- smbd processes all read the latest printer_list.tdb data, and update
  their share listings

This procedure is not scalable, as all smbd processes hit
printer_list.tdb in parallel, resulting in a large spike in CPU usage.

This change sees smbd processes only update their printer share lists
only when a client asks for this information, e.g. via NetShareEnum or
EnumPrinters.

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

Suggested-by: Volker Lendecke <vl at samba.org>
Signed-off-by: David Disseldorp <ddiss at samba.org>
---
 source3/printing/spoolssd.c                 | 34 +++++------------------------
 source3/rpc_server/spoolss/srv_spoolss_nt.c | 11 +++++++++-
 source3/rpc_server/srvsvc/srv_srvsvc_nt.c   |  1 +
 source3/smbd/server.c                       | 20 -----------------
 4 files changed, 16 insertions(+), 50 deletions(-)

diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c
index f181fcc..afb8f4f 100644
--- a/source3/printing/spoolssd.c
+++ b/source3/printing/spoolssd.c
@@ -132,27 +132,6 @@ static void smb_conf_updated(struct messaging_context *msg,
 	update_conf(ev_ctx, msg);
 }
 
-static void update_pcap(struct tevent_context *ev_ctx,
-			struct messaging_context *msg_ctx)
-{
-	change_to_root_user();
-	delete_and_reload_printers(ev_ctx, msg_ctx);
-}
-
-static void pcap_updated(struct messaging_context *msg,
-			 void *private_data,
-			 uint32_t msg_type,
-			 struct server_id server_id,
-			 DATA_BLOB *data)
-{
-	struct tevent_context *ev_ctx;
-
-	ev_ctx = talloc_get_type_abort(private_data, struct tevent_context);
-
-	DEBUG(10, ("Got message that pcap updated. Reloading.\n"));
-	update_pcap(ev_ctx, msg);
-}
-
 static void spoolss_sig_term_handler(struct tevent_context *ev,
 				     struct tevent_signal *se,
 				     int signum,
@@ -318,8 +297,6 @@ static bool spoolss_child_init(struct tevent_context *ev_ctx,
 
 	messaging_register(msg_ctx, ev_ctx,
 			   MSG_SMB_CONF_UPDATED, smb_conf_updated);
-	messaging_register(msg_ctx, ev_ctx, MSG_PRINTER_PCAP,
-			   pcap_updated);
 	messaging_register(msg_ctx, ev_ctx,
 			   MSG_PREFORK_PARENT_EVENT, parent_ping);
 
@@ -739,15 +716,14 @@ pid_t start_spoolssd(struct tevent_context *ev_ctx,
 			   MSG_SMB_CONF_UPDATED, smb_conf_updated);
 	messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
 			   print_queue_forward);
-	messaging_register(msg_ctx, ev_ctx, MSG_PRINTER_PCAP,
-			   pcap_updated);
 	messaging_register(msg_ctx, ev_ctx,
 			   MSG_PREFORK_CHILD_EVENT, child_ping);
 
-	/* As soon as messaging is up check if pcap has been loaded already.
-	 * If so then we probably missed a message and should load_printers()
-	 * ourselves. If pcap has not been loaded yet, then ignore, we will get
-	 * a message as soon as the bq process completes the reload. */
+	/*
+	 * As soon as messaging is up check if pcap has been loaded already.
+	 * If pcap has not been loaded yet, then ignore, as we will reload on
+	 * client enumeration anyway.
+	 */
 	if (pcap_cache_loaded()) {
 		load_printers(ev_ctx, msg_ctx);
 	}
diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index 760c924..b8cae89 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -4312,7 +4312,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
 					   uint32_t *count_p)
 {
 	int snum;
-	int n_services = lp_numservices();
+	int n_services;
 	union spoolss_PrinterInfo *info = NULL;
 	uint32_t count = 0;
 	WERROR result = WERR_OK;
@@ -4324,6 +4324,15 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
 		return WERR_NOMEM;
 	}
 
+	/*
+	 * printer shares are only updated on client enumeration. The background
+	 * printer process updates printer_list.tdb at regular intervals.
+	 */
+	become_root();
+	delete_and_reload_printers(server_event_context(), msg_ctx);
+	unbecome_root();
+
+	n_services = lp_numservices();
 	*count_p = 0;
 	*info_p = NULL;
 
diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
index e030b98..11abc6c 100644
--- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
@@ -548,6 +548,7 @@ static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
 
 	/* Ensure all the usershares are loaded. */
 	become_root();
+	delete_and_reload_printers(server_event_context(), p->msg_ctx);
 	load_usershare_shares(NULL, connections_snum_used);
 	load_registry_shares();
 	num_services = lp_numservices();
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index ec9348c..bc07c0f 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -110,24 +110,6 @@ static void smbd_parent_conf_updated(struct messaging_context *msg,
 }
 
 /*******************************************************************
- What to do when printcap is updated.
- ********************************************************************/
-
-static void smb_pcap_updated(struct messaging_context *msg,
-			     void *private_data,
-			     uint32_t msg_type,
-			     struct server_id server_id,
-			     DATA_BLOB *data)
-{
-	struct tevent_context *ev_ctx =
-		talloc_get_type_abort(private_data, struct tevent_context);
-
-	DEBUG(10,("Got message saying pcap was updated. Reloading.\n"));
-	change_to_root_user();
-	delete_and_reload_printers(ev_ctx, msg);
-}
-
-/*******************************************************************
  Delete a statcache entry.
  ********************************************************************/
 
@@ -894,8 +876,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 	messaging_register(msg_ctx, NULL, MSG_SMB_STAT_CACHE_DELETE,
 			   smb_stat_cache_delete);
 	messaging_register(msg_ctx, NULL, MSG_DEBUG, smbd_msg_debug);
-	messaging_register(msg_ctx, ev_ctx, MSG_PRINTER_PCAP,
-			   smb_pcap_updated);
 	messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE,
 			   brl_revalidate);
 	messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS,
-- 
1.8.4.5



More information about the samba-technical mailing list