From: "Matthew Wilcox (Oracle)" <wi...@infradead.org> Remove the hw_filter list in favour of using one of the XArray mark bits which lets us iterate more efficiently than walking a linked list.
Signed-off-by: Matthew Wilcox (Oracle) <wi...@infradead.org> --- net/sched/cls_flower.c | 47 ++++++++++-------------------------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 2a1999d2b507..4625de5e29a7 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -85,11 +85,12 @@ struct fl_flow_tmplt { struct tcf_chain *chain; }; +#define HW_FILTER XA_MARK_1 + struct cls_fl_head { struct rhashtable ht; spinlock_t masks_lock; /* Protect masks list */ struct list_head masks; - struct list_head hw_filters; struct rcu_work rwork; struct xarray filters; }; @@ -102,7 +103,6 @@ struct cls_fl_filter { struct tcf_result res; struct fl_flow_key key; struct list_head list; - struct list_head hw_list; u32 handle; u32 flags; u32 in_hw_count; @@ -332,7 +332,6 @@ static int fl_init(struct tcf_proto *tp) spin_lock_init(&head->masks_lock); INIT_LIST_HEAD_RCU(&head->masks); - INIT_LIST_HEAD(&head->hw_filters); rcu_assign_pointer(tp->root, head); xa_init_flags(&head->filters, XA_FLAGS_ALLOC1); @@ -421,7 +420,6 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f, tc_setup_cb_call(block, TC_SETUP_CLSFLOWER, &cls_flower, false); spin_lock(&tp->lock); - list_del_init(&f->hw_list); tcf_block_offload_dec(block, &f->flags); spin_unlock(&tp->lock); @@ -433,7 +431,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, struct cls_fl_filter *f, bool rtnl_held, struct netlink_ext_ack *extack) { - struct cls_fl_head *head = fl_head_dereference(tp); struct tcf_block *block = tp->chain->block; struct flow_cls_offload cls_flower = {}; bool skip_sw = tc_skip_sw(f->flags); @@ -485,9 +482,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, goto errout; } - spin_lock(&tp->lock); - list_add(&f->hw_list, &head->hw_filters); - spin_unlock(&tp->lock); errout: if (!rtnl_held) rtnl_unlock(); @@ -1581,7 +1575,6 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, err = -ENOBUFS; goto errout_tb; } - INIT_LIST_HEAD(&fnew->hw_list); refcount_set(&fnew->refcnt, 1); err = tcf_exts_init(&fnew->exts, net, TCA_FLOWER_ACT, 0); @@ -1698,6 +1691,11 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, *arg = fnew; + if (!tc_skip_hw(fnew->flags)) + xa_set_mark(&head->filters, fnew->handle, HW_FILTER); + else if (fold) + xa_clear_mark(&head->filters, fnew->handle, HW_FILTER); + kfree(tb); tcf_queue_work(&mask->rwork, fl_uninit_mask_free_work); return 0; @@ -1770,37 +1768,14 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg, arg->cookie = id; } -static struct cls_fl_filter * -fl_get_next_hw_filter(struct tcf_proto *tp, struct cls_fl_filter *f, bool add) -{ - struct cls_fl_head *head = fl_head_dereference(tp); - - spin_lock(&tp->lock); - if (list_empty(&head->hw_filters)) { - spin_unlock(&tp->lock); - return NULL; - } - - if (!f) - f = list_entry(&head->hw_filters, struct cls_fl_filter, - hw_list); - list_for_each_entry_continue(f, &head->hw_filters, hw_list) { - if (!(add && f->deleted) && refcount_inc_not_zero(&f->refcnt)) { - spin_unlock(&tp->lock); - return f; - } - } - - spin_unlock(&tp->lock); - return NULL; -} - static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb, void *cb_priv, struct netlink_ext_ack *extack) { + struct cls_fl_head *head = fl_head_dereference(tp); struct tcf_block *block = tp->chain->block; struct flow_cls_offload cls_flower = {}; - struct cls_fl_filter *f = NULL; + struct cls_fl_filter *f; + unsigned long handle; int err; /* hw_filters list can only be changed by hw offload functions after @@ -1809,7 +1784,7 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb, */ ASSERT_RTNL(); - while ((f = fl_get_next_hw_filter(tp, f, add))) { + xa_for_each_marked(&head->filters, handle, f, HW_FILTER) { cls_flower.rule = flow_rule_alloc(tcf_exts_num_actions(&f->exts)); if (!cls_flower.rule) { -- 2.23.0.rc1