aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorAndy Zhou <azhou@nicira.com>2014-09-08 16:14:22 -0400
committerPravin B Shelar <pshelar@nicira.com>2014-11-06 02:52:34 -0500
commitcc3a5ae6f23336ddc1d136a66c0a6a60276e99a3 (patch)
tree6c3af8e0e35ca25c331659a7f6c5c057158ba1d4 /net/openvswitch
parentca7105f278b3f7bd2c6f2b336c928f679054de4d (diff)
openvswitch: Refactor get_dp() function into multiple access APIs.
Avoid recursive read_rcu_lock() by using the lighter weight get_dp_rcu() API. Add proper locking assertions to get_dp(). Signed-off-by: Andy Zhou <azhou@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/datapath.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index bbb920bf48da..cdbc44c18714 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -140,19 +140,30 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *,
140static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, 140static int queue_userspace_packet(struct datapath *dp, struct sk_buff *,
141 const struct dp_upcall_info *); 141 const struct dp_upcall_info *);
142 142
143/* Must be called with rcu_read_lock or ovs_mutex. */ 143/* Must be called with rcu_read_lock. */
144static struct datapath *get_dp(struct net *net, int dp_ifindex) 144static struct datapath *get_dp_rcu(struct net *net, int dp_ifindex)
145{ 145{
146 struct datapath *dp = NULL; 146 struct net_device *dev = dev_get_by_index_rcu(net, dp_ifindex);
147 struct net_device *dev;
148 147
149 rcu_read_lock();
150 dev = dev_get_by_index_rcu(net, dp_ifindex);
151 if (dev) { 148 if (dev) {
152 struct vport *vport = ovs_internal_dev_get_vport(dev); 149 struct vport *vport = ovs_internal_dev_get_vport(dev);
153 if (vport) 150 if (vport)
154 dp = vport->dp; 151 return vport->dp;
155 } 152 }
153
154 return NULL;
155}
156
157/* The caller must hold either ovs_mutex or rcu_read_lock to keep the
158 * returned dp pointer valid.
159 */
160static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
161{
162 struct datapath *dp;
163
164 WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_ovsl_is_held());
165 rcu_read_lock();
166 dp = get_dp_rcu(net, dp_ifindex);
156 rcu_read_unlock(); 167 rcu_read_unlock();
157 168
158 return dp; 169 return dp;
@@ -573,7 +584,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
573 packet->mark = flow->key.phy.skb_mark; 584 packet->mark = flow->key.phy.skb_mark;
574 585
575 rcu_read_lock(); 586 rcu_read_lock();
576 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 587 dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
577 err = -ENODEV; 588 err = -ENODEV;
578 if (!dp) 589 if (!dp)
579 goto err_unlock; 590 goto err_unlock;
@@ -1227,7 +1238,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1227 struct datapath *dp; 1238 struct datapath *dp;
1228 1239
1229 rcu_read_lock(); 1240 rcu_read_lock();
1230 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 1241 dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
1231 if (!dp) { 1242 if (!dp) {
1232 rcu_read_unlock(); 1243 rcu_read_unlock();
1233 return -ENODEV; 1244 return -ENODEV;
@@ -1989,7 +2000,7 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1989 int i, j = 0; 2000 int i, j = 0;
1990 2001
1991 rcu_read_lock(); 2002 rcu_read_lock();
1992 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 2003 dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
1993 if (!dp) { 2004 if (!dp) {
1994 rcu_read_unlock(); 2005 rcu_read_unlock();
1995 return -ENODEV; 2006 return -ENODEV;