mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net_sched: use idr to allocate basic filter handles
Instead of calling basic_get() in a loop to find a unused handle, just switch to idr API to allocate new handles. Cc: Chris Mi <chrism@mellanox.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									76cf546c28
								
							
						
					
					
						commit
						1d8134fea2
					
				
					 1 changed files with 23 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -17,13 +17,14 @@
 | 
			
		|||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/rtnetlink.h>
 | 
			
		||||
#include <linux/skbuff.h>
 | 
			
		||||
#include <linux/idr.h>
 | 
			
		||||
#include <net/netlink.h>
 | 
			
		||||
#include <net/act_api.h>
 | 
			
		||||
#include <net/pkt_cls.h>
 | 
			
		||||
 | 
			
		||||
struct basic_head {
 | 
			
		||||
	u32			hgenerator;
 | 
			
		||||
	struct list_head	flist;
 | 
			
		||||
	struct idr		handle_idr;
 | 
			
		||||
	struct rcu_head		rcu;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +79,7 @@ static int basic_init(struct tcf_proto *tp)
 | 
			
		|||
	if (head == NULL)
 | 
			
		||||
		return -ENOBUFS;
 | 
			
		||||
	INIT_LIST_HEAD(&head->flist);
 | 
			
		||||
	idr_init(&head->handle_idr);
 | 
			
		||||
	rcu_assign_pointer(tp->root, head);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -99,8 +101,10 @@ static void basic_destroy(struct tcf_proto *tp)
 | 
			
		|||
	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);
 | 
			
		||||
		call_rcu(&f->rcu, basic_delete_filter);
 | 
			
		||||
	}
 | 
			
		||||
	idr_destroy(&head->handle_idr);
 | 
			
		||||
	kfree_rcu(head, rcu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +115,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);
 | 
			
		||||
	call_rcu(&f->rcu, basic_delete_filter);
 | 
			
		||||
	*last = list_empty(&head->flist);
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +159,7 @@ 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;
 | 
			
		||||
| 
						 | 
				
			
			@ -179,30 +185,31 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
 | 
			
		|||
	err = -EINVAL;
 | 
			
		||||
	if (handle) {
 | 
			
		||||
		fnew->handle = handle;
 | 
			
		||||
	} else if (fold) {
 | 
			
		||||
		fnew->handle = fold->handle;
 | 
			
		||||
	} else {
 | 
			
		||||
		unsigned int i = 0x80000000;
 | 
			
		||||
		do {
 | 
			
		||||
			if (++head->hgenerator == 0x7FFFFFFF)
 | 
			
		||||
				head->hgenerator = 1;
 | 
			
		||||
		} while (--i > 0 && basic_get(tp, head->hgenerator));
 | 
			
		||||
 | 
			
		||||
		if (i <= 0) {
 | 
			
		||||
			pr_err("Insufficient number of handles\n");
 | 
			
		||||
		if (!fold) {
 | 
			
		||||
			err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index,
 | 
			
		||||
					    handle, handle + 1, GFP_KERNEL);
 | 
			
		||||
			if (err)
 | 
			
		||||
				goto errout;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fnew->handle = head->hgenerator;
 | 
			
		||||
	} else {
 | 
			
		||||
		err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index,
 | 
			
		||||
				    1, 0x7FFFFFFF, GFP_KERNEL);
 | 
			
		||||
		if (err)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		fnew->handle = idr_index;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		if (!fold)
 | 
			
		||||
			idr_remove_ext(&head->handle_idr, fnew->handle);
 | 
			
		||||
		goto errout;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*arg = fnew;
 | 
			
		||||
 | 
			
		||||
	if (fold) {
 | 
			
		||||
		idr_replace_ext(&head->handle_idr, fnew, fnew->handle);
 | 
			
		||||
		list_replace_rcu(&fold->link, &fnew->link);
 | 
			
		||||
		tcf_unbind_filter(tp, &fold->res);
 | 
			
		||||
		call_rcu(&fold->rcu, basic_delete_filter);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue