mirror of
https://github.com/samba-team/samba.git
synced 2025-02-01 05:47:28 +03:00
0b188e7784
Since commit 7022554, smbds share a printcap cache (printer_list.tdb), therefore ordering of events between smbd processes is important when updating printcap cache information. Consider the following two process example: 1) smbd1 receives HUP or printcap cache time expiry 2) smbd1 checks whether pcap needs refresh, it does 3) smbd1 marks pcap as refreshed 4) smbd1 forks child1 to obtain cups printer info 5) smbd2 receives HUP or printcap cache time expiry 6) smbd2 checks whether pcap needs refresh, it does not (due to step 3) 7) smbd2 reloads printer shares prior to child1 completion (stale pcap) 8) child1 completion, pcap cache (printer_list.tdb) is updated by smbd1 9) smbd1 reloads printer shares based on new pcap information In this case both smbd1 and smbd2 are reliant on the pcap update performed on child1 completion. The prior commit "reload shares after pcap cache fill" ensures that smbd1 only reloads printer shares following pcap update, however smbd2 continues to present shares based on stale pcap data. This commit addresses the above problem by driving pcap cache and printer share updates from the parent smbd process. 1) smbd0 (parent) receives a HUP or printcap cache time expiry 2) smbd0 forks child0 to obtain cups printer info 3) child0 completion, pcap cache (printer_list.tdb) is updated by smbd0 4) smbd0 reloads printer shares 5) smbd0 notifies child smbds of pcap update via message_send_all() 6) child smbds read fresh pcap data and reload printer shares This architecture has the additional advantage that only a single process (the parent smbd) requests printer information from the printcap backend. Use time_mono in housekeeping functions As suggested by Björn Jacke.
147 lines
4.1 KiB
C
147 lines
4.1 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
Main SMB server routines
|
|
Copyright (C) Andrew Tridgell 1992-1998
|
|
Copyright (C) Martin Pool 2002
|
|
Copyright (C) Jelmer Vernooij 2002-2003
|
|
Copyright (C) Volker Lendecke 1993-2007
|
|
Copyright (C) Jeremy Allison 1993-2007
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "smbd/globals.h"
|
|
#include "librpc/gen_ndr/messaging.h"
|
|
#include "nt_printing.h"
|
|
#include "printing/pcap.h"
|
|
|
|
/****************************************************************************
|
|
purge stale printers and reload from pre-populated pcap cache
|
|
**************************************************************************/
|
|
void reload_printers(struct tevent_context *ev,
|
|
struct messaging_context *msg_ctx)
|
|
{
|
|
struct auth_serversupplied_info *server_info = NULL;
|
|
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
|
|
int snum;
|
|
int n_services = lp_numservices();
|
|
int pnum = lp_servicenumber(PRINTERS_NAME);
|
|
const char *pname;
|
|
NTSTATUS status;
|
|
bool skip = false;
|
|
|
|
SMB_ASSERT(pcap_cache_loaded());
|
|
DEBUG(10, ("reloading printer services from pcap cache\n"));
|
|
|
|
status = make_server_info_system(talloc_tos(), &server_info);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
DEBUG(3, ("reload_printers: "
|
|
"Could not create system server_info\n"));
|
|
/* can't remove stale printers before we
|
|
* are fully initilized */
|
|
skip = true;
|
|
}
|
|
|
|
/* remove stale printers */
|
|
for (snum = 0; skip == false && snum < n_services; snum++) {
|
|
/* avoid removing PRINTERS_NAME or non-autoloaded printers */
|
|
if (snum == pnum || !(lp_snum_ok(snum) && lp_print_ok(snum) &&
|
|
lp_autoloaded(snum)))
|
|
continue;
|
|
|
|
pname = lp_printername(snum);
|
|
if (!pcap_printername_ok(pname)) {
|
|
DEBUG(3, ("removing stale printer %s\n", pname));
|
|
|
|
if (is_printer_published(server_info, server_info,
|
|
msg_ctx,
|
|
NULL, lp_servicename(snum),
|
|
NULL, &pinfo2)) {
|
|
nt_printer_publish(server_info,
|
|
server_info,
|
|
msg_ctx,
|
|
pinfo2,
|
|
DSPRINT_UNPUBLISH);
|
|
TALLOC_FREE(pinfo2);
|
|
}
|
|
nt_printer_remove(server_info, server_info, msg_ctx,
|
|
pname);
|
|
lp_killservice(snum);
|
|
}
|
|
}
|
|
|
|
load_printers(ev, msg_ctx);
|
|
|
|
TALLOC_FREE(server_info);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Reload the services file.
|
|
**************************************************************************/
|
|
|
|
bool reload_services(struct messaging_context *msg_ctx, int smb_sock,
|
|
bool test)
|
|
{
|
|
bool ret;
|
|
|
|
if (lp_loaded()) {
|
|
char *fname = lp_configfile();
|
|
if (file_exist(fname) &&
|
|
!strcsequal(fname, get_dyn_CONFIGFILE())) {
|
|
set_dyn_CONFIGFILE(fname);
|
|
test = False;
|
|
}
|
|
}
|
|
|
|
reopen_logs();
|
|
|
|
if (test && !lp_file_list_changed())
|
|
return(True);
|
|
|
|
lp_killunused(conn_snum_used);
|
|
|
|
ret = lp_load(get_dyn_CONFIGFILE(), False, False, True, True);
|
|
|
|
/* perhaps the config filename is now set */
|
|
if (!test)
|
|
reload_services(msg_ctx, smb_sock, True);
|
|
|
|
reopen_logs();
|
|
|
|
load_interfaces();
|
|
|
|
if (smb_sock != -1) {
|
|
set_socket_options(smb_sock,"SO_KEEPALIVE");
|
|
set_socket_options(smb_sock, lp_socket_options());
|
|
}
|
|
|
|
mangle_reset_cache();
|
|
reset_stat_cache();
|
|
|
|
/* this forces service parameters to be flushed */
|
|
set_current_service(NULL,0,True);
|
|
|
|
return(ret);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Notify smbds of new printcap data
|
|
**************************************************************************/
|
|
void reload_pcap_change_notify(struct tevent_context *ev,
|
|
struct messaging_context *msg_ctx)
|
|
{
|
|
message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL);
|
|
}
|