We currently use a specialized version of what amounts to genl_dereference() to protect the flow table. This prepares to propose genl_dereference() upstream and uses it instead of our version.
Signed-off-by: Jesse Gross <je...@nicira.com> --- datapath/datapath.c | 25 ++++++++++------------ datapath/linux/compat/include/linux/genetlink.h | 8 +++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 1ea5d1e..0f503df 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -112,12 +112,6 @@ static struct datapath *get_dp(int dp_ifindex) return dp; } -/* Must be called with genl_mutex. */ -static struct flow_table *get_table_protected(struct datapath *dp) -{ - return rcu_dereference_protected(dp->table, lockdep_genl_is_held()); -} - /* Must be called with rcu_read_lock or RTNL lock. */ static struct vport *get_vport_protected(struct datapath *dp, u16 port_no) { @@ -506,7 +500,7 @@ static int flush_flows(int dp_ifindex) if (!dp) return -ENODEV; - old_table = get_table_protected(dp); + old_table = genl_dereference(dp->table); new_table = flow_tbl_alloc(TBL_MIN_BUCKETS); if (!new_table) return -ENOMEM; @@ -828,7 +822,7 @@ static struct genl_ops dp_packet_genl_ops[] = { static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats) { int i; - struct flow_table *table = get_table_protected(dp); + struct flow_table *table = genl_dereference(dp->table); stats->n_flows = flow_tbl_count(table); @@ -1016,7 +1010,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) if (!dp) goto error; - table = get_table_protected(dp); + table = genl_dereference(dp->table); flow = flow_tbl_lookup(table, &key, key_len); if (!flow) { struct sw_flow_actions *acts; @@ -1034,7 +1028,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) if (!IS_ERR(new_table)) { rcu_assign_pointer(dp->table, new_table); flow_tbl_deferred_destroy(table); - table = get_table_protected(dp); + table = genl_dereference(dp->table); } } @@ -1143,7 +1137,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) if (!dp) return -ENODEV; - table = get_table_protected(dp); + table = genl_dereference(dp->table); flow = flow_tbl_lookup(table, &key, key_len); if (!flow) return -ENOENT; @@ -1178,7 +1172,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) if (!dp) return -ENODEV; - table = get_table_protected(dp); + table = genl_dereference(dp->table); flow = flow_tbl_lookup(table, &key, key_len); if (!flow) return -ENOENT; @@ -1204,18 +1198,21 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh)); struct datapath *dp; + struct flow_table *table; dp = get_dp(ovs_header->dp_ifindex); if (!dp) return -ENODEV; + table = genl_dereference(dp->table); + for (;;) { struct sw_flow *flow; u32 bucket, obj; bucket = cb->args[0]; obj = cb->args[1]; - flow = flow_tbl_next(get_table_protected(dp), &bucket, &obj); + flow = flow_tbl_next(table, &bucket, &obj); if (!flow) break; @@ -1429,7 +1426,7 @@ err_destroy_local_port: err_destroy_percpu: free_percpu(dp->stats_percpu); err_destroy_table: - flow_tbl_destroy(get_table_protected(dp)); + flow_tbl_destroy(genl_dereference(dp->table)); err_free_dp: kfree(dp); err_put_module: diff --git a/datapath/linux/compat/include/linux/genetlink.h b/datapath/linux/compat/include/linux/genetlink.h index e45d0854..f7b96d9 100644 --- a/datapath/linux/compat/include/linux/genetlink.h +++ b/datapath/linux/compat/include/linux/genetlink.h @@ -12,4 +12,12 @@ static inline int lockdep_genl_is_held(void) } #endif +/* This is also not upstream yet. */ +#ifndef genl_dereference +#include <linux/rcupdate.h> + +#define genl_dereference(p) \ + rcu_dereference_protected(p, lockdep_genl_is_held()) +#endif + #endif /* linux/genetlink.h wrapper */ -- 1.7.5.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev