When ovs-vswitchd fails to acquire the ovsdb idl lock (either due to
contention or due to invalid database path), ovs-vswitchd will spin
on the global connectivity sequence number and consume 100% cpu.
This is in that the local copy is different to the global sequence
number and never updated when ovsdb idl is not locked.

To fix this issue, this commit makes ovs-vswitchd not checking the
global connectivity sequence number in that situation.

Signed-off-by: Alex Wang <[email protected]>
---
 tests/ovs-vswitchd.at |   24 ++++++++++++++++++++++++
 vswitchd/bridge.c     |   15 ++++++++++++---
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/tests/ovs-vswitchd.at b/tests/ovs-vswitchd.at
index 4e7206a..3b7c516 100644
--- a/tests/ovs-vswitchd.at
+++ b/tests/ovs-vswitchd.at
@@ -129,3 +129,27 @@ AT_CHECK([sed -n "
 # cleanup.
 kill `cat ovsdb-server.pid`
 AT_CLEANUP
+
+dnl ----------------------------------------------------------------------
+AT_SETUP([ovs-vswitchd -- invalid database path])
+
+# start an ovs-vswitchd process with invalid db path.
+ovs-vswitchd unix:invalid.db.sock --log-file=fakelog --enable-dummy 
--unixctl="`pwd`"/unixctl &
+
+# sleep for a while.
+sleep 10
+
+# stop the process.
+ovs-appctl -t `pwd`/unixctl exit
+
+# should not see this log (which indicates high cpu utilization).
+AT_CHECK([grep "wakeup due to" fakelog], [ignore])
+
+# check the fakelog, should not see any WARN/ERR/EMER log.
+AT_CHECK([sed -n "
+/|WARN|/p
+/|ERR|/p
+/|EMER|/p" fakelog
+])
+
+AT_CLEANUP
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 2918f04..11c485f 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -141,6 +141,8 @@ static struct hmap all_bridges = 
HMAP_INITIALIZER(&all_bridges);
 
 /* OVSDB IDL used to obtain configuration. */
 static struct ovsdb_idl *idl;
+/* True if OVSDB IDL is locked successfully. */
+static bool idl_locked;
 
 /* We want to complete daemonization, fully detaching from our parent process,
  * only after we have completed our initial configuration, committed our state
@@ -2734,6 +2736,12 @@ run_status_update(void)
 static void
 status_update_wait(void)
 {
+    /* This prevents the process from constantly waking up on
+     * connectivity seq, when there is no connection to ovsdb. */
+    if (!idl_locked) {
+        return;
+    }
+
     /* If the 'status_txn' is non-null (transaction incomplete), waits for the
      * transaction to complete.  If the status update to database needs to be
      * run again (transaction fails), registers a timeout in
@@ -2796,12 +2804,13 @@ bridge_run(void)
          * with the current situation of multiple ovs-vswitchd daemons,
          * disable system stats collection. */
         system_stats_enable(false);
-        /* This prevents the process from constantly waking up on
-         * connectivity seq. */
-        connectivity_seqno = seq_read(connectivity_seq_get());
+        idl_locked = false;
         return;
     } else if (!ovsdb_idl_has_lock(idl)) {
+        idl_locked = false;
         return;
+    } else {
+        idl_locked = true;
     }
     cfg = ovsrec_open_vswitch_first(idl);
 
-- 
1.7.9.5

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to