43fe83
From f5e317a62939f1b06081f309ee4e7b146385509b Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <f5e317a62939f1b06081f309ee4e7b146385509b.1377873636.git.jdenemar@redhat.com>
43fe83
From: Michal Privoznik <mprivozn@redhat.com>
43fe83
Date: Mon, 5 Aug 2013 11:30:16 +0200
43fe83
Subject: [PATCH] RPC: Don't accept client if it would overcommit max_clients
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=981729
43fe83
43fe83
Currently, even if max_client limit is hit, we accept() incoming
43fe83
connection request, but close it immediately. This has disadvantage of
43fe83
not using listen() queue. We should accept() only those clients we
43fe83
know we can serve and let all other wait in the (limited) queue.
43fe83
(cherry picked from commit 2737aaafe953fc63c3387aa3ecc540b0f44c735c)
43fe83
---
43fe83
 src/rpc/virnetserver.c | 29 ++++++++++++++++++++++++++---
43fe83
 1 file changed, 26 insertions(+), 3 deletions(-)
43fe83
43fe83
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
43fe83
index cb770c3..2306e10 100644
43fe83
--- a/src/rpc/virnetserver.c
43fe83
+++ b/src/rpc/virnetserver.c
43fe83
@@ -115,6 +115,8 @@ struct _virNetServer {
43fe83
 
43fe83
 static virClassPtr virNetServerClass;
43fe83
 static void virNetServerDispose(void *obj);
43fe83
+static void virNetServerUpdateServicesLocked(virNetServerPtr srv,
43fe83
+                                             bool enabled);
43fe83
 
43fe83
 static int virNetServerOnceInit(void)
43fe83
 {
43fe83
@@ -270,6 +272,12 @@ static int virNetServerAddClient(virNetServerPtr srv,
43fe83
     srv->clients[srv->nclients-1] = client;
43fe83
     virObjectRef(client);
43fe83
 
43fe83
+    if (srv->nclients == srv->nclients_max) {
43fe83
+        /* Temporarily stop accepting new clients */
43fe83
+        VIR_DEBUG("Temporarily suspending services due to max_clients");
43fe83
+        virNetServerUpdateServicesLocked(srv, false);
43fe83
+    }
43fe83
+
43fe83
     virNetServerClientSetDispatcher(client,
43fe83
                                     virNetServerDispatchNewMessage,
43fe83
                                     srv);
43fe83
@@ -1034,15 +1042,22 @@ static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
43fe83
 }
43fe83
 
43fe83
 
43fe83
-void virNetServerUpdateServices(virNetServerPtr srv,
43fe83
-                                bool enabled)
43fe83
+static void
43fe83
+virNetServerUpdateServicesLocked(virNetServerPtr srv,
43fe83
+                                 bool enabled)
43fe83
 {
43fe83
     size_t i;
43fe83
 
43fe83
-    virObjectLock(srv);
43fe83
     for (i = 0; i < srv->nservices; i++)
43fe83
         virNetServerServiceToggle(srv->services[i], enabled);
43fe83
+}
43fe83
 
43fe83
+
43fe83
+void virNetServerUpdateServices(virNetServerPtr srv,
43fe83
+                                bool enabled)
43fe83
+{
43fe83
+    virObjectLock(srv);
43fe83
+    virNetServerUpdateServicesLocked(srv, enabled);
43fe83
     virObjectUnlock(srv);
43fe83
 }
43fe83
 
43fe83
@@ -1120,6 +1135,14 @@ void virNetServerRun(virNetServerPtr srv)
43fe83
                     srv->nclients = 0;
43fe83
                 }
43fe83
 
43fe83
+                /* Enable services if we can accept a new client.
43fe83
+                 * The new client can be accepted if we are at the limit. */
43fe83
+                if (srv->nclients == srv->nclients_max - 1) {
43fe83
+                    /* Now it makes sense to accept() a new client. */
43fe83
+                    VIR_DEBUG("Re-enabling services");
43fe83
+                    virNetServerUpdateServicesLocked(srv, true);
43fe83
+                }
43fe83
+
43fe83
                 virObjectUnlock(srv);
43fe83
                 virObjectUnref(client);
43fe83
                 virObjectLock(srv);
43fe83
-- 
43fe83
1.8.3.2
43fe83