[PATCH 7/7] smbd: split printer reload processing

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


All printer inventory updates are currently done via
delete_and_reload_printers(), which handles registry.tdb updates for
added or removed printers, AD printer unpublishing on removal, as well
as share service creation and deletion.

This change splits this functionality into two functions such that
per-client smbd processes do not perform registry.tdb updates or printer
unpublishing. This is now only performed by the process that performs
the printcap cache update.

This change is similar to ac6604868d1325dd4c872dc0f6ab056d10ebaecf from
the 3.6 branch.

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

Signed-off-by: David Disseldorp <ddiss at samba.org>
---
 source3/printing/queue_process.c |  8 +++--
 source3/smbd/proto.h             |  2 ++
 source3/smbd/server_reload.c     | 78 +++++++++++++++++++++++++++++++++-------
 3 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c
index 24d361c..7c097cd 100644
--- a/source3/printing/queue_process.c
+++ b/source3/printing/queue_process.c
@@ -50,7 +50,7 @@ static void reload_pcap_change_notify(struct tevent_context *ev,
 	 * This will block the process for some time (~1 sec per printer), but
 	 * it doesn't block smbd's servering clients.
 	 */
-	delete_and_reload_printers(ev, msg_ctx);
+	delete_and_reload_printers_full(ev, msg_ctx);
 
 	message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL);
 }
@@ -372,7 +372,8 @@ bool printing_subsystem_init(struct tevent_context *ev_ctx,
 		ret = printing_subsystem_queue_tasks(ev_ctx, msg_ctx);
 
 		/* Publish nt printers, this requires a working winreg pipe */
-		pcap_cache_reload(ev_ctx, msg_ctx, &delete_and_reload_printers);
+		pcap_cache_reload(ev_ctx, msg_ctx,
+				  &delete_and_reload_printers_full);
 
 		return ret;
 	}
@@ -401,5 +402,6 @@ void printing_subsystem_update(struct tevent_context *ev_ctx,
 		return;
 	}
 
-	pcap_cache_reload(ev_ctx, msg_ctx, &delete_and_reload_printers);
+	pcap_cache_reload(ev_ctx, msg_ctx,
+			  &delete_and_reload_printers_full);
 }
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index eab05c2..eb529e2 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -954,6 +954,8 @@ const struct security_token *sec_ctx_active_token(void);
 struct memcache *smbd_memcache(void);
 void delete_and_reload_printers(struct tevent_context *ev,
 				struct messaging_context *msg_ctx);
+void delete_and_reload_printers_full(struct tevent_context *ev,
+				     struct messaging_context *msg_ctx);
 bool reload_services(struct smbd_server_connection *sconn,
 		     bool (*snumused) (struct smbd_server_connection *, int),
 		     bool test);
diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c
index ad148e1..e6006bc 100644
--- a/source3/smbd/server_reload.c
+++ b/source3/smbd/server_reload.c
@@ -44,14 +44,10 @@ static bool snum_is_shared_printer(int snum)
 }
 
 /**
- * @brief Purge stale printers and reload from pre-populated pcap cache.
+ * @brief Purge stale printer shares and reload from pre-populated pcap cache.
  *
  * This function should normally only be called as a callback on a successful
- * pcap_cache_reload() or after a MSG_PRINTER_CAP message is received.
- *
- * This function can cause DELETION of printers and drivers from our registry,
- * so calling it on a failed pcap reload may REMOVE permanently all printers
- * and drivers.
+ * pcap_cache_reload(), or on client enumeration.
  *
  * @param[in] ev        The event context.
  *
@@ -60,25 +56,24 @@ static bool snum_is_shared_printer(int snum)
 void delete_and_reload_printers(struct tevent_context *ev,
 				struct messaging_context *msg_ctx)
 {
-	struct auth_session_info *session_info = NULL;
-	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
 	int n_services;
 	int pnum;
 	int snum;
 	const char *pname;
-	const char *sname;
-	NTSTATUS status;
 	bool ok;
 	time_t pcap_last_update;
+	TALLOC_CTX *frame = talloc_stackframe();
 
 	ok = pcap_cache_loaded(&pcap_last_update);
 	if (!ok) {
 		DEBUG(1, ("pcap cache not loaded\n"));
+		talloc_free(frame);
 		return;
 	}
 
 	if (reload_last_pcap_time == pcap_last_update) {
 		DEBUG(5, ("skipping printer reload, already up to date.\n"));
+		talloc_free(frame);
 		return;
 	}
 	reload_last_pcap_time = pcap_last_update;
@@ -91,6 +86,64 @@ void delete_and_reload_printers(struct tevent_context *ev,
 
 	DEBUG(10, ("reloading printer services from pcap cache\n"));
 
+	/*
+	 * Add default config for printers added to smb.conf file and remove
+	 * stale printers
+	 */
+	for (snum = 0; snum < n_services; snum++) {
+		/* avoid removing PRINTERS_NAME */
+		if (snum == pnum) {
+			continue;
+		}
+
+		/* skip no-printer services */
+		if (!snum_is_shared_printer(snum)) {
+			continue;
+		}
+
+		pname = lp_printername(frame, snum);
+
+		/* check printer, but avoid removing non-autoloaded printers */
+		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
+			lp_killservice(snum);
+		}
+	}
+
+	/* Make sure deleted printers are gone */
+	load_printers(ev, msg_ctx);
+
+	talloc_free(frame);
+}
+
+/**
+ * @brief Purge stale printers and reload from pre-populated pcap cache.
+ *
+ * This function should normally only be called as a callback on a successful
+ * pcap_cache_reload().
+ *
+ * This function can cause DELETION of printers and drivers from our registry,
+ * so calling it on a failed pcap reload may REMOVE permanently all printers
+ * and drivers.
+ *
+ * @param[in] ev        The event context.
+ *
+ * @param[in] msg_ctx   The messaging context.
+ */
+void delete_and_reload_printers_full(struct tevent_context *ev,
+				     struct messaging_context *msg_ctx)
+{
+	struct auth_session_info *session_info = NULL;
+	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+	int n_services;
+	int pnum;
+	int snum;
+	const char *pname;
+	const char *sname;
+	NTSTATUS status;
+
+	n_services = lp_numservices();
+	pnum = lp_servicenumber(PRINTERS_NAME);
+
 	status = make_session_info_system(talloc_tos(), &session_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("reload_printers: "
@@ -137,7 +190,6 @@ void delete_and_reload_printers(struct tevent_context *ev,
 			}
 			nt_printer_remove(session_info, session_info, msg_ctx,
 					  pname);
-			lp_killservice(snum);
 		} else {
 			DEBUG(8, ("Adding default registry entry for printer "
 				  "[%s], if it doesn't exist.\n", sname));
@@ -146,8 +198,8 @@ void delete_and_reload_printers(struct tevent_context *ev,
 		}
 	}
 
-	/* Make sure deleted printers are gone */
-	load_printers(ev, msg_ctx);
+	/* finally, purge old snums */
+	delete_and_reload_printers(ev, msg_ctx);
 
 	TALLOC_FREE(session_info);
 }
-- 
1.8.4.5



More information about the samba-technical mailing list