1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

source4/smbd: refactor the process model for prefork

Refactor the process model code to allow the addition of a prefork
    process model.

    - Add a process context to contain process model specific state
    - Add a service details structure to allow service to indicate which
      process model options they can support.

    In the new code the services advertise the features they support to the
    process model.  The process model context is plumbed through to allow the
    process model to keep track of the supported options, and any state
    the process model may require.

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
This commit is contained in:
Gary Lockyer 2017-09-15 07:09:23 +12:00 committed by Andrew Bartlett
parent 6d7a8d80cd
commit b852ad044b
35 changed files with 322 additions and 105 deletions

View File

@ -97,5 +97,9 @@ NTSTATUS server_service_s3fs_init(TALLOC_CTX *);
NTSTATUS server_service_s3fs_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "s3fs", s3fs_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "s3fs", s3fs_task_init, &details);
}

View File

@ -243,5 +243,10 @@ static void cldapd_task_init(struct task_server *task)
*/
NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "cldap", cldapd_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "cldap", cldapd_task_init,
&details);
}

View File

@ -642,7 +642,8 @@ static NTSTATUS dns_add_socket(struct dns_server *dns,
&dns_tcp_stream_ops,
"ip", address, &port,
lpcfg_socket_options(dns->task->lp_ctx),
dns_socket);
dns_socket,
dns->task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
address, port, nt_errstr(status)));
@ -929,5 +930,9 @@ static void dns_task_init(struct task_server *task)
NTSTATUS server_service_dns_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "dns", dns_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
};
return register_server_service(ctx, "dns", dns_task_init, &details);
}

View File

@ -707,5 +707,10 @@ static void dnsupdate_task_init(struct task_server *task)
*/
NTSTATUS server_service_dnsupdate_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "dnsupdate", dnsupdate_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
};
return register_server_service(ctx, "dnsupdate", dnsupdate_task_init,
&details);
}

View File

@ -347,5 +347,9 @@ static void kccsrv_task_init(struct task_server *task)
*/
NTSTATUS server_service_kcc_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "kcc", kccsrv_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "kcc", kccsrv_task_init, &details);
}

View File

@ -528,5 +528,10 @@ static void dreplsrv_task_init(struct task_server *task)
*/
NTSTATUS server_service_drepl_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "drepl", dreplsrv_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
};
return register_server_service(ctx, "drepl", dreplsrv_task_init,
&details);
}

View File

@ -343,5 +343,9 @@ static void echo_task_init(struct task_server *task)
*/
NTSTATUS server_service_echo_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "echo", echo_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "echo", echo_task_init, &details);
}

View File

@ -468,5 +468,20 @@ static void kdc_task_init(struct task_server *task)
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_kdc_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "kdc", kdc_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
/*
* Need to prevent pre-forking on kdc.
* The task_init function is run on the master process only
* and the irpc process name is registered in it's event loop.
* The child worker processes initialise their event loops on
* fork, so are not listening for the irpc event.
*
* The master process does not wait on that event context
* the master process is responsible for managing the worker
* processes not performing work.
*/
.inhibit_pre_fork = true
};
return register_server_service(ctx, "kdc", kdc_task_init, &details);
}

View File

@ -578,7 +578,8 @@ NTSTATUS kdc_add_socket(struct kdc_server *kdc,
&kdc_tcp_stream_ops,
"ip", address, &port,
lpcfg_socket_options(kdc->task->lp_ctx),
kdc_socket);
kdc_socket,
kdc->task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
address, port, nt_errstr(status)));

View File

@ -358,5 +358,21 @@ NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
{
return register_server_service(mem_ctx, "kdc", mitkdc_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
/*
* Need to prevent pre-forking on kdc.
* The task_init function is run on the master process only
* and the irpc process name is registered in it's event loop.
* The child worker processes initialise their event loops on
* fork, so are not listening for the irpc event.
*
* The master process does not wait on that event context
* the master process is responsible for managing the worker
* processes not performing work.
*/
.inhibit_pre_fork = true
};
return register_server_service(mem_ctx, "kdc", mitkdc_task_init,
&details);
}

View File

@ -1030,7 +1030,7 @@ static NTSTATUS add_socket(struct task_server *task,
model_ops, &ldap_stream_nonpriv_ops,
"ip", address, &port,
lpcfg_socket_options(lp_ctx),
ldap_service);
ldap_service, task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
@ -1045,7 +1045,8 @@ static NTSTATUS add_socket(struct task_server *task,
&ldap_stream_nonpriv_ops,
"ip", address, &port,
lpcfg_socket_options(lp_ctx),
ldap_service);
ldap_service,
task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
@ -1067,7 +1068,8 @@ static NTSTATUS add_socket(struct task_server *task,
&ldap_stream_nonpriv_ops,
"ip", address, &port,
lpcfg_socket_options(lp_ctx),
ldap_service);
ldap_service,
task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
@ -1081,7 +1083,8 @@ static NTSTATUS add_socket(struct task_server *task,
&ldap_stream_nonpriv_ops,
"ip", address, &port,
lpcfg_socket_options(lp_ctx),
ldap_service);
ldap_service,
task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
@ -1210,7 +1213,7 @@ static void ldapsrv_task_init(struct task_server *task)
model_ops, &ldap_stream_nonpriv_ops,
"unix", ldapi_path, NULL,
lpcfg_socket_options(task->lp_ctx),
ldap_service);
ldap_service, task->process_context);
talloc_free(ldapi_path);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s - %s\n",
@ -1241,7 +1244,8 @@ static void ldapsrv_task_init(struct task_server *task)
model_ops, &ldap_stream_priv_ops,
"unix", ldapi_path, NULL,
lpcfg_socket_options(task->lp_ctx),
ldap_service);
ldap_service,
task->process_context);
talloc_free(ldapi_path);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s - %s\n",
@ -1261,5 +1265,10 @@ failed:
NTSTATUS server_service_ldap_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "ldap", ldapsrv_task_init);
struct service_details details = {
.inhibit_fork_on_accept = false,
.inhibit_pre_fork = false
};
return register_server_service(ctx, "ldap", ldapsrv_task_init,
&details);
}

View File

@ -100,5 +100,9 @@ static void nbtd_task_init(struct task_server *task)
*/
NTSTATUS server_service_nbtd_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "nbt", nbtd_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "nbt", nbtd_task_init, &details);
}

View File

@ -541,7 +541,8 @@ static void ntp_signd_task_init(struct task_server *task)
&ntp_signd_stream_ops,
"unix", address, NULL,
lpcfg_socket_options(ntp_signd->task->lp_ctx),
ntp_signd);
ntp_signd,
ntp_signd->task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s - %s\n",
address, nt_errstr(status)));
@ -554,5 +555,10 @@ static void ntp_signd_task_init(struct task_server *task)
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_ntp_signd_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "ntp_signd", ntp_signd_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "ntp_signd", ntp_signd_task_init,
&details);
}

View File

@ -2870,7 +2870,9 @@ static const struct stream_server_ops dcesrv_stream_ops = {
static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx, const struct model_ops *model_ops)
struct tevent_context *event_ctx,
const struct model_ops *model_ops,
void *process_context)
{
struct dcesrv_socket_context *dcesrv_sock;
uint16_t port = 1;
@ -2890,7 +2892,7 @@ static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
model_ops, &dcesrv_stream_ops,
"unix", endpoint, &port,
lpcfg_socket_options(lp_ctx),
dcesrv_sock);
dcesrv_sock, process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
endpoint, nt_errstr(status)));
@ -2902,7 +2904,9 @@ static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx, const struct model_ops *model_ops)
struct tevent_context *event_ctx,
const struct model_ops *model_ops,
void *process_context)
{
struct dcesrv_socket_context *dcesrv_sock;
uint16_t port = 1;
@ -2944,7 +2948,7 @@ static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
model_ops, &dcesrv_stream_ops,
"unix", full_path, &port,
lpcfg_socket_options(lp_ctx),
dcesrv_sock);
dcesrv_sock, process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
endpoint, full_path, nt_errstr(status)));
@ -2955,7 +2959,9 @@ static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx, const struct model_ops *model_ops)
struct tevent_context *event_ctx,
const struct model_ops *model_ops,
void *process_context)
{
struct dcesrv_socket_context *dcesrv_sock;
NTSTATUS status;
@ -2977,7 +2983,7 @@ static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
model_ops, &dcesrv_stream_ops,
endpoint,
dcesrv_sock);
dcesrv_sock, process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
endpoint, nt_errstr(status)));
@ -2990,9 +2996,12 @@ static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
/*
add a socket address to the list of events, one event per dcerpc endpoint
*/
static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
struct tevent_context *event_ctx, const struct model_ops *model_ops,
const char *address)
static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx,
const struct model_ops *model_ops,
const char *address,
void *process_context)
{
struct dcesrv_socket_context *dcesrv_sock;
uint16_t port = 0;
@ -3016,7 +3025,7 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct
model_ops, &dcesrv_stream_ops,
"ip", address, &port,
lpcfg_socket_options(dce_ctx->lp_ctx),
dcesrv_sock);
dcesrv_sock, process_context);
if (!NT_STATUS_IS_OK(status)) {
struct dcesrv_if_list *iface;
DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
@ -3055,7 +3064,9 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct
static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx, const struct model_ops *model_ops)
struct tevent_context *event_ctx,
const struct model_ops *model_ops,
void *process_context)
{
NTSTATUS status;
@ -3070,7 +3081,9 @@ static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
num_interfaces = iface_list_count(ifaces);
for(i = 0; i < num_interfaces; i++) {
const char *address = iface_list_n_ip(ifaces, i);
status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
model_ops, address,
process_context);
NT_STATUS_NOT_OK_RETURN(status);
}
} else {
@ -3080,7 +3093,9 @@ static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
wcard = iface_list_wildcard(dce_ctx);
NT_STATUS_HAVE_NO_MEMORY(wcard);
for (i=0; wcard[i]; i++) {
status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
model_ops, wcard[i],
process_context);
if (NT_STATUS_IS_OK(status)) {
num_binds++;
}
@ -3098,23 +3113,28 @@ NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx,
const struct model_ops *model_ops)
const struct model_ops *model_ops,
void *process_context)
{
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport(e->ep_description);
switch (transport) {
case NCACN_UNIX_STREAM:
return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
model_ops, process_context);
case NCALRPC:
return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
model_ops, process_context);
case NCACN_IP_TCP:
return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
model_ops, process_context);
case NCACN_NP:
return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
model_ops, process_context);
default:
return NT_STATUS_NOT_SUPPORTED;

View File

@ -467,7 +467,8 @@ NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
struct loadparm_context *lp_ctx,
struct dcesrv_endpoint *e,
struct tevent_context *event_ctx,
const struct model_ops *model_ops);
const struct model_ops *model_ops,
void *process_context);
/**
* retrieve credentials from a dce_call

View File

@ -116,7 +116,7 @@ static void dcesrv_task_init(struct task_server *task)
}
status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx,
this_model_ops);
this_model_ops, task->process_context);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
@ -142,5 +142,16 @@ failed:
NTSTATUS server_service_rpc_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "rpc", dcesrv_task_init);
struct service_details details = {
/*
* This is a SNOWFLAKE, but sadly one that we
* will have to keep for now. The RPC server
* code above overstamps the SINGLE process model
* most of the time, but we need to be in forking
* mode by defult to get a forking NETLOGON server
*/
.inhibit_fork_on_accept = false,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "rpc", dcesrv_task_init, &details);
}

View File

@ -60,7 +60,11 @@ static void smbsrv_task_init(struct task_server *task)
*/
for(i = 0; i < num_interfaces; i++) {
const char *address = iface_list_n_ip(ifaces, i);
status = smbsrv_add_socket(task, task->event_ctx, task->lp_ctx, task->model_ops, address);
status = smbsrv_add_socket(task, task->event_ctx,
task->lp_ctx,
task->model_ops,
address,
task->process_context);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
} else {
@ -72,7 +76,11 @@ static void smbsrv_task_init(struct task_server *task)
goto failed;
}
for (i=0; wcard[i]; i++) {
status = smbsrv_add_socket(task, task->event_ctx, task->lp_ctx, task->model_ops, wcard[i]);
status = smbsrv_add_socket(task, task->event_ctx,
task->lp_ctx,
task->model_ops,
wcard[i],
task->process_context);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
talloc_free(wcard);
@ -87,7 +95,11 @@ failed:
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_smb_init(TALLOC_CTX *ctx)
{
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
ntvfs_init(cmdline_lp_ctx);
share_init();
return register_server_service(ctx, "smb", smbsrv_task_init);
return register_server_service(ctx, "smb", smbsrv_task_init, &details);
}

View File

@ -179,7 +179,8 @@ _PUBLIC_ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx,
struct tevent_context *event_context,
struct loadparm_context *lp_ctx,
const struct model_ops *model_ops,
const char *address)
const char *address,
void *process_context)
{
const char **ports = lpcfg_smb_ports(lp_ctx);
int i;
@ -192,7 +193,7 @@ _PUBLIC_ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx,
model_ops, &smb_stream_ops,
"ip", address, &port,
lpcfg_socket_options(lp_ctx),
NULL);
NULL, process_context);
NT_STATUS_NOT_OK_RETURN(status);
}

View File

@ -397,7 +397,8 @@ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx,
struct tevent_context *event_context,
struct loadparm_context *lp_ctx,
const struct model_ops *model_ops,
const char *address);
const char *address,
void *process_context);
struct loadparm_context;

View File

@ -51,8 +51,8 @@ struct model_ops {
void (*)(struct tevent_context *,
struct loadparm_context *,
struct socket_context *,
struct server_id , void *),
void *);
struct server_id , void *, void *),
void *, void *);
/* function to create a task */
void (*new_task)(struct tevent_context *,
@ -60,13 +60,16 @@ struct model_ops {
const char *service_name,
void (*)(struct tevent_context *,
struct loadparm_context *, struct server_id,
void *),
void *, void *),
void *,
int);
const struct service_details*,
const int);
/* function to terminate a connection or task */
void (*terminate)(struct tevent_context *, struct loadparm_context *lp_ctx,
const char *reason);
void (*terminate)(struct tevent_context *,
struct loadparm_context *lp_ctx,
const char *reason,
void * process_context);
/* function to set a title for the connection or task */
void (*set_title)(struct tevent_context *, const char *title);

View File

@ -44,8 +44,10 @@ static void single_accept_connection(struct tevent_context *ev,
void (*new_conn)(struct tevent_context *,
struct loadparm_context *,
struct socket_context *,
struct server_id , void *),
void *private_data)
struct server_id, void *,
void *),
void *private_data,
void *process_context)
{
NTSTATUS status;
struct socket_context *connected_socket;
@ -79,7 +81,8 @@ static void single_accept_connection(struct tevent_context *ev,
* combination of pid/fd should be unique system-wide
*/
new_conn(ev, lp_ctx, connected_socket,
cluster_id(pid, socket_get_fd(connected_socket)), private_data);
cluster_id(pid, socket_get_fd(connected_socket)), private_data,
process_context);
}
/*
@ -88,8 +91,11 @@ static void single_accept_connection(struct tevent_context *ev,
static void single_new_task(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *service_name,
void (*new_task)(struct tevent_context *, struct loadparm_context *, struct server_id, void *),
void (*new_task)(struct tevent_context *,
struct loadparm_context *,
struct server_id, void *, void *),
void *private_data,
const struct service_details *service_details,
int from_parent_fd)
{
pid_t pid = getpid();
@ -105,12 +111,15 @@ static void single_new_task(struct tevent_context *ev,
* Using the pid unaltered makes debugging of which process
* owns the messaging socket easier.
*/
new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data);
new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data, NULL);
}
/* called when a task goes down */
static void single_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx, const char *reason)
static void single_terminate(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *reason,
void *process_context)
{
DEBUG(3,("single_terminate: reason[%s]\n",reason));
}

View File

@ -222,13 +222,18 @@ static struct standard_child_state *setup_standard_child_pipe(struct tevent_cont
/*
called when a listening socket becomes readable.
*/
static void standard_accept_connection(struct tevent_context *ev,
static void standard_accept_connection(
struct tevent_context *ev,
struct loadparm_context *lp_ctx,
struct socket_context *sock,
void (*new_conn)(struct tevent_context *,
struct loadparm_context *, struct socket_context *,
struct server_id , void *),
void *private_data)
struct loadparm_context *,
struct socket_context *,
struct server_id,
void *,
void *),
void *private_data,
void *process_context)
{
NTSTATUS status;
struct socket_context *sock2;
@ -340,7 +345,8 @@ static void standard_accept_connection(struct tevent_context *ev,
talloc_free(s);
/* setup this new connection. Cluster ID is PID based for this process model */
new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);
new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data,
NULL);
/* we can't return to the top level here, as that event context is gone,
so we now process events in the new event context until there are no
@ -357,8 +363,9 @@ static void standard_accept_connection(struct tevent_context *ev,
static void standard_new_task(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *service_name,
void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *),
void *private_data,
const struct service_details *service_details,
int new_from_parent_fd)
{
pid_t pid;
@ -438,7 +445,7 @@ static void standard_new_task(struct tevent_context *ev,
setproctitle("task %s server_id[%d]", service_name, (int)pid);
/* setup this new task. Cluster ID is PID based for this process model */
new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);
new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, NULL);
/* we can't return to the top level here, as that event context is gone,
so we now process events in the new event context until there are no
@ -452,7 +459,8 @@ static void standard_new_task(struct tevent_context *ev,
/* called when a task goes down */
_NORETURN_ static void standard_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx,
const char *reason)
const char *reason,
void *process_context)
{
DEBUG(2,("standard_terminate: reason[%s]\n",reason));

View File

@ -30,6 +30,7 @@
static struct registered_server {
struct registered_server *next, *prev;
const char *service_name;
struct service_details *service_details;
void (*task_init)(struct task_server *);
} *registered_servers;
@ -38,13 +39,17 @@ static struct registered_server {
*/
NTSTATUS register_server_service(TALLOC_CTX *ctx,
const char *name,
void (*task_init)(struct task_server *))
void (*task_init) (struct task_server *),
struct service_details *details)
{
struct registered_server *srv;
srv = talloc(ctx, struct registered_server);
NT_STATUS_HAVE_NO_MEMORY(srv);
srv->service_name = name;
srv->task_init = task_init;
srv->service_details =
talloc_memdup(ctx, details, sizeof(struct service_details));
NT_STATUS_HAVE_NO_MEMORY(srv->service_details);
DLIST_ADD_END(registered_servers, srv);
return NT_STATUS_OK;
}
@ -64,7 +69,9 @@ static NTSTATUS server_service_init(const char *name,
if (strcasecmp(name, srv->service_name) == 0) {
return task_server_startup(event_context, lp_ctx,
srv->service_name,
model_ops, srv->task_init,
model_ops,
srv->task_init,
srv->service_details,
from_parent_fd);
}
}

View File

@ -23,8 +23,26 @@
#ifndef __SERVICE_H__
#define __SERVICE_H__
#include "smbd/service_stream.h"
#include "smbd/service_task.h"
struct service_details {
/*
* Prevent the standard process model from forking a new worker
* process when accepting a new connection. Do this when the service
* relies on shared state, or the over-head of forking would be a
* significant part of the response time
*/
bool inhibit_fork_on_accept;
/*
* Prevent the pre-fork process model from pre-forking any worker
* processes. In this mode pre-fork is equivalent to standard with
* inhibit_fork_on_accept set.
*/
bool inhibit_pre_fork;
};
#include "smbd/service_proto.h"
#endif /* __SERVICE_H__ */

View File

@ -188,7 +188,8 @@ NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
const struct model_ops *model_ops,
const struct stream_server_ops *stream_ops,
const char *pipe_name,
void *private_data)
void *private_data,
void *process_context)
{
char *dirname;
struct named_pipe_socket *pipe_sock;
@ -248,7 +249,8 @@ NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
pipe_sock->pipe_path,
NULL,
NULL,
pipe_sock);
pipe_sock,
process_context);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}

View File

@ -44,6 +44,7 @@ struct stream_socket {
const struct model_ops *model_ops;
struct socket_context *sock;
void *private_data;
void *process_context;
};
@ -55,6 +56,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char
struct tevent_context *event_ctx = srv_conn->event.ctx;
const struct model_ops *model_ops = srv_conn->model_ops;
struct loadparm_context *lp_ctx = srv_conn->lp_ctx;
void *process_context = srv_conn->process_context;
TALLOC_CTX *frame = NULL;
if (!reason) reason = "unknown reason";
@ -89,8 +91,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char
srv_conn->event.fde = NULL;
imessaging_cleanup(srv_conn->msg_ctx);
TALLOC_FREE(srv_conn);
model_ops->terminate(event_ctx, lp_ctx, reason);
model_ops->terminate(event_ctx, lp_ctx, reason, process_context);
TALLOC_FREE(frame);
}
@ -138,7 +139,8 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev,
const struct stream_server_ops *stream_ops,
struct imessaging_context *msg_ctx,
void *private_data,
struct stream_connection **_srv_conn)
struct stream_connection **_srv_conn,
void *process_context)
{
struct stream_connection *srv_conn;
@ -154,6 +156,7 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev,
srv_conn->event.ctx = ev;
srv_conn->lp_ctx = lp_ctx;
srv_conn->event.fde = NULL;
srv_conn->process_context = process_context;
*_srv_conn = srv_conn;
return NT_STATUS_OK;
@ -166,7 +169,9 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev,
static void stream_new_connection(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
struct socket_context *sock,
struct server_id server_id, void *private_data)
struct server_id server_id,
void *private_data,
void *process_context)
{
struct stream_socket *stream_socket = talloc_get_type(private_data, struct stream_socket);
struct stream_connection *srv_conn;
@ -186,6 +191,7 @@ static void stream_new_connection(struct tevent_context *ev,
srv_conn->ops = stream_socket->ops;
srv_conn->event.ctx = ev;
srv_conn->lp_ctx = lp_ctx;
srv_conn->process_context = process_context;
if (!socket_check_access(sock, "smbd", lpcfg_hosts_allow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hosts_deny(NULL, lpcfg_default_service(lp_ctx)))) {
stream_terminate_connection(srv_conn, "denied by access rules");
@ -259,7 +265,8 @@ static void stream_accept_handler(struct tevent_context *ev, struct tevent_fd *f
with the newly created socket */
stream_socket->model_ops->accept_connection(ev, stream_socket->lp_ctx,
stream_socket->sock,
stream_new_connection, stream_socket);
stream_new_connection, stream_socket,
stream_socket->process_context);
}
/*
@ -279,7 +286,8 @@ NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx,
const char *sock_addr,
uint16_t *port,
const char *socket_options,
void *private_data)
void *private_data,
void *process_context)
{
NTSTATUS status;
struct stream_socket *stream_socket;
@ -385,6 +393,7 @@ NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx,
stream_socket->ops = stream_ops;
stream_socket->event_ctx = event_context;
stream_socket->model_ops = model_ops;
stream_socket->process_context = process_context;
return NT_STATUS_OK;
}

View File

@ -62,6 +62,7 @@ struct stream_connection {
uint processing;
const char *terminate;
void *process_context;
};

View File

@ -50,8 +50,8 @@ void task_server_terminate(struct task_server *task, const char *reason, bool fa
imessaging_cleanup(task->msg_ctx);
model_ops->terminate(event_ctx, task->lp_ctx, reason);
model_ops->terminate(event_ctx, task->lp_ctx, reason,
task->process_context);
/* don't free this above, it might contain the 'reason' being printed */
talloc_free(task);
}
@ -69,7 +69,9 @@ struct task_state {
*/
static void task_server_callback(struct tevent_context *event_ctx,
struct loadparm_context *lp_ctx,
struct server_id server_id, void *private_data)
struct server_id server_id,
void *private_data,
void *context)
{
struct task_state *state = talloc_get_type(private_data, struct task_state);
struct task_server *task;
@ -81,6 +83,7 @@ static void task_server_callback(struct tevent_context *event_ctx,
task->model_ops = state->model_ops;
task->server_id = server_id;
task->lp_ctx = lp_ctx;
task->process_context = context;
task->msg_ctx = imessaging_init(task,
task->lp_ctx,
@ -102,6 +105,7 @@ NTSTATUS task_server_startup(struct tevent_context *event_ctx,
const char *service_name,
const struct model_ops *model_ops,
void (*task_init)(struct task_server *),
const struct service_details *service_details,
int from_parent_fd)
{
struct task_state *state;
@ -113,7 +117,7 @@ NTSTATUS task_server_startup(struct tevent_context *event_ctx,
state->model_ops = model_ops;
state->model_ops->new_task(event_ctx, lp_ctx, service_name,
task_server_callback, state,
task_server_callback, state, service_details,
from_parent_fd);
return NT_STATUS_OK;

View File

@ -31,6 +31,7 @@ struct task_server {
struct loadparm_context *lp_ctx;
struct server_id server_id;
void *private_data;
void *process_context;
};

View File

@ -474,7 +474,9 @@ static bool test_start_dcerpc_server(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, status,
"unable to initialize process models");
status = smbsrv_add_socket(tctx, event_ctx, tctx->lp_ctx, process_model_startup("single"), address);
status = smbsrv_add_socket(tctx, event_ctx, tctx->lp_ctx,
process_model_startup("single"),
address, NULL);
torture_assert_ntstatus_ok(tctx, status, "starting smb server");
status = dcesrv_init_context(tctx, tctx->lp_ctx, endpoints, &dce_ctx);
@ -483,7 +485,8 @@ static bool test_start_dcerpc_server(struct torture_context *tctx,
for (e=dce_ctx->endpoint_list;e;e=e->next) {
status = dcesrv_add_ep(dce_ctx, tctx->lp_ctx,
e, tctx->ev, process_model_startup("single"));
e, tctx->ev,
process_model_startup("single"), NULL);
torture_assert_ntstatus_ok(tctx, status,
"unable listen on dcerpc endpoint server");
}

View File

@ -330,8 +330,10 @@ static void websrv_task_init(struct task_server *task)
task->lp_ctx, model_ops,
&web_stream_ops,
"ip", address,
&port, lpcfg_socket_options(task->lp_ctx),
task);
&port,
lpcfg_socket_options(task->lp_ctx),
task,
task->process_context);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
@ -350,7 +352,8 @@ static void websrv_task_init(struct task_server *task)
&web_stream_ops,
"ip", wcard[i],
&port, lpcfg_socket_options(task->lp_ctx),
wdata);
wdata,
task->process_context);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
talloc_free(wcard);
@ -372,5 +375,9 @@ failed:
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_web_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "web", websrv_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "web", websrv_task_init, &details);
}

View File

@ -90,9 +90,16 @@ NTSTATUS server_service_winbindd_init(TALLOC_CTX *);
NTSTATUS server_service_winbindd_init(TALLOC_CTX *ctx)
{
NTSTATUS status = register_server_service(ctx, "winbindd", winbindd_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
};
NTSTATUS status = register_server_service(ctx, "winbindd",
winbindd_task_init, &details);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return register_server_service(ctx, "winbind", winbindd_task_init);
return register_server_service(ctx, "winbind", winbindd_task_init,
&details);
}

View File

@ -347,7 +347,8 @@ static const struct stream_server_ops wreplsrv_stream_ops = {
NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
uint32_t peer_assoc_ctx,
struct tstream_context **stream,
struct wreplsrv_in_connection **_wrepl_in)
struct wreplsrv_in_connection **_wrepl_in,
void* process_context)
{
struct wreplsrv_service *service = partner->service;
struct wreplsrv_in_connection *wrepl_in;
@ -379,7 +380,8 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
&wreplsrv_stream_ops,
service->task->msg_ctx,
wrepl_in,
&conn);
&conn,
process_context);
NT_STATUS_NOT_OK_RETURN(status);
/*
@ -461,7 +463,7 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadpar
&wreplsrv_stream_ops,
"ipv4", address, &port,
lpcfg_socket_options(task->lp_ctx),
service);
service, task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",
address, port, nt_errstr(status)));
@ -473,7 +475,7 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadpar
status = stream_setup_socket(task, task->event_ctx, task->lp_ctx,
model_ops, &wreplsrv_stream_ops,
"ipv4", address, &port, lpcfg_socket_options(task->lp_ctx),
service);
service, task->process_context);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",
address, port, nt_errstr(status)));

View File

@ -988,6 +988,7 @@ static NTSTATUS wreplsrv_push_notify_wait_update(struct wreplsrv_push_notify_sta
{
struct wreplsrv_in_connection *wrepl_in;
struct tstream_context *stream;
void *process_context = NULL;
NTSTATUS status;
status = wrepl_request_recv(state->subreq, state, NULL);
@ -1011,10 +1012,11 @@ static NTSTATUS wreplsrv_push_notify_wait_update(struct wreplsrv_push_notify_sta
* NOTE: stream will be stolen by
* wreplsrv_in_connection_merge()
*/
process_context = state->io->in.partner->service->task->process_context;
status = wreplsrv_in_connection_merge(state->io->in.partner,
state->wreplconn->assoc_ctx.peer_ctx,
&stream,
&wrepl_in);
&wrepl_in, process_context);
NT_STATUS_NOT_OK_RETURN(status);
/* now we can free the wreplsrv_out_connection */

View File

@ -508,5 +508,10 @@ static void wreplsrv_task_init(struct task_server *task)
*/
NTSTATUS server_service_wrepl_init(TALLOC_CTX *ctx)
{
return register_server_service(ctx, "wrepl", wreplsrv_task_init);
struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true
};
return register_server_service(ctx, "wrepl", wreplsrv_task_init,
&details);
}