From 9c160941403ba833c8e67981806ccae73ff7aca7 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 09:48:43 -0500 Subject: idr: Delete idr_remove_ext function Simply changing idr_remove's 'id' argument to 'unsigned long' suffices for all callers. Signed-off-by: Matthew Wilcox --- net/sched/act_api.c | 2 +- net/sched/cls_api.c | 2 +- net/sched/cls_basic.c | 6 +++--- net/sched/cls_bpf.c | 4 ++-- net/sched/cls_flower.c | 4 ++-- net/sched/cls_u32.c | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 52622a3d2517..be5b2b455371 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -78,7 +78,7 @@ static void free_tcf(struct tc_action *p) static void tcf_idr_remove(struct tcf_idrinfo *idrinfo, struct tc_action *p) { spin_lock_bh(&idrinfo->lock); - idr_remove_ext(&idrinfo->action_idr, p->tcfa_index); + idr_remove(&idrinfo->action_idr, p->tcfa_index); spin_unlock_bh(&idrinfo->lock); gen_kill_estimator(&p->tcfa_rate_est); free_tcf(p); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index bcb4ccb5f894..6d0e9bc4c782 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -393,7 +393,7 @@ static void tcf_block_remove(struct tcf_block *block, struct net *net) { struct tcf_net *tn = net_generic(net, tcf_net_id); - idr_remove_ext(&tn->idr, block->index); + idr_remove(&tn->idr, block->index); } static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index d333f5c5101d..121dff0a1763 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -120,7 +120,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) list_for_each_entry_safe(f, n, &head->flist, link) { list_del_rcu(&f->link); tcf_unbind_filter(tp, &f->res); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); if (tcf_exts_get_net(&f->exts)) call_rcu(&f->rcu, basic_delete_filter); else @@ -138,7 +138,7 @@ static int basic_delete(struct tcf_proto *tp, void *arg, bool *last, list_del_rcu(&f->link); tcf_unbind_filter(tp, &f->res); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); tcf_exts_get_net(&f->exts); call_rcu(&f->rcu, basic_delete_filter); *last = list_empty(&head->flist); @@ -228,7 +228,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, extack); if (err < 0) { if (!fold) - idr_remove_ext(&head->handle_idr, fnew->handle); + idr_remove(&head->handle_idr, fnew->handle); goto errout; } diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 8e5326bc6440..e45137e3f567 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -295,7 +295,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog, { struct cls_bpf_head *head = rtnl_dereference(tp->root); - idr_remove_ext(&head->handle_idr, prog->handle); + idr_remove(&head->handle_idr, prog->handle); cls_bpf_stop_offload(tp, prog, extack); list_del_rcu(&prog->link); tcf_unbind_filter(tp, &prog->res); @@ -542,7 +542,7 @@ errout_parms: cls_bpf_free_parms(prog); errout_idr: if (!oldprog) - idr_remove_ext(&head->handle_idr, prog->handle); + idr_remove(&head->handle_idr, prog->handle); errout: tcf_exts_destroy(&prog->exts); kfree(prog); diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index dc9acaafc0a8..e098e8ab76c9 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -288,7 +288,7 @@ static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f, { struct cls_fl_head *head = rtnl_dereference(tp->root); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); list_del_rcu(&f->list); if (!tc_skip_hw(f->flags)) fl_hw_destroy_filter(tp, f, extack); @@ -981,7 +981,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, errout_idr: if (fnew->handle) - idr_remove_ext(&head->handle_idr, fnew->handle); + idr_remove(&head->handle_idr, fnew->handle); errout: tcf_exts_destroy(&fnew->exts); kfree(fnew); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index e3c5e390ec23..bd55ed783cb1 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -596,7 +596,7 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht, rtnl_dereference(n->next)); tcf_unbind_filter(tp, &n->res); u32_remove_hw_knode(tp, n, extack); - idr_remove_ext(&ht->handle_idr, n->handle); + idr_remove(&ht->handle_idr, n->handle); if (tcf_exts_get_net(&n->exts)) call_rcu(&n->rcu, u32_delete_key_freepf_rcu); else @@ -623,7 +623,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht, if (phn == ht) { u32_clear_hw_hnode(tp, ht, extack); idr_destroy(&ht->handle_idr); - idr_remove_ext(&tp_c->handle_idr, ht->handle); + idr_remove(&tp_c->handle_idr, ht->handle); RCU_INIT_POINTER(*hn, ht->next); kfree_rcu(ht, rcu); return 0; @@ -1026,7 +1026,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, err = u32_replace_hw_hnode(tp, ht, flags, extack); if (err) { - idr_remove_ext(&tp_c->handle_idr, handle); + idr_remove(&tp_c->handle_idr, handle); kfree(ht); return err; } @@ -1162,7 +1162,7 @@ errfree: #endif kfree(n); erridr: - idr_remove_ext(&ht->handle_idr, handle); + idr_remove(&ht->handle_idr, handle); return err; } -- cgit v1.2.3 From 234a4624efe5629a777b4c00dbdf41dd8b7332db Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 09:56:36 -0500 Subject: idr: Delete idr_replace_ext function Changing idr_replace's 'id' argument to 'unsigned long' works for all callers. Callers which passed a negative ID now get -ENOENT instead of -EINVAL. No callers relied on this error value. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 3 +-- lib/idr.c | 15 +++------------ net/sched/act_api.c | 2 +- net/sched/cls_basic.c | 2 +- net/sched/cls_bpf.c | 2 +- net/sched/cls_flower.c | 2 +- net/sched/cls_u32.c | 2 +- 7 files changed, 9 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/include/linux/idr.h b/include/linux/idr.h index 118987a17ada..f1299c4dc45f 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -136,8 +136,7 @@ int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); void *idr_get_next(struct idr *, int *nextid); void *idr_get_next_ext(struct idr *idr, unsigned long *nextid); -void *idr_replace(struct idr *, void *, int id); -void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id); +void *idr_replace(struct idr *, void *, unsigned long id); void idr_destroy(struct idr *); static inline void *idr_remove(struct idr *idr, unsigned long id) diff --git a/lib/idr.c b/lib/idr.c index 2593ce513a18..577bfd4fe5c2 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -147,18 +147,9 @@ EXPORT_SYMBOL(idr_get_next_ext); * the one being replaced!). * * Returns: the old value on success. %-ENOENT indicates that @id was not - * found. %-EINVAL indicates that @id or @ptr were not valid. + * found. %-EINVAL indicates that @ptr was not valid. */ -void *idr_replace(struct idr *idr, void *ptr, int id) -{ - if (id < 0) - return ERR_PTR(-EINVAL); - - return idr_replace_ext(idr, ptr, id); -} -EXPORT_SYMBOL(idr_replace); - -void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id) +void *idr_replace(struct idr *idr, void *ptr, unsigned long id) { struct radix_tree_node *node; void __rcu **slot = NULL; @@ -175,7 +166,7 @@ void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id) return entry; } -EXPORT_SYMBOL(idr_replace_ext); +EXPORT_SYMBOL(idr_replace); /** * DOC: IDA description diff --git a/net/sched/act_api.c b/net/sched/act_api.c index be5b2b455371..1572466be031 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -348,7 +348,7 @@ void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a) struct tcf_idrinfo *idrinfo = tn->idrinfo; spin_lock_bh(&idrinfo->lock); - idr_replace_ext(&idrinfo->action_idr, a, a->tcfa_index); + idr_replace(&idrinfo->action_idr, a, a->tcfa_index); spin_unlock_bh(&idrinfo->lock); } EXPORT_SYMBOL(tcf_idr_insert); diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 121dff0a1763..588c635f195e 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -235,7 +235,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, *arg = fnew; if (fold) { - idr_replace_ext(&head->handle_idr, fnew, fnew->handle); + idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->link, &fnew->link); tcf_unbind_filter(tp, &fold->res); tcf_exts_get_net(&fold->exts); diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index e45137e3f567..8cb3a33b1afd 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -526,7 +526,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW; if (oldprog) { - idr_replace_ext(&head->handle_idr, prog, handle); + idr_replace(&head->handle_idr, prog, handle); list_replace_rcu(&oldprog->link, &prog->link); tcf_unbind_filter(tp, &oldprog->res); tcf_exts_get_net(&oldprog->exts); diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index e098e8ab76c9..0d1b0c11de34 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -967,7 +967,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, if (fold) { fnew->handle = handle; - idr_replace_ext(&head->handle_idr, fnew, fnew->handle); + idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->list, &fnew->list); tcf_unbind_filter(tp, &fold->res); tcf_exts_get_net(&fold->exts); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index bd55ed783cb1..5b256da985b1 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -848,7 +848,7 @@ static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c, if (pins->handle == n->handle) break; - idr_replace_ext(&ht->handle_idr, n, n->handle); + idr_replace(&ht->handle_idr, n, n->handle); RCU_INIT_POINTER(n->next, pins->next); rcu_assign_pointer(*ins, n); } -- cgit v1.2.3 From 322d884ba731e05ca79ae58e9dee1ef7dc4de504 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:01:24 -0500 Subject: idr: Delete idr_find_ext function Simply changing idr_remove's 'id' argument to 'unsigned long' works for all callers. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 7 +------ net/sched/act_api.c | 2 +- net/sched/cls_api.c | 2 +- net/sched/cls_flower.c | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/include/linux/idr.h b/include/linux/idr.h index f1299c4dc45f..7867d6117535 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -179,16 +179,11 @@ static inline void idr_preload_end(void) * This function can be called under rcu_read_lock(), given that the leaf * pointers lifetimes are correctly managed. */ -static inline void *idr_find_ext(const struct idr *idr, unsigned long id) +static inline void *idr_find(const struct idr *idr, unsigned long id) { return radix_tree_lookup(&idr->idr_rt, id); } -static inline void *idr_find(const struct idr *idr, int id) -{ - return idr_find_ext(idr, id); -} - /** * idr_for_each_entry - iterate over an idr's elements of a given type * @idr: idr handle diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 1572466be031..89e9189ab35c 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -222,7 +222,7 @@ static struct tc_action *tcf_idr_lookup(u32 index, struct tcf_idrinfo *idrinfo) struct tc_action *p = NULL; spin_lock_bh(&idrinfo->lock); - p = idr_find_ext(&idrinfo->action_idr, index); + p = idr_find(&idrinfo->action_idr, index); spin_unlock_bh(&idrinfo->lock); return p; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6d0e9bc4c782..802ac9d1eaab 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -434,7 +434,7 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index) { struct tcf_net *tn = net_generic(net, tcf_net_id); - return idr_find_ext(&tn->idr, block_index); + return idr_find(&tn->idr, block_index); } static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 0d1b0c11de34..2162e1c1f382 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -334,7 +334,7 @@ static void *fl_get(struct tcf_proto *tp, u32 handle) { struct cls_fl_head *head = rtnl_dereference(tp->root); - return idr_find_ext(&head->handle_idr, handle); + return idr_find(&head->handle_idr, handle); } static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { -- cgit v1.2.3 From 339913a8be8a98fca5c72f5552f0316ff6d5e701 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:28:15 -0500 Subject: net sched actions: Convert to use idr_alloc_u32 Use the new helper. Also untangle the error path, and in so doing noticed that estimator generator failure would lead to us leaking an ID. Fix that bug. Signed-off-by: Matthew Wilcox --- net/sched/act_api.c | 60 ++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) (limited to 'net') diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 89e9189ab35c..9b6916a92423 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -274,7 +274,6 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tcf_idrinfo *idrinfo = tn->idrinfo; struct idr *idr = &idrinfo->action_idr; int err = -ENOMEM; - unsigned long idr_index; if (unlikely(!p)) return -ENOMEM; @@ -284,45 +283,28 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, if (cpustats) { p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); - if (!p->cpu_bstats) { -err1: - kfree(p); - return err; - } - p->cpu_qstats = alloc_percpu(struct gnet_stats_queue); - if (!p->cpu_qstats) { -err2: - free_percpu(p->cpu_bstats); + if (!p->cpu_bstats) goto err1; - } + p->cpu_qstats = alloc_percpu(struct gnet_stats_queue); + if (!p->cpu_qstats) + goto err2; } spin_lock_init(&p->tcfa_lock); + idr_preload(GFP_KERNEL); + spin_lock_bh(&idrinfo->lock); /* user doesn't specify an index */ if (!index) { - idr_preload(GFP_KERNEL); - spin_lock_bh(&idrinfo->lock); - err = idr_alloc_ext(idr, NULL, &idr_index, 1, 0, - GFP_ATOMIC); - spin_unlock_bh(&idrinfo->lock); - idr_preload_end(); - if (err) { -err3: - free_percpu(p->cpu_qstats); - goto err2; - } - p->tcfa_index = idr_index; + index = 1; + err = idr_alloc_u32(idr, NULL, &index, UINT_MAX, GFP_ATOMIC); } else { - idr_preload(GFP_KERNEL); - spin_lock_bh(&idrinfo->lock); - err = idr_alloc_ext(idr, NULL, NULL, index, index + 1, - GFP_ATOMIC); - spin_unlock_bh(&idrinfo->lock); - idr_preload_end(); - if (err) - goto err3; - p->tcfa_index = index; + err = idr_alloc_u32(idr, NULL, &index, index, GFP_ATOMIC); } + spin_unlock_bh(&idrinfo->lock); + idr_preload_end(); + if (err) + goto err3; + p->tcfa_index = index; p->tcfa_tm.install = jiffies; p->tcfa_tm.lastuse = jiffies; p->tcfa_tm.firstuse = 0; @@ -330,9 +312,8 @@ err3: err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, &p->tcfa_rate_est, &p->tcfa_lock, NULL, est); - if (err) { - goto err3; - } + if (err) + goto err4; } p->idrinfo = idrinfo; @@ -340,6 +321,15 @@ err3: INIT_LIST_HEAD(&p->list); *a = p; return 0; +err4: + idr_remove(idr, index); +err3: + free_percpu(p->cpu_qstats); +err2: + free_percpu(p->cpu_bstats); +err1: + kfree(p); + return err; } EXPORT_SYMBOL(tcf_idr_create); -- cgit v1.2.3 From 9ce75499ac140af71f0003322c99b6e58f39dfbe Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 6 Feb 2018 16:37:52 -0500 Subject: cls_api: Convert to idr_alloc_u32 Use the new helper. Signed-off-by: Matthew Wilcox --- net/sched/cls_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 802ac9d1eaab..2bc1bc23d42e 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -381,8 +381,8 @@ static int tcf_block_insert(struct tcf_block *block, struct net *net, struct tcf_net *tn = net_generic(net, tcf_net_id); int err; - err = idr_alloc_ext(&tn->idr, block, NULL, block_index, - block_index + 1, GFP_KERNEL); + err = idr_alloc_u32(&tn->idr, block, &block_index, block_index, + GFP_KERNEL); if (err) return err; block->index = block_index; -- cgit v1.2.3 From 05af0ebb0810ba3f9669649134b4b4ad42540eba Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:36:09 -0500 Subject: cls_basic: Convert to use idr_alloc_u32 Use the new helper which saves a temporary variable and a few lines of code. Signed-off-by: Matthew Wilcox --- net/sched/cls_basic.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 588c635f195e..6b7ab3512f5b 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -185,7 +185,6 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, struct nlattr *tb[TCA_BASIC_MAX + 1]; struct basic_filter *fold = (struct basic_filter *) *arg; struct basic_filter *fnew; - unsigned long idr_index; if (tca[TCA_OPTIONS] == NULL) return -EINVAL; @@ -208,21 +207,17 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, if (err < 0) goto errout; - if (handle) { - fnew->handle = handle; - if (!fold) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (err) - goto errout; - } - } else { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - 1, 0x7FFFFFFF, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; + if (!handle) { + handle = 1; + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + INT_MAX, GFP_KERNEL); + } else if (!fold) { + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + handle, GFP_KERNEL); } + if (err) + goto errout; + fnew->handle = handle; err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr, extack); -- cgit v1.2.3 From 0b4ce8da79d65f9773601619bfc90d096f0a170e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:46:29 -0500 Subject: cls_bpf: Convert to use idr_alloc_u32 Use the new helper. This has a modest reduction in both lines of code and compiled code size. Signed-off-by: Matthew Wilcox --- net/sched/cls_bpf.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'net') diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 8cb3a33b1afd..b07c1fa8bc0d 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -471,7 +471,6 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, struct cls_bpf_prog *oldprog = *arg; struct nlattr *tb[TCA_BPF_MAX + 1]; struct cls_bpf_prog *prog; - unsigned long idr_index; int ret; if (tca[TCA_OPTIONS] == NULL) @@ -498,21 +497,18 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, } if (handle == 0) { - ret = idr_alloc_ext(&head->handle_idr, prog, &idr_index, - 1, 0x7FFFFFFF, GFP_KERNEL); - if (ret) - goto errout; - prog->handle = idr_index; - } else { - if (!oldprog) { - ret = idr_alloc_ext(&head->handle_idr, prog, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (ret) - goto errout; - } - prog->handle = handle; + handle = 1; + ret = idr_alloc_u32(&head->handle_idr, prog, &handle, + INT_MAX, GFP_KERNEL); + } else if (!oldprog) { + ret = idr_alloc_u32(&head->handle_idr, prog, &handle, + handle, GFP_KERNEL); } + if (ret) + goto errout; + prog->handle = handle; + ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr, extack); if (ret < 0) -- cgit v1.2.3 From 85bd0438a249e7a7a0622e0b0b6663595fadcc27 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:53:03 -0500 Subject: cls_flower: Convert to idr_alloc_u32 Use the new helper which saves a temporary variable and a few lines of code. Signed-off-by: Matthew Wilcox --- net/sched/cls_flower.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 2162e1c1f382..7d0ce2c40f93 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -865,7 +865,6 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, struct cls_fl_filter *fnew; struct nlattr **tb; struct fl_flow_mask mask = {}; - unsigned long idr_index; int err; if (!tca[TCA_OPTIONS]) @@ -896,21 +895,17 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, goto errout; if (!handle) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - 1, 0x80000000, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; - } - - /* user specifies a handle and it doesn't exist */ - if (handle && !fold) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; + handle = 1; + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + INT_MAX, GFP_KERNEL); + } else if (!fold) { + /* user specifies a handle and it doesn't exist */ + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + handle, GFP_KERNEL); } + if (err) + goto errout; + fnew->handle = handle; if (tb[TCA_FLOWER_FLAGS]) { fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]); @@ -966,7 +961,6 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, *arg = fnew; if (fold) { - fnew->handle = handle; idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->list, &fnew->list); tcf_unbind_filter(tp, &fold->res); -- cgit v1.2.3 From ffdc2d9e1afd20e9f9d205115661481e984542d6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 12:05:54 -0500 Subject: cls_u32: Reinstate cyclic allocation Commit e7614370d6f0 ("net_sched: use idr to allocate u32 filter handles) converted htid allocation to use the IDR. The ID allocated by this scheme changes; it used to be cyclic, but now always allocates the lowest available. The IDR supports cyclic allocation, so just use the right function. Signed-off-by: Matthew Wilcox --- net/sched/cls_u32.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 5b256da985b1..d2805f24ddd3 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -316,19 +316,13 @@ static void *u32_get(struct tcf_proto *tp, u32 handle) return u32_lookup_key(ht, handle); } +/* Protected by rtnl lock */ static u32 gen_new_htid(struct tc_u_common *tp_c, struct tc_u_hnode *ptr) { - unsigned long idr_index; - int err; - - /* This is only used inside rtnl lock it is safe to increment - * without read _copy_ update semantics - */ - err = idr_alloc_ext(&tp_c->handle_idr, ptr, &idr_index, - 1, 0x7FF, GFP_KERNEL); - if (err) + int id = idr_alloc_cyclic(&tp_c->handle_idr, ptr, 1, 0x7FF, GFP_KERNEL); + if (id < 0) return 0; - return (u32)(idr_index | 0x800) << 20; + return (id | 0x800U) << 20; } static struct hlist_head *tc_u_common_hash; -- cgit v1.2.3 From f730cb93db8e640f95ba4acb339d5732e1721730 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 13:45:02 -0500 Subject: cls_u32: Convert to idr_alloc_u32 No real benefit to this classifier, but since we're allocating a u32 anyway, we should use this function. Signed-off-by: Matthew Wilcox --- net/sched/cls_u32.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d2805f24ddd3..82f85d6a245a 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -740,19 +740,17 @@ ret: static u32 gen_new_kid(struct tc_u_hnode *ht, u32 htid) { - unsigned long idr_index; - u32 start = htid | 0x800; + u32 index = htid | 0x800; u32 max = htid | 0xFFF; - u32 min = htid; - if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index, - start, max + 1, GFP_KERNEL)) { - if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index, - min + 1, max + 1, GFP_KERNEL)) - return max; + if (idr_alloc_u32(&ht->handle_idr, NULL, &index, max, GFP_KERNEL)) { + index = htid + 1; + if (idr_alloc_u32(&ht->handle_idr, NULL, &index, max, + GFP_KERNEL)) + index = max; } - return (u32)idr_index; + return index; } static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { @@ -1003,8 +1001,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, return -ENOMEM; } } else { - err = idr_alloc_ext(&tp_c->handle_idr, ht, NULL, - handle, handle + 1, GFP_KERNEL); + err = idr_alloc_u32(&tp_c->handle_idr, ht, &handle, + handle, GFP_KERNEL); if (err) { kfree(ht); return err; @@ -1060,8 +1058,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, return -EINVAL; } handle = htid | TC_U32_NODE(handle); - err = idr_alloc_ext(&ht->handle_idr, NULL, NULL, - handle, handle + 1, + err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, GFP_KERNEL); if (err) return err; -- cgit v1.2.3 From 7a4575778f4db109b8b78e6dba03271096793f88 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 15:39:51 -0500 Subject: idr: Rename idr_for_each_entry_ext Most places in the kernel that we need to distinguish functions by the type of their arguments, we use '_ul' as a suffix for the unsigned long variant, not '_ext'. Also add kernel-doc. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 52 ++++++++++++++++++++++++++++++++-------------------- lib/idr.c | 30 ++++++++++++++++++++---------- net/sched/act_api.c | 6 +++--- 3 files changed, 55 insertions(+), 33 deletions(-) (limited to 'net') diff --git a/include/linux/idr.h b/include/linux/idr.h index fa2a04b984df..95a82cf2ed02 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -88,7 +88,7 @@ int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t); int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); void *idr_get_next(struct idr *, int *nextid); -void *idr_get_next_ext(struct idr *idr, unsigned long *nextid); +void *idr_get_next_ul(struct idr *, unsigned long *nextid); void *idr_replace(struct idr *, void *, unsigned long id); void idr_destroy(struct idr *); @@ -121,16 +121,18 @@ static inline void idr_preload_end(void) } /** - * idr_find - return pointer for given id - * @idr: idr handle - * @id: lookup key + * idr_find() - Return pointer for given ID. + * @idr: IDR handle. + * @id: Pointer ID. * - * Return the pointer given the id it has been registered with. A %NULL - * return indicates that @id is not valid or you passed %NULL in - * idr_get_new(). + * Looks up the pointer associated with this ID. A %NULL pointer may + * indicate that @id is not allocated or that the %NULL pointer was + * associated with this ID. * * This function can be called under rcu_read_lock(), given that the leaf * pointers lifetimes are correctly managed. + * + * Return: The pointer associated with this ID. */ static inline void *idr_find(const struct idr *idr, unsigned long id) { @@ -138,28 +140,38 @@ static inline void *idr_find(const struct idr *idr, unsigned long id) } /** - * idr_for_each_entry - iterate over an idr's elements of a given type - * @idr: idr handle - * @entry: the type * to use as cursor - * @id: id entry's key + * idr_for_each_entry() - Iterate over an IDR's elements of a given type. + * @idr: IDR handle. + * @entry: The type * to use as cursor + * @id: Entry ID. * * @entry and @id do not need to be initialized before the loop, and - * after normal terminatinon @entry is left with the value NULL. This + * after normal termination @entry is left with the value NULL. This * is convenient for a "not found" value. */ #define idr_for_each_entry(idr, entry, id) \ for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id) -#define idr_for_each_entry_ext(idr, entry, id) \ - for (id = 0; ((entry) = idr_get_next_ext(idr, &(id))) != NULL; ++id) /** - * idr_for_each_entry_continue - continue iteration over an idr's elements of a given type - * @idr: idr handle - * @entry: the type * to use as cursor - * @id: id entry's key + * idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type. + * @idr: IDR handle. + * @entry: The type * to use as cursor. + * @id: Entry ID. + * + * @entry and @id do not need to be initialized before the loop, and + * after normal termination @entry is left with the value NULL. This + * is convenient for a "not found" value. + */ +#define idr_for_each_entry_ul(idr, entry, id) \ + for (id = 0; ((entry) = idr_get_next_ul(idr, &(id))) != NULL; ++id) + +/** + * idr_for_each_entry_continue() - Continue iteration over an IDR's elements of a given type + * @idr: IDR handle. + * @entry: The type * to use as a cursor. + * @id: Entry ID. * - * Continue to iterate over list of given type, continuing after - * the current position. + * Continue to iterate over entries, continuing after the current position. */ #define idr_for_each_entry_continue(idr, entry, id) \ for ((entry) = idr_get_next((idr), &(id)); \ diff --git a/lib/idr.c b/lib/idr.c index c3f16307b908..3df44d528b68 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -136,13 +136,13 @@ int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) EXPORT_SYMBOL(idr_alloc_cyclic); /** - * idr_for_each - iterate through all stored pointers - * @idr: idr handle - * @fn: function to be called for each pointer - * @data: data passed to callback function + * idr_for_each() - Iterate through all stored pointers. + * @idr: IDR handle. + * @fn: Function to be called for each pointer. + * @data: Data passed to callback function. * * The callback function will be called for each entry in @idr, passing - * the id, the pointer and the data pointer passed to this function. + * the ID, the entry and @data. * * If @fn returns anything other than %0, the iteration stops and that * value is returned from this function. @@ -169,9 +169,9 @@ int idr_for_each(const struct idr *idr, EXPORT_SYMBOL(idr_for_each); /** - * idr_get_next - Find next populated entry - * @idr: idr handle - * @nextid: Pointer to lowest possible ID to return + * idr_get_next() - Find next populated entry. + * @idr: IDR handle. + * @nextid: Pointer to an ID. * * Returns the next populated entry in the tree with an ID greater than * or equal to the value pointed to by @nextid. On exit, @nextid is updated @@ -192,7 +192,17 @@ void *idr_get_next(struct idr *idr, int *nextid) } EXPORT_SYMBOL(idr_get_next); -void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) +/** + * idr_get_next_ul() - Find next populated entry. + * @idr: IDR handle. + * @nextid: Pointer to an ID. + * + * Returns the next populated entry in the tree with an ID greater than + * or equal to the value pointed to by @nextid. On exit, @nextid is updated + * to the ID of the found value. To use in a loop, the value pointed to by + * nextid must be incremented by the user. + */ +void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) { struct radix_tree_iter iter; void __rcu **slot; @@ -204,7 +214,7 @@ void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) *nextid = iter.index; return rcu_dereference_raw(*slot); } -EXPORT_SYMBOL(idr_get_next_ext); +EXPORT_SYMBOL(idr_get_next_ul); /** * idr_replace() - replace pointer for given ID. diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 9b6916a92423..eba6682727dd 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -124,7 +124,7 @@ static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, s_i = cb->args[0]; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { index++; if (index < s_i) continue; @@ -181,7 +181,7 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, if (nla_put_string(skb, TCA_KIND, ops->kind)) goto nla_put_failure; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { ret = __tcf_idr_release(p, false, true); if (ret == ACT_P_DELETED) { module_put(ops->owner); @@ -351,7 +351,7 @@ void tcf_idrinfo_destroy(const struct tc_action_ops *ops, int ret; unsigned long id = 1; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { ret = __tcf_idr_release(p, false, true); if (ret == ACT_P_DELETED) module_put(ops->owner); -- cgit v1.2.3