summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml7
-rw-r--r--selftest/knownfail.d/process_limit1
-rw-r--r--source4/smbd/process_standard.c33
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);
/*