1 From 61c58824cc9117ffe206ae7c126929bfa2384486 Mon Sep 17 00:00:00 2001
2 From: David Disseldorp <ddiss@samba.org>
3 Date: Thu, 10 Jul 2014 00:18:10 +0200
4 Subject: [PATCH 1/7] PATCHSET18: printing: traverse_read the printer list for
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
10 The printcap update procedure involves the background printer process
11 obtaining the printcap information from the printing backend, writing
12 this to printer_list.tdb, and then notifying all smbd processes of the
13 new list. The processes then all attempt to simultaneously traverse
14 printer_list.tdb, in order to update their local share lists.
16 With a large number of printers, and a large number of per-client smbd
17 processes, this traversal results in significant lock contention, mostly
18 due to the fact that the traversal is unnecessarily done with an
19 exclusive (write) lock on the printer_list.tdb database.
21 This commit changes the share update code path to perform a read-only
24 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
26 Reported-by: Alex K <korobkin+samba@gmail.com>
27 Reported-by: Franz Pförtsch <franz.pfoertsch@brose.com>
28 Signed-off-by: David Disseldorp <ddiss@samba.org>
30 source3/printing/load.c | 2 +-
31 source3/printing/pcap.c | 4 ++--
32 source3/printing/pcap.h | 2 +-
33 source3/printing/printer_list.c | 17 +++++++++++------
34 source3/printing/printer_list.h | 4 ++--
35 5 files changed, 17 insertions(+), 12 deletions(-)
37 diff --git a/source3/printing/load.c b/source3/printing/load.c
38 index 829c3e3..0a3de73 100644
39 --- a/source3/printing/load.c
40 +++ b/source3/printing/load.c
41 @@ -70,5 +70,5 @@ void load_printers(struct tevent_context *ev,
43 /* load all printcap printers */
44 if (lp_load_printers() && lp_servicenumber(PRINTERS_NAME) >= 0)
45 - pcap_printer_fn(lp_add_one_printer, NULL);
46 + pcap_printer_read_fn(lp_add_one_printer, NULL);
48 diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
49 index 62db4f5..6ad8e33 100644
50 --- a/source3/printing/pcap.c
51 +++ b/source3/printing/pcap.c
52 @@ -229,11 +229,11 @@ void pcap_printer_fn_specific(const struct pcap_cache *pc,
56 -void pcap_printer_fn(void (*fn)(const char *, const char *, const char *, void *), void *pdata)
57 +void pcap_printer_read_fn(void (*fn)(const char *, const char *, const char *, void *), void *pdata)
61 - status = printer_list_run_fn(fn, pdata);
62 + status = printer_list_read_run_fn(fn, pdata);
63 if (!NT_STATUS_IS_OK(status)) {
64 DEBUG(3, ("Failed to run fn for all printers!\n"));
66 diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
67 index 7056213..6c062c3 100644
68 --- a/source3/printing/pcap.h
69 +++ b/source3/printing/pcap.h
70 @@ -39,7 +39,7 @@ bool pcap_cache_add(const char *name, const char *comment, const char *location)
71 bool pcap_cache_loaded(void);
72 bool pcap_cache_replace(const struct pcap_cache *cache);
73 void pcap_printer_fn_specific(const struct pcap_cache *, void (*fn)(const char *, const char *, const char *, void *), void *);
74 -void pcap_printer_fn(void (*fn)(const char *, const char *, const char *, void *), void *);
75 +void pcap_printer_read_fn(void (*fn)(const char *, const char *, const char *, void *), void *);
77 void pcap_cache_reload(struct tevent_context *ev,
78 struct messaging_context *msg_ctx,
79 diff --git a/source3/printing/printer_list.c b/source3/printing/printer_list.c
80 index 603ce4b..b24bf83 100644
81 --- a/source3/printing/printer_list.c
82 +++ b/source3/printing/printer_list.c
83 @@ -280,7 +280,8 @@ done:
84 typedef int (printer_list_trv_fn_t)(struct db_record *, void *);
86 static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
91 struct db_context *db;
93 @@ -290,7 +291,11 @@ static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
94 return NT_STATUS_INTERNAL_DB_CORRUPTION;
97 - ret = db->traverse(db, fn, private_data);
99 + ret = db->traverse_read(db, fn, private_data);
101 + ret = db->traverse(db, fn, private_data);
104 return NT_STATUS_UNSUCCESSFUL;
106 @@ -357,7 +362,7 @@ NTSTATUS printer_list_clean_old(void)
108 state.status = NT_STATUS_OK;
110 - status = printer_list_traverse(printer_list_clean_fn, &state);
111 + status = printer_list_traverse(printer_list_clean_fn, &state, false);
112 if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
113 !NT_STATUS_IS_OK(state.status)) {
114 status = state.status;
115 @@ -404,8 +409,8 @@ static int printer_list_exec_fn(struct db_record *rec, void *private_data)
119 -NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *, void *),
120 - void *private_data)
121 +NTSTATUS printer_list_read_run_fn(void (*fn)(const char *, const char *, const char *, void *),
122 + void *private_data)
124 struct printer_list_exec_state state;
126 @@ -414,7 +419,7 @@ NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *
127 state.private_data = private_data;
128 state.status = NT_STATUS_OK;
130 - status = printer_list_traverse(printer_list_exec_fn, &state);
131 + status = printer_list_traverse(printer_list_exec_fn, &state, true);
132 if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
133 !NT_STATUS_IS_OK(state.status)) {
134 status = state.status;
135 diff --git a/source3/printing/printer_list.h b/source3/printing/printer_list.h
136 index fb2e007..b12c192 100644
137 --- a/source3/printing/printer_list.h
138 +++ b/source3/printing/printer_list.h
139 @@ -100,6 +100,6 @@ NTSTATUS printer_list_mark_reload(void);
141 NTSTATUS printer_list_clean_old(void);
143 -NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *, void *),
144 - void *private_data);
145 +NTSTATUS printer_list_read_run_fn(void (*fn)(const char *, const char *, const char *, void *),
146 + void *private_data);
147 #endif /* _PRINTER_LIST_H_ */
152 From 18b15f127b656ad9232789b073460c95b1aaa835 Mon Sep 17 00:00:00 2001
153 From: David Disseldorp <ddiss@samba.org>
154 Date: Fri, 11 Jul 2014 17:00:05 +0200
155 Subject: [PATCH 2/7] PATCHSET18: printing: only reload printer shares on
158 Currently, automatic printer share updates are handled in the following
160 - Background printer process (BPP) forked on startup
161 - Parent smbd and per-client children await MSG_PRINTER_PCAP messages
162 - BPP periodically polls the printing backend for printcap data
163 - printcap data written to printer_list.tdb
164 - MSG_PRINTER_PCAP sent to all smbd processes following update
165 - smbd processes all read the latest printer_list.tdb data, and update
168 This procedure is not scalable, as all smbd processes hit
169 printer_list.tdb in parallel, resulting in a large spike in CPU usage.
171 This change sees smbd processes only update their printer share lists
172 only when a client asks for this information, e.g. via NetShareEnum or
175 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
177 Suggested-by: Volker Lendecke <vl@samba.org>
178 Signed-off-by: David Disseldorp <ddiss@samba.org>
180 source3/printing/spoolssd.c | 17 +----------------
181 source3/rpc_server/spoolss/srv_spoolss_nt.c | 11 ++++++++++-
182 source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 1 +
183 source3/smbd/lanman.c | 3 +++
184 source3/smbd/server.c | 27 +++++----------------------
185 5 files changed, 20 insertions(+), 39 deletions(-)
187 diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c
188 index 83727df..7953237 100644
189 --- a/source3/printing/spoolssd.c
190 +++ b/source3/printing/spoolssd.c
191 @@ -74,20 +74,6 @@ static void smb_conf_updated(struct messaging_context *msg,
192 spoolss_reopen_logs();
195 -static void spoolss_pcap_updated(struct messaging_context *msg,
196 - void *private_data,
198 - struct server_id server_id,
201 - struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
202 - struct tevent_context);
204 - DEBUG(10, ("Got message saying pcap was updated. Reloading.\n"));
205 - change_to_root_user();
206 - reload_printers(ev_ctx, msg);
209 static void spoolss_sig_term_handler(struct tevent_context *ev,
210 struct tevent_signal *se,
212 @@ -206,12 +192,11 @@ void start_spoolssd(struct tevent_context *ev_ctx,
216 + /* printer shares updated from printer_list.tdb on client enumeration */
217 messaging_register(msg_ctx, NULL,
218 MSG_PRINTER_UPDATE, print_queue_receive);
219 messaging_register(msg_ctx, ev_ctx,
220 MSG_SMB_CONF_UPDATED, smb_conf_updated);
221 - messaging_register(msg_ctx, ev_ctx,
222 - MSG_PRINTER_PCAP, spoolss_pcap_updated);
225 * Initialize spoolss with an init function to convert printers first.
226 diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
227 index 516b7dc..db48574 100644
228 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
229 +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
230 @@ -4316,12 +4316,21 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
234 - int n_services = lp_numservices();
236 union spoolss_PrinterInfo *info = NULL;
238 WERROR result = WERR_OK;
239 struct dcerpc_binding_handle *b = NULL;
242 + * printer shares are only updated on client enumeration. The background
243 + * printer process updates printer_list.tdb at regular intervals.
246 + reload_printers(messaging_event_context(msg_ctx), msg_ctx);
249 + n_services = lp_numservices();
253 diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
254 index b9345d6..4600da3 100644
255 --- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
256 +++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
257 @@ -568,6 +568,7 @@ static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
259 /* Ensure all the usershares are loaded. */
261 + reload_printers(messaging_event_context(p->msg_ctx), p->msg_ctx);
262 load_usershare_shares();
263 load_registry_shares();
264 num_services = lp_numservices();
265 diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
266 index f56ea30..49f7583 100644
267 --- a/source3/smbd/lanman.c
268 +++ b/source3/smbd/lanman.c
270 #include "passdb/machine_sid.h"
272 #include "rpc_server/rpc_ncacn_np.h"
273 +#include "messages.h"
277 @@ -2091,6 +2092,8 @@ static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
279 /* Ensure all the usershares are loaded. */
281 + reload_printers(messaging_event_context(sconn->msg_ctx),
283 load_registry_shares();
284 count = load_usershare_shares();
286 diff --git a/source3/smbd/server.c b/source3/smbd/server.c
287 index a26dbc4..102e8dd 100644
288 --- a/source3/smbd/server.c
289 +++ b/source3/smbd/server.c
290 @@ -111,24 +111,6 @@ static void smb_conf_updated(struct messaging_context *msg,
291 /* printer reload triggered by background printing process */
294 -/*******************************************************************
295 - What to do when printcap is updated.
296 - ********************************************************************/
298 -static void smb_pcap_updated(struct messaging_context *msg,
299 - void *private_data,
301 - struct server_id server_id,
304 - struct tevent_context *ev_ctx =
305 - talloc_get_type_abort(private_data, struct tevent_context);
307 - DEBUG(10,("Got message saying pcap was updated. Reloading.\n"));
308 - change_to_root_user();
309 - reload_printers(ev_ctx, msg);
312 static void smbd_sig_term_handler(struct tevent_context *ev,
313 struct tevent_signal *se,
315 @@ -1287,10 +1269,11 @@ extern void build_options(bool screen);
317 if (is_daemon && !interactive
318 && lp_parm_bool(-1, "smbd", "backgroundqueue", true)) {
319 - /* background queue is responsible for printcap cache updates */
320 - messaging_register(smbd_server_conn->msg_ctx,
321 - smbd_event_context(),
322 - MSG_PRINTER_PCAP, smb_pcap_updated);
324 + * background queue is responsible for printcap cache updates.
325 + * Other smbd processes only reload printers when a client
326 + * issues an enumeration request.
328 start_background_queue(server_event_context(),
329 smbd_server_conn->msg_ctx);
335 From 52196380547dde4784e42c35c46135bb5230a08d Mon Sep 17 00:00:00 2001
336 From: David Disseldorp <ddiss@samba.org>
337 Date: Tue, 22 Jul 2014 20:17:38 +0200
338 Subject: [PATCH 3/7] PATCHSET18: printing: reload printer_list.tdb from in
341 This will allow in future for a single atomic printer_list.tdb update.
343 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
345 Signed-off-by: David Disseldorp <ddiss@samba.org>
347 source3/printing/pcap.c | 26 +++++++++++---------------
348 source3/printing/pcap.h | 8 ++++----
349 source3/printing/print_aix.c | 17 ++++++++++++++---
350 source3/printing/print_iprint.c | 16 ++++++++++------
351 source3/printing/print_standard.c | 8 ++++++--
352 source3/printing/print_svid.c | 11 +++++++----
353 6 files changed, 52 insertions(+), 34 deletions(-)
355 diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
356 index 6ad8e33..5173fc9 100644
357 --- a/source3/printing/pcap.c
358 +++ b/source3/printing/pcap.c
359 @@ -83,7 +83,7 @@ void pcap_cache_destroy_specific(struct pcap_cache **pp_cache)
363 -bool pcap_cache_add(const char *name, const char *comment, const char *location)
364 +static bool pcap_cache_add(const char *name, const char *comment, const char *location)
367 time_t t = time_mono(NULL);
368 @@ -132,8 +132,8 @@ void pcap_cache_reload(struct tevent_context *ev,
370 const char *pcap_name = lp_printcapname();
371 bool pcap_reloaded = False;
373 bool post_cache_fill_fn_handled = false;
374 + struct pcap_cache *pcache = NULL;
376 DEBUG(3, ("reloading printcap cache\n"));
378 @@ -143,12 +143,6 @@ void pcap_cache_reload(struct tevent_context *ev,
382 - status = printer_list_mark_reload();
383 - if (!NT_STATUS_IS_OK(status)) {
384 - DEBUG(0, ("Failed to mark printer list for reload!\n"));
389 if (strequal(pcap_name, "cups")) {
390 pcap_reloaded = cups_cache_reload(ev, msg_ctx,
391 @@ -164,26 +158,26 @@ void pcap_cache_reload(struct tevent_context *ev,
394 if (strequal(pcap_name, "iprint")) {
395 - pcap_reloaded = iprint_cache_reload();
396 + pcap_reloaded = iprint_cache_reload(&pcache);
401 #if defined(SYSV) || defined(HPUX)
402 if (strequal(pcap_name, "lpstat")) {
403 - pcap_reloaded = sysv_cache_reload();
404 + pcap_reloaded = sysv_cache_reload(&pcache);
410 if (strstr_m(pcap_name, "/qconfig") != NULL) {
411 - pcap_reloaded = aix_cache_reload();
412 + pcap_reloaded = aix_cache_reload(&pcache);
417 - pcap_reloaded = std_pcap_cache_reload(pcap_name);
418 + pcap_reloaded = std_pcap_cache_reload(pcap_name, &pcache);
421 DEBUG(3, ("reload status: %s\n", (pcap_reloaded) ? "ok" : "error"));
422 @@ -192,14 +186,16 @@ done:
423 /* cleanup old entries only if the operation was successful,
424 * otherwise keep around the old entries until we can
425 * successfuly reaload */
426 - status = printer_list_clean_old();
427 - if (!NT_STATUS_IS_OK(status)) {
428 - DEBUG(0, ("Failed to cleanup printer list!\n"));
430 + if (!pcap_cache_replace(pcache)) {
431 + DEBUG(0, ("Failed to replace printer list!\n"));
434 if (post_cache_fill_fn != NULL) {
435 post_cache_fill_fn(ev, msg_ctx);
438 + pcap_cache_destroy_specific(&pcache);
442 diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
443 index 6c062c3..d388d7d 100644
444 --- a/source3/printing/pcap.h
445 +++ b/source3/printing/pcap.h
446 @@ -49,7 +49,7 @@ bool pcap_printername_ok(const char *printername);
448 /* The following definitions come from printing/print_aix.c */
450 -bool aix_cache_reload(void);
451 +bool aix_cache_reload(struct pcap_cache **_pcache);
453 /* The following definitions come from printing/print_cups.c */
455 @@ -60,13 +60,13 @@ bool cups_cache_reload(struct tevent_context *ev,
457 /* The following definitions come from printing/print_iprint.c */
459 -bool iprint_cache_reload(void);
460 +bool iprint_cache_reload(struct pcap_cache **_pcache);
462 /* The following definitions come from printing/print_svid.c */
464 -bool sysv_cache_reload(void);
465 +bool sysv_cache_reload(struct pcap_cache **_pcache);
467 /* The following definitions come from printing/print_standard.c */
468 -bool std_pcap_cache_reload(const char *pcap_name);
469 +bool std_pcap_cache_reload(const char *pcap_name, struct pcap_cache **_pcache);
471 #endif /* _PRINTING_PCAP_H_ */
472 diff --git a/source3/printing/print_aix.c b/source3/printing/print_aix.c
473 index 23d9a86..927a71b 100644
474 --- a/source3/printing/print_aix.c
475 +++ b/source3/printing/print_aix.c
477 #include "printing/pcap.h"
480 -bool aix_cache_reload(void)
481 +bool aix_cache_reload(struct pcap_cache **_pcache)
485 char *line = NULL, *p;
487 + struct pcap_cache *pcache = NULL;
488 TALLOC_CTX *ctx = talloc_init("aix_cache_reload");
491 @@ -52,6 +53,8 @@ bool aix_cache_reload(void)
493 /* scan qconfig file for searching <printername>: */
494 for (;(line = fgets_slash(NULL, 1024, pfile)); free(line)) {
497 if (*line == '*' || *line == 0)
500 @@ -67,6 +70,7 @@ bool aix_cache_reload(void)
501 if (strcmp(p, "bsh") != 0) {
502 name = talloc_strdup(ctx, p);
504 + pcap_cache_destroy_specific(&pcache);
508 @@ -86,7 +90,10 @@ bool aix_cache_reload(void)
509 /* name is found without stanza device */
510 /* probably a good printer ??? */
512 - if (!pcap_cache_add(name, NULL, NULL)) {
513 + ok = pcap_cache_add_specific(&pcache,
516 + pcap_cache_destroy_specific(&pcache);
520 @@ -101,7 +108,10 @@ bool aix_cache_reload(void)
521 } else if (strstr_m(line, "device")) {
522 /* it's a good virtual printer */
524 - if (!pcap_cache_add(name, NULL, NULL)) {
525 + ok = pcap_cache_add_specific(&pcache,
528 + pcap_cache_destroy_specific(&pcache);
532 @@ -113,6 +123,7 @@ bool aix_cache_reload(void)
540 diff --git a/source3/printing/print_iprint.c b/source3/printing/print_iprint.c
541 index 529f0dd..6e91747 100644
542 --- a/source3/printing/print_iprint.c
543 +++ b/source3/printing/print_iprint.c
544 @@ -204,7 +204,8 @@ static int iprint_get_server_version(http_t *http, char* serviceUri)
546 static int iprint_cache_add_printer(http_t *http,
550 + struct pcap_cache **pcache)
552 ipp_t *request = NULL, /* IPP Request */
553 *response = NULL; /* IPP Response */
554 @@ -340,7 +341,7 @@ static int iprint_cache_add_printer(http_t *http,
557 if (name != NULL && !secure && smb_enabled)
558 - pcap_cache_add(name, info, NULL);
559 + pcap_cache_add_specific(pcache, name, info, NULL);
563 @@ -349,7 +350,7 @@ static int iprint_cache_add_printer(http_t *http,
567 -bool iprint_cache_reload(void)
568 +bool iprint_cache_reload(struct pcap_cache **_pcache)
570 http_t *http = NULL; /* HTTP connection to server */
571 ipp_t *request = NULL, /* IPP Request */
572 @@ -357,7 +358,8 @@ bool iprint_cache_reload(void)
573 ipp_attribute_t *attr; /* Current attribute */
574 cups_lang_t *language = NULL; /* Default language */
578 + struct pcap_cache *pcache = NULL;
580 DEBUG(5, ("reloading iprint printcap cache\n"));
582 @@ -439,14 +441,16 @@ bool iprint_cache_reload(void)
583 char *url = ippGetString(attr, i, NULL);
584 if (!url || !strlen(url))
586 - iprint_cache_add_printer(http, i+2, url);
587 + iprint_cache_add_printer(http, i+2, url,
591 attr = ippNextAttribute(response);
601 diff --git a/source3/printing/print_standard.c b/source3/printing/print_standard.c
602 index c4f9c5b..b5f1056 100644
603 --- a/source3/printing/print_standard.c
604 +++ b/source3/printing/print_standard.c
606 #include "printing/pcap.h"
608 /* handle standard printcap - moved from pcap_printer_fn() */
609 -bool std_pcap_cache_reload(const char *pcap_name)
610 +bool std_pcap_cache_reload(const char *pcap_name, struct pcap_cache **_pcache)
614 + struct pcap_cache *pcache = NULL;
616 if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) {
617 DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name));
618 @@ -117,12 +118,15 @@ bool std_pcap_cache_reload(const char *pcap_name)
622 - if (*name && !pcap_cache_add(name, comment, NULL)) {
623 + if ((*name != '\0')
624 + && !pcap_cache_add_specific(&pcache, name, comment, NULL)) {
626 + pcap_cache_destroy_specific(&pcache);
635 diff --git a/source3/printing/print_svid.c b/source3/printing/print_svid.c
636 index 2226493..879661b 100644
637 --- a/source3/printing/print_svid.c
638 +++ b/source3/printing/print_svid.c
640 #include "printing/pcap.h"
642 #if defined(SYSV) || defined(HPUX)
643 -bool sysv_cache_reload(void)
644 +bool sysv_cache_reload(struct pcap_cache **_pcache)
648 + struct pcap_cache *pcache = NULL;
651 DEBUG(5, ("reloading hpux printcap cache\n"));
652 @@ -111,14 +112,16 @@ bool sysv_cache_reload(void)
655 /* add it to the cache */
656 - if (!pcap_cache_add(name, NULL, NULL)) {
657 + if (!pcap_cache_add_specific(&pcache, name, NULL, NULL)) {
660 + pcap_cache_destroy_specific(&pcache);
676 From 91c0b6477fcd4ad20d1cda45f78f160cee8e58ff Mon Sep 17 00:00:00 2001
677 From: David Disseldorp <ddiss@samba.org>
678 Date: Fri, 25 Jul 2014 12:18:54 +0200
679 Subject: [PATCH 4/7] PATCHSET18: printing: remove pcap_cache_add()
681 All print list updates are now done via pcap_cache_replace(), which can
682 call into the print_list code directly.
684 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
686 Signed-off-by: David Disseldorp <ddiss@samba.org>
688 source3/printing/pcap.c | 16 ++++++----------
689 source3/printing/pcap.h | 1 -
690 2 files changed, 6 insertions(+), 11 deletions(-)
692 diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
693 index 5173fc9..5059f20 100644
694 --- a/source3/printing/pcap.c
695 +++ b/source3/printing/pcap.c
696 @@ -83,15 +83,6 @@ void pcap_cache_destroy_specific(struct pcap_cache **pp_cache)
700 -static bool pcap_cache_add(const char *name, const char *comment, const char *location)
703 - time_t t = time_mono(NULL);
705 - status = printer_list_set_printer(talloc_tos(), name, comment, location, t);
706 - return NT_STATUS_IS_OK(status);
709 bool pcap_cache_loaded(void)
712 @@ -105,6 +96,7 @@ bool pcap_cache_replace(const struct pcap_cache *pcache)
714 const struct pcap_cache *p;
716 + time_t t = time_mono(NULL);
718 status = printer_list_mark_reload();
719 if (!NT_STATUS_IS_OK(status)) {
720 @@ -113,7 +105,11 @@ bool pcap_cache_replace(const struct pcap_cache *pcache)
723 for (p = pcache; p; p = p->next) {
724 - pcap_cache_add(p->name, p->comment, p->location);
725 + status = printer_list_set_printer(talloc_tos(), p->name,
726 + p->comment, p->location, t);
727 + if (!NT_STATUS_IS_OK(status)) {
732 status = printer_list_clean_old();
733 diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
734 index d388d7d..7dccf84 100644
735 --- a/source3/printing/pcap.h
736 +++ b/source3/printing/pcap.h
737 @@ -35,7 +35,6 @@ struct pcap_cache;
739 bool pcap_cache_add_specific(struct pcap_cache **ppcache, const char *name, const char *comment, const char *location);
740 void pcap_cache_destroy_specific(struct pcap_cache **ppcache);
741 -bool pcap_cache_add(const char *name, const char *comment, const char *location);
742 bool pcap_cache_loaded(void);
743 bool pcap_cache_replace(const struct pcap_cache *cache);
744 void pcap_printer_fn_specific(const struct pcap_cache *, void (*fn)(const char *, const char *, const char *, void *), void *);
749 From 10582491e417d5ab5c77afe2337793dbacd98fa8 Mon Sep 17 00:00:00 2001
750 From: David Disseldorp <ddiss@samba.org>
751 Date: Wed, 23 Jul 2014 12:12:34 +0200
752 Subject: [PATCH 5/7] PATCHSET18: printing: return last change time with
755 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
757 Signed-off-by: David Disseldorp <ddiss@samba.org>
759 source3/printing/load.c | 2 +-
760 source3/printing/pcap.c | 10 ++++++++--
761 source3/printing/pcap.h | 2 +-
762 source3/web/swat.c | 4 ++--
763 4 files changed, 12 insertions(+), 6 deletions(-)
765 diff --git a/source3/printing/load.c b/source3/printing/load.c
766 index 0a3de73..83f1095 100644
767 --- a/source3/printing/load.c
768 +++ b/source3/printing/load.c
769 @@ -64,7 +64,7 @@ load automatic printer services from pre-populated pcap cache
770 void load_printers(struct tevent_context *ev,
771 struct messaging_context *msg_ctx)
773 - SMB_ASSERT(pcap_cache_loaded());
774 + SMB_ASSERT(pcap_cache_loaded(NULL));
778 diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
779 index 5059f20..027c1b2 100644
780 --- a/source3/printing/pcap.c
781 +++ b/source3/printing/pcap.c
782 @@ -83,13 +83,19 @@ void pcap_cache_destroy_specific(struct pcap_cache **pp_cache)
786 -bool pcap_cache_loaded(void)
787 +bool pcap_cache_loaded(time_t *_last_change)
792 status = printer_list_get_last_refresh(&last);
793 - return NT_STATUS_IS_OK(status);
794 + if (!NT_STATUS_IS_OK(status)) {
797 + if (_last_change != NULL) {
798 + *_last_change = last;
803 bool pcap_cache_replace(const struct pcap_cache *pcache)
804 diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
805 index 7dccf84..8fc9e9d 100644
806 --- a/source3/printing/pcap.h
807 +++ b/source3/printing/pcap.h
808 @@ -35,7 +35,7 @@ struct pcap_cache;
810 bool pcap_cache_add_specific(struct pcap_cache **ppcache, const char *name, const char *comment, const char *location);
811 void pcap_cache_destroy_specific(struct pcap_cache **ppcache);
812 -bool pcap_cache_loaded(void);
813 +bool pcap_cache_loaded(time_t *_last_change);
814 bool pcap_cache_replace(const struct pcap_cache *cache);
815 void pcap_printer_fn_specific(const struct pcap_cache *, void (*fn)(const char *, const char *, const char *, void *), void *);
816 void pcap_printer_read_fn(void (*fn)(const char *, const char *, const char *, void *), void *);
817 diff --git a/source3/web/swat.c b/source3/web/swat.c
818 index f8933d2..a1a035c 100644
819 --- a/source3/web/swat.c
820 +++ b/source3/web/swat.c
821 @@ -586,7 +586,7 @@ static int save_reload(int snum)
824 iNumNonAutoPrintServices = lp_numservices();
825 - if (pcap_cache_loaded()) {
826 + if (pcap_cache_loaded(NULL)) {
827 load_printers(server_event_context(),
828 server_messaging_context());
830 @@ -1572,7 +1572,7 @@ const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
833 iNumNonAutoPrintServices = lp_numservices();
834 - if (pcap_cache_loaded()) {
835 + if (pcap_cache_loaded(NULL)) {
836 load_printers(server_event_context(),
837 server_messaging_context());
843 From 484667ff73b54b275f8629264aef27ec9628c7fd Mon Sep 17 00:00:00 2001
844 From: David Disseldorp <ddiss@samba.org>
845 Date: Wed, 23 Jul 2014 14:42:00 +0200
846 Subject: [PATCH 6/7] PATCHSET18: smbd: only reprocess printer_list.tdb if it
849 The per-client smbd printer share inventory is currently updated from
850 printer_list.tdb when a client enumerates printers, via EnumPrinters or
852 printer_list.tdb is populated by the background print process, based on
853 the latest printcap values retrieved from the printing backend (e.g.
854 CUPS) at regular intervals.
855 This change ensures that per-client smbd processes don't reparse
856 printer_list.tdb if it hasn't been updated since the last enumeration.
858 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
860 Suggested-by: Volker Lendecke <vl@samba.org>
861 Signed-off-by: David Disseldorp <ddiss@samba.org>
863 source3/smbd/server_reload.c | 21 +++++++++++++++++++++
864 1 file changed, 21 insertions(+)
866 diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c
867 index c4c5a8d..57f7972 100644
868 --- a/source3/smbd/server_reload.c
869 +++ b/source3/smbd/server_reload.c
872 #include "messages.h"
875 + * The persistent pcap cache is populated by the background print process. Per
876 + * client smbds should only reload their printer share inventories if this
877 + * information has changed. Use last_reload_time to detect this.
879 +static time_t reload_last_pcap_time = 0;
881 /****************************************************************************
882 purge stale printers and reload from pre-populated pcap cache
883 **************************************************************************/
884 @@ -40,6 +47,20 @@ void reload_printers(struct tevent_context *ev,
889 + time_t pcap_last_update;
891 + ok = pcap_cache_loaded(&pcap_last_update);
893 + DEBUG(1, ("pcap cache not loaded\n"));
897 + if (reload_last_pcap_time == pcap_last_update) {
898 + DEBUG(5, ("skipping printer reload, already up to date.\n"));
901 + reload_last_pcap_time = pcap_last_update;
903 n_services = lp_numservices();
904 pnum = lp_servicenumber(PRINTERS_NAME);
909 From 08848f939b735b5a68066ebcc995247d77f5fa2d Mon Sep 17 00:00:00 2001
910 From: David Disseldorp <ddiss@samba.org>
911 Date: Wed, 6 Aug 2014 14:33:02 +0200
912 Subject: [PATCH 7/7] PATCHSET18: printing: reload printer shares on
915 The printer share inventory should be reloaded on open _and_
916 enumeration, as there are some clients, such as cupsaddsmb, that do not
917 perform an enumeration prior to access.
919 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
921 Signed-off-by: David Disseldorp <ddiss@samba.org>
923 source3/rpc_server/spoolss/srv_spoolss_nt.c | 12 +++++++++++-
924 1 file changed, 11 insertions(+), 1 deletion(-)
926 diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
927 index db48574..fb8f61f 100644
928 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
929 +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
930 @@ -1737,6 +1737,16 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
931 return WERR_INVALID_PARAM;
935 + * The printcap printer share inventory is updated on client
936 + * enumeration. For clients that do not perform enumeration prior to
937 + * access, such as cupssmbadd, we reinitialise the printer share
938 + * inventory on open as well.
941 + reload_printers(messaging_event_context(p->msg_ctx), p->msg_ctx);
944 /* some sanity check because you can open a printer or a print server */
945 /* aka: \\server\printer or \\server */
947 @@ -4323,7 +4333,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
948 struct dcerpc_binding_handle *b = NULL;
951 - * printer shares are only updated on client enumeration. The background
952 + * printer shares are updated on client enumeration. The background
953 * printer process updates printer_list.tdb at regular intervals.