diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-01-30 02:55:30 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:23 -0500 |
commit | 1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e (patch) | |
tree | fea0e3bc04a63cb7d3eb0dfad86e0589b12a235d /source4/smbd | |
parent | 597142ddd3575a50a491a89dd5ce5fb40945028f (diff) | |
download | samba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.tar.gz samba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.tar.bz2 samba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.zip |
r5104: - added support for task based servers. These are servers that within
themselves are run as a single process, but run as a child of the
main process when smbd is run in the standard model, and run as part
of the main process when in the single mode.
- rewrote the winbind template code to use the new task services. Also
fixed the packet queueing
- got rid of event_context_merge() as it is no longer needed
(This used to be commit 339964a596689278d2138cff05d7d444798a3504)
Diffstat (limited to 'source4/smbd')
-rw-r--r-- | source4/smbd/config.mk | 3 | ||||
-rw-r--r-- | source4/smbd/process_model.h | 10 | ||||
-rw-r--r-- | source4/smbd/process_single.c | 18 | ||||
-rw-r--r-- | source4/smbd/process_standard.c | 58 | ||||
-rw-r--r-- | source4/smbd/process_thread.c | 69 | ||||
-rw-r--r-- | source4/smbd/service_stream.c | 4 | ||||
-rw-r--r-- | source4/smbd/service_task.c | 90 | ||||
-rw-r--r-- | source4/smbd/service_task.h | 30 |
8 files changed, 266 insertions, 16 deletions
diff --git a/source4/smbd/config.mk b/source4/smbd/config.mk index 07847b7fc8..4d5e929c79 100644 --- a/source4/smbd/config.mk +++ b/source4/smbd/config.mk @@ -45,7 +45,8 @@ REQUIRED_SUBSYSTEMS = \ [SUBSYSTEM::SERVER_SERVICE] INIT_OBJ_FILES = \ smbd/service.o \ - smbd/service_stream.o + smbd/service_stream.o \ + smbd/service_task.o REQUIRED_SUBSYSTEMS = \ MESSAGING # End SUBSYSTEM SERVER diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h index 943538d7b2..2e064f4277 100644 --- a/source4/smbd/process_model.h +++ b/source4/smbd/process_model.h @@ -44,8 +44,14 @@ struct model_ops { uint32_t , void *), void *); - /* function to terminate a connection */ - void (*terminate_connection)(struct event_context *, const char *reason); + /* function to create a task */ + void (*new_task)(struct event_context *, + void (*)(struct event_context *, uint32_t, void *), + void *); + + /* function to terminate a task */ + void (*terminate)(struct event_context *, const char *reason); + }; /* this structure is used by modules to determine the size of some critical types */ diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index d6217d8712..7d43855f6c 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -59,17 +59,29 @@ static void single_accept_connection(struct event_context *ev, new_conn(ev, sock2, socket_get_fd(sock), private); } +/* + called to startup a new task +*/ +static void single_new_task(struct event_context *ev, + void (*new_task)(struct event_context *, uint32_t, void *), + void *private) +{ + static uint32_t taskid = 0x10000000; + new_task(ev, taskid++, private); +} + -/* called when a connection goes down */ -static void single_terminate_connection(struct event_context *ev, const char *reason) +/* called when a task goes down */ +static void single_terminate(struct event_context *ev, const char *reason) { } static const struct model_ops single_ops = { .name = "single", .model_init = single_model_init, + .new_task = single_new_task, .accept_connection = single_accept_connection, - .terminate_connection = single_terminate_connection, + .terminate = single_terminate, }; /* diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index ee73cfadcf..b7e9076e5d 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -104,11 +104,60 @@ static void standard_accept_connection(struct event_context *ev, exit(0); } +/* + called to create a new server task +*/ +static void standard_new_task(struct event_context *ev, + void (*new_task)(struct event_context *, uint32_t , void *), + void *private) +{ + pid_t pid; + struct event_context *ev2; + + pid = fork(); + + if (pid != 0) { + /* parent or error code ... go back to the event loop */ + return; + } + + /* This is now the child code. We need a completely new event_context to work with */ + ev2 = event_context_init(NULL); + + /* the service has given us a private pointer that + encapsulates the context it needs for this new connection - + everything else will be freed */ + talloc_steal(ev2, private); + + /* this will free all the listening sockets and all state that + is not associated with this new connection */ + talloc_free(ev); + + /* tdb needs special fork handling */ + if (tdb_reopen_all() == -1) { + DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n")); + } + + /* Ensure that the forked children do not expose identical random streams */ + set_need_random_reseed(); + + /* setup this new connection */ + new_task(ev2, getpid(), private); + + /* 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 + more to process */ + event_loop_wait(ev2); + + talloc_free(ev2); + exit(0); +} + -/* called when a connection goes down */ -static void standard_terminate_connection(struct event_context *ev, const char *reason) +/* called when a task goes down */ +static void standard_terminate(struct event_context *ev, const char *reason) { - DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason)); + DEBUG(2,("standard_terminate: reason[%s]\n",reason)); /* this init_iconv() has the effect of freeing the iconv context memory, which makes leak checking easier */ @@ -128,7 +177,8 @@ static const struct model_ops standard_ops = { .name = "standard", .model_init = standard_model_init, .accept_connection = standard_accept_connection, - .terminate_connection = standard_terminate_connection, + .new_task = standard_new_task, + .terminate = standard_terminate, }; /* diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c index 6b62ca413e..223fb02085 100644 --- a/source4/smbd/process_thread.c +++ b/source4/smbd/process_thread.c @@ -105,10 +105,70 @@ static void thread_accept_connection(struct event_context *ev, } } -/* called when a SMB connection goes down */ -static void thread_terminate_connection(struct event_context *event_ctx, const char *reason) + +struct new_task_state { + struct event_context *ev; + void (*new_task)(struct event_context *, uint32_t , void *); + void *private; +}; + +static void *thread_task_fn(void *thread_parm) +{ + struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state); + + new_task->new_task(new_task->ev, pthread_self(), new_task->private); + + /* run this connection from here */ + event_loop_wait(new_task->ev); + + talloc_free(new_task); + + return NULL; +} + +/* + called when a new task is needed +*/ +static void thread_new_task(struct event_context *ev, + void (*new_task)(struct event_context *, uint32_t , void *), + void *private) +{ + int rc; + pthread_t thread_id; + pthread_attr_t thread_attr; + struct new_task_state *state; + struct event_context *ev2; + + ev2 = event_context_init(ev); + if (ev2 == NULL) return; + + state = talloc(ev2, struct new_task_state); + if (state == NULL) { + talloc_free(ev2); + return; + } + + state->new_task = new_task; + state->private = private; + state->ev = ev2; + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state); + pthread_attr_destroy(&thread_attr); + if (rc == 0) { + DEBUG(4,("thread_new_task: created thread_id=%lu\n", + (unsigned long int)thread_id)); + } else { + DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc)); + talloc_free(ev2); + } +} + +/* called when a task goes down */ +static void thread_terminate(struct event_context *event_ctx, const char *reason) { - DEBUG(10,("thread_terminate_connection: reason[%s]\n",reason)); + DEBUG(10,("thread_terminate: reason[%s]\n",reason)); talloc_free(event_ctx); @@ -442,7 +502,8 @@ static const struct model_ops thread_ops = { .name = "thread", .model_init = thread_model_init, .accept_connection = thread_accept_connection, - .terminate_connection = thread_terminate_connection, + .new_task = thread_new_task, + .terminate = thread_terminate, }; /* diff --git a/source4/smbd/service_stream.c b/source4/smbd/service_stream.c index 72a6703995..0d29c9fcb8 100644 --- a/source4/smbd/service_stream.c +++ b/source4/smbd/service_stream.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. - hepler functions for stream based servers + helper functions for stream based servers Copyright (C) Andrew Tridgell 2003-2005 Copyright (C) Stefan (metze) Metzmacher 2004 @@ -54,7 +54,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char struct event_ctx *event_ctx = srv_conn->event.ctx; const struct model_ops *model_ops = srv_conn->model_ops; talloc_free(srv_conn); - model_ops->terminate_connection(event_ctx, reason); + model_ops->terminate(event_ctx, reason); } /* diff --git a/source4/smbd/service_task.c b/source4/smbd/service_task.c new file mode 100644 index 0000000000..ea09edf3f4 --- /dev/null +++ b/source4/smbd/service_task.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + + helper functions for task based servers (nbtd, winbind etc) + + Copyright (C) Andrew Tridgell 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "process_model.h" +#include "events.h" +#include "smbd/service_task.h" + +/* + terminate a task service +*/ +void task_terminate(struct task_server *task, const char *reason) +{ + struct event_ctx *event_ctx = task->event_ctx; + const struct model_ops *model_ops = task->model_ops; + talloc_free(task); + model_ops->terminate(event_ctx, reason); +} + +/* used for the callback from the process model code */ +struct task_state { + void (*task_init)(struct task_server *); + const struct model_ops *model_ops; +}; + + +/* + called by the process model code when the new task starts up. This then calls + the server specific startup code +*/ +static void task_server_callback(struct event_context *event_ctx, uint32_t server_id, void *private) +{ + struct task_state *state = talloc_get_type(private, struct task_state); + struct task_server *task; + + task = talloc(event_ctx, struct task_server); + if (task == NULL) return; + + task->event_ctx = event_ctx; + task->model_ops = state->model_ops; + task->server_id = server_id; + + task->msg_ctx = messaging_init(task, task->server_id, task->event_ctx); + if (!task->msg_ctx) { + task_terminate(task, "messaging_init() failed"); + return; + } + + state->task_init(task); +} + +/* + startup a task based server +*/ +NTSTATUS task_server_startup(struct event_context *event_ctx, + const struct model_ops *model_ops, + void (*task_init)(struct task_server *)) +{ + struct task_state *state; + + state = talloc(event_ctx, struct task_state); + NT_STATUS_HAVE_NO_MEMORY(state); + + state->task_init = task_init; + state->model_ops = model_ops; + + model_ops->new_task(event_ctx, task_server_callback, state); + + return NT_STATUS_OK; +} + diff --git a/source4/smbd/service_task.h b/source4/smbd/service_task.h new file mode 100644 index 0000000000..e8d90d7631 --- /dev/null +++ b/source4/smbd/service_task.h @@ -0,0 +1,30 @@ +/* + Unix SMB/CIFS implementation. + + structures for task based servers + + Copyright (C) Andrew Tridgell 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +struct task_server { + struct event_context *event_ctx; + const struct model_ops *model_ops; + struct messaging_context *msg_ctx; + uint32_t server_id; +}; + |