diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-07-30 18:39:39 -0400 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2013-08-23 19:37:59 -0400 |
commit | d57170b1b1d71382a0d9cf31b01364a97add3f19 (patch) | |
tree | 7d8ce91219303f31fa7e08ab22c0735580cfcde3 /net/openvswitch | |
parent | 2771399ac9986c75437a83b1c723493cfcdfa439 (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.c | 17 |
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 | ||