On Mon, Jul 29, 2019 at 7:50 PM Saeed Mahameed <sae...@mellanox.com> wrote: > > From: Vlad Buslov <vla...@mellanox.com> > > In order to remove dependency on rtnl lock, access to tc flows hashtable > must be explicitly protected from concurrent flows removal. > > Extend tc flow structure with rcu to allow concurrent parallel access. Use > rcu read lock to safely lookup flow in tc flows hash table, and take > reference to it. Use rcu free for flow deletion to accommodate concurrent > stats requests. > > Add new DELETED flow flag. Imlement new flow_flag_test_and_set() helper > that is used to set a flag and return its previous value. Use it to > atomically set the flag in mlx5e_delete_flower() to guarantee that flow can > only be deleted once, even when same flow is deleted concurrently by > multiple tasks. > > Signed-off-by: Vlad Buslov <vla...@mellanox.com> > Reviewed-by: Jianbo Liu <jian...@mellanox.com> > Reviewed-by: Roi Dayan <r...@mellanox.com> > Signed-off-by: Saeed Mahameed <sae...@mellanox.com> > ---
> @@ -3492,16 +3507,32 @@ int mlx5e_delete_flower(struct net_device *dev, > struct mlx5e_priv *priv, > { > struct rhashtable *tc_ht = get_tc_ht(priv, flags); > struct mlx5e_tc_flow *flow; > + int err; > > + rcu_read_lock(); > flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params); > - if (!flow || !same_flow_direction(flow, flags)) > - return -EINVAL; > + if (!flow || !same_flow_direction(flow, flags)) { > + err = -EINVAL; > + goto errout; > + } > > + /* Only delete the flow if it doesn't have MLX5E_TC_FLOW_DELETED flag > + * set. > + */ > + if (flow_flag_test_and_set(flow, DELETED)) { > + err = -EINVAL; > + goto errout; > + } > rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params); > + rcu_read_unlock(); > > mlx5e_flow_put(priv, flow); Dereferencing flow outside rcu readside critical section? Does a build with lockdep not complain? > > return 0; > + > +errout: > + rcu_read_unlock(); > + return err; > } > > int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, > @@ -3517,8 +3548,10 @@ int mlx5e_stats_flower(struct net_device *dev, struct > mlx5e_priv *priv, > u64 bytes = 0; > int err = 0; > > - flow = mlx5e_flow_get(rhashtable_lookup_fast(tc_ht, &f->cookie, > - tc_ht_params)); > + rcu_read_lock(); > + flow = mlx5e_flow_get(rhashtable_lookup(tc_ht, &f->cookie, > + tc_ht_params)); > + rcu_read_unlock(); > if (IS_ERR(flow)) > return PTR_ERR(flow); Same, in code below this check?