Commit 27f9a00a authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[PKT_SCHED]: de-inline qdiscipline locking functions

This qdisc code has several inline functions for locking that is only
used when adding/deleting queuing disciplines; so make them functions
instead.  The new qdisc_lock_tree encapsulates the locking used throughout
this code.

Also qdisc_run() is only called from net/core/dev.c so it should be
defined there.
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 6f7e7e9e
...@@ -105,43 +105,15 @@ struct qdisc_rate_table ...@@ -105,43 +105,15 @@ struct qdisc_rate_table
int refcnt; int refcnt;
}; };
static inline void sch_tree_lock(struct Qdisc *q) extern void qdisc_lock_tree(struct net_device *dev);
{ extern void qdisc_unlock_tree(struct net_device *dev);
write_lock(&qdisc_tree_lock);
spin_lock_bh(&q->dev->queue_lock);
}
static inline void sch_tree_unlock(struct Qdisc *q)
{
spin_unlock_bh(&q->dev->queue_lock);
write_unlock(&qdisc_tree_lock);
}
static inline void tcf_tree_lock(struct tcf_proto *tp)
{
write_lock(&qdisc_tree_lock);
spin_lock_bh(&tp->q->dev->queue_lock);
}
static inline void tcf_tree_unlock(struct tcf_proto *tp)
{
spin_unlock_bh(&tp->q->dev->queue_lock);
write_unlock(&qdisc_tree_lock);
}
#define sch_tree_lock(q) qdisc_lock_tree((q)->dev)
#define sch_tree_unlock(q) qdisc_unlock_tree((q)->dev)
#define tcf_tree_lock(tp) qdisc_lock_tree((tp)->q->dev)
#define tcf_tree_unlock(tp) qdisc_unlock_tree((tp)->q->dev)
static inline unsigned long #define cls_set_class(tp, clp, cl) tcf_set_class(tp, clp, cl)
cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
{
unsigned long old_cl;
tcf_tree_lock(tp);
old_cl = *clp;
*clp = cl;
tcf_tree_unlock(tp);
return old_cl;
}
static inline unsigned long static inline unsigned long
__cls_set_class(unsigned long *clp, unsigned long cl) __cls_set_class(unsigned long *clp, unsigned long cl)
{ {
...@@ -407,6 +379,8 @@ extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int); ...@@ -407,6 +379,8 @@ extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int);
extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a); extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a);
#endif #endif
extern unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp,
unsigned long cl);
extern int tcf_police(struct sk_buff *skb, struct tcf_police *p); extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock); extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock);
extern void tcf_police_destroy(struct tcf_police *p); extern void tcf_police_destroy(struct tcf_police *p);
...@@ -458,13 +432,6 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab); ...@@ -458,13 +432,6 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab);
extern int qdisc_restart(struct net_device *dev); extern int qdisc_restart(struct net_device *dev);
static inline void qdisc_run(struct net_device *dev)
{
while (!netif_queue_stopped(dev) &&
qdisc_restart(dev)<0)
/* NOTHING */;
}
/* Calculate maximal size of packet seen by hard_start_xmit /* Calculate maximal size of packet seen by hard_start_xmit
routine of this device. routine of this device.
*/ */
......
...@@ -1320,6 +1320,13 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask) ...@@ -1320,6 +1320,13 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask)
} \ } \
} }
static inline void qdisc_run(struct net_device *dev)
{
while (!netif_queue_stopped(dev) &&
qdisc_restart(dev)<0)
/* NOTHING */;
}
/** /**
* dev_queue_xmit - transmit a buffer * dev_queue_xmit - transmit a buffer
* @skb: buffer to transmit * @skb: buffer to transmit
......
...@@ -236,12 +236,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -236,12 +236,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
kfree(tp); kfree(tp);
goto errout; goto errout;
} }
write_lock(&qdisc_tree_lock);
spin_lock_bh(&dev->queue_lock); qdisc_lock_tree(dev);
tp->next = *back; tp->next = *back;
*back = tp; *back = tp;
spin_unlock_bh(&dev->queue_lock); qdisc_unlock_tree(dev);
write_unlock(&qdisc_tree_lock);
} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind)) } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
goto errout; goto errout;
...@@ -249,11 +249,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -249,11 +249,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
if (fh == 0) { if (fh == 0) {
if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
write_lock(&qdisc_tree_lock); qdisc_lock_tree(dev);
spin_lock_bh(&dev->queue_lock);
*back = tp->next; *back = tp->next;
spin_unlock_bh(&dev->queue_lock); qdisc_unlock_tree(dev);
write_unlock(&qdisc_tree_lock);
tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER); tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
tcf_destroy(tp); tcf_destroy(tp);
err = 0; err = 0;
...@@ -294,6 +293,19 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -294,6 +293,19 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
return err; return err;
} }
unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp,
unsigned long cl)
{
unsigned long old_cl;
tcf_tree_lock(tp);
old_cl = __cls_set_class(clp, cl);
tcf_tree_unlock(tp);
return old_cl;
}
static int static int
tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
u32 pid, u32 seq, unsigned flags, int event) u32 pid, u32 seq, unsigned flags, int event)
...@@ -459,3 +471,4 @@ subsys_initcall(tc_filter_init); ...@@ -459,3 +471,4 @@ subsys_initcall(tc_filter_init);
EXPORT_SYMBOL(register_tcf_proto_ops); EXPORT_SYMBOL(register_tcf_proto_ops);
EXPORT_SYMBOL(unregister_tcf_proto_ops); EXPORT_SYMBOL(unregister_tcf_proto_ops);
EXPORT_SYMBOL(tcf_set_class);
...@@ -306,8 +306,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) ...@@ -306,8 +306,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
dev_deactivate(dev); dev_deactivate(dev);
write_lock(&qdisc_tree_lock); qdisc_lock_tree(dev);
spin_lock_bh(&dev->queue_lock);
if (qdisc && qdisc->flags&TCQ_F_INGRES) { if (qdisc && qdisc->flags&TCQ_F_INGRES) {
oqdisc = dev->qdisc_ingress; oqdisc = dev->qdisc_ingress;
/* Prune old scheduler */ /* Prune old scheduler */
...@@ -334,8 +333,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) ...@@ -334,8 +333,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
dev->qdisc = &noop_qdisc; dev->qdisc = &noop_qdisc;
} }
spin_unlock_bh(&dev->queue_lock); qdisc_unlock_tree(dev);
write_unlock(&qdisc_tree_lock);
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
dev_activate(dev); dev_activate(dev);
...@@ -454,10 +452,11 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) ...@@ -454,10 +452,11 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
* before we set a netdevice's qdisc pointer to sch */ * before we set a netdevice's qdisc pointer to sch */
smp_wmb(); smp_wmb();
if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
write_lock(&qdisc_tree_lock); qdisc_lock_tree(dev);
sch->next = dev->qdisc_list; sch->next = dev->qdisc_list;
dev->qdisc_list = sch; dev->qdisc_list = sch;
write_unlock(&qdisc_tree_lock); qdisc_unlock_tree(dev);
#ifdef CONFIG_NET_ESTIMATOR #ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1]) if (tca[TCA_RATE-1])
qdisc_new_estimator(&sch->stats, sch->stats_lock, qdisc_new_estimator(&sch->stats, sch->stats_lock,
......
...@@ -54,6 +54,18 @@ ...@@ -54,6 +54,18 @@
*/ */
rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED; rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED;
void qdisc_lock_tree(struct net_device *dev)
{
write_lock(&qdisc_tree_lock);
spin_lock_bh(&dev->queue_lock);
}
void qdisc_unlock_tree(struct net_device *dev)
{
spin_unlock_bh(&dev->queue_lock);
write_unlock(&qdisc_tree_lock);
}
/* /*
dev->queue_lock serializes queue accesses for this device dev->queue_lock serializes queue accesses for this device
AND dev->qdisc pointer itself. AND dev->qdisc pointer itself.
...@@ -513,13 +525,11 @@ void dev_deactivate(struct net_device *dev) ...@@ -513,13 +525,11 @@ void dev_deactivate(struct net_device *dev)
void dev_init_scheduler(struct net_device *dev) void dev_init_scheduler(struct net_device *dev)
{ {
write_lock(&qdisc_tree_lock); qdisc_lock_tree(dev);
spin_lock_bh(&dev->queue_lock);
dev->qdisc = &noop_qdisc; dev->qdisc = &noop_qdisc;
spin_unlock_bh(&dev->queue_lock);
dev->qdisc_sleeping = &noop_qdisc; dev->qdisc_sleeping = &noop_qdisc;
dev->qdisc_list = NULL; dev->qdisc_list = NULL;
write_unlock(&qdisc_tree_lock); qdisc_unlock_tree(dev);
dev_watchdog_init(dev); dev_watchdog_init(dev);
} }
...@@ -528,8 +538,7 @@ void dev_shutdown(struct net_device *dev) ...@@ -528,8 +538,7 @@ void dev_shutdown(struct net_device *dev)
{ {
struct Qdisc *qdisc; struct Qdisc *qdisc;
write_lock(&qdisc_tree_lock); qdisc_lock_tree(dev);
spin_lock_bh(&dev->queue_lock);
qdisc = dev->qdisc_sleeping; qdisc = dev->qdisc_sleeping;
dev->qdisc = &noop_qdisc; dev->qdisc = &noop_qdisc;
dev->qdisc_sleeping = &noop_qdisc; dev->qdisc_sleeping = &noop_qdisc;
...@@ -543,8 +552,7 @@ void dev_shutdown(struct net_device *dev) ...@@ -543,8 +552,7 @@ void dev_shutdown(struct net_device *dev)
BUG_TRAP(dev->qdisc_list == NULL); BUG_TRAP(dev->qdisc_list == NULL);
BUG_TRAP(!timer_pending(&dev->watchdog_timer)); BUG_TRAP(!timer_pending(&dev->watchdog_timer));
dev->qdisc_list = NULL; dev->qdisc_list = NULL;
spin_unlock_bh(&dev->queue_lock); qdisc_unlock_tree(dev);
write_unlock(&qdisc_tree_lock);
} }
EXPORT_SYMBOL(__netdev_watchdog_up); EXPORT_SYMBOL(__netdev_watchdog_up);
...@@ -554,4 +562,5 @@ EXPORT_SYMBOL(qdisc_create_dflt); ...@@ -554,4 +562,5 @@ EXPORT_SYMBOL(qdisc_create_dflt);
EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_destroy);
EXPORT_SYMBOL(qdisc_reset); EXPORT_SYMBOL(qdisc_reset);
EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_restart);
EXPORT_SYMBOL(qdisc_tree_lock); EXPORT_SYMBOL(qdisc_lock_tree);
EXPORT_SYMBOL(qdisc_unlock_tree);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment