]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/samba/samba-3.6.99-fix_printcap_cpu_utilization.patch
Merge branch 'core110'
[ipfire-2.x.git] / src / patches / samba / samba-3.6.99-fix_printcap_cpu_utilization.patch
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
5 share updates
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
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.
15
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.
20
21 This commit changes the share update code path to perform a read-only
22 traversal.
23
24 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
25
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>
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
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,
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 }
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,
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 }
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 *);
76
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 *);
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;
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);
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 --
149 2.1.0
150
151
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
156 client enum
157
158 Currently, automatic printer share updates are handled in the following
159 way:
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
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.
170
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
173 EnumPrinters.
174
175 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
176
177 Suggested-by: Volker Lendecke <vl@samba.org>
178 Signed-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
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();
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.
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,
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
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,
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();
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
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();
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 */
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 --
332 2.1.0
333
334
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
339 memory list
340
341 This will allow in future for a single atomic printer_list.tdb update.
342
343 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
344
345 Signed-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
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)
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 }
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);
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_ */
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
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;
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)
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)
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
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 }
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
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 --
673 2.1.0
674
675
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()
680
681 All print list updates are now done via pcap_cache_replace(), which can
682 call into the print_list code directly.
683
684 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
685
686 Signed-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
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)
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();
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;
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 --
746 2.1.0
747
748
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
753 pcap_cache_loaded()
754
755 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
756
757 Signed-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
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)
772 {
773 - SMB_ASSERT(pcap_cache_loaded());
774 + SMB_ASSERT(pcap_cache_loaded(NULL));
775
776 add_auto_printers();
777
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)
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)
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;
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 *);
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)
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 --
840 2.1.0
841
842
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
847 changed
848
849 The per-client smbd printer share inventory is currently updated from
850 printer_list.tdb when a client enumerates printers, via EnumPrinters or
851 NetShareEnum.
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.
857
858 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
859
860 Suggested-by: Volker Lendecke <vl@samba.org>
861 Signed-off-by: David Disseldorp <ddiss@samba.org>
862 ---
863 source3/smbd/server_reload.c | 21 +++++++++++++++++++++
864 1 file changed, 21 insertions(+)
865
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
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 --
906 2.1.0
907
908
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
913 OpenPrinter
914
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.
918
919 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652
920
921 Signed-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
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;
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 --
957 2.1.0
958