[ovs-dev] [PATCH 1/3] netdev: Free netdev with ovsrcu_postpone.

Ryan Wilson wryan at nicira.com
Fri May 9 09:34:10 UTC 2014


Previously, RCU reader threads had to take refs to netdevs, so the netdev was
not freed while reading the object. This also means the netdev still
exists in the global netdev hash table. If the main thread tries to re-create
a netdev with the same name and different type while RCU threads hold refs, it
will fail as the netdev still exists in the global netdev hash table.

This patch removes the netdev from the global netdev hash table when the ref
count is 0 but does not free the netdev until all threads have reached a
quiescent state. Thus, RCU reader threads can continue reading netdev properties
while the main thread is not blocked from making netdev configuration changes.

Note that any RCU reader threads reading netdev should not call netdev_ref or
netdev_close.

Signed-off-by: Ryan Wilson <wryan at nicira.com>
---
 lib/netdev.c |   37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/lib/netdev.c b/lib/netdev.c
index 5bf2220..65ceb22 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -35,6 +35,7 @@
 #include "netdev-vport.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
+#include "ovs-rcu.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "shash.h"
@@ -478,27 +479,35 @@ netdev_get_tunnel_config(const struct netdev *netdev)
 }
 
 static void
+netdev_free(struct netdev *dev)
+{
+    const struct netdev_class *class = dev->netdev_class;
+    struct netdev_registered_class *rc;
+    int old_ref_cnt;
+
+    ovs_assert(!dev->ref_cnt);
+
+    dev->netdev_class->destruct(dev);
+    free(dev->name);
+    dev->netdev_class->dealloc(dev);
+
+    ovs_mutex_lock(&netdev_class_mutex);
+    rc = netdev_lookup_class(class->type);
+    atomic_sub(&rc->ref_cnt, 1, &old_ref_cnt);
+    ovs_assert(old_ref_cnt > 0);
+    ovs_mutex_unlock(&netdev_class_mutex);
+}
+
+
+static void
 netdev_unref(struct netdev *dev)
     OVS_RELEASES(netdev_mutex)
 {
     ovs_assert(dev->ref_cnt);
     if (!--dev->ref_cnt) {
-        const struct netdev_class *class = dev->netdev_class;
-        struct netdev_registered_class *rc;
-        int old_ref_cnt;
-
-        dev->netdev_class->destruct(dev);
-
         shash_delete(&netdev_shash, dev->node);
-        free(dev->name);
-        dev->netdev_class->dealloc(dev);
+        ovsrcu_postpone(netdev_free, dev);
         ovs_mutex_unlock(&netdev_mutex);
-
-        ovs_mutex_lock(&netdev_class_mutex);
-        rc = netdev_lookup_class(class->type);
-        atomic_sub(&rc->ref_cnt, 1, &old_ref_cnt);
-        ovs_assert(old_ref_cnt > 0);
-        ovs_mutex_unlock(&netdev_class_mutex);
     } else {
         ovs_mutex_unlock(&netdev_mutex);
     }
-- 
1.7.9.5




More information about the dev mailing list