diff options
-rw-r--r-- | docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml | 7 | ||||
-rw-r--r-- | selftest/knownfail.d/process_limit | 1 | ||||
-rw-r--r-- | source4/smbd/process_standard.c | 33 |
3 files changed, 38 insertions, 3 deletions
diff --git a/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml b/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml index a194a26a13c..f5b1e4230be 100644 --- a/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml +++ b/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml @@ -10,6 +10,13 @@ conditions, each user will have an <citerefentry><refentrytitle>smbd</refentrytitle> <manvolnum>8</manvolnum></citerefentry> associated with him or her to handle connections to all shares from a given host.</para> + + <para>For a Samba ADDC running the standard process model this option + limits the number of processes forked to handle requests. + Currently new processes are only forked for ldap and netlogon + requests. + </para> + </description> <value type="default">0</value> diff --git a/selftest/knownfail.d/process_limit b/selftest/knownfail.d/process_limit deleted file mode 100644 index db34dae23ca..00000000000 --- a/selftest/knownfail.d/process_limit +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.process_limits.samba.tests.process_limits.StandardModelProcessLimitTests.test_process_limits diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index b1cc7de155d..139339c92ec 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -32,6 +32,9 @@ #include "lib/util/debug.h" #include "source3/lib/messages_dgm.h" +static unsigned connections_active = 0; +static unsigned smbd_max_processes = 0; + struct standard_child_state { const char *name; pid_t pid; @@ -143,8 +146,7 @@ static void standard_child_pipe_handler(struct tevent_context *ev, if (errno == 0) { errno = ECHILD; } - TALLOC_FREE(state); - return; + goto done; } if (WIFEXITED(status)) { status = WEXITSTATUS(status); @@ -157,7 +159,17 @@ static void standard_child_pipe_handler(struct tevent_context *ev, DBG_ERR("Child %d (%s) terminated with signal %d\n", (int)state->pid, state->name, status); } +done: TALLOC_FREE(state); + if (smbd_max_processes > 0) { + if (connections_active < 1) { + DBG_ERR("Number of active connections " + "less than 1 (%d)\n", + connections_active); + connections_active = 1; + } + connections_active--; + } return; } @@ -282,6 +294,21 @@ static void standard_accept_connection( return; } + if (smbd_max_processes > 0) { + if (connections_active >= smbd_max_processes) { + DBG_ERR("(%d) connections already active, " + "maximum is (%d). Dropping request\n", + connections_active, + smbd_max_processes); + /* + * Drop the connection as we're overloaded at the moment + */ + talloc_free(sock2); + return; + } + connections_active++; + } + state = setup_standard_child_pipe(ev, NULL); if (state == NULL) { return; @@ -486,6 +513,8 @@ static void standard_new_task(struct tevent_context *ev, service_details->inhibit_fork_on_accept; proc_ctx->forked_on_accept = false; + smbd_max_processes = lpcfg_max_smbd_processes(lp_ctx); + /* setup this new task. Cluster ID is PID based for this process model */ task = new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx); /* |