This patch adds 3 new configuration variables to allow the number of threads to be tuned, and also to limit the number of server connections from clients. # The maximum number of concurrent client connections to allow # over all sockets combined. # max_clients = 20 # The minimum limit sets the number of workers to start up # initially. If the number of active clients exceeds this, # then more threads are spawned, upto max_workers limit. # Typically you'd want max_workers to equal maximum number # of clients allowed #min_workers = 5 #max_workers = 20 NB, this patch does not yet implement the logic to automatically spawn more threads upto 'max_workers' - its currently just fixed at the initial 'min_workers' level. I'll address this next time I post it. One question I'd like opinions on, is whether we should have separate 'max client' limits for the local UNIX socket, vs the remotely accessible TCP/TLS sockets ? Or alternatively, follow the postgresql practice, of always allowing the 'root' user to connect to the UNIX socket regardless of limits. Only applying the limits to non-root users on UNIX socket, and TCP sockets libvirtd.aug | 6 ++++++ libvirtd.conf | 19 +++++++++++++++++++ qemud.c | 18 +++++++++++++++++- test_libvirtd.aug | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) Daniel diff --git a/qemud/libvirtd.aug b/qemud/libvirtd.aug --- a/qemud/libvirtd.aug +++ b/qemud/libvirtd.aug @@ -13,11 +13,13 @@ module Libvirtd = let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" let bool_val = store /0|1/ + let int_val = store /[0-9]+/ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ "" let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end let str_entry (kw:string) = [ key kw . value_sep . str_val ] let bool_entry (kw:string) = [ key kw . value_sep . bool_val ] + let int_entry (kw:string) = [ key kw . value_sep . int_val ] let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ] @@ -48,6 +50,9 @@ module Libvirtd = | str_array_entry "tls_allowed_dn_list" | str_array_entry "sasl_allowed_username_list" + let processing_entry = int_entry "min_workers" + | int_entry "max_workers" + | int_entry "max_clients" (* Each enty in the config is one of the following three ... *) let entry = network_entry @@ -55,6 +60,7 @@ module Libvirtd = | authentication_entry | certificate_entry | authorization_entry + | processing_entry let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ] let empty = [ label "#empty" . eol ] diff --git a/qemud/libvirtd.conf b/qemud/libvirtd.conf --- a/qemud/libvirtd.conf +++ b/qemud/libvirtd.conf @@ -225,3 +225,22 @@ #sasl_allowed_username_list = ["joe@xxxxxxxxxxx", "fred@xxxxxxxxxxx" ] + +################################################################# +# +# Processing controls +# + +# The maximum number of concurrent client connections to allow +# over all sockets combined. +# max_clients = 20 + + +# The minimum limit sets the number of workers to start up +# initially. If the number of active clients exceeds this, +# then more threads are spawned, upto max_workers limit. +# Typically you'd want max_workers to equal maximum number +# of clients allowed +#min_workers = 5 +#max_workers = 20 + diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -105,6 +105,10 @@ static char *crl_file = (char *) ""; static gnutls_certificate_credentials_t x509_cred; static gnutls_dh_params_t dh_params; + +static int min_workers = 5; +static int max_workers = 20; +static int max_clients = 20; #define DH_BITS 1024 @@ -1101,6 +1105,13 @@ static int qemudDispatchServer(struct qe qemudLog(QEMUD_ERR, _("Failed to accept connection: %s"), strerror(errno)); return -1; } + + if (server->nclients >= max_clients) { + qemudLog(QEMUD_ERR, "%s", _("Too many active clients, dropping connection")); + close(fd); + return -1; + } + fprintf(stderr, "New client %d\n", fd); if (VIR_REALLOC_N(server->clients, server->nclients+1) < 0) { qemudLog(QEMUD_ERR, "%s", _("Out of memory allocating clients")); @@ -1744,7 +1755,7 @@ static int qemudRunLoop(struct qemud_ser pthread_mutex_lock(&server->lock); - server->nworkers = 10; + server->nworkers = min_workers; if (VIR_ALLOC_N(server->workers, server->nworkers) < 0) { qemudLog(QEMUD_ERR, "%s", _("Failed to allocate workers")); return -1; @@ -2137,6 +2148,11 @@ remoteReadConfigFile (struct qemud_serve if (remoteReadSaslAllowedUsernameList (conf, server, filename) < 0) goto free_and_fail; + + + GET_CONF_INT (conf, filename, min_workers); + GET_CONF_INT (conf, filename, max_workers); + GET_CONF_INT (conf, filename, max_clients); virConfFree (conf); return 0; diff --git a/qemud/test_libvirtd.aug b/qemud/test_libvirtd.aug --- a/qemud/test_libvirtd.aug +++ b/qemud/test_libvirtd.aug @@ -227,6 +227,25 @@ sasl_allowed_username_list = [ \"joe@xxxxxxxxxxx\", \"fred@xxxxxxxxxxx\" ] + + +################################################################# +# +# Processing controls +# + +# The maximum number of concurrent client connections to allow +# over all sockets combined. +max_clients = 20 + + +# The minimum limit sets the number of workers to start up +# initially. If the number of active clients exceeds this, +# then more threads are spawned, upto max_workers limit. +# Typically you'd want max_workers to equal maximum number +# of clients allowed +min_workers = 5 +max_workers = 20 " test Libvirtd.lns get conf = @@ -461,3 +480,22 @@ sasl_allowed_username_list = [ { "1" = "joe@xxxxxxxxxxx" } { "2" = "fred@xxxxxxxxxxx" } } + { "#empty" } + { "#empty" } + { "#comment" = "################################################################"} + { "#comment" = ""} + { "#comment" = "Processing controls"} + { "#comment" = ""} + { "#empty" } + { "#comment" = "The maximum number of concurrent client connections to allow"} + { "#comment" = "over all sockets combined."} + { "max_clients" = "20" } + { "#empty" } + { "#empty" } + { "#comment" = "The minimum limit sets the number of workers to start up"} + { "#comment" = "initially. If the number of active clients exceeds this,"} + { "#comment" = "then more threads are spawned, upto max_workers limit."} + { "#comment" = "Typically you'd want max_workers to equal maximum number"} + { "#comment" = "of clients allowed"} + { "min_workers" = "5" } + { "max_workers" = "20" } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list