Skip to content

Commit 165f013

Browse files
w1ldptrdavem330
authored andcommitted
net: sched: protect block->chain0 with block->lock
In order to remove dependency on rtnl lock, use block->lock to protect chain0 struct from concurrent modification. Rearrange code in chain0 callback add and del functions to only access chain0 when block->lock is held. Signed-off-by: Vlad Buslov <[email protected]> Acked-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2cbfab0 commit 165f013

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

net/sched/cls_api.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,11 @@ static void tcf_chain0_head_change(struct tcf_chain *chain,
244244

245245
if (chain->index)
246246
return;
247+
248+
mutex_lock(&block->lock);
247249
list_for_each_entry(item, &block->chain0.filter_chain_list, list)
248250
tcf_chain_head_change_item(item, tp_head);
251+
mutex_unlock(&block->lock);
249252
}
250253

251254
/* Returns true if block can be safely freed. */
@@ -756,8 +759,8 @@ tcf_chain0_head_change_cb_add(struct tcf_block *block,
756759
struct tcf_block_ext_info *ei,
757760
struct netlink_ext_ack *extack)
758761
{
759-
struct tcf_chain *chain0 = block->chain0.chain;
760762
struct tcf_filter_chain_list_item *item;
763+
struct tcf_chain *chain0;
761764

762765
item = kmalloc(sizeof(*item), GFP_KERNEL);
763766
if (!item) {
@@ -766,30 +769,38 @@ tcf_chain0_head_change_cb_add(struct tcf_block *block,
766769
}
767770
item->chain_head_change = ei->chain_head_change;
768771
item->chain_head_change_priv = ei->chain_head_change_priv;
772+
773+
mutex_lock(&block->lock);
774+
chain0 = block->chain0.chain;
769775
if (chain0 && chain0->filter_chain)
770776
tcf_chain_head_change_item(item, chain0->filter_chain);
771777
list_add(&item->list, &block->chain0.filter_chain_list);
778+
mutex_unlock(&block->lock);
779+
772780
return 0;
773781
}
774782

775783
static void
776784
tcf_chain0_head_change_cb_del(struct tcf_block *block,
777785
struct tcf_block_ext_info *ei)
778786
{
779-
struct tcf_chain *chain0 = block->chain0.chain;
780787
struct tcf_filter_chain_list_item *item;
781788

789+
mutex_lock(&block->lock);
782790
list_for_each_entry(item, &block->chain0.filter_chain_list, list) {
783791
if ((!ei->chain_head_change && !ei->chain_head_change_priv) ||
784792
(item->chain_head_change == ei->chain_head_change &&
785793
item->chain_head_change_priv == ei->chain_head_change_priv)) {
786-
if (chain0)
794+
if (block->chain0.chain)
787795
tcf_chain_head_change_item(item, NULL);
788796
list_del(&item->list);
797+
mutex_unlock(&block->lock);
798+
789799
kfree(item);
790800
return;
791801
}
792802
}
803+
mutex_unlock(&block->lock);
793804
WARN_ON(1);
794805
}
795806

0 commit comments

Comments
 (0)