Commit 476d61b7 authored by Eli Britstein's avatar Eli Britstein Committed by Saeed Mahameed

net/mlx5: Add a locked flag to node removal functions

Add a locked flag to the node removal functions to signal if the
parent is already locked from the caller function or not as a pre-step
towards outside lock. Currently always use false with no functional
change.
Signed-off-by: default avatarEli Britstein <elibr@mellanox.com>
Reviewed-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Reviewed-by: default avatarMark Bloch <markb@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent e7aafc8f
...@@ -263,10 +263,11 @@ static void nested_down_write_ref_node(struct fs_node *node, ...@@ -263,10 +263,11 @@ static void nested_down_write_ref_node(struct fs_node *node,
} }
} }
static void down_write_ref_node(struct fs_node *node) static void down_write_ref_node(struct fs_node *node, bool locked)
{ {
if (node) { if (node) {
down_write(&node->lock); if (!locked)
down_write(&node->lock);
refcount_inc(&node->refcount); refcount_inc(&node->refcount);
} }
} }
...@@ -277,13 +278,14 @@ static void up_read_ref_node(struct fs_node *node) ...@@ -277,13 +278,14 @@ static void up_read_ref_node(struct fs_node *node)
up_read(&node->lock); up_read(&node->lock);
} }
static void up_write_ref_node(struct fs_node *node) static void up_write_ref_node(struct fs_node *node, bool locked)
{ {
refcount_dec(&node->refcount); refcount_dec(&node->refcount);
up_write(&node->lock); if (!locked)
up_write(&node->lock);
} }
static void tree_put_node(struct fs_node *node) static void tree_put_node(struct fs_node *node, bool locked)
{ {
struct fs_node *parent_node = node->parent; struct fs_node *parent_node = node->parent;
...@@ -294,27 +296,27 @@ static void tree_put_node(struct fs_node *node) ...@@ -294,27 +296,27 @@ static void tree_put_node(struct fs_node *node)
/* Only root namespace doesn't have parent and we just /* Only root namespace doesn't have parent and we just
* need to free its node. * need to free its node.
*/ */
down_write_ref_node(parent_node); down_write_ref_node(parent_node, locked);
list_del_init(&node->list); list_del_init(&node->list);
if (node->del_sw_func) if (node->del_sw_func)
node->del_sw_func(node); node->del_sw_func(node);
up_write_ref_node(parent_node); up_write_ref_node(parent_node, locked);
} else { } else {
kfree(node); kfree(node);
} }
node = NULL; node = NULL;
} }
if (!node && parent_node) if (!node && parent_node)
tree_put_node(parent_node); tree_put_node(parent_node, locked);
} }
static int tree_remove_node(struct fs_node *node) static int tree_remove_node(struct fs_node *node, bool locked)
{ {
if (refcount_read(&node->refcount) > 1) { if (refcount_read(&node->refcount) > 1) {
refcount_dec(&node->refcount); refcount_dec(&node->refcount);
return -EEXIST; return -EEXIST;
} }
tree_put_node(node); tree_put_node(node, locked);
return 0; return 0;
} }
...@@ -867,7 +869,7 @@ static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, ...@@ -867,7 +869,7 @@ static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
fs_get_obj(fte, rule->node.parent); fs_get_obj(fte, rule->node.parent);
if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
return -EINVAL; return -EINVAL;
down_write_ref_node(&fte->node); down_write_ref_node(&fte->node, false);
fs_get_obj(fg, fte->node.parent); fs_get_obj(fg, fte->node.parent);
fs_get_obj(ft, fg->node.parent); fs_get_obj(ft, fg->node.parent);
...@@ -875,7 +877,7 @@ static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, ...@@ -875,7 +877,7 @@ static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
root = find_root(&ft->node); root = find_root(&ft->node);
err = root->cmds->update_fte(get_dev(&ft->node), ft, fg->id, err = root->cmds->update_fte(get_dev(&ft->node), ft, fg->id,
modify_mask, fte); modify_mask, fte);
up_write_ref_node(&fte->node); up_write_ref_node(&fte->node, false);
return err; return err;
} }
...@@ -1025,11 +1027,11 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa ...@@ -1025,11 +1027,11 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
if (err) if (err)
goto destroy_ft; goto destroy_ft;
ft->node.active = true; ft->node.active = true;
down_write_ref_node(&fs_prio->node); down_write_ref_node(&fs_prio->node, false);
tree_add_node(&ft->node, &fs_prio->node); tree_add_node(&ft->node, &fs_prio->node);
list_add_flow_table(ft, fs_prio); list_add_flow_table(ft, fs_prio);
fs_prio->num_ft++; fs_prio->num_ft++;
up_write_ref_node(&fs_prio->node); up_write_ref_node(&fs_prio->node, false);
mutex_unlock(&root->chain_lock); mutex_unlock(&root->chain_lock);
trace_mlx5_fs_add_ft(ft); trace_mlx5_fs_add_ft(ft);
return ft; return ft;
...@@ -1123,17 +1125,17 @@ struct mlx5_flow_group *mlx5_create_flow_group(struct mlx5_flow_table *ft, ...@@ -1123,17 +1125,17 @@ struct mlx5_flow_group *mlx5_create_flow_group(struct mlx5_flow_table *ft,
if (ft->autogroup.active) if (ft->autogroup.active)
return ERR_PTR(-EPERM); return ERR_PTR(-EPERM);
down_write_ref_node(&ft->node); down_write_ref_node(&ft->node, false);
fg = alloc_insert_flow_group(ft, match_criteria_enable, match_criteria, fg = alloc_insert_flow_group(ft, match_criteria_enable, match_criteria,
start_index, end_index, start_index, end_index,
ft->node.children.prev); ft->node.children.prev);
up_write_ref_node(&ft->node); up_write_ref_node(&ft->node, false);
if (IS_ERR(fg)) if (IS_ERR(fg))
return fg; return fg;
err = root->cmds->create_flow_group(dev, ft, fg_in, &fg->id); err = root->cmds->create_flow_group(dev, ft, fg_in, &fg->id);
if (err) { if (err) {
tree_put_node(&fg->node); tree_put_node(&fg->node, false);
return ERR_PTR(err); return ERR_PTR(err);
} }
trace_mlx5_fs_add_fg(fg); trace_mlx5_fs_add_fg(fg);
...@@ -1530,10 +1532,10 @@ static void free_match_list(struct match_list_head *head) ...@@ -1530,10 +1532,10 @@ static void free_match_list(struct match_list_head *head)
struct match_list *iter, *match_tmp; struct match_list *iter, *match_tmp;
list_del(&head->first.list); list_del(&head->first.list);
tree_put_node(&head->first.g->node); tree_put_node(&head->first.g->node, false);
list_for_each_entry_safe(iter, match_tmp, &head->list, list_for_each_entry_safe(iter, match_tmp, &head->list,
list) { list) {
tree_put_node(&iter->g->node); tree_put_node(&iter->g->node, false);
list_del(&iter->list); list_del(&iter->list);
kfree(iter); kfree(iter);
} }
...@@ -1611,7 +1613,7 @@ lookup_fte_locked(struct mlx5_flow_group *g, ...@@ -1611,7 +1613,7 @@ lookup_fte_locked(struct mlx5_flow_group *g,
goto out; goto out;
} }
if (!fte_tmp->node.active) { if (!fte_tmp->node.active) {
tree_put_node(&fte_tmp->node); tree_put_node(&fte_tmp->node, false);
fte_tmp = NULL; fte_tmp = NULL;
goto out; goto out;
} }
...@@ -1619,7 +1621,7 @@ lookup_fte_locked(struct mlx5_flow_group *g, ...@@ -1619,7 +1621,7 @@ lookup_fte_locked(struct mlx5_flow_group *g,
nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD); nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
out: out:
if (take_write) if (take_write)
up_write_ref_node(&g->node); up_write_ref_node(&g->node, false);
else else
up_read_ref_node(&g->node); up_read_ref_node(&g->node);
return fte_tmp; return fte_tmp;
...@@ -1661,8 +1663,8 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, ...@@ -1661,8 +1663,8 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
continue; continue;
rule = add_rule_fg(g, spec->match_value, rule = add_rule_fg(g, spec->match_value,
flow_act, dest, dest_num, fte_tmp); flow_act, dest, dest_num, fte_tmp);
up_write_ref_node(&fte_tmp->node); up_write_ref_node(&fte_tmp->node, false);
tree_put_node(&fte_tmp->node); tree_put_node(&fte_tmp->node, false);
kmem_cache_free(steering->ftes_cache, fte); kmem_cache_free(steering->ftes_cache, fte);
return rule; return rule;
} }
...@@ -1698,7 +1700,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, ...@@ -1698,7 +1700,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
err = insert_fte(g, fte); err = insert_fte(g, fte);
if (err) { if (err) {
up_write_ref_node(&g->node); up_write_ref_node(&g->node, false);
if (err == -ENOSPC) if (err == -ENOSPC)
continue; continue;
kmem_cache_free(steering->ftes_cache, fte); kmem_cache_free(steering->ftes_cache, fte);
...@@ -1706,11 +1708,11 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, ...@@ -1706,11 +1708,11 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
} }
nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD); nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
up_write_ref_node(&g->node); up_write_ref_node(&g->node, false);
rule = add_rule_fg(g, spec->match_value, rule = add_rule_fg(g, spec->match_value,
flow_act, dest, dest_num, fte); flow_act, dest, dest_num, fte);
up_write_ref_node(&fte->node); up_write_ref_node(&fte->node, false);
tree_put_node(&fte->node); tree_put_node(&fte->node, false);
return rule; return rule;
} }
rule = ERR_PTR(-ENOENT); rule = ERR_PTR(-ENOENT);
...@@ -1752,7 +1754,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft, ...@@ -1752,7 +1754,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
err = build_match_list(&match_head, ft, spec); err = build_match_list(&match_head, ft, spec);
if (err) { if (err) {
if (take_write) if (take_write)
up_write_ref_node(&ft->node); up_write_ref_node(&ft->node, false);
else else
up_read_ref_node(&ft->node); up_read_ref_node(&ft->node);
return ERR_PTR(err); return ERR_PTR(err);
...@@ -1767,7 +1769,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft, ...@@ -1767,7 +1769,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
if (!IS_ERR(rule) || if (!IS_ERR(rule) ||
(PTR_ERR(rule) != -ENOENT && PTR_ERR(rule) != -EAGAIN)) { (PTR_ERR(rule) != -ENOENT && PTR_ERR(rule) != -EAGAIN)) {
if (take_write) if (take_write)
up_write_ref_node(&ft->node); up_write_ref_node(&ft->node, false);
return rule; return rule;
} }
...@@ -1783,12 +1785,12 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft, ...@@ -1783,12 +1785,12 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
g = alloc_auto_flow_group(ft, spec); g = alloc_auto_flow_group(ft, spec);
if (IS_ERR(g)) { if (IS_ERR(g)) {
rule = ERR_CAST(g); rule = ERR_CAST(g);
up_write_ref_node(&ft->node); up_write_ref_node(&ft->node, false);
return rule; return rule;
} }
nested_down_write_ref_node(&g->node, FS_LOCK_PARENT); nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
up_write_ref_node(&ft->node); up_write_ref_node(&ft->node, false);
err = create_auto_flow_group(ft, g); err = create_auto_flow_group(ft, g);
if (err) if (err)
...@@ -1807,17 +1809,17 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft, ...@@ -1807,17 +1809,17 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
} }
nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD); nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
up_write_ref_node(&g->node); up_write_ref_node(&g->node, false);
rule = add_rule_fg(g, spec->match_value, flow_act, dest, rule = add_rule_fg(g, spec->match_value, flow_act, dest,
dest_num, fte); dest_num, fte);
up_write_ref_node(&fte->node); up_write_ref_node(&fte->node, false);
tree_put_node(&fte->node); tree_put_node(&fte->node, false);
tree_put_node(&g->node); tree_put_node(&g->node, false);
return rule; return rule;
err_release_fg: err_release_fg:
up_write_ref_node(&g->node); up_write_ref_node(&g->node, false);
tree_put_node(&g->node); tree_put_node(&g->node, false);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -1883,7 +1885,7 @@ void mlx5_del_flow_rules(struct mlx5_flow_handle *handle) ...@@ -1883,7 +1885,7 @@ void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
int i; int i;
for (i = handle->num_rules - 1; i >= 0; i--) for (i = handle->num_rules - 1; i >= 0; i--)
tree_remove_node(&handle->rule[i]->node); tree_remove_node(&handle->rule[i]->node, false);
kfree(handle); kfree(handle);
} }
EXPORT_SYMBOL(mlx5_del_flow_rules); EXPORT_SYMBOL(mlx5_del_flow_rules);
...@@ -1986,7 +1988,7 @@ int mlx5_destroy_flow_table(struct mlx5_flow_table *ft) ...@@ -1986,7 +1988,7 @@ int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
mutex_unlock(&root->chain_lock); mutex_unlock(&root->chain_lock);
return err; return err;
} }
if (tree_remove_node(&ft->node)) if (tree_remove_node(&ft->node, false))
mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n", mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n",
ft->id); ft->id);
mutex_unlock(&root->chain_lock); mutex_unlock(&root->chain_lock);
...@@ -1997,7 +1999,7 @@ EXPORT_SYMBOL(mlx5_destroy_flow_table); ...@@ -1997,7 +1999,7 @@ EXPORT_SYMBOL(mlx5_destroy_flow_table);
void mlx5_destroy_flow_group(struct mlx5_flow_group *fg) void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
{ {
if (tree_remove_node(&fg->node)) if (tree_remove_node(&fg->node, false))
mlx5_core_warn(get_dev(&fg->node), "Flow group %d wasn't destroyed, refcount > 1\n", mlx5_core_warn(get_dev(&fg->node), "Flow group %d wasn't destroyed, refcount > 1\n",
fg->id); fg->id);
} }
...@@ -2381,8 +2383,8 @@ static void clean_tree(struct fs_node *node) ...@@ -2381,8 +2383,8 @@ static void clean_tree(struct fs_node *node)
tree_get_node(node); tree_get_node(node);
list_for_each_entry_safe(iter, temp, &node->children, list) list_for_each_entry_safe(iter, temp, &node->children, list)
clean_tree(iter); clean_tree(iter);
tree_put_node(node); tree_put_node(node, false);
tree_remove_node(node); tree_remove_node(node, false);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment