aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-07-30 18:39:39 -0400
committerJesse Gross <jesse@nicira.com>2013-08-23 19:37:59 -0400
commitd57170b1b1d71382a0d9cf31b01364a97add3f19 (patch)
tree7d8ce91219303f31fa7e08ab22c0735580cfcde3 /net/openvswitch
parent2771399ac9986c75437a83b1c723493cfcdfa439 (diff)
openvswitch: Use RCU lock for flow dump operation.
Flow dump operation is read-only operation. There is no need to take ovs-lock. Following patch use rcu-lock for dumping flows. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/datapath.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f2ed7600084e..e6fb866e4ed4 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1104,7 +1104,6 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
1104 u32 seq, u32 flags, u8 cmd) 1104 u32 seq, u32 flags, u8 cmd)
1105{ 1105{
1106 const int skb_orig_len = skb->len; 1106 const int skb_orig_len = skb->len;
1107 const struct sw_flow_actions *sf_acts;
1108 struct nlattr *start; 1107 struct nlattr *start;
1109 struct ovs_flow_stats stats; 1108 struct ovs_flow_stats stats;
1110 struct ovs_header *ovs_header; 1109 struct ovs_header *ovs_header;
@@ -1113,8 +1112,6 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
1113 u8 tcp_flags; 1112 u8 tcp_flags;
1114 int err; 1113 int err;
1115 1114
1116 sf_acts = ovsl_dereference(flow->sf_acts);
1117
1118 ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd); 1115 ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd);
1119 if (!ovs_header) 1116 if (!ovs_header)
1120 return -EMSGSIZE; 1117 return -EMSGSIZE;
@@ -1161,6 +1158,11 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
1161 */ 1158 */
1162 start = nla_nest_start(skb, OVS_FLOW_ATTR_ACTIONS); 1159 start = nla_nest_start(skb, OVS_FLOW_ATTR_ACTIONS);
1163 if (start) { 1160 if (start) {
1161 const struct sw_flow_actions *sf_acts;
1162
1163 sf_acts = rcu_dereference_check(flow->sf_acts,
1164 lockdep_ovsl_is_held());
1165
1164 err = actions_to_attr(sf_acts->actions, sf_acts->actions_len, skb); 1166 err = actions_to_attr(sf_acts->actions, sf_acts->actions_len, skb);
1165 if (!err) 1167 if (!err)
1166 nla_nest_end(skb, start); 1168 nla_nest_end(skb, start);
@@ -1440,15 +1442,14 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1440 struct datapath *dp; 1442 struct datapath *dp;
1441 struct flow_table *table; 1443 struct flow_table *table;
1442 1444
1443 ovs_lock(); 1445 rcu_read_lock();
1444 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 1446 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
1445 if (!dp) { 1447 if (!dp) {
1446 ovs_unlock(); 1448 rcu_read_unlock();
1447 return -ENODEV; 1449 return -ENODEV;
1448 } 1450 }
1449 1451
1450 table = ovsl_dereference(dp->table); 1452 table = rcu_dereference(dp->table);
1451
1452 for (;;) { 1453 for (;;) {
1453 struct sw_flow *flow; 1454 struct sw_flow *flow;
1454 u32 bucket, obj; 1455 u32 bucket, obj;
@@ -1468,7 +1469,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1468 cb->args[0] = bucket; 1469 cb->args[0] = bucket;
1469 cb->args[1] = obj; 1470 cb->args[1] = obj;
1470 } 1471 }
1471 ovs_unlock(); 1472 rcu_read_unlock();
1472 return skb->len; 1473 return skb->len;
1473} 1474}
1474 1475