]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/samba/samba-3.6.99-fix_printcap_cpu_utilization.patch
core115: Include captive portal in updater
[ipfire-2.x.git] / src / patches / samba / samba-3.6.99-fix_printcap_cpu_utilization.patch
CommitLineData
1d13e637
AF
1From 61c58824cc9117ffe206ae7c126929bfa2384486 Mon Sep 17 00:00:00 2001
2From: David Disseldorp <ddiss@samba.org>
3Date: Thu, 10 Jul 2014 00:18:10 +0200
4Subject: [PATCH 1/7] PATCHSET18: printing: traverse_read the printer list for
5 share updates
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10The printcap update procedure involves the background printer process
11obtaining the printcap information from the printing backend, writing
12this to printer_list.tdb, and then notifying all smbd processes of the
13new list. The processes then all attempt to simultaneously traverse
14printer_list.tdb, in order to update their local share lists.
15
16With a large number of printers, and a large number of per-client smbd
17processes, this traversal results in significant lock contention, mostly
18due to the fact that the traversal is unnecessarily done with an
19exclusive (write) lock on the printer_list.tdb database.
20
21This commit changes the share update code path to perform a read-only
22traversal.
23
24Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
25
26Reported-by: Alex K <korobkin+samba@gmail.com>
27Reported-by: Franz Pförtsch <franz.pfoertsch@brose.com>
28Signed-off-by: David Disseldorp <ddiss@samba.org>
29---
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(-)
36
37diff --git a/source3/printing/load.c b/source3/printing/load.c
38index 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,
42
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);
47 }
48diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
49index 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,
53 return;
54 }
55
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)
58 {
59 NTSTATUS status;
60
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"));
65 }
66diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
67index 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 *);
76
77 void pcap_cache_reload(struct tevent_context *ev,
78 struct messaging_context *msg_ctx,
79diff --git a/source3/printing/printer_list.c b/source3/printing/printer_list.c
80index 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 *);
85
86 static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
87- void *private_data)
88+ void *private_data,
89+ bool read_only)
90 {
91 struct db_context *db;
92 int ret;
93@@ -290,7 +291,11 @@ static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
94 return NT_STATUS_INTERNAL_DB_CORRUPTION;
95 }
96
97- ret = db->traverse(db, fn, private_data);
98+ if (read_only) {
99+ ret = db->traverse_read(db, fn, private_data);
100+ } else {
101+ ret = db->traverse(db, fn, private_data);
102+ }
103 if (ret < 0) {
104 return NT_STATUS_UNSUCCESSFUL;
105 }
106@@ -357,7 +362,7 @@ NTSTATUS printer_list_clean_old(void)
107
108 state.status = NT_STATUS_OK;
109
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)
116 return 0;
117 }
118
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)
123 {
124 struct printer_list_exec_state state;
125 NTSTATUS status;
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;
129
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;
135diff --git a/source3/printing/printer_list.h b/source3/printing/printer_list.h
136index 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);
140 */
141 NTSTATUS printer_list_clean_old(void);
142
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_ */
148--
1492.1.0
150
151
152From 18b15f127b656ad9232789b073460c95b1aaa835 Mon Sep 17 00:00:00 2001
153From: David Disseldorp <ddiss@samba.org>
154Date: Fri, 11 Jul 2014 17:00:05 +0200
155Subject: [PATCH 2/7] PATCHSET18: printing: only reload printer shares on
156 client enum
157
158Currently, automatic printer share updates are handled in the following
159way:
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
166 their share listings
167
168This procedure is not scalable, as all smbd processes hit
169printer_list.tdb in parallel, resulting in a large spike in CPU usage.
170
171This change sees smbd processes only update their printer share lists
172only when a client asks for this information, e.g. via NetShareEnum or
173EnumPrinters.
174
175Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
176
177Suggested-by: Volker Lendecke <vl@samba.org>
178Signed-off-by: David Disseldorp <ddiss@samba.org>
179---
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(-)
186
187diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c
188index 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();
193 }
194
195-static void spoolss_pcap_updated(struct messaging_context *msg,
196- void *private_data,
197- uint32_t msg_type,
198- struct server_id server_id,
199- DATA_BLOB *data)
200-{
201- struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
202- struct tevent_context);
203-
204- DEBUG(10, ("Got message saying pcap was updated. Reloading.\n"));
205- change_to_root_user();
206- reload_printers(ev_ctx, msg);
207-}
208-
209 static void spoolss_sig_term_handler(struct tevent_context *ev,
210 struct tevent_signal *se,
211 int signum,
212@@ -206,12 +192,11 @@ void start_spoolssd(struct tevent_context *ev_ctx,
213 exit(1);
214 }
215
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);
223
224 /*
225 * Initialize spoolss with an init function to convert printers first.
226diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
227index 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,
231 uint32_t *count_p)
232 {
233 int snum;
234- int n_services = lp_numservices();
235+ int n_services;
236 union spoolss_PrinterInfo *info = NULL;
237 uint32_t count = 0;
238 WERROR result = WERR_OK;
239 struct dcerpc_binding_handle *b = NULL;
240
241+ /*
242+ * printer shares are only updated on client enumeration. The background
243+ * printer process updates printer_list.tdb at regular intervals.
244+ */
245+ become_root();
246+ reload_printers(messaging_event_context(msg_ctx), msg_ctx);
247+ unbecome_root();
248+
249+ n_services = lp_numservices();
250 *count_p = 0;
251 *info_p = NULL;
252
253diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
254index 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,
258
259 /* Ensure all the usershares are loaded. */
260 become_root();
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();
265diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
266index f56ea30..49f7583 100644
267--- a/source3/smbd/lanman.c
268+++ b/source3/smbd/lanman.c
269@@ -43,6 +43,7 @@
270 #include "passdb/machine_sid.h"
271 #include "auth.h"
272 #include "rpc_server/rpc_ncacn_np.h"
273+#include "messages.h"
274
275 #ifdef CHECK_TYPES
276 #undef CHECK_TYPES
277@@ -2091,6 +2092,8 @@ static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
278
279 /* Ensure all the usershares are loaded. */
280 become_root();
281+ reload_printers(messaging_event_context(sconn->msg_ctx),
282+ sconn->msg_ctx);
283 load_registry_shares();
284 count = load_usershare_shares();
285 unbecome_root();
286diff --git a/source3/smbd/server.c b/source3/smbd/server.c
287index 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 */
292 }
293
294-/*******************************************************************
295- What to do when printcap is updated.
296- ********************************************************************/
297-
298-static void smb_pcap_updated(struct messaging_context *msg,
299- void *private_data,
300- uint32_t msg_type,
301- struct server_id server_id,
302- DATA_BLOB *data)
303-{
304- struct tevent_context *ev_ctx =
305- talloc_get_type_abort(private_data, struct tevent_context);
306-
307- DEBUG(10,("Got message saying pcap was updated. Reloading.\n"));
308- change_to_root_user();
309- reload_printers(ev_ctx, msg);
310-}
311-
312 static void smbd_sig_term_handler(struct tevent_context *ev,
313 struct tevent_signal *se,
314 int signum,
315@@ -1287,10 +1269,11 @@ extern void build_options(bool screen);
316
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);
323+ /*
324+ * background queue is responsible for printcap cache updates.
325+ * Other smbd processes only reload printers when a client
326+ * issues an enumeration request.
327+ */
328 start_background_queue(server_event_context(),
329 smbd_server_conn->msg_ctx);
330 } else {
331--
3322.1.0
333
334
335From 52196380547dde4784e42c35c46135bb5230a08d Mon Sep 17 00:00:00 2001
336From: David Disseldorp <ddiss@samba.org>
337Date: Tue, 22 Jul 2014 20:17:38 +0200
338Subject: [PATCH 3/7] PATCHSET18: printing: reload printer_list.tdb from in
339 memory list
340
341This will allow in future for a single atomic printer_list.tdb update.
342
343Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
344
345Signed-off-by: David Disseldorp <ddiss@samba.org>
346---
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(-)
354
355diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
356index 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)
360 *pp_cache = NULL;
361 }
362
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)
365 {
366 NTSTATUS status;
367 time_t t = time_mono(NULL);
368@@ -132,8 +132,8 @@ void pcap_cache_reload(struct tevent_context *ev,
369 {
370 const char *pcap_name = lp_printcapname();
371 bool pcap_reloaded = False;
372- NTSTATUS status;
373 bool post_cache_fill_fn_handled = false;
374+ struct pcap_cache *pcache = NULL;
375
376 DEBUG(3, ("reloading printcap cache\n"));
377
378@@ -143,12 +143,6 @@ void pcap_cache_reload(struct tevent_context *ev,
379 return;
380 }
381
382- status = printer_list_mark_reload();
383- if (!NT_STATUS_IS_OK(status)) {
384- DEBUG(0, ("Failed to mark printer list for reload!\n"));
385- return;
386- }
387-
388 #ifdef HAVE_CUPS
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,
392
393 #ifdef HAVE_IPRINT
394 if (strequal(pcap_name, "iprint")) {
395- pcap_reloaded = iprint_cache_reload();
396+ pcap_reloaded = iprint_cache_reload(&pcache);
397 goto done;
398 }
399 #endif
400
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);
405 goto done;
406 }
407 #endif
408
409 #ifdef AIX
410 if (strstr_m(pcap_name, "/qconfig") != NULL) {
411- pcap_reloaded = aix_cache_reload();
412+ pcap_reloaded = aix_cache_reload(&pcache);
413 goto done;
414 }
415 #endif
416
417- pcap_reloaded = std_pcap_cache_reload(pcap_name);
418+ pcap_reloaded = std_pcap_cache_reload(pcap_name, &pcache);
419
420 done:
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"));
429+
430+ if (!pcap_cache_replace(pcache)) {
431+ DEBUG(0, ("Failed to replace printer list!\n"));
432 }
433+
434 if (post_cache_fill_fn != NULL) {
435 post_cache_fill_fn(ev, msg_ctx);
436 }
437 }
438+ pcap_cache_destroy_specific(&pcache);
439
440 return;
441 }
442diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
443index 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);
447
448 /* The following definitions come from printing/print_aix.c */
449
450-bool aix_cache_reload(void);
451+bool aix_cache_reload(struct pcap_cache **_pcache);
452
453 /* The following definitions come from printing/print_cups.c */
454
455@@ -60,13 +60,13 @@ bool cups_cache_reload(struct tevent_context *ev,
456
457 /* The following definitions come from printing/print_iprint.c */
458
459-bool iprint_cache_reload(void);
460+bool iprint_cache_reload(struct pcap_cache **_pcache);
461
462 /* The following definitions come from printing/print_svid.c */
463
464-bool sysv_cache_reload(void);
465+bool sysv_cache_reload(struct pcap_cache **_pcache);
466
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);
470
471 #endif /* _PRINTING_PCAP_H_ */
472diff --git a/source3/printing/print_aix.c b/source3/printing/print_aix.c
473index 23d9a86..927a71b 100644
474--- a/source3/printing/print_aix.c
475+++ b/source3/printing/print_aix.c
476@@ -29,12 +29,13 @@
477 #include "printing/pcap.h"
478
479 #ifdef AIX
480-bool aix_cache_reload(void)
481+bool aix_cache_reload(struct pcap_cache **_pcache)
482 {
483 int iEtat;
484 XFILE *pfile;
485 char *line = NULL, *p;
486 char *name = NULL;
487+ struct pcap_cache *pcache = NULL;
488 TALLOC_CTX *ctx = talloc_init("aix_cache_reload");
489
490 if (!ctx) {
491@@ -52,6 +53,8 @@ bool aix_cache_reload(void)
492 iEtat = 0;
493 /* scan qconfig file for searching <printername>: */
494 for (;(line = fgets_slash(NULL, 1024, pfile)); free(line)) {
495+ bool ok;
496+
497 if (*line == '*' || *line == 0)
498 continue;
499
500@@ -67,6 +70,7 @@ bool aix_cache_reload(void)
501 if (strcmp(p, "bsh") != 0) {
502 name = talloc_strdup(ctx, p);
503 if (!name) {
504+ pcap_cache_destroy_specific(&pcache);
505 SAFE_FREE(line);
506 x_fclose(pfile);
507 TALLOC_FREE(ctx);
508@@ -86,7 +90,10 @@ bool aix_cache_reload(void)
509 /* name is found without stanza device */
510 /* probably a good printer ??? */
511 iEtat = 0;
512- if (!pcap_cache_add(name, NULL, NULL)) {
513+ ok = pcap_cache_add_specific(&pcache,
514+ name, NULL, NULL);
515+ if (!ok) {
516+ pcap_cache_destroy_specific(&pcache);
517 SAFE_FREE(line);
518 x_fclose(pfile);
519 TALLOC_FREE(ctx);
520@@ -101,7 +108,10 @@ bool aix_cache_reload(void)
521 } else if (strstr_m(line, "device")) {
522 /* it's a good virtual printer */
523 iEtat = 0;
524- if (!pcap_cache_add(name, NULL, NULL)) {
525+ ok = pcap_cache_add_specific(&pcache,
526+ name, NULL, NULL);
527+ if (!ok) {
528+ pcap_cache_destroy_specific(&pcache);
529 SAFE_FREE(line);
530 x_fclose(pfile);
531 TALLOC_FREE(ctx);
532@@ -113,6 +123,7 @@ bool aix_cache_reload(void)
533 }
534 }
535
536+ *_pcache = pcache;
537 x_fclose(pfile);
538 TALLOC_FREE(ctx);
539 return true;
540diff --git a/source3/printing/print_iprint.c b/source3/printing/print_iprint.c
541index 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)
545
546 static int iprint_cache_add_printer(http_t *http,
547 int reqId,
548- char* url)
549+ char *url,
550+ struct pcap_cache **pcache)
551 {
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,
555 */
556
557 if (name != NULL && !secure && smb_enabled)
558- pcap_cache_add(name, info, NULL);
559+ pcap_cache_add_specific(pcache, name, info, NULL);
560 }
561
562 out:
563@@ -349,7 +350,7 @@ static int iprint_cache_add_printer(http_t *http,
564 return(0);
565 }
566
567-bool iprint_cache_reload(void)
568+bool iprint_cache_reload(struct pcap_cache **_pcache)
569 {
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 */
575 int i;
576- bool ret = False;
577+ bool ret = false;
578+ struct pcap_cache *pcache = NULL;
579
580 DEBUG(5, ("reloading iprint printcap cache\n"));
581
582@@ -439,14 +441,16 @@ bool iprint_cache_reload(void)
583 char *url = ippGetString(attr, i, NULL);
584 if (!url || !strlen(url))
585 continue;
586- iprint_cache_add_printer(http, i+2, url);
587+ iprint_cache_add_printer(http, i+2, url,
588+ &pcache);
589 }
590 }
591 attr = ippNextAttribute(response);
592 }
593 }
594
595- ret = True;
596+ ret = true;
597+ *_pcache = pcache;
598
599 out:
600 if (response)
601diff --git a/source3/printing/print_standard.c b/source3/printing/print_standard.c
602index c4f9c5b..b5f1056 100644
603--- a/source3/printing/print_standard.c
604+++ b/source3/printing/print_standard.c
605@@ -59,10 +59,11 @@
606 #include "printing/pcap.h"
607
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)
611 {
612 XFILE *pcap_file;
613 char *pcap_line;
614+ struct pcap_cache *pcache = NULL;
615
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)
619 }
620 }
621
622- if (*name && !pcap_cache_add(name, comment, NULL)) {
623+ if ((*name != '\0')
624+ && !pcap_cache_add_specific(&pcache, name, comment, NULL)) {
625 x_fclose(pcap_file);
626+ pcap_cache_destroy_specific(&pcache);
627 return false;
628 }
629 }
630
631 x_fclose(pcap_file);
632+ *_pcache = pcache;
633 return true;
634 }
635diff --git a/source3/printing/print_svid.c b/source3/printing/print_svid.c
636index 2226493..879661b 100644
637--- a/source3/printing/print_svid.c
638+++ b/source3/printing/print_svid.c
639@@ -35,10 +35,11 @@
640 #include "printing/pcap.h"
641
642 #if defined(SYSV) || defined(HPUX)
643-bool sysv_cache_reload(void)
644+bool sysv_cache_reload(struct pcap_cache **_pcache)
645 {
646 char **lines;
647 int i;
648+ struct pcap_cache *pcache = NULL;
649
650 #if defined(HPUX)
651 DEBUG(5, ("reloading hpux printcap cache\n"));
652@@ -111,14 +112,16 @@ bool sysv_cache_reload(void)
653 *tmp = '\0';
654
655 /* add it to the cache */
656- if (!pcap_cache_add(name, NULL, NULL)) {
657+ if (!pcap_cache_add_specific(&pcache, name, NULL, NULL)) {
658 TALLOC_FREE(lines);
659- return False;
660+ pcap_cache_destroy_specific(&pcache);
661+ return false;
662 }
663 }
664
665 TALLOC_FREE(lines);
666- return True;
667+ *_pcache = pcache;
668+ return true;
669 }
670
671 #else
672--
6732.1.0
674
675
676From 91c0b6477fcd4ad20d1cda45f78f160cee8e58ff Mon Sep 17 00:00:00 2001
677From: David Disseldorp <ddiss@samba.org>
678Date: Fri, 25 Jul 2014 12:18:54 +0200
679Subject: [PATCH 4/7] PATCHSET18: printing: remove pcap_cache_add()
680
681All print list updates are now done via pcap_cache_replace(), which can
682call into the print_list code directly.
683
684Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
685
686Signed-off-by: David Disseldorp <ddiss@samba.org>
687---
688 source3/printing/pcap.c | 16 ++++++----------
689 source3/printing/pcap.h | 1 -
690 2 files changed, 6 insertions(+), 11 deletions(-)
691
692diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
693index 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)
697 *pp_cache = NULL;
698 }
699
700-static bool pcap_cache_add(const char *name, const char *comment, const char *location)
701-{
702- NTSTATUS status;
703- time_t t = time_mono(NULL);
704-
705- status = printer_list_set_printer(talloc_tos(), name, comment, location, t);
706- return NT_STATUS_IS_OK(status);
707-}
708-
709 bool pcap_cache_loaded(void)
710 {
711 NTSTATUS status;
712@@ -105,6 +96,7 @@ bool pcap_cache_replace(const struct pcap_cache *pcache)
713 {
714 const struct pcap_cache *p;
715 NTSTATUS status;
716+ time_t t = time_mono(NULL);
717
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)
721 }
722
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)) {
728+ return false;
729+ }
730 }
731
732 status = printer_list_clean_old();
733diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
734index d388d7d..7dccf84 100644
735--- a/source3/printing/pcap.h
736+++ b/source3/printing/pcap.h
737@@ -35,7 +35,6 @@ struct pcap_cache;
738
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 *);
745--
7462.1.0
747
748
749From 10582491e417d5ab5c77afe2337793dbacd98fa8 Mon Sep 17 00:00:00 2001
750From: David Disseldorp <ddiss@samba.org>
751Date: Wed, 23 Jul 2014 12:12:34 +0200
752Subject: [PATCH 5/7] PATCHSET18: printing: return last change time with
753 pcap_cache_loaded()
754
755Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
756
757Signed-off-by: David Disseldorp <ddiss@samba.org>
758---
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(-)
764
765diff --git a/source3/printing/load.c b/source3/printing/load.c
766index 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)
772 {
773- SMB_ASSERT(pcap_cache_loaded());
774+ SMB_ASSERT(pcap_cache_loaded(NULL));
775
776 add_auto_printers();
777
778diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
779index 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)
783 *pp_cache = NULL;
784 }
785
786-bool pcap_cache_loaded(void)
787+bool pcap_cache_loaded(time_t *_last_change)
788 {
789 NTSTATUS status;
790 time_t last;
791
792 status = printer_list_get_last_refresh(&last);
793- return NT_STATUS_IS_OK(status);
794+ if (!NT_STATUS_IS_OK(status)) {
795+ return false;
796+ }
797+ if (_last_change != NULL) {
798+ *_last_change = last;
799+ }
800+ return true;
801 }
802
803 bool pcap_cache_replace(const struct pcap_cache *pcache)
804diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h
805index 7dccf84..8fc9e9d 100644
806--- a/source3/printing/pcap.h
807+++ b/source3/printing/pcap.h
808@@ -35,7 +35,7 @@ struct pcap_cache;
809
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 *);
817diff --git a/source3/web/swat.c b/source3/web/swat.c
818index 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)
822 return 0;
823 }
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());
829 }
830@@ -1572,7 +1572,7 @@ const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
831 reopen_logs();
832 load_interfaces();
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());
838 }
839--
8402.1.0
841
842
843From 484667ff73b54b275f8629264aef27ec9628c7fd Mon Sep 17 00:00:00 2001
844From: David Disseldorp <ddiss@samba.org>
845Date: Wed, 23 Jul 2014 14:42:00 +0200
846Subject: [PATCH 6/7] PATCHSET18: smbd: only reprocess printer_list.tdb if it
847 changed
848
849The per-client smbd printer share inventory is currently updated from
850printer_list.tdb when a client enumerates printers, via EnumPrinters or
851NetShareEnum.
852printer_list.tdb is populated by the background print process, based on
853the latest printcap values retrieved from the printing backend (e.g.
854CUPS) at regular intervals.
855This change ensures that per-client smbd processes don't reparse
856printer_list.tdb if it hasn't been updated since the last enumeration.
857
858Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
859
860Suggested-by: Volker Lendecke <vl@samba.org>
861Signed-off-by: David Disseldorp <ddiss@samba.org>
862---
863 source3/smbd/server_reload.c | 21 +++++++++++++++++++++
864 1 file changed, 21 insertions(+)
865
866diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c
867index c4c5a8d..57f7972 100644
868--- a/source3/smbd/server_reload.c
869+++ b/source3/smbd/server_reload.c
870@@ -30,6 +30,13 @@
871 #include "auth.h"
872 #include "messages.h"
873
874+/*
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.
878+ */
879+static time_t reload_last_pcap_time = 0;
880+
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,
885 int pnum;
886 int snum;
887 const char *pname;
888+ bool ok;
889+ time_t pcap_last_update;
890+
891+ ok = pcap_cache_loaded(&pcap_last_update);
892+ if (!ok) {
893+ DEBUG(1, ("pcap cache not loaded\n"));
894+ return;
895+ }
896+
897+ if (reload_last_pcap_time == pcap_last_update) {
898+ DEBUG(5, ("skipping printer reload, already up to date.\n"));
899+ return;
900+ }
901+ reload_last_pcap_time = pcap_last_update;
902
903 n_services = lp_numservices();
904 pnum = lp_servicenumber(PRINTERS_NAME);
905--
9062.1.0
907
908
909From 08848f939b735b5a68066ebcc995247d77f5fa2d Mon Sep 17 00:00:00 2001
910From: David Disseldorp <ddiss@samba.org>
911Date: Wed, 6 Aug 2014 14:33:02 +0200
912Subject: [PATCH 7/7] PATCHSET18: printing: reload printer shares on
913 OpenPrinter
914
915The printer share inventory should be reloaded on open _and_
916enumeration, as there are some clients, such as cupsaddsmb, that do not
917perform an enumeration prior to access.
918
919Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
920
921Signed-off-by: David Disseldorp <ddiss@samba.org>
922---
923 source3/rpc_server/spoolss/srv_spoolss_nt.c | 12 +++++++++++-
924 1 file changed, 11 insertions(+), 1 deletion(-)
925
926diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
927index 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;
932 }
933
934+ /*
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.
939+ */
940+ become_root();
941+ reload_printers(messaging_event_context(p->msg_ctx), p->msg_ctx);
942+ unbecome_root();
943+
944 /* some sanity check because you can open a printer or a print server */
945 /* aka: \\server\printer or \\server */
946
947@@ -4323,7 +4333,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
948 struct dcerpc_binding_handle *b = NULL;
949
950 /*
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.
954 */
955 become_root();
956--
9572.1.0
958