diff options
| author | John Fastabend <john.fastabend@gmail.com> | 2014-09-13 07:05:27 +0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-09-13 20:30:25 +0400 | 
| commit | 25d8c0d55f241ce2d360df1bea48e23a55836ee6 (patch) | |
| tree | c0aca67607e7ce560a4a2cebef5fb6d55adf4112 /net/sched/cls_api.c | |
| parent | 46e5da40aec256155cfedee96dd21a75da941f2c (diff) | |
| download | linux-25d8c0d55f241ce2d360df1bea48e23a55836ee6.tar.xz | |
net: rcu-ify tcf_proto
rcu'ify tcf_proto this allows calling tc_classify() without holding
any locks. Updaters are protected by RTNL.
This patch prepares the core net_sched infrastracture for running
the classifier/action chains without holding the qdisc lock however
it does nothing to ensure cls_xxx and act_xxx types also work without
locking. Additional patches are required to address the fall out.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_api.c')
| -rw-r--r-- | net/sched/cls_api.c | 30 | 
1 files changed, 15 insertions, 15 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index c28b0d327b12..e547efdaba9d 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -117,7 +117,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)  {  	struct net *net = sock_net(skb->sk);  	struct nlattr *tca[TCA_MAX + 1]; -	spinlock_t *root_lock;  	struct tcmsg *t;  	u32 protocol;  	u32 prio; @@ -125,7 +124,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)  	u32 parent;  	struct net_device *dev;  	struct Qdisc  *q; -	struct tcf_proto **back, **chain; +	struct tcf_proto __rcu **back; +	struct tcf_proto __rcu **chain;  	struct tcf_proto *tp;  	const struct tcf_proto_ops *tp_ops;  	const struct Qdisc_class_ops *cops; @@ -197,7 +197,9 @@ replay:  		goto errout;  	/* Check the chain for existence of proto-tcf with this priority */ -	for (back = chain; (tp = *back) != NULL; back = &tp->next) { +	for (back = chain; +	     (tp = rtnl_dereference(*back)) != NULL; +	     back = &tp->next) {  		if (tp->prio >= prio) {  			if (tp->prio == prio) {  				if (!nprio || @@ -209,8 +211,6 @@ replay:  		}  	} -	root_lock = qdisc_root_sleeping_lock(q); -  	if (tp == NULL) {  		/* Proto-tcf does not exist, create new one */ @@ -259,7 +259,8 @@ replay:  		}  		tp->ops = tp_ops;  		tp->protocol = protocol; -		tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back)); +		tp->prio = nprio ? : +			       TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));  		tp->q = q;  		tp->classify = tp_ops->classify;  		tp->classid = parent; @@ -280,9 +281,9 @@ replay:  	if (fh == 0) {  		if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { -			spin_lock_bh(root_lock); -			*back = tp->next; -			spin_unlock_bh(root_lock); +			struct tcf_proto *next = rtnl_dereference(tp->next); + +			RCU_INIT_POINTER(*back, next);  			tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);  			tcf_destroy(tp); @@ -322,10 +323,8 @@ replay:  			      n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);  	if (err == 0) {  		if (tp_created) { -			spin_lock_bh(root_lock); -			tp->next = *back; -			*back = tp; -			spin_unlock_bh(root_lock); +			RCU_INIT_POINTER(tp->next, rtnl_dereference(*back)); +			rcu_assign_pointer(*back, tp);  		}  		tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER);  	} else { @@ -420,7 +419,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)  	int s_t;  	struct net_device *dev;  	struct Qdisc *q; -	struct tcf_proto *tp, **chain; +	struct tcf_proto *tp, __rcu **chain;  	struct tcmsg *tcm = nlmsg_data(cb->nlh);  	unsigned long cl = 0;  	const struct Qdisc_class_ops *cops; @@ -454,7 +453,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)  	s_t = cb->args[0]; -	for (tp = *chain, t = 0; tp; tp = tp->next, t++) { +	for (tp = rtnl_dereference(*chain), t = 0; +	     tp; tp = rtnl_dereference(tp->next), t++) {  		if (t < s_t)  			continue;  		if (TC_H_MAJ(tcm->tcm_info) &&  | 
