[ovs-dev] [PATCH 08/12] datapath: Convert rcu_dereference() to correct variant.

Jesse Gross jesse at nicira.com
Sun Dec 12 20:53:03 UTC 2010


Using rcu_dereference() makes lockdep complain if rcu_read_lock
is not held.  This is OK if the update side lock is held.  This
adds checks to see if RTNL lock is held, if that is also a
correct form of protection.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 datapath/tunnel.c       |    8 ++++----
 datapath/vport-netdev.c |    4 ++--
 datapath/vport-patch.c  |    7 ++++---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 4873e19..395cf6c 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -181,7 +181,7 @@ static int port_cmp(const struct tbl_node *node, void *target)
 	const struct tnl_vport *tnl_vport = tnl_vport_table_cast(node);
 	struct port_lookup_key *lookup = target;
 
-	lookup->mutable = rcu_dereference(tnl_vport->mutable);
+	lookup->mutable = rcu_dereference_rtnl(tnl_vport->mutable);
 
 	return (lookup->mutable->tunnel_type == lookup->tunnel_type &&
 		lookup->mutable->port_config.daddr == lookup->daddr &&
@@ -313,7 +313,7 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
 			    const struct tnl_mutable_config **mutable)
 {
 	struct port_lookup_key lookup;
-	struct tbl *table = rcu_dereference(port_table);
+	struct tbl *table = rcu_dereference_rtnl(port_table);
 	struct tbl_node *tbl_node;
 
 	if (unlikely(!table))
@@ -1511,13 +1511,13 @@ const char *tnl_get_name(const struct vport *vport)
 const unsigned char *tnl_get_addr(const struct vport *vport)
 {
 	const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-	return rcu_dereference(tnl_vport->mutable)->eth_addr;
+	return rcu_dereference_rtnl(tnl_vport->mutable)->eth_addr;
 }
 
 int tnl_get_mtu(const struct vport *vport)
 {
 	const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-	return rcu_dereference(tnl_vport->mutable)->mtu;
+	return rcu_dereference_rtnl(tnl_vport->mutable)->mtu;
 }
 
 void tnl_free_linked_skbs(struct sk_buff *skb)
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 8827473..d492d19 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -279,11 +279,11 @@ struct vport *netdev_get_vport(struct net_device *dev)
 #else
 	if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook))	
 #endif
-		return (struct vport *)rcu_dereference(dev->rx_handler_data);
+		return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data);
 	else
 		return NULL;
 #else
-	return (struct vport *)rcu_dereference(dev->br_port);
+	return (struct vport *)rcu_dereference_rtnl(dev->br_port);
 #endif
 }
 
diff --git a/datapath/vport-patch.c b/datapath/vport-patch.c
index 8bb204b..4fdbcf5 100644
--- a/datapath/vport-patch.c
+++ b/datapath/vport-patch.c
@@ -9,6 +9,7 @@
 #include <linux/dcache.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/rtnetlink.h>
 
 #include "datapath.h"
 #include "vport.h"
@@ -58,7 +59,7 @@ static void assign_config_rcu(struct vport *vport,
 	struct patch_vport *patch_vport = patch_vport_priv(vport);
 	struct device_config *old_config;
 
-	old_config = rcu_dereference(patch_vport->devconf);
+	old_config = rtnl_dereference(patch_vport->devconf);
 	rcu_assign_pointer(patch_vport->devconf, new_config);
 	call_rcu(&old_config->rcu, free_config);
 }
@@ -228,13 +229,13 @@ static const char *patch_get_name(const struct vport *vport)
 static const unsigned char *patch_get_addr(const struct vport *vport)
 {
 	const struct patch_vport *patch_vport = patch_vport_priv(vport);
-	return rcu_dereference(patch_vport->devconf)->eth_addr;
+	return rcu_dereference_rtnl(patch_vport->devconf)->eth_addr;
 }
 
 static int patch_get_mtu(const struct vport *vport)
 {
 	const struct patch_vport *patch_vport = patch_vport_priv(vport);
-	return rcu_dereference(patch_vport->devconf)->mtu;
+	return rcu_dereference_rtnl(patch_vport->devconf)->mtu;
 }
 
 static int patch_send(struct vport *vport, struct sk_buff *skb)
-- 
1.7.1





More information about the dev mailing list