diff options
| author | Pravin B Shelar <pshelar@nicira.com> | 2013-07-30 18:42:19 -0400 |
|---|---|---|
| committer | Jesse Gross <jesse@nicira.com> | 2013-08-23 19:37:59 -0400 |
| commit | 59a35d60af3ab80037ad2fa2d60671ce2818b9e4 (patch) | |
| tree | f37b0c0b2a892d82f75e82dfb0b0fc5dc76511f1 | |
| parent | d57170b1b1d71382a0d9cf31b01364a97add3f19 (diff) | |
openvswitch: Use RCU lock for dp dump operation.
RCUfy dp-dump operation which is already read-only. This
makes all ovs dump operations lockless.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
| -rw-r--r-- | net/openvswitch/datapath.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index e6fb866e4ed4..9d97ef3c9830 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -951,9 +951,10 @@ static struct genl_ops dp_packet_genl_ops[] = { | |||
| 951 | 951 | ||
| 952 | static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats) | 952 | static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats) |
| 953 | { | 953 | { |
| 954 | struct flow_table *table; | ||
| 954 | int i; | 955 | int i; |
| 955 | struct flow_table *table = ovsl_dereference(dp->table); | ||
| 956 | 956 | ||
| 957 | table = rcu_dereference_check(dp->table, lockdep_ovsl_is_held()); | ||
| 957 | stats->n_flows = ovs_flow_tbl_count(table); | 958 | stats->n_flows = ovs_flow_tbl_count(table); |
| 958 | 959 | ||
| 959 | stats->n_hit = stats->n_missed = stats->n_lost = 0; | 960 | stats->n_hit = stats->n_missed = stats->n_lost = 0; |
| @@ -1665,7 +1666,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
| 1665 | goto err_destroy_local_port; | 1666 | goto err_destroy_local_port; |
| 1666 | 1667 | ||
| 1667 | ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); | 1668 | ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); |
| 1668 | list_add_tail(&dp->list_node, &ovs_net->dps); | 1669 | list_add_tail_rcu(&dp->list_node, &ovs_net->dps); |
| 1669 | 1670 | ||
| 1670 | ovs_unlock(); | 1671 | ovs_unlock(); |
| 1671 | 1672 | ||
| @@ -1703,7 +1704,7 @@ static void __dp_destroy(struct datapath *dp) | |||
| 1703 | ovs_dp_detach_port(vport); | 1704 | ovs_dp_detach_port(vport); |
| 1704 | } | 1705 | } |
| 1705 | 1706 | ||
| 1706 | list_del(&dp->list_node); | 1707 | list_del_rcu(&dp->list_node); |
| 1707 | 1708 | ||
| 1708 | /* OVSP_LOCAL is datapath internal port. We need to make sure that | 1709 | /* OVSP_LOCAL is datapath internal port. We need to make sure that |
| 1709 | * all port in datapath are destroyed first before freeing datapath. | 1710 | * all port in datapath are destroyed first before freeing datapath. |
| @@ -1808,8 +1809,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1808 | int skip = cb->args[0]; | 1809 | int skip = cb->args[0]; |
| 1809 | int i = 0; | 1810 | int i = 0; |
| 1810 | 1811 | ||
| 1811 | ovs_lock(); | 1812 | rcu_read_lock(); |
| 1812 | list_for_each_entry(dp, &ovs_net->dps, list_node) { | 1813 | list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) { |
| 1813 | if (i >= skip && | 1814 | if (i >= skip && |
| 1814 | ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, | 1815 | ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, |
| 1815 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1816 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| @@ -1817,7 +1818,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1817 | break; | 1818 | break; |
| 1818 | i++; | 1819 | i++; |
| 1819 | } | 1820 | } |
| 1820 | ovs_unlock(); | 1821 | rcu_read_unlock(); |
| 1821 | 1822 | ||
| 1822 | cb->args[0] = i; | 1823 | cb->args[0] = i; |
| 1823 | 1824 | ||
